[SOLVED] [GAME] Cycling An Allocated Array Seamlessly

Hello! I am working on a DDR based game, where directional buttons scroll from below the screen and must be timed. I have an array of 32 structs that contain 1. button id and 2. coords(x,y).

The way the code works is that it pre-generates the coords and ids with a function, which begin below the screen. The issue is after the 32 buttons pass, I don’t know how to regenerate parts to continue the spawning of buttons. At the moment I used a workaround to regenerate the array from scratch, but the downside is it starts below the screen, leaving a 1s gap between the other tiles.

I attempted to reset the button id and coords after they are clicked, but the way I determine the next button ID to track (to make sure keypress happens) conflicts and breaks stuff (idk what happens but it sure doesn’t work).

Here is the github. I realize the code is probably confusing so I tried to document the code as best as possible. I’m currently exhausted and hoping some of the more advanced devs will discover a much more efficient solution that what I work with now.


1 Like

At first I was a bit confused, but now I see that the values 1-6 are unpressed buttons and 7-12 are the pressed versions.

In which case the most logical thing is to track the height of your Keys and once they reach a certain height, re-randomise that specific key.

The easiest way is to take

if (button_queue[i].coords[1] < -16 && button_queue[i].button <= 6) {
	game_state = 3;

And turn it into something like:

		if (button_queue[i].coords[1] < -16)
			if(button_queue[i].button <= 6)
				game_state = 3;
				uint8_t random_button = random(1, 7);
				button_queue[i].button = random_button; //1-6 L,R,U,D,A,B
				button_queue[i].coords[0] = random_button * 16;
				button_queue[i].coords[1] = HEIGHT + (i * 16);

I tested that and it seems to cause a game over on the third correct press for some reason.

By the way, unless your game is playable in 4 dimensions it seems you’re wasting 2 ints worth of memory. Your Key struct has an array of 4 ints, which I presume should be just 2.

(Better yet, make Coord its own struct, that would also make your code clearer since the x value would be coord.x instead of coord[0].)

Perhaps you ought to make your queue array into a proper queue data structure?

Like the one I gave to @filmote for Lode Runner:

1 Like

What I usually do to save space with this kind of thing is create a fixed length array with a length no greater than the maximum number of elements that could possibly be active at the same time.
Then give your struct an ‘active’ or ‘alive’ variable designating it should be updated. Once it gets below the screen and to the point that you don’t need it anymore, deactivate it (set it to false). When you create a new element traverse the array to find the first struct instance that is not active, set it to active and update the rest of the values accordingly.

I believe I did something like this for Trolly Fish if I’m remembering correctly. http://team-arg.com/fish-manual.html

If space isn’t really an issue it can be easier and more flexible to use a queue class like @Pharap suggested.

1 Like

In this case @tytydraco could get away with assigning the 0 value of button as an’inactive’ value. No extra byte required and the existing system is already halfway there (e.g. case 0 is explicitly ignored in the drawing routing)

My Queue implementation is backed by a fixed size array, no dynamic allocation involved. That’s one of the main reasons I gave it as an example.

That’s also one of the main reasons @filmote is using it. Before switching to mine he tried two different dynamic implementations (QueueArray and QueueList) and decided they weren’t good enough.
(There’s a similar story with Stack.h from Choplifter.)

I wouldn’t have suggested a dynamic implementation anyway, dynamic allocation should be generally avoided on the Arduboy (with very few exceptions).

1 Like

Thanks for the responses.
I ended up using your first method @Pharap, with recycling the newest index. I discovered that the issue with the GAME OVER screen appearing prematurely was due to the function that finds the next_index. Instead of running it by index, it now runs it by dynamic location, so that we can continuously refill an array of 4 items seamlessly.

I pushed the update to github, and it uses FAR less memory. I also removed the 7-12 pressed icons because it teleports the button south anyway, so that uses less memory as well ( i think ). Plus I made the array 4 instead of 32, and the coords array 2 instead of 4 ( good suggestion, got mixed up with bytes ).

Thanks for being patient with me :sweat_smile:

1 Like

Glad you found the issue, I was struggling to spot what the cause was.

It does, but only because it means there’s less cases for you to handle.

If you want to keep the pressed icons in then you could add them using less memory if you treated one of the bits in button as a ‘pressed’ flag. (Bits 0 to 2 are used for the button index, so bit 4 would be a good candidate.)

I was thinking only having 4 Keys might be too few, but given that the symbols are going across the shorter axis of the screen it seems to work out alright.

I’m not entirely sure if it’s the best decision since it makes it more of a reaction game than a rythm game, but then using the other axis would mine either using less buttons or smaller icons, so it’s a bit of a catch 22 I guess.

By the way, I hadn’t noticed before but you’re using #import instead of #include.

#import isn’t actually a C++ directive, it’s actually a gcc extension. The proper C++ directive is #include.
It won’t really make a difference for Arduboy games, but other compilers will probably give you a big angry error message, so try to remember to use #include instead.

As always if you ever want any more help or suggestions then be sure to ask.

Oh cool, I’ll need to look at that in-depth when I get a chance. I also have been meaning to learn how to use your fixed point library. Good stuff!

1 Like

Both FixedPoints and that Queue class (and the related Stack class) originate from a library I was writing a long time ago. If you get through those and want to see the original, let me know and I’ll point you to it.
I also have a github full of weird and interesting things.

(Not that I’m trying to force my stuff on people or be un-humble, but just in case you are interested.)

1 Like