Part 10 – Grab the Treasure III

Introduction to Mobile Game Development

Written July, 2015, by Rachel J. Morris

Creative Commons License Introduction to Mobile Game Development by Rachel J. Morris is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License. Based on a work at http://www.moosader.com/learn/ccckc/introduction-to-mobile-game-development/.

Return to the main page


Finally, in Grab the Treasure III, we’re going to add enemies! The programming for the enemies will be similar to what we’ve already covered, except that we are going to introduce arrays and for-loops this time around. Arrays are a good way to store multiples of something, in our case – enemies.

We will need to load Bitmaps for the enemies, we will have the enemy follow the player, much like the player character moves towards its goal coordinates, and we will check on collision between the enemies and the player character, just like we’re already doing for the player and treasure.

Creating Enemy Bitmaps

We are going to use an array to make handling multiple enemies a lot easier. Using a loop, we can execute the same code over and over, for different items. First, let’s load the enemy texture, so we can reuse the same art for different Bitmaps.

enemy_texture = Texture.new( "content/enemy.png" )

To make a variable that will be an array, we use the curly-braces:

enemies = {}

Then, we can use a loop to set up each enemy, setting their initial position (to a random position) and loading the texture into each Bitmap.

for i = 1, 2 do
    enemies[i] = Bitmap.new( enemy_texture )
    local x = math.random( 0, 320 - 64 )
    local y = math.random( 0, 480 - 64 )
    enemies[i]:setPosition( x, y )
end

This for loop will repeat the internal code several times, and it keeps track of counter variable i every time it loops.  So, i starts at 1, and will keep looping until it is equal to 2. We will have two enemies.  The first time through the loop, i will be 1, and then it will be 2.

Note that, with Lua, arrays count up from 1, not 0 like in other programming languages.

Because we have an array of enemies now, we can access the two that we’ve created with enemies[1] and enemies[2], or we can use a variable between the square brackets, like we are doing in the loop.

We will do the same thing when we are wanting to output the enemies to the screen via stage:addChild…:

for i = 1, 2 do
    stage:addChild( enemies[i] )
end

and for any time we update the enemy movement, or check for collision.  But, for the most part, a lot of this code should be familiar.

Chase the Player

Every frame of the game on Update, both enemies will reassess where the player is in relation to them, and chase the player down.  The code we write to handle this will be exactly like how the player follows the mouse click or screen tap.

We have to iterate through all enemies, compare (x, y) coordinates, adjust, and update the sprite’s position on screen.

for i = 1, 2 do
    enemyX, enemyY = enemies[i]:getPosition()
    
    if ( playerX < enemyX ) then        enemyX = enemyX - 1
    elseif ( playerX > enemyX ) then     enemyX = enemyX + 1
    end
    
    if ( playerY < enemyY ) then        enemyY = enemyY - 1
    elseif ( playerY > enemyY ) then     enemyY = enemyY + 1
    end
    
    enemies[i]:setPosition( enemyX, enemyY )
end

Collision Detection between the Player and Enemies

To make sure the player cannot play after being defeated by an enemy, we will add a boolean variable for whether the player is alive.  A boolean variable can store true or false, basically a yes/no question.

playerAlive = true

Then, while we’re updating the game, we will check the collision between the player and the enemies.  If the player is hit, we’re going to change playerAlive to false, and use this as a flag to stop the player from moving anymore.

We can also set the rotation to 90 or -90 so that the player Bitmap looks like it is laying down.

for i = 1, enemyCount do
    -- [Player following code goes here]
    
    -- enemy / Player collision?
    if ( Distance( playerX, playerY, enemyX, enemyY ) < 20 ) then
        playerAlive = false
        player:setRotation( -90 )
    end
end

Adding Game Over text

If playerAlive is false (aka - no, not alive), we want to draw some "Game Over!" text on the screen:

gameoverText = TextField.new( bigFont, "Game Over!" )
gameoverText:setTextColor( 0xFF0000 )
gameoverText:setPosition( 40, 480/2 )

And back where we're checking whether the player and enemy have collided, we want to make sure to draw the Game Over text to the screen with the stage:addChild function.

if ( Distance( playerX, playerY, enemyX, enemyY ) < 20 ) then
    stage:addChild( gameoverText )
    playerAlive = false
    player:setRotation( -90 )
end

Don't let the Player move once they've been defeated

Finally, we are going to update our HandleClick function. We will now check to see whether the player is alive, and only allow the new goalX and goalY coordinates to be set if the player character is alive. Otherwise, it won't be updated, and they cannot move anymore.

function HandleClick( event )
    if ( playerAlive ) then
        goalX = event.x
        goalY = event.y
    end
end

Gold!

Adding enemies for this game was similar to what we've already implemented before. Remember to add a little bit at a time, build, and test. It is much easier to fix something if you're just moving a step at a time, than running a mile and wondering, out of all the code you wrote, where you went wrong.

Make sure to look at the GitHub page to view the complete source, and download the Gideros project files.

Feature Ideas

Here are some things you might try to add, to continue learning from this example:

  • Add a title screen and an instruction screen - can you figure out how to do this with if statements and functions? Remember that you can use stage:removeChild as well as stage:addChild !
  • Add a "Reset" button so that, if the player loses, it resets their score and lets them play again.
  • Add obstacles in the game that have different effects - quick sand slows you down, enemies can't cross traps, whatever you can think of!

Sample code is available on the GitHub page at:

https://github.com/Rachels-Courses/Intro-to-Mobile-Game-Development-with-Gideros

 

Print Friendly