First Monkey-X Game: Player Destruction and Game State for Losing

Our player can fire projectiles and destroy enemies. He can run into enemies and take damage. But right now the player does not get destroyed.

In this part of the tutorial, we will move to a Game Over state whenever the player gets destroyed. This will cover some of the basics of FantomEngine’s layers and scenes.

Game Over State

Right now, we only have the default layer and scene which we are playing our game in.

In order to be able to move to a Game Over state, we need to create a new scene that the game can transition too.

#FantomX_UsePhysics = True
Import fantomX
Import character
Import projectile
Import custom_engine
Class Game Extends App
Field engine:ftEngine
' create a play scene and a game over scene and a game over layer
Field play_layer:ftLayer
Field play_scene:ftScene
Field game_over_scene:ftScene
Field game_over_layer:ftLayer
Field player:Character
Field enemies:List<Character>
Field last_enemy_time:Float
Field next_enemy_interval:Float
Field projectiles:List<Projectile>

Now we have a play scene that we will run the game in, and a game over scene that we will show when the player gets destroyed.

Right now the game over scene doesn’t have anything in it. In the game’s OnCreate method, we will build our game over scene by adding some text that says “GAME OVER”.

' Game Class
Method OnCreate()
Self.engine = New CustomEngine
' rename defaults
play_scene = engine.GetDefaultScene()
play_layer = engine.GetDefaultLayer()
play_scene.AddLayer(play_layer)
Local box:ftObject = Self.engine.CreateBox(120, 20, engine.GetCanvasWidth()/2, engine.GetCanvasHeight()/2)
box.SetColor(0, 70, 70)
box.SetMaxSpeed(20.0)
box.SetMinSpeed(-20.0)
box.SetColGroup(PLAYER_GROUP)
box.SetColType(Self.engine.ctBox)
box.SetText("PLAYER")
Local projectile_type:ProjectileType = New ProjectileType()
Self.player = New Character(box, projectile_type, 0, 3, True)
Self.enemies = New List<Character>()
Self.last_enemy_time = Millisecs()
Self.next_enemy_interval = 3000
Self.projectiles = New List<Projectile>()
' create our game over scene
game_over_scene = engine.CreateScene()
game_over_layer = engine.CreateLayer()
game_over_scene.AddLayer(game_over_layer)
' add some things to the game over scene
engine.SetDefaultLayer(game_over_layer)
' Font created with Hiero (rename .fnt file to .txt)
Local font:ftFont = engine.LoadFont("vt323_sample_2.txt")
Local game_over_text:ftObject = engine.CreateText(font, "GAME OVER",
engine.GetCanvasWidth()/3, engine.GetCanvasHeight()/2, engine.taBottomLeft)
game_over_scene.SetActive(False)
engine.SetDefaultLayer(play_layer)
Seed = Millisecs()
End

It is important to remember with FantomEngine that whatever layer is the current default layer will be the one that things get added to. This is why we need to change the default layer to the game over layer when adding the Text object and switch back when we are done.

NOTE: The font system is not particularly well documented for FantomEngine. It supports FontMachine and EZGui style fonts. You will need a PNG file and a TXT file describing the layout in your project_name.data folder for it to work. I was able to use a tool called Hiero to convert Google font VT323 to this format. There will be an appendix section covering this. There is a sample font in the examples that come with FantomEngine which you can use in the meantime. I will also try to make the converted font I did available.

Switching Scenes

Our final step will be to add a check to the OnUpdate method to switch the scenes if the player is destroyed.

' Game Class
Method OnUpdate()
Local time_delta:Float = Float(engine.CalcDeltaTime())/60.0
' Change scenese when the player is destroyed
If (player.box.GetText() = "DESTROYED" And play_scene.isActive = True)
play_scene.SetActive(False)
game_over_scene.SetActive(True)
game_over_scene.SetAlpha(1.0)
Else
If ((Millisecs() - Self.last_enemy_time) > Self.next_enemy_interval)
CreateEnemy()
Self.last_enemy_time = Millisecs()
End
player.Update(engine.GetCanvasWidth(), engine.GetCanvasHeight())
If (KeyDown(KEY_SPACE) And player.FireProjectile())
CreateProjectile(player)
End
For Local projectile:Projectile = Eachin Self.projectiles
projectile.Update()
If (projectile.box.GetText() = "DESTROYED")
projectile.box.Remove()
Self.projectiles.RemoveFirst(projectile)
End
End
For Local enemy:Character = Eachin Self.enemies
enemy.Update(engine.GetCanvasWidth(), engine.GetCanvasHeight())
If (enemy.box.GetText() = "DESTROYED")
If (enemy.current_health <= 0)
Self.player.IncreaseScore(enemy.point_value)
End
enemy.box.Remove()
Self.enemies.RemoveFirst(enemy)
End
End
End
If engine.GetPaused() = False
engine.Update(time_delta)
engine.CollisionCheck()
End
End

And now we have a playable and basic version of our game where the player can move, shoot enemies, and be destroyed which ends the game.

I Want to Be a Better Developer