Fly Catch
We have been progressing nicely with the fly catch program. One of the main remaining challenges has been our inability to break up main
and move the handle input and update game logic. We also have some inefficiencies in passing copies of struct parameters that we could now re-code as constant references to enhance performance.
These changes are relatively small, but will greatly help us grow the logic of any program we create.
Handle Input
Within main
we have a bunch of code that is associated with the handle input actions, as shown in the following pseudocode from the control flow chapter.
For this game, input will always impact the spider. This is what the player can control. Now that we have references, we can move this logic into its own procedure and pass a reference to the spider to update.
When you code this, you can now call handle input and pass in the game’s spider. The compiler will get the address of the spider, and pass that to the reference. So updates to this in the handle input code will affect the game’s spider - thereby changing what is drawn to the screen.
When you code this, you can mostly just copy and paste the code from main
into a new handle_input
procedure you create. You will need to change the game.spider
to just be spider
, which you should see as a sign that this is looking better now. We have reduced the scope so that we only see the things we need to deal with, and there is no longer the need to go through the game to get to the spider.
Update Game
We can apply the same idea to the update game logic. The following code snippet shows the logic we set up for this part of main in the control flow chapter.
Notice that this needs all the game data. We need to know about the fly and the spider. So here we can pass the game_data
by reference to the update_game
procedure.
Update game can also be passed the current time, so that the update game code does not need to know about the game timer. This will match what we did with the time_to_appear
and time_to_escape
functions.
You can implement this by copying and pasting the code from main into the new update_game
procedure. In this case the code will only need minor changes to remove the need to access the time (replacing timer_ticks(GAME_TIMER)
with current_time
). The fly and spider details will still come from the game
parameter which has the same name as the variable in main.
This doesn’t get to as nice a place as we were with handle_input
where we had reduced the scope to only have the details we need. So we can berak this down further.
Update Fly
To improve this further, we can implement an update_fly
procedure. This could take the logic from the first part of update game, and apply that to a passed in fly parameter.
We could potentially also pass in the spider, and include the logic for the caught test - but I think that may be better left outside the fly update logic. It is conceptually different, as it is no longer just about the fly.
Then update_game
can just involve calling update_fly
and then checking if the fly was caught.
The event loop in main should look really nice now. Each of the steps is clear, with just a simple procedure call being made for each of the actions - handle input, update game, and draw game. The code for this section is shown below.
This is making each of these procedures nice and small, dealing with a single task that takes in only the data that we need to make this work.
This is something we can build upon in the next chapter.
Draw game and other struct parameters
In our draw game code, we can make a tiny change to the parameter declarations to make these constant references. The calls don’t change, so little else is needed, but this will save some time and space as the program runs.
For examples:
Becomes:
Remember to change this for the draw_fly
, draw_spider
, and draw_game
procedures and the spider_caught_fly
, time_to_escape
, and time_to_appear
functions.