Anyway, let's see how this code works...
This was the easier of the two tasks. Moving something (a shape, sprite, whatever) was covered pretty well in the Squashy tutorial. All we need is to change the X and Y values the object and then call this in the _update() function. The only difference here was instead of a single object, I had bunch of objects stored inside a table, each under its own number. This is where my lack of knowledge of Lua syntax, and of programming in general, slowed me down. On paper I knew exactly how to do it. Get a loop going that updates the X and Y values of each element inside the table. Now All I needed to get it going was to find a way to access stuff in that table. So I had spent some time looking for Pico8 carts that have random enemies and try to dissect their code. I have noticed few of them using the FOREACH statement in conjunction with a table and a function that had one parameter - o. This "got the ball rolling," so to speak.
At this point I thought that the naming of the parameter (o) had to be the same to the one used in creation of my table (which also was o). That's not the case. To my understanding FOREACH looks up the values from the table (in the case of bugs, it returns the table for each enemy), and plants it into the function. The function can now process each enemy one by one. Thanks to that it changes X and Y for enemy 1, then 2, than 3 and so on. The "o" parameter is simply a "placeholder" a local variable (as I said, I mostly understand tables )
After finding a way to update X and Y of every enemy I just added some IF statements to keep the balls on screen (bounce of the wall just like in Squashy) and another one to eliminate a bug where a ball would get stuck on one of the walls after collision. I guess I could have combined them into one function, but having them separated makes it more clear what each section does.
After I had the balls moving and bouncing of the walls I wanted them to bounce of each other. For that I needed...
This was the tricky syntax part that I couldn't figure out on my own. It felt like it was within my grasp after figuring all the math and learning about FOREACH, but it felt like a strange blind spot in my brain whenever I was trying to create syntax to compare two different enemies from inside the table. I spent a day or so trying to find a solution, but again, documentation simply wasn't there (I really hope that Pico-8 manual will eventually become a little noob friendly). This is where the awesome community of this fantasy console stepped in.
This is the second version of the collision code. The original way was working fine, but used over twice as much CPU clock. It was based around FOR x in ALL(table) instead of FOR x=1,#table (length of the table) which meant that the code would check enemy 1 vs enemy 2, but also check enemy 2 vs enemy 1, which was not necessary, as we already checked if they collided. I am not really on the level of proficiency to optimize my code, but when there was an opportunity to do so, I jumped on it. Here's a comparison how the old (left) vs current (right) works:
Easiest way (at least for me) to understand it is to treat every unique number as an unique enemy. Each number holds a table for one enemy. So Bugs holds X,Y and other attributes of the first enemy, Bugs the second and so on. As you can see, the current version does "less work" as shown by the white spaces. Later on I added to the formula, so B starts at A+1 instead just A, so the function won't check collisions against against the same enemy. This saved a little more CPU time and a token, as I didn't have to add A != B (A does not equal to B) to the IF statement. Anyway, let's break down the current code...
function collision_bugbug() initiates the function, so we can call it later in _update(). Next two lines (for x in...) cycle through the enemies' table twice and generate pairs of numbers (A and B) which we can compare.
Next we need to find out the distance between the circles to see if they are overlapping. This is where Pythagorean Theorem comes in handy yet again (honestly I never thought I will get that much millage out of something I have learnt in primary school). We basically find the distance between two points (centers of the two enemies) and put it in a variable ( local distance=sqrt((bugs[a].x-bugs[b].x)^2+(bugs[a].y-bugs[b].y)^2) ) for clarity. Then we check if this distance is equal or smaller then the sum of the sizes (radiuses) of the circles. If it is, it means that the circles are touching / colliding.
THEN we put whatever we need upon collision, in this test I just reverse the directions at which the circles travel (also add one to test variable, just for troubleshooting).
That's it. When it is broken down like that it doesn't seem that difficult, but it took me a long time to get there, and would probably take me much, much longer without the community's help.
If you want to check out the whole code for the spawner, feel free to download the cartridge to the left and mess with it. Right now there are still some bugs (circles can spawn on top of one another or can get stuck if multiple circles collide at the same time) that I will try to fix in the near future (well, basically as soon as I can figure out the syntax for it). My next step is to transplant this into the game code proper and do some tests with squares, sprites and maybe even pixel perfect collision (which maybe way beyond my skill level, but there is a Pixel Perfect Collision Demo cart that I plan on digging in).