How to add simple High Score function to game?

Discussion in 'iOS Programming' started by Ryan Burgess, May 2, 2013.

  1. Ryan Burgess macrumors 6502

    Joined:
    Jan 26, 2013
    #1
    Hi guys, I'm just learning how to code and I created a very simple, yet fun game (with help from a tutorial) that I want to add a high score function too. I can upload the source code below in a zip folder.

    Anyways, I basically want to add a "Highscore: X" in the upper right corner of the screen, and have the ability for the game to store the 5 highest scores, and that players name.

    I'm not sure how to do it, or if its even possible but if someone with expierence could help me out I'd really appreciate it!
     

    Attached Files:

  2. truehybridx macrumors member

    Joined:
    Dec 6, 2010
    #2
    You could keep the high scores in a plist, load it into memory, and compare and shuffle values when the high score rankings change
     
  3. Ryan Burgess thread starter macrumors 6502

    Joined:
    Jan 26, 2013
    #3
    That sounds right based on my tinkering with other games, but I literally have no idea how to write that from scratch...is there any tutorial on the Internet I could follow, or if its simple could someone post it here?

    Thanks!
     
  4. ArtOfWarfare macrumors 604

    ArtOfWarfare

    Joined:
    Nov 26, 2007
    #4
    Look at the documentation for NSUserDefaults.
     
  5. xArtx macrumors 6502a

    Joined:
    Mar 30, 2012
    #5
    Don't know if it's the best way, but right now I'd also use NSUserDefaults.

    If it's five or so scores, I think the best way to deal with it is sort the arrays
    in order of high score values, and save them by whatever means in keys
    that are numbered from 0-4 or 1-5 (at high score time).
    Then at program start you can read them back in correct order with no effort.
     
  6. charmofmaking macrumors member

    Joined:
    Feb 2, 2013
    #6
    I would break it down into small bits and use it as a way to learn to write your own code.

    Start with putting a number into a variable and getting it back out. Use NSLog to output to the console while you get things working. Once it works you can then decide how to present it on the screen using text or pictures.

    Then look at using an Array. Something like int highScore[5] to hold 5 scores and again put numbers in and get them back out. Arrays are great as you can use a loop to check each number.

    You should end up with a loop that compares the current score with each score in the array so you can slot it into place and push the lower scores down with the last score dropping off the bottom - hope this makes sense!

    Solving problems like this is what programming is all about :D
     
  7. dejo Moderator

    dejo

    Staff Member

    Joined:
    Sep 2, 2004
    Location:
    The Centennial State
    #7
    What resources have you been using to learn the fundamentals of Objective-C / iOS programming. Please try to be as specific as possible.

    Tutorials can't address every single problem to solve. At some point you need to take the fundamentals you've learned through tutorials and other resources and start to build your own solutions. This is the essence of programming.

    If it's simple, you should be able to tackle it yourself.

    Hear, hear. This is always good advice.

    And look into using NSArray. More complicated but more powerful.
     
  8. Ryan Burgess thread starter macrumors 6502

    Joined:
    Jan 26, 2013
    #8
    Thanks to everyone, I'll look into the NSArray and other resources and come back with any problems I encounter!
     
  9. ArtOfWarfare macrumors 604

    ArtOfWarfare

    Joined:
    Nov 26, 2007
    #9
    This seems like too simple a question to be asking for something like a game with any GUI.

    You should learn C first.
     
  10. Duncan C macrumors 6502a

    Duncan C

    Joined:
    Jan 21, 2008
    Location:
    Northern Virginia
    #10
    Agreed. If you're going to be saving the data to user defaults, you need an NSArray.

    An NSArray of NSObjects

    Look into the sorting methods for NSArray.


    Create a mutable array of NSNumber objects.

    Use the NSArray method sortUsingSelector to sort the array. Pass in a selector of @selector(compare:) to sort NSNumbers in numeric order.

    Save the array to user defaults.

    On startup:

    load the array into a temporary array variable.

    Copy the array into a mutable array property using the method mutableCopy.

    When the user ends his game, compare his score to the lowest score in the array, and if the score is higher, add the score to the end of the array, sort the array, then remove the object with the lowest value. (at the beginning or end of the array, depending on the order of the array.)

    If you're a beginning objective C developer that should keep you busy for a while.
     
  11. Ryan Burgess thread starter macrumors 6502

    Joined:
    Jan 26, 2013
    #11
    Hahaha you know that's right. Anyways, I've been writing some code to incorporate the high score and realized all I want is the highest score to be displayed. Since I only need 1 score I wouldn't use the NSArray (I think) and would just use NSObjects.

    So far I've gotten to the point where I can see a score, but I need to make it know the highest score (and have the user input their initials to display next to the score). I need to make a code that will compare the users score to the current high score, and replace it if necessary.

    Would I use NSObjects for this? :confused:
     
  12. lastcall macrumors member

    lastcall

    Joined:
    Jan 10, 2013
    #12
    If you want to store custom data in NSUserDefaults that doesn't follow a simple format,
    then you need to archive it. That is the purpose of the archiver.

    To use the archiver, you should look up docs on NSKeyedArchiver, NSKeyedUnarchiver, NSCoder, NSCoding, and NSObject.
     
  13. ArtOfWarfare macrumors 604

    ArtOfWarfare

    Joined:
    Nov 26, 2007
    #13
    How are the numbers currently stored? If they're primitives, use < or >. If they're NSNumbers, use compare:

    I sense that you're way ahead of yourself. You need to learn C first.
     
  14. Duncan C macrumors 6502a

    Duncan C

    Joined:
    Jan 21, 2008
    Location:
    Northern Virginia
    #14
    Just create an integer or float property highScore. When the user completes a game, use an if statement to see if the new score is higher than the high score. If it is, display a message that he's got the new high score, prompt him for his name/initials, and save both to user defaults (NSUserDefaults has a method setInteger:forKey and another one setFloat:forKey that would let you store the high score, and a method setObject:forKey: that lets you store objects like NSStrings.

    When your app loads, load the saved high score value and the high score holder's names from user defaults, save them to properties, and display them.
     
  15. dacoolest macrumors regular

    Joined:
    Nov 11, 2011
    #15
    if its a high score that you want to keep track of and in any incident if the someone scores more than the current high score then the new score should replace the current high score, then you can use NSUserDefaults to store the value of the high score. If you want to keep track of all the scores i would recommend Core Data.
     
  16. Duncan C macrumors 6502a

    Duncan C

    Joined:
    Jan 21, 2008
    Location:
    Northern Virginia
    #16

    Core Data to store an array of integers? Really?!? Isn't that a bit light firing up a 747 to go to the grocery store?

    Core Data is cool, powerful, and lets you add all kinds of great features to your app without a lot of work once you figure it out.

    However, it is not a beginner-level framework by any means, and even for experienced developers it takes some time and effort working with it before the light bulb comes on and you understand how to use it. I spent about a week with it before I "got it", and I've been doing IT professionally for about 33 years.
     
  17. Ryan Burgess, May 5, 2013
    Last edited by a moderator: May 5, 2013

    Ryan Burgess thread starter macrumors 6502

    Joined:
    Jan 26, 2013
    #17
    I only want to save the highest score, the other ones can be forgotten.

    Could you post a sample code of what that should look like? And where would that be implemented? I tried this but kept getting errors:

    Code:
     NSUserDefaults *highs = [NSUserDefaults standardUserDefaults];
        
        int highScore = 10;
        
         [highs setObject:[NSNumber numberWithInt:highScore] forKey:@"highScore"];
    
    Please let me know what I'm doing wrong!
     
  18. Duncan C macrumors 6502a

    Duncan C

    Joined:
    Jan 21, 2008
    Location:
    Northern Virginia
    #18
    The code you posted looks correct. It should work.

    What error are you getting?

    You should put that code in the method that processes a new high score - wherever that may be.

    BTW, a couple of suggestions.

    Dont call your NSUserDefaults highs. That's very misleading and confusing. Just call it defaults.

    NSUserDefaults has helper methods for saving/reading common values like integers.

    There is a method setInteger:forKey: that's easier to use than creating an NSNumber and using setObject:forKey. Under the covers the helper method does exactly what you're doing, but makes your code simpler.
     
  19. Ryan Burgess, May 5, 2013
    Last edited by a moderator: May 5, 2013

    Ryan Burgess thread starter macrumors 6502

    Joined:
    Jan 26, 2013
    #19
    Rght now I have this:
    Code:
    - (void)setHighScore {
        NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
        
        int highScore = 10;
        
        [defaults setInteger:[NSNumber numberWithInt:highScore] forKey:@"highScore"];
    }
    
    and I get the error code "Incompatible pointer to integer conversion sending 'NSNumber *' to parameter of type 'NSInteger' (aka 'int')

    Thanks for your help so far! I'm learning alot by trying these things!!
     
  20. chown33 macrumors 604

    Joined:
    Aug 9, 2009
    #20
    Break down the error message. Understand each part.

    It says you're "sending 'NSNumber *'", so start by identifying where you have an NSNumber pointer. Then look at the reference doc for the method where the error occurs, and see if the expected type is NSNumber pointer, or whether it might be expecting a different type. If it's expecting a different type, like maybe NSInteger, then that would jibe with the rest of the error message: "to parameter of type 'NSInteger' (aka 'int')".

    If you're not familiar with the difference between NSNumber and NSInteger, you should study that before proceeding.

    And please use CODE tags.
     
  21. ArtOfWarfare macrumors 604

    ArtOfWarfare

    Joined:
    Nov 26, 2007
    #21
    Apple frequently assigns names to things in their APIs that beginners mistake as being subclasses from NSObject. The NSInteger is a prime example. NSInteger is not an Object at all, it's just typedefed to be an int. You should refer to it as an NSInteger, however, and not an int, because Apple uses that term in their APIs. In the future they might change NSInteger to be typedefed to a long instead, at which point code you wrote assuming NSIntegers would be int's could cause problems.
     
  22. Ryan Burgess thread starter macrumors 6502

    Joined:
    Jan 26, 2013
    #22
    Hi, ok I updated my code and this is what a snippet of it looks like:
    Code:
    - (void)setHighScore {
        NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
        
        integer_t highScore = 10;
        
        [defaults setInteger:[NSNumber numberWithInteger:highScore] forKey:@"highLabel"];
    }
    
    - (void)setupGame {
    
                
        // 1
        seconds = 30;
        count = 0;
        
        
    
        
        // 2
        timerLabel.text = [NSString stringWithFormat:@"Time: %i", seconds];
        scoreLabel.text = [NSString stringWithFormat:@"Score:\n%i", count];
        highLabel.text = [NSString stringWithFormat:@"High Score:\n%i", highScore];
    
        // 3
        timer = [NSTimer scheduledTimerWithTimeInterval:1.0f
                                                 target:self
                                               selector:@selector(subtractTime)
                                               userInfo:nil
                                                repeats:YES];
        [backgroundMusic setVolume:0.3];
        [backgroundMusic play];
    
    }
    - (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
        [self setupGame];
    }
    
    The problem is now I get the error code: "Local declaration of instance variable hides highScore" In addition to the error mentioned previously.

    I never thought adding this simple function would be so hard!

    Thanks
     
  23. dejo, May 8, 2013
    Last edited: May 8, 2013

    dejo Moderator

    dejo

    Staff Member

    Joined:
    Sep 2, 2004
    Location:
    The Centennial State
    #23
    Seems you also have an instance variable named highScore. So, there's no need to re-declare it here!

    EDIT:
    P.S. NSUserDefault's setInteger:forKey: instance method takes an integer (a primitive) not an NSNumber (an object) for the setInteger: parameter. There's no need to wrap it in an NSNumber.
     
  24. Ryan Burgess, May 8, 2013
    Last edited: May 8, 2013

    Ryan Burgess thread starter macrumors 6502

    Joined:
    Jan 26, 2013
    #24
    Thanks very much for your responses! I figured out my main issue, getting the high score to display, and remain saved. I couldn't have done it without your help!
     

Share This Page