Difference between revisions of "Love - Bomberman Concept"
(→Player Class) |
|||
(4 intermediate revisions by the same user not shown) | |||
Line 2: | Line 2: | ||
The image resources for this tutorial are these: | The image resources for this tutorial are these: | ||
− | [[File:Bomb.png] | + | [[File:Bomb.png]] |
− | [[File:Brick.png] | + | [[File:Brick.png]] |
− | [[File:Explosion.png] | + | [[File:Explosion.png]] |
− | [[File:Ground.png] | + | [[File:Ground.png]] |
− | [[File:Wall.png] | + | [[File:Wall.png]] |
− | [[File:Bomber.png] | + | [[File:Bomber.png]] |
=Variables= | =Variables= | ||
Line 45: | Line 45: | ||
local self = {} | local self = {} | ||
− | self.map = {} -- create the | + | self.map = {} -- create the Map |
for i=0,size do | for i=0,size do | ||
self.map[i] = {} -- create a new row | self.map[i] = {} -- create a new row | ||
for j=0,size do | for j=0,size do | ||
− | if i%2==1 and j%2==1 then | + | if i%2==1 and j%2==1 then -- every other tile is a wall |
self.map[i][j] = Tile("wall") | self.map[i][j] = Tile("wall") | ||
else | else | ||
Line 57: | Line 57: | ||
end | end | ||
− | self.map[3][2] = Tile("brick") | + | self.map[3][2] = Tile("brick") -- set the positions of the bricks |
self.map[4][7] = Tile("brick") | self.map[4][7] = Tile("brick") | ||
− | function self.draw() | + | function self.draw() -- draw method cycles through each tile, and draws it to the screen |
for i=0,size do | for i=0,size do | ||
for j=0,size do | for j=0,size do | ||
Line 77: | Line 77: | ||
<syntaxhighlight lang=lua> | <syntaxhighlight lang=lua> | ||
− | function self.update(dt) | + | function self.update(dt) -- this goes inside the Map class above |
− | for i=0,size do | + | for i=0,size do -- cycle through each tile |
for j=0,size do | for j=0,size do | ||
tile = self.map[i][j] | tile = self.map[i][j] | ||
− | if tile.timer > 0 then | + | if tile.timer > 0 then -- if the tile timer is above 0 then reduce the timer |
tile.timer=tile.timer-dt | tile.timer=tile.timer-dt | ||
− | else | + | else -- timer has elapsed |
− | if tile.tiletype=='explosion' then | + | if tile.tiletype=='explosion' then -- explosions change to ground |
tile.tiletype='ground' | tile.tiletype='ground' | ||
tile.setimage() | tile.setimage() | ||
end | end | ||
− | if tile.tiletype=='bomb' then | + | if tile.tiletype=='bomb' then -- bombs change to explosions, timer is seconds |
tile.tiletype='explosion' | tile.tiletype='explosion' | ||
tile.setimage() | tile.setimage() | ||
tile.timer=.5 | tile.timer=.5 | ||
− | for a=0, 3 do | + | for a=0, 3 do -- the explosions spread in four directions |
− | if a == 0 then | + | if a == 0 then -- if statement to set the angle for each direction |
angle=0 | angle=0 | ||
elseif a== 1 then | elseif a== 1 then | ||
Line 106: | Line 106: | ||
cosa = math.floor(math.cos(math.rad(angle))) | cosa = math.floor(math.cos(math.rad(angle))) | ||
sina = math.floor(math.sin(math.rad(angle))) | sina = math.floor(math.sin(math.rad(angle))) | ||
− | for r = 1, range do | + | for r = 1, range do -- the range of the explosion is in the variables |
xoffset = r * cosa | xoffset = r * cosa | ||
yoffset = r * sina | yoffset = r * sina | ||
− | if i+xoffset >=0 and i+xoffset <=size | + | |
+ | 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 | and j+yoffset >=0 and j+yoffset <=size then | ||
− | if self.map[i+xoffset][j+yoffset].tiletype ~= "wall" 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].tiletype='explosion' | ||
self.map[i+xoffset][j+yoffset].setimage() | self.map[i+xoffset][j+yoffset].setimage() | ||
self.map[i+xoffset][j+yoffset].timer=.5 | self.map[i+xoffset][j+yoffset].timer=.5 | ||
else | else | ||
− | break | + | break -- break to stop the explosion in that direction |
end | end | ||
end | end | ||
− | if i-xoffset >=0 and i-xoffset <=size | + | if i-xoffset >=0 and i-xoffset <=size -- as above but minus the offset |
and j-yoffset >=0 and j-yoffset <=size then | and j-yoffset >=0 and j-yoffset <=size then | ||
if self.map[i-xoffset][j-yoffset].tiletype ~= "wall" then | if self.map[i-xoffset][j-yoffset].tiletype ~= "wall" then | ||
Line 146: | Line 147: | ||
function Player(startx, starty) | function Player(startx, starty) | ||
local self = { | local self = { | ||
− | x=startx, | + | x=startx, -- x and y for player position |
y=starty, | y=starty, | ||
− | timer=0, | + | timer=0, -- timer is used for key presses |
− | interval =.3, | + | interval =.3, -- interval for key press timer |
lives = 3, | lives = 3, | ||
− | deadtimer = 0 | + | deadtimer = 0 -- this will be the time from death, a player can be killed again |
} | } | ||
− | self.image = love.graphics.newImage("bomber.png") | + | self.image = love.graphics.newImage("bomber.png") -- image to use for player |
function self.draw() | function self.draw() | ||
− | love.graphics.draw(self.image,self.x*45+space,self.y*45+space) | + | love.graphics.draw(self.image,self.x*45+space,self.y*45+space) -- draw player at current position |
end | end | ||
Line 166: | Line 167: | ||
===Player Update Method=== | ===Player Update Method=== | ||
<syntaxhighlight lang=lua> | <syntaxhighlight lang=lua> | ||
− | function self.update(dt, gamemap) | + | function self.update(dt, gamemap) -- this should be part of the player class above |
− | local x = self.x | + | local x = self.x -- store the current x & y locally |
− | local y = self.y | + | local y = self.y -- these will be used to reset the position if needed |
− | if self.deadtimer > 0 then | + | if self.deadtimer > 0 then -- player has died and cant die again until this runs out |
self.deadtimer = self.deadtimer - dt | self.deadtimer = self.deadtimer - dt | ||
end | end | ||
− | if self.timer<=0 then | + | if self.timer<=0 then -- this timer controls key presses, so that only one press is registered |
if love.keyboard.isDown('a') then | if love.keyboard.isDown('a') then | ||
self.x = self.x - 1 | self.x = self.x - 1 | ||
Line 189: | Line 190: | ||
end | end | ||
else | else | ||
− | self.timer = self.timer - dt | + | self.timer = self.timer - dt -- key press timer still active, so minus delta time |
end | end | ||
if self.x >= 0 and self.x <= size-1 | if self.x >= 0 and self.x <= size-1 | ||
− | and self.y >= 0 and self.y <= size-1 then | + | 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 | + | if gamemap.map[self.x][self.y].tiletype~= "ground" then -- check the new position is a ground tile |
− | self.x=x | + | self.x=x -- if not reset position |
self.y=y | self.y=y | ||
end | end | ||
else | else | ||
− | self.x=x | + | self.x=x -- player move not on map so reset position |
self.y=y | self.y=y | ||
end | end | ||
− | if love.keyboard.isDown('b') and gamemap.map[self.x][self.y].tiletype == "ground" then | + | 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].tiletype= "bomb" | ||
gamemap.map[self.x][self.y].setimage() | gamemap.map[self.x][self.y].setimage() | ||
− | gamemap.map[self.x][self.y].timer=3 | + | gamemap.map[self.x][self.y].timer=3 -- seconds before the bomb explodes |
end | end | ||
− | if gamemap.map[self.x][self.y].tiletype== "explosion" and self.deadtimer <= 0 then | + | if gamemap.map[self.x][self.y].tiletype== "explosion" and self.deadtimer <= 0 then -- player hit by explosion |
− | self.x=0 | + | self.x=0 -- reset back to start |
self.y=0 | self.y=0 | ||
− | self.lives = self.lives-1 | + | self.lives = self.lives-1 -- reduce lives |
− | self.deadtimer=1 | + | self.deadtimer=1 -- 1 second before the player can die again |
print ("lives "..self.lives) | print ("lives "..self.lives) | ||
end | end |
Latest revision as of 10:49, 11 July 2019
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