Too Many Rocks
04/28/21 07:50 Filed in: PICO-8
Today, I limit the number of rocks to make the game playable.
Last time, I got my "game" to leave debris (a rock) wherever a meteor crashed. If you remember, I had a list of things I wanted to do. Here it is.
So, why do I care about #2? This is what happens if you run for a long enough time.
Even before this point is reached, Ferb can't jump over the rocks if two of them are next to each other. It's too far for him to jump. That's the point of point 3. I want to tackle point 2 first. As is, every time I create a rock, I add it to my therocks table. What I can do is check to see how many rocks there are and if the number is above a certain value I can either stop the "rain" (not fun) or remove a rock before I add a new one. This should be a straight-forward solution. I'll just remove the "oldest" rock before I add the new one. As a guess, I'll limit the number of rocks to five. I'll probably have to adjust this later.
Next, the check to see if I have more than that many rocks. I can do this before I add the rock to the array.
Line 293 is the key. The weird thing about PICO-8 and Lua are they use the # prefix operator to return the number of items in a table. When I run this, I discover a problem. This code doesn't seem to work. Well, it does. The rock isn't added to the array, but the rock has already been created and therefore drawn. Let's move line 293 above line 292 and see what happens.
This looks better. However, when I run the code I still have the same issue. Too many rocks! That means I'm adding rocks to therocks somewhere else. That shouldn't be! A quick scan through the code and I find the culprit. Ah ha!
Line 332! I add the rock to the table, outside addrocktoarray(). That's the problem–and an easy fix. I just need to replace line 332.
Let's give it a run. Click the image.
That's much better. But that's not what I want. I took this route to show you the problem with the misplaced line of code. Instead of not adding a rock to the table, I want to remove the first rock before adding the new rock. It's time to look at addrocktoarray again.
I've rearranged the existing code to show you what I want to try. So how do I remove the first item from therocks array? In Lua I'd do this:
table.remove(x,1)
Which removes the first element of a table named "x". This line actually returns the item removed, but I don't care about that, so I won't save it in another variable. Here is the updated code.
And what happens when I run this:
It looks like this is one command that doesn't work in PICO-8, but works in Lua. I could just set the first element to nil, to remove it:
therocks[1] = nil — (Lua arrays are 1-based.)
But I know this causes issues because the memory released isn't recaptured (I won't go into it.) Time to check the PICO-8 docs. … some time later …
It doesn't look there is a built-in way to clear an element from an array. It's time to build my own. The way I'm going to do this is to create a copy of the array without the first element by iterating over therocks. Then, I'll set therocks to the copy. Let's see if that works. I'll create a test PICO-8 project to try it.
That's what I came up with and it works when I run it.
I'll create a function and then call it from line 292 from my Ferb game.
I could make this more generic by not referencing therocks and passing that in as a parameter, but keep-it-simple. Here's how I use it.
Note, I changed line 295 as well by reversing the condition, because I only want to remove a rock if I'm over the rock limit. Running this, I get this (click).
Much better! That's item number 2 on my list.
Next time, I'll work on item 3.
Again, here is the cartridge.
- DONE - place more rocks (this means creating an array to track the rocks and changing existing code to use the array)
- put an upper limit to the number of rocks placed.
- space the rocks (which means spacing the meteors)
So, why do I care about #2? This is what happens if you run for a long enough time.
Even before this point is reached, Ferb can't jump over the rocks if two of them are next to each other. It's too far for him to jump. That's the point of point 3. I want to tackle point 2 first. As is, every time I create a rock, I add it to my therocks table. What I can do is check to see how many rocks there are and if the number is above a certain value I can either stop the "rain" (not fun) or remove a rock before I add a new one. This should be a straight-forward solution. I'll just remove the "oldest" rock before I add the new one. As a guess, I'll limit the number of rocks to five. I'll probably have to adjust this later.
Next, the check to see if I have more than that many rocks. I can do this before I add the rock to the array.
Line 293 is the key. The weird thing about PICO-8 and Lua are they use the # prefix operator to return the number of items in a table. When I run this, I discover a problem. This code doesn't seem to work. Well, it does. The rock isn't added to the array, but the rock has already been created and therefore drawn. Let's move line 293 above line 292 and see what happens.
This looks better. However, when I run the code I still have the same issue. Too many rocks! That means I'm adding rocks to therocks somewhere else. That shouldn't be! A quick scan through the code and I find the culprit. Ah ha!
Line 332! I add the rock to the table, outside addrocktoarray(). That's the problem–and an easy fix. I just need to replace line 332.
Let's give it a run. Click the image.
That's much better. But that's not what I want. I took this route to show you the problem with the misplaced line of code. Instead of not adding a rock to the table, I want to remove the first rock before adding the new rock. It's time to look at addrocktoarray again.
I've rearranged the existing code to show you what I want to try. So how do I remove the first item from therocks array? In Lua I'd do this:
table.remove(x,1)
Which removes the first element of a table named "x". This line actually returns the item removed, but I don't care about that, so I won't save it in another variable. Here is the updated code.
And what happens when I run this:
It looks like this is one command that doesn't work in PICO-8, but works in Lua. I could just set the first element to nil, to remove it:
therocks[1] = nil — (Lua arrays are 1-based.)
But I know this causes issues because the memory released isn't recaptured (I won't go into it.) Time to check the PICO-8 docs. … some time later …
It doesn't look there is a built-in way to clear an element from an array. It's time to build my own. The way I'm going to do this is to create a copy of the array without the first element by iterating over therocks. Then, I'll set therocks to the copy. Let's see if that works. I'll create a test PICO-8 project to try it.
That's what I came up with and it works when I run it.
I'll create a function and then call it from line 292 from my Ferb game.
I could make this more generic by not referencing therocks and passing that in as a parameter, but keep-it-simple. Here's how I use it.
Note, I changed line 295 as well by reversing the condition, because I only want to remove a rock if I'm over the rock limit. Running this, I get this (click).
Much better! That's item number 2 on my list.
- DONE - place more rocks (this means creating an array to track the rocks and changing existing code to use the array)
- DONE - put an upper limit to the number of rocks placed.
- space the rocks (which means spacing the meteors)
Next time, I'll work on item 3.
Again, here is the cartridge.