Difference between revisions of "Love - Bomberman Concept"

From TRCCompSci - AQA Computer Science
Jump to: navigation, search
(Player Class)
 
(6 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|thumb]]
+
[[File:Bomb.png]]
[[File:Brick.png|thumb]]
+
[[File:Brick.png]]
[[File:Explosion.png|thumb]]
+
[[File:Explosion.png]]
[[File:Ground.png|thumb]]
+
[[File:Ground.png]]
[[File:Wall.png|thumb]]
+
[[File:Wall.png]]
[[File:Bomber.png|thumb]]
+
[[File:Bomber.png]]
  
 
=Variables=
 
=Variables=
Line 45: Line 45:
 
local self = {}
 
local self = {}
 
 
self.map = {}  -- create the matrix
+
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: Bomb.png Brick.png Explosion.png Ground.png Wall.png Bomber.png

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