EEPROM high score data is super high

I made a simple game using EEPROM to save the highest score won by the player.

But the highscore data shows a super high number, could it be the other EEPROM data interfering?

Since you started a new thread…

The bug I mentioned (in the other thread) in your current code is here:

I’ll explain it in more depth in the morning, but basically what your current code is doing is:

  • score is declared, but not given a value, so it ends up with an effectively random value
  • What should be your test condition is assigning 0 to score (= is assignment, == is an equality check), which means it’ll always evaluate to false (because trying to convert an int to bool produces false for zero and true for any other value)
  • What should be the code that changes/increments score is the test score > highscore. The result is evaluated and then discarded because nothing is using it
  • You have a stray ; before the curly braces, so actually the entire for loop doesn’t do anything. And for that matter this probably shouldn’t compile because the highscore = score; line can’t actually see the score variable. Unless you have another one somewhere?

I think what you meant to write was probably:

  for (int score = 0; score > highscore;) {
    highscore = score;
    EEPROM.get(EEPROM_STORAGE_SPACE_START, highscore);
    EEPROM.put(EEPROM_STORAGE_SPACE_START, highscore);
  }

But that’s not really right either because all it will do is read a score and then write it back to the same location. Unless highscore is less than 0, in which case it’ll do the same thing forever and then never break out of the loop because score is always 0 (which is a bad thing because you’ll just be burning through EEPROM read cycles, which will wear out your EEPROM). (Edit: I got muddled up, only writes have a limited number of cycles.)
(Maybe it should be score = highscore; rather than highscore = score;?)

I’ll explain it more in the morning (again, if someone else can’t help you sort it in the meantime).
For now you might want to try using a while loop instead, it’ll be a bit easier to get right because there’s fewer ;s to juggle.
(This tutorial is probably sufficient.)

1 Like

Yes, after I posted and before I saw your reply, I noticed and I changed it to

if (score > highscore) {
highscore = score;
}

As for the EEPROM cycles, since the B button is free in the title gamestate, maybe I could do something so pressing B will only save it to the EEPROM, not automatically every time I have a new highscore. For the score = highscore and vice versa, score is what I’m displaying in the gameplay state, and highscore is what is printed on the title screen, so doesn’t highscore = score make more sense?

Reading from EEPROM doesn’t cause any wear. Only writes do.

Also, EEPROM.put does an update, not a write. It only writes if the contents would change, which they wouldn’t in this case, so no wear at all. To rephrase that:
There would be no wear; wear nowhere. The EEPROM would not be under wear. :stuck_out_tongue_winking_eye:

2 Likes

I added in a justPressed if statement with both EEPROM lines inside the curly brackets, but when I press b, which activates those 2 lines, the number goes insanely big (21587!). Am I missing something and using the EEPROM code wrong?

Your code …

  if (arduboy.justPressed(B_BUTTON)) {
    EEPROM.get(EEPROM_STORAGE_SPACE_START, highscore);
    EEPROM.put(EEPROM_STORAGE_SPACE_START, highscore);
  }

… retrieves the value from the EEPROM using EEPROM.get() into the var highscore then immediately writes it back out again. Whatever value you had in highscore is overwritten with whatever garbage was in EEPROM.

YOu can probably just delete the ‘get’ line.

1 Like

I removed it, and now, after pressing B, then rebooting the Arduboy, my score resets to 0, and not whatever number I saved it as. Also, I have updated the Github code to which it is currently as in my IDE.

1 Like

The reboot should not be necessary.

By reboot, I mean I just pressed reset button and loaded the game again.

Could you just combine the two bits …

if (score > highscore) {
    highscore = score;
    EEPROM.put(EEPROM_STORAGE_SPACE_START, highscore);
}

… and drop the pressing of B? Pressing a button to save the high score is not a common thing.

I combined them, but still the same result. I had 4 points, then after restarting, it had reset to 0. Also, if it updated every single time I got a new high score, wouldn’t it burn through EEPROM cycles?

The code is in your title screen sequence so if you complete a game and have a score greater than the previous highscore, it will write it to the EEPROM once. The Highscore is then updated to the new highscore so the score isn’t writtten a second time. It would only be written when you get a new high score in the game.

As @MLXXXp pointed out, the EEPROM.put() function only write to the EEPROM if it needs to so as to minimise wear.

I have just noticed that you do not seem to read the high score from EEPROM when you first start the game - this is why its zero after reseting. Change you setup() to retrieve the previous highscore when the game first starts.


void setup() {
  arduboy.begin();
  arduboy.setFrameRate(45);
  arduboy.initRandomSeed();
  arduboy.clear();
  EEPROM.get(EEPROM_STORAGE_SPACE_START, highscore); 
}

