Love - Bomberman Concept
This will create a Bomberman esque game, in which the player is blocked by bricks and places bombs to remove them. I have tried to make this example very object oriented with classes for Player, Map, and Tile. I have also tried to make most of the code within these classes.
The image resources for this tutorial are these:
Contents
Variables
local size = 9
local space = 5
local width = size * 45 + space
local height = size * 45 + space
local range = 2
Tile Class
function Tile(tiletype)
local self = {
tiletype=tiletype,
timer=0
}
function self.getimage(tiletype)
return love.graphics.newImage(tiletype..".png")
end
function self.setimage()
self.image=self.getimage(self.tiletype)
end
self.image=self.getimage(tiletype)
return self
end
Map Class
function Map()
local self = {}
self.map = {} -- create the Map
for i=0,size do
self.map[i] = {} -- create a new row
for j=0,size do
if i%2==1 and j%2==1 then -- every other tile is a wall
self.map[i][j] = Tile("wall")
else
self.map[i][j] = Tile("ground")
end
end
end
self.map[3][2] = Tile("brick") -- set the positions of the bricks
self.map[4][7] = Tile("brick")
function self.draw() -- draw method cycles through each tile, and draws it to the screen
for i=0,size do
for j=0,size do
love.graphics.draw(self.map[i][j].image,i*45+space,j*45+space)
end
end
end
end
return self
end
Map Update Method
function self.update(dt) -- this goes inside the Map class above
for i=0,size do -- cycle through each tile
for j=0,size do
tile = self.map[i][j]
if tile.timer > 0 then -- if the tile timer is above 0 then reduce the timer
tile.timer=tile.timer-dt
else -- timer has elapsed
if tile.tiletype=='explosion' then -- explosions change to ground
tile.tiletype='ground'
tile.setimage()
end
if tile.tiletype=='bomb' then -- bombs change to explosions, timer is seconds
tile.tiletype='explosion'
tile.setimage()
tile.timer=.5
for a=0, 3 do -- the explosions spread in four directions
if a == 0 then -- if statement to set the angle for each direction
angle=0
elseif a== 1 then
angle = 360
elseif a== 2 then
angle=90
elseif a== 2 then
angle=180
end
cosa = math.floor(math.cos(math.rad(angle)))
sina = math.floor(math.sin(math.rad(angle)))
for r = 1, range do -- the range of the explosion is in the variables
xoffset = r * cosa
yoffset = r * sina
if i+xoffset >=0 and i+xoffset <=size -- this checks if this explosion is on the screen
and j+yoffset >=0 and j+yoffset <=size then
if self.map[i+xoffset][j+yoffset].tiletype ~= "wall" then -- a wall will stop the explosion
self.map[i+xoffset][j+yoffset].tiletype='explosion'
self.map[i+xoffset][j+yoffset].setimage()
self.map[i+xoffset][j+yoffset].timer=.5
else
break -- break to stop the explosion in that direction
end
end
if i-xoffset >=0 and i-xoffset <=size -- as above but minus the offset
and j-yoffset >=0 and j-yoffset <=size then
if self.map[i-xoffset][j-yoffset].tiletype ~= "wall" then
self.map[i-xoffset][j-yoffset].tiletype='explosion'
self.map[i-xoffset][j-yoffset].setimage()
self.map[i-xoffset][j-yoffset].timer=.5
else
break
end
end
end
end
end
end
end
end
Player Class
function Player(startx, starty)
local self = {
x=startx, -- x and y for player position
y=starty,
timer=0, -- timer is used for key presses
interval =.3, -- interval for key press timer
lives = 3,
deadtimer = 0 -- this will be the time from death, a player can be killed again
}
self.image = love.graphics.newImage("bomber.png") -- image to use for player
function self.draw()
love.graphics.draw(self.image,self.x*45+space,self.y*45+space) -- draw player at current position
end
return self
end
Player Update Method
function self.update(dt, gamemap) -- this should be part of the player class above
local x = self.x -- store the current x & y locally
local y = self.y -- these will be used to reset the position if needed
if self.deadtimer > 0 then -- player has died and cant die again until this runs out
self.deadtimer = self.deadtimer - dt
end
if self.timer<=0 then -- this timer controls key presses, so that only one press is registered
if love.keyboard.isDown('a') then
self.x = self.x - 1
self.timer=self.interval
elseif love.keyboard.isDown('d') then
self.x = self.x + 1
self.timer=self.interval
elseif love.keyboard.isDown('w') then
self.y = self.y - 1
self.timer=self.interval
elseif love.keyboard.isDown('s') then
self.y = self.y + 1
self.timer=self.interval
end
else
self.timer = self.timer - dt -- key press timer still active, so minus delta time
end
if self.x >= 0 and self.x <= size-1
and self.y >= 0 and self.y <= size-1 then -- check the movement is within the map
if gamemap.map[self.x][self.y].tiletype~= "ground" then -- check the new position is a ground tile
self.x=x -- if not reset position
self.y=y
end
else
self.x=x -- player move not on map so reset position
self.y=y
end
if love.keyboard.isDown('b') and gamemap.map[self.x][self.y].tiletype == "ground" then -- drop bomb
gamemap.map[self.x][self.y].tiletype= "bomb"
gamemap.map[self.x][self.y].setimage()
gamemap.map[self.x][self.y].timer=3 -- seconds before the bomb explodes
end
if gamemap.map[self.x][self.y].tiletype== "explosion" and self.deadtimer <= 0 then -- player hit by explosion
self.x=0 -- reset back to start
self.y=0
self.lives = self.lives-1 -- reduce lives
self.deadtimer=1 -- 1 second before the player can die again
print ("lives "..self.lives)
end
end
LOVE Load, Update, Draw
function love.load()
love.window.setMode(width, height)
gamemap = Map()
player = Player(0,0)
end
function love.update(dt)
player.update(dt, gamemap)
gamemap.update(dt)
end
function love.draw()
gamemap.draw()
player.draw()
end