03-26-2025, 08:51 PM
Part 10 - Game Over
Well, all good things must come to an end, and so it is with our game (and this tutorial). All that's left from what we set out to cover is to detect when the game has ended and show a "Game Over" message. This message should be shown if the player falls off the screen or when he successfully makes it to the end of the level.
In order to draw text on the screen we need to implement a new event handler for the "Draw Screen" event. So let's add a new Case statement to our GXOnGameEvent and call a new OnDrawScreen method. For testing purposes let's just have it use the GXDrawText method to display a test message on the screen:
If we run the program now, we'll see "TEST" displayed in the upper left corner of the screen. Let's adjust this to show instead the current x coordinate of our player. We'll switch to use the default black font as it should show up better against the light sky:
Let's add a new variable to track our game over state:
Now, let's add the logic to our OnUpdate method to detect the end of game
Finally, let's update our OnDrawScreen method to remove our test message and show a "Game Over" message when our gameOver variable has been set to true:
Bitmap Fonts
However, it might be nice to make the message stand out a bit more. Let's load a custom bitmap font from the following image:
We can create our font with the GXFontCreate method:
With the font loaded we can now use it instead of the default font in our OnDrawScreen method:
And with that we've come to the end of our platformer tutorial. We've even made a few enhancements along the way to our original target program:
Miscellaneous
I thought I'd mention a couple of additional items that didn't make it into this tutorial but might be useful to you:
Final Thoughts
Just to reiterate what I said at the outset, I'd be very curious to hear of any feedback on the tutorial or game engine, positive or negative. Would there be other topics of interest to see (e.g. sound, device input, enemies, projectiles)? Did anyone even make it this far? Or was it more of a case of TL;DR and I should have just made a YouTube video?
Well, all good things must come to an end, and so it is with our game (and this tutorial). All that's left from what we set out to cover is to detect when the game has ended and show a "Game Over" message. This message should be shown if the player falls off the screen or when he successfully makes it to the end of the level.
In order to draw text on the screen we need to implement a new event handler for the "Draw Screen" event. So let's add a new Case statement to our GXOnGameEvent and call a new OnDrawScreen method. For testing purposes let's just have it use the GXDrawText method to display a test message on the screen:
Code: (Select All)
...
Sub GXOnGameEvent (e As GXEvent)
Select Case e.event
Case GXEVENT_UPDATE: OnUpdate e
Case GXEVENT_COLLISION_TILE: OnTileCollision e
Case GXEVENT_DRAWSCREEN: OnDrawScreen e
End Select
End Sub
...
Sub OnDrawScreen (e As GXEvent)
GXDrawText GXFONT_DEFAULT, 1, 1, "TEST"
End Sub
...
The first parameter to the GXDrawText method indicates the bitmap font to use. There are two default fonts included with the engine GXFONT_DEFAULT and GXFONT_DEFAULT_BLACK. The next two parameters indicate the screen coordinates of where to place the text and the final parameter is the text to display.If we run the program now, we'll see "TEST" displayed in the upper left corner of the screen. Let's adjust this to show instead the current x coordinate of our player. We'll switch to use the default black font as it should show up better against the light sky:
Code: (Select All)
...
Sub OnDrawScreen (e As GXEvent)
GXDrawText GXFONT_DEFAULT_BLACK, 1, 1, Str$(Fix(GXEntityX(player)))
End Sub
...
Now we can just run to the end of the board and find the x coordinate which should trigger that the player has made it to the end of the level.Let's add a new variable to track our game over state:
Code: (Select All)
...
Const COLLISION_TILE2 = 71
Dim Shared gameOver As Integer
Dim Shared direction As Integer
...
Now, let's add the logic to our OnUpdate method to detect the end of game
Code: (Select All)
...
Sub OnUpdate (e As GXEvent)
HandlePlayerMovement e
If gameOver Then GXSceneStop
If GXEntityY(player) > GXSceneHeight Or GXEntityX(player) > 1462 Then
gameOver = GX_TRUE
End If
End Sub
...
Finally, let's update our OnDrawScreen method to remove our test message and show a "Game Over" message when our gameOver variable has been set to true:
Code: (Select All)
...
Sub OnDrawScreen (e As GXEvent)
'GXDrawText GXFONT_DEFAULT_BLACK, 1, 1, Str$(Fix(GXEntityX(player)))
If gameOver Then
Dim As Integer x, y
x = GXSceneWidth / 2 - 32
y = GXSceneHeight / 2 - 8
GXDrawText GXFONT_DEFAULT, x, y, "GAME OVER"
End If
End Sub
...
If we run the game now, we'll see our "Game Over" message anytime we fall off the screen or reach the end. Bitmap Fonts
However, it might be nice to make the message stand out a bit more. Let's load a custom bitmap font from the following image:
We can create our font with the GXFontCreate method:
Code: (Select All)
...
GXSceneConstrain GXSCENE_CONSTRAIN_TO_MAP
Dim Shared gfont As Long
gfont = GXFontCreate("img/font.png", 8, 9, _
"0123456789ABCDEF" + GX_CRLF + _
"GHIJKLMNOPQRSTUV" + GX_CRLF + _
"WXYZc>-x'!/")
GXSceneStart
...
The first parameter specifies the path to the file containing the font image. The next two parameters are the character width and height in pixels. The last parameter is a string which defines the character map.With the font loaded we can now use it instead of the default font in our OnDrawScreen method:
Code: (Select All)
...
If gameOver Then
Dim As Integer x, y
x = GXSceneWidth / 2 - 32
y = GXSceneHeight / 2 - 8
'GXDrawText GXFONT_DEFAULT, x, y, "GAME OVER"
GXDrawText gfont, x, y, "GAME OVER"
End If
...
If we run our program again, we'll now see the new font in action:And with that we've come to the end of our platformer tutorial. We've even made a few enhancements along the way to our original target program:
Miscellaneous
I thought I'd mention a couple of additional items that didn't make it into this tutorial but might be useful to you:
- Fullscreen Mode
If you'd like to run your game in full screen mode, simply call the following method after creating your scene:
Code: (Select All)GXFullscreen GX_TRUE
- Hardware Images
While it might not make a huge difference for a game as simple as this one you can enable hardware image support in QB64 by calling:
Code: (Select All)
If used, his needs to be the first GX method called in your application.GXHardwareAcceleration GX_TRUE
Final Thoughts
Just to reiterate what I said at the outset, I'd be very curious to hear of any feedback on the tutorial or game engine, positive or negative. Would there be other topics of interest to see (e.g. sound, device input, enemies, projectiles)? Did anyone even make it this far? Or was it more of a case of TL;DR and I should have just made a YouTube video?