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,
}
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.
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
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.
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.
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