Polishing
Before going further, you may have noticed a couple of issues :
- cakes disappear if you don't catch them
- some cakes don't reappear when you catch them
- and your player can leave the screen ! This is because we didn't check sufficient scenarios. We call them "out of bounds".
Out of bounds positions
Character
What we want to do is restrict the movement so that the player stays in screen. We already know the height and width of the screen, so we just have to be careful to only move when it's not over those borders. In the "update" callback, modify the movement of the player to the right like:
if love.keyboard.isDown("right") and player.x < window.width - player.width then
Do the same for the left action
if love.keyboard.isDown("left") and player.x > 0 then
Adapt those 2 snippets of code to use for the vertical axis, for the "up" and "down" actions !
In the end, you should have the following code
Cakes
As you may have seen, some cakes disappear and when they leave (you miss them and go to the left) they don't reappear.
Fixing the height respawn issue
The issue is caused by our random position when we create cakes. Because a cake has a height, it may appear at a lower position than the max height. Hence, replace in the "update" callback the height generation of the cakes to remove the cake own height.
cakes.instances[i].y = math.random(0, window.height - cakes.dimensions[cakes.instances[i].type].height)
You'll have to reorganize the code to get the type assigned before assigning the height, as we need to get the height of this image before calculating where it can appear. You should end up with this
Removing the cake once it goes out of bounds
When the cake goes too far on the left, we want it to reappear. To do so, we need to add a check that it's horizontal position is not less than 0 in our "update" callback.
if lecake.x <= 0 then
What this block should contain has been seen when the player is eating a cake, reuse this function ! You should end up with this
Randomness
If you play long enough, you'll see that cakes tend to spawn alltogether. This is due to the random call being called many times in a very small time lapse. To fix this, we need to "seed" our randomness. Generally, time is used, but even is this scenario, a loop isn't taking long enough to get a different time. But "i" varies, so me just need to add "i" to our time-based seed :) Add the following to the first line of the loop of creation of cakes.
math.randomseed( os.time() + i )
Animations
Animations are there to give a feedback to actions of the player. When you throw a snowball, you expect a mouvement from the one throwing, and a reaction from the one receiving. That's a part of what makes a game immersive. Our animation will be Marie-antoinette opening her mouth to eat the cake. We're going to change from the image "player" to "player-animated". Once again, you can open it in piskel to modify it freely. Then, add to our "init" step the following :
player.img = {}
player.img.standby = love.graphics.newQuad(0, 0, 96, 96, player.image:getDimensions())
player.img.eating = love.graphics.newQuad(96, 0, 96, 96, player.image:getDimensions())
player.eating = 0
As well, change the player.x and player.y values t ofixed values. The reason for this is that the size of the image is no more the size of our sprite. Our sprite is now a Quad containing 2 sprites. You should get the following code instead
player.width, player.height = 96, 96
Then, we want to set when we eat. We have a variable for that, called "player.eating". Let's set it to 1 (true) when we are in collision with any cake. Also, set the value to 0 (false) at the beginning of every "update" step. Finally, on the draw step, do the selection of the sprite
local sprite = player.img.standby
if player.eating == 1 then
sprite = player.img.eating
end
and update your draw function of your player
love.graphics.draw(player.image, sprite, player.x, player.y)