Make-Games-With-Love

Enemies

Since we want to make a simple SHMUP we need enemies that come from the top. The enemie table looks very similar to our ship:

local enemyShip = {
    name    = "enemy",
    health  = 100,
    x       = 400,
    y       = -100,
    velocity = 200,
}

Generator

One enemy is not enough. We need a function that generates us new enemies!

local newEnemy = function()
    local enemyShip = {
        name    = "enemy",
        health  = 100,
        x       = 400,
        y       = 200,
        velocity = 200,
    }
    return enemyShip
end

Since we use the local keyword, the enemyShip table is only visible inside the function. Therefor everytime we call newEnemy() a new ship table is returned.

We can even customize the parameters of the ship. For example the position:

local newEnemy = function(x, y)
    local enemyShip = {
        name    = "enemy",
        health  = 100,
        x       = x,
        y       = y,
        velocity = 200,
    }
    return enemyShip
end

If we now call newEnemy(200, 300) it will be at 200, 300.

Drawing the enemy

The enemy needs function that we call later that draws the rectangle:

local drawEnemy = function(enemyShip)
    love.graphics.rectangle("fill", enemyShip.x, enemyShip.y, 32, 32)
end
local newEnemy = function(x, y)
    local enemyShip = {
        name    = "enemy",
        health  = 100,
        x       = x,
        y       = y,
        velocity = 200,
        draw = drawEnemy
    }
    return enemyShip
end

We need a way to draw all enemies. We achieve this by inserting all enemyShips into a table. For convienience the inserting should be done inside the newEnemy function. But first we create an empty table enemies.

local drawEnemy = function(enemyShip)
    love.graphics.rectangle("fill", enemyShip.x, enemyShip.y, 32, 32)
end

local enemies = {}

local newEnemy = function(x, y)
    local enemyShip = {
        name    = "enemy",
        health  = 100,
        x       = x,
        y       = y,
        velocity = 200,
        draw = drawEnemy
    }
    table.insert(enemies, enemyShip)
    return enemyShip
end

Looping Through A Table

In love.draw we loop through the table and call the draw function for each ship.

function love.draw()
    love.graphics.rectangle("fill", ship.x, ship.y, 32, 32)

    for _, ship in ipairs(enemies) do
        ship:draw()
    end

end

The for keyword indicates that a loop is about to begin. The _, ship are the key and value pair of every row in the table. The in ipairs(enemies) is called iterator and says that the loop should go through the table in numerical order of the indexes. We call the draw function with a colon ship:draw() because this way we can omit the first argument which would have been the ship any way.

Don't worry about this stuff right now. We will come back to it later.

Create Enemies

We need to call the newEnemy function in order to create some enemies.

We do this in the love.load callback. The one which is executed at the start of the game.

function love.load()
    newEnemy(200,50)
    newEnemy(300,50)
    newEnemy(400,50)
    newEnemy(500,50)
end

You should now see 5 rectangles on the screen.

The whole code

local drawEnemy = function(enemyShip)
    love.graphics.rectangle("fill", enemyShip.x, enemyShip.y, 32, 32)
end

local enemies = {}

local newEnemy = function(x, y)
    local enemyShip = {
        name        = "enemy",
        health      = 100,
        x           = x,
        y           = y,
        velocity     = 200,
        draw         = drawEnemy
    }
    table.insert(enemies, enemyShip)
    return enemyShip
end

local ship = {
        name        = "USS Enterspace",
        health        = 100,
        x           = 100,
        y           = 100,
        velocity    = 100
}

function love.load()
    newEnemy(200,50)
    newEnemy(300,50)
    newEnemy(400,50)
    newEnemy(500,50)
end

function love.draw()
    love.graphics.rectangle("fill", ship.x, ship.y, 32, 32)
    for _,ship in ipairs(enemies) do
        ship:draw()
    end
end

 function love.update(dt)
    if love.keyboard.isDown("left") then
        ship.x = ship.x - dt * ship.velocity
    elseif love.keyboard.isDown("right") then
        ship.x = ship.x + dt * ship.velocity
    end
    if love.keyboard.isDown("up") then
        ship.y = ship.y - dt * ship.velocity
    elseif love.keyboard.isDown("down") then
        ship.y = ship.y + dt * ship.velocity
    end
end