You can leave this bit of code as it is:

if (score > highscore) {
    highscore = score;
    EEPROM.put(EEPROM_STORAGE_SPACE_START, highscore);
}
2 Likes

Thank you! it works :slightly_smiling_face:. Now that I have a working highscore function, it won’t be long 'till my game is complete :wink:.

2 Likes

Cannot wait to see this masterpiece!

1 Like

You seem to also have enemyx / enemyy and similarly named enemyX / enemyY variables. You handle the lowercase ones but not the uppercase ones. Do you mean to have two sets of variables?

Yes, I do. Originally my first enemy (the one which bounces horizontally) is enemyy/enemyx, the second one which bounces vertically is enemyY/enemyX, and my third one which bounces everywhere, is enemyY2/enemyX2. I needed three entities which more or less do the exact same thing, and I couldn’t reuse the same variables. So I made three different sets, for three different entities.

I will also add that there is a predefined struct called Point in the Arduboy2 Library that lets you do things like:

Point enemy;

enemy.x = 12;
enemy.y = 45;

// or

Point player = { 34, 67 };

Its similar to the rectangle you are using now put has only an X and Y value.

Structs can be handy when you want to return multiple values from a function. You have the code:

    enemyy = random(11, 54);
    enemyX = random(11, 113);

But you could wrap it in a function called launchEnemy() like this:

Point enemy;

...

Point launchEnemy() {

    Point newEnemy;
    newEnemy.y = random(11, 54);
    newEnemy.x = random(11, 113);
 
    return newEnemy;

}

...

enemy = launchEnemy();

You cannot normally return more than one variable from a function (in this case the X value or the Y value). I say normally because you can using a thing called references but that’s a different topic.

1 Like

I’m fairly new to c++, and while I was reviewing some of your Steve the dinosaur code, I saw “enum” and “struct” used a lot, so I’m going to try and learn more about this stuff :+1:

Nice … they are both really handy.

Once you have mastered structs you will realise that not only can you group related variables together but you can add code into the struct. So you might have a struct that represents an enemy and it might have some code that relates to the enemy itself. like:

struct Enemy {

    int x;
    int y;

    void launchEnemy() {
        this->y = random(11, 54);
        this->x = random(11, 113);
    }

}

...

Enemy enemy1;
 
enemy1.launchEnemy();
Sprites::drawOverwrite(enemy1.x, enemy1.y, ImageName, 0);

Anyhow, that’s enough preaching for one day … have fun!

1 Like

You’re quite right. God knows what made me think reads have a limit as well.
Maybe I got read/write mixed up with write/erase?

That much I was certain of. Source code sticks with me better than technical documents.


I didn’t spot you already had a score in your global variable list.
I only saw the score you were trying to put in the for loop, and I wasn’t quite sure what you were trying to do with that loop.
I thought perhaps you were trying to have more than one highscore and not quite managing to do it.
(If you later decide to have more than one highscore then you will definitely need a for loop to update the score list.)

if (score > highscore)
{
	highscore = score;
}

Does indeed make sense, depending on where you put it.

E.g. if you’re displaying the current score and the high score then it would make sense to put this in the game logic (so that when the player surpasses the highscore, the highscore printed to the screen also updates), but you should probably only update the EEPROM data when it’s game over (so you only update it once per game, and only when it needs to be updated - you can’t really do any better than that).

Damn, @filmote stole the fun stuff while I was sleeping.
So I’m going to be mean and steal the next fun bit… :P

@Ard_Flamingo

When you’ve got a type you can use to represent your enemies, whether it’s Point, Rect or your own Enemy class/struct, you can put them in a kind of list called an ‘array’, which effectively lets you use a single variable to refer to multiple different instances of a type.

// Three enemies, stored in an 'array'
Enemy enemies[3];

And you can then use a variable to select an enemy by number, e.g. the code:

for(uint8_t index = 0; index < 3; ++index)
{
  arduboy.print(F("Enemy number "));
  arduboy.print(index);
  arduboy.print(F(" is at position ("));
  arduboy.print(enemies[index].x);
  arduboy.print(F(", "));
  arduboy.print(enemies[index].y);
  arduboy.println(F(")"));
}

Might print something like:

Enemy number 0 is at position (10, 16)
Enemy number 1 is at position (35, 45)
Enemy number 2 is at position (100, 34)

You would also likely use an array if you wanted to store more than one highscore, as you would need to read and update the whole score list (since a new score might not be the top score).

Feel free to ask if you get stuck.


@filmote, I think you can guess what I was about to point out here…

1 Like