Clean Up and Collisions
03/10/21 07:52 Filed in: PICO-8
Last time I gave Ferb a background in which to run through. However, he runs through the rocks we placed and can't jump high enough. What I've created feels like the start of a game, so I think I'll take a break and fix the two issues. After that, I'll add a few things to make what I have feel more like a game and less like an experiment.
The Story So Far
I've:
- created a sprite and animated it to run across the screen.
- added sound effects for running and jumping.
- created obstacles and a background.
As a reminder here is what I have.

Fixing the Hop
The first thing I want to do is fix the height of the hop. Here is the function:

This should be an easy fix. I use the variable hopDirection as a flag to indicate whether Ferb is going up or down. I'm also using it as the offset to y, that is how high to jump. That's not good. I need to split that functionality. I'll create a variable hopHeight and multiply it by hopDirection. That should fix the poor design as well as the hop problem.
When I do this, and with playing around with the value of hopHeight, I settle on a value of 5 which gives Ferb enough altitude. But now, it's obvious he's not traveling forward far enough to clear the rock.

Here's where Ferb moves forward.

Changing this to get Ferb to move differently when hopping would be bad design. That is, I'd have to check to see if Ferb is in the middle of a hop and do something. The function hop already handles hopping. I'll rework the hop function above, and leave moveLeftToRight alone.
Here's my new code.

I've refactored the vertical code into its own function and added a new function handleHorizontalHop which uses a new variable hopAhead. This does the same thing that hopHeight does, but in a horizontal direction. Testing different values for hopAhead, I settle on 5.
This is the result.

That fixes the first problem. The hopping isn't physics-accurate, but it's good enough for this simple game.
Ferb, however, still runs through rocks. It's time for a diversion.
Collision Detection
What I need is a way to detect when Ferb collides with something. I need a collision detection function. I'm going to leave Ferb for a while and create a test program.

My function collision sees if two objects on the screen have collided. I'm using a very simple technique known as hitbox testing. Each object is represented as a rectangle at a given position. The collision function sees if the two rectangles overlap. If they do, it returns true meaning there has been a collision.
In the _init function I create a flag that indicates the two objects have collided (and destroyed). I then create two Lua tables (more info here) Each table represents an object on the screen and has a position and a hitbox. The first object will be a circle, the second a square. Each object has a rectangular hit box with a position and a width and height.
One thing to remember is hit box testing tests rectangles, not the actual shape of the object.
In the _update function I see if the objects are destroyed, if not, I move the circle closer to the square.
In the _draw function I draw both objects then test for a collision. If the objects have collided, I set my flag and print a message on the screen.
This is just a test program to see if my collision function does what I think it does. Here is the result.

It works!
Now I can rework the Ferb code to use hit boxes. I'll leave that for next time. Instead, I want to make Ferb more of a game. I want to give him more things to avoid.
The Sky Is Falling
I think I want to rain meteors down on Ferb as he runs. In the sprite editor, I've created a new sprite that represents a meteor.

Now I just need the code to drop meteors. I'll start simply by only dropping one. I need to initialize some new variables in _init.

I'm calling two new functions: initGeneral will be used to initialize miscellaneous variables, initMeteors will handle the falling rocks. Here they are.

I'm using a table to store a single Meteor. In line 16 I set the meteor's x coordinate to a random number up to the maximum x coordinate. On line 18 I get a random speed for the meteor. NOTE TO SELF: I need to rework Ferb so he uses a table as well.
I need to move the meteor in _update.

That's easy. Now I just need to write updateMeteors.

Again, I'm starting simply. All this does is move the meteor down based on its speed. If it hits the ground (I don't need to use my collision function here) I just reset the meteor back to the top of the screen. I'll probably do something different later.
Finally, I need to draw the meteor.


In drawMeteors I'm just drawing my one meteor. I'll change this once I know it works the way I want.
That's all we need. Let's run it.

That's what I want.
Next time, I'll handle collisions between Ferb and the rocks, Ferb and the meteor(s), and the meteor(s) and the ground.
Here is the cart so far:
