Skip to content

Instantly share code, notes, and snippets.

@mgussekloo
Created May 28, 2014 11:17
Show Gist options
  • Save mgussekloo/309c3463986443048c3d to your computer and use it in GitHub Desktop.
Save mgussekloo/309c3463986443048c3d to your computer and use it in GitHub Desktop.
local Class = require "hump.class"
local AStar = require "Marsgus.astar"
local Marsgus = {}
Marsgus.Tilemap = Class {
init = function(self, image)
self.tilesetBatch = love.graphics.newSpriteBatch(image, gameSettings.resolution.width / (gameSettings.tileWidth * gameSettings.zoom) * gameSettings.resolution.height / (gameSettings.tileHeight * gameSettings.zoom))
self.quads = {}
self.quads[0] = love.graphics.newQuad(0, 0, 16, 16, image:getWidth(), image:getHeight()) -- empty
self.quads[1] = love.graphics.newQuad(16, 0, 16, 16, image:getWidth(), image:getHeight()) -- wood
self.quads[2] = love.graphics.newQuad(32, 0, 16, 16, image:getWidth(), image:getHeight()) -- rope
self.quads[3] = love.graphics.newQuad(48, 0, 16, 16, image:getWidth(), image:getHeight()) -- water
self.quads[4] = love.graphics.newQuad(64, 0, 16, 16, image:getWidth(), image:getHeight()) -- rock
self.quads[5] = love.graphics.newQuad(80, 0, 16, 16, image:getWidth(), image:getHeight()) -- boot1
self.quads[6] = love.graphics.newQuad(96, 0, 16, 16, image:getWidth(), image:getHeight()) -- boot2
self.quads[7] = love.graphics.newQuad(112, 0, 16, 16, image:getWidth(), image:getHeight()) -- boot3
self.quads[8] = love.graphics.newQuad(128, 0, 16, 16, image:getWidth(), image:getHeight()) -- boot4
self.quads[9] = love.graphics.newQuad(144, 0, 16, 16, image:getWidth(), image:getHeight()) -- dode survivor
self.quads[10] = love.graphics.newQuad(176, 0, 16, 16, image:getWidth(), image:getHeight()) -- tree
self.quads[11] = love.graphics.newQuad(192, 0, 16, 16, image:getWidth(), image:getHeight()) -- vis
self.quads[12] = love.graphics.newQuad(0, 16, 16, 16, image:getWidth(), image:getHeight()) -- multiple vis
self.quads[13] = love.graphics.newQuad(16, 16, 16, 16, image:getWidth(), image:getHeight()) -- palm tree
self.quads[14] = love.graphics.newQuad(80, 16, 16, 16, image:getWidth(), image:getHeight()) -- man op schip
self.quads[99] = love.graphics.newQuad(160, 0, 16, 16, image:getWidth(), image:getHeight()) -- homepos
end,
updateTilesetBatch = function(self)
self.tilesetBatch:clear()
for x=1, gameSettings.resolution.width / (gameSettings.tileWidth * gameSettings.zoom) do
for y=1, gameSettings.resolution.height / (gameSettings.tileHeight * gameSettings.zoom) do
self.tilesetBatch:add(
self.quads[self.map[y][x]],
(x - 1) * (gameSettings.tileWidth * gameSettings.zoom),
(y - 1) * (gameSettings.tileHeight * gameSettings.zoom),
0, gameSettings.zoom
)
end
end
end,
loadMap = function(self, map)
self.map = map
self:updateTilesetBatch()
end,
updateMap = function(self, pos, value)
self.map[pos.y][pos.x] = value
self:updateTilesetBatch()
end,
draw = function(self)
love.graphics.draw(self.tilesetBatch)
end,
tile = function(self, x, y)
return self.map[y][x]
end,
blocked = function(self, pos)
if (self:valid(pos)) then
if (self.map[pos.y][pos.x] == 3) then return true end
if (self.map[pos.y][pos.x] == 4) then return true end
if (self.map[pos.y][pos.x] == 5) then return true end
if (self.map[pos.y][pos.x] == 6) then return true end
if (self.map[pos.y][pos.x] == 7) then return true end
if (self.map[pos.y][pos.x] == 10) then return true end
if (self.map[pos.y][pos.x] == 11) then return true end
if (self.map[pos.y][pos.x] == 12) then return true end
if (self.map[pos.y][pos.x] == 13) then return true end
do return false end
end
return true
end,
water = function(self, pos)
if (self:valid(pos)) then
if (self.map[pos.y][pos.x] == 3) then return true end
do return false end
end
return false
end,
valid = function(self, pos)
if (pos.y > 0 and pos.y <= #self.map) then
if (pos.x > 0 and pos.x <= #self.map[1]) then
return true
end
end
do return false end
end,
placeRandom = function(self, value)
local x=love.math.random(1, gameSettings.resolution.width / (gameSettings.tileWidth * gameSettings.zoom))
local y=love.math.random(1, gameSettings.resolution.height / (gameSettings.tileHeight * gameSettings.zoom))
-- local safety = 1
while (tilemap:tile(x,y) > 0) do
x=love.math.random(1, gameSettings.resolution.width / (gameSettings.tileWidth * gameSettings.zoom))
y=love.math.random(1, gameSettings.resolution.height / (gameSettings.tileHeight * gameSettings.zoom))
-- safety = safety + 1
-- if (safety > 9) then
-- return
-- end
end
tilemap:updateMap({x=x, y=y}, value)
end
}
-- ----------------------------------------------------------------------------------------------------------------------------
Marsgus.Animation = Class {
init = function(self, image, pos, steps, updateDelay)
if (steps == nil) then steps = 1 end
if (updateDelay == nil) then updateDelay = 0.1 end
self.animationRunning = false
self.pos = pos
self.width = image:getWidth()
self.height = image:getHeight()
self.frames = {}
self.currentFrameNumber = 1
self.cyclesSinceLastUpdate = 0
self.updateDelay = updateDelay
self.frameWidth = self.width / steps
self.frameHeight = self.height
self:setFrames(image, steps)
end,
setFrames = function(self, image, steps)
self.image = image
for x=0, steps do
self.frames[x+1] = love.graphics.newQuad((x*self.frameWidth), 0, self.frameWidth, self.frameHeight, self.width, self.height)
end
end,
update = function(self, dt)
if (not self.animationRunning) then return true end
if (#self.frames == 1) then return true end
self.cyclesSinceLastUpdate = self.cyclesSinceLastUpdate + dt
if (self.cyclesSinceLastUpdate > self.updateDelay) then
self.currentFrameNumber = self.currentFrameNumber + 1
if (self.currentFrameNumber == #self.frames) then self.currentFrameNumber = 1 end
self.cyclesSinceLastUpdate = 0
end
end,
draw = function(self)
love.graphics.draw(self.image, self.frames[self.currentFrameNumber], self.pos.x, self.pos.y, 0, gameSettings.zoom, gameSettings.zoom)
end,
start = function(self)
self.animationRunning = true
end,
stop = function(self)
self.currentFrameNumber = 1
self.cyclesSinceLastUpdate = 0
self.animationRunning = false
end,
intersect = function(self, x, y)
if (
x>=self.pos.x and x<=self.pos.x+(self.frameWidth * gameSettings.zoom) and
y>=self.pos.y and y<=self.pos.y+(self.frameHeight * gameSettings.zoom)
) then
return true
end
end,
center = function(self)
return {x=self.pos.x+((self.frameWidth * gameSettings.zoom) / 2), y=self.pos.y+((self.frameHeight * gameSettings.zoom) / 2)}
end
}
-- ----------------------------------------------------------------------------------------------------------------------------
Marsgus.Entity = Class {
init = function(self, image, pos, steps)
self.sprite = Marsgus.Animation(
image,
{x=(pos.x-1)*gameSettings.tileWidth*gameSettings.zoom, y=(pos.y-1)*gameSettings.tileHeight*gameSettings.zoom},
steps
)
self.job = nil
self.dead = false
end,
tilePos = function(self)
if (self.dead) then return {x=0,y=0} end
tile_x = math.floor(self.sprite.pos.x / (gameSettings.tileWidth * gameSettings.zoom)) + 1
tile_y = math.floor(self.sprite.pos.y / (gameSettings.tileHeight * gameSettings.zoom)) + 1
return {x = tile_x, y=tile_y}
end,
draw = function(self)
if (self.dead) then return false end
self.sprite:draw()
end,
update = function(self, dt)
if (self.dead) then return false end
self.sprite:update(dt)
if (self.job) then
local jobResult = self.job:update(dt)
if (not jobResult) then self.job=nil end
end
end,
die = function(self)
self.dead = true
end,
giveJob = function(self, name, options)
-- load a dynamic class based on "name" variable
self.job = Marsgus[name](self, options)
end
}
Marsgus.Survivor = Class {
__includes = Marsgus.Entity,
init = function(self, pos)
self.normalImage = love.graphics.newImage("tileset/spaceman.png")
self.hiliteImage = love.graphics.newImage("tileset/spaceman-hilite.png")
Marsgus.Entity.init(self, self.normalImage, pos, 4)
self.selected = false
self.wood = 0
self.rope = 0
end,
setUnselect = function(self)
self.selected = false
self.sprite:setFrames(self.normalImage, 4)
end,
setSelect = function(self)
self.selected = true
self.sprite:setFrames(self.hiliteImage, 4)
end,
arrive = function(self, x, y)
--aankomen op de basis (bezorgen)
if (x == levelManager.homePos.x and y == levelManager.homePos.y) then
if (self.wood > 0) then
self.wood = 0
player.wood = player.wood + 1
player.score = player.score + math.max(50, math.ceil(((player.wood + player.rope + player.gold) / math.max(1, player.time)) * 1000))
if (levelManager.winning.wood > player.wood or levelManager.winning.rope > player.rope) then
tilemap:placeRandom(1) -- plaats hout
end
end
if (self.rope > 0) then
self.rope = 0
player.rope = player.rope + 1
player.score = player.score + math.max(50, math.ceil(((player.wood + player.rope + player.gold) / math.max(1, player.time)) * 1000))
if (levelManager.winning.rope > player.rope or levelManager.winning.wood > player.wood) then
tilemap:placeRandom(2) -- plaats hout
end
end
if (player.wood > 0 or player.rope > 0) then
local woodPercentage = math.min(100,player.wood/levelManager.winning.wood*100)
local ropePercentage = math.min(100,player.rope/levelManager.winning.rope*100)
local percentage = (woodPercentage+ropePercentage)/2
if (percentage <=25)then
tilemap:updateMap(levelManager.exitPos,5)
elseif (percentage>25 and percentage<=50) then
tilemap:updateMap(levelManager.exitPos,6)
elseif (percentage>50 and percentage<=75) then
tilemap:updateMap(levelManager.exitPos,7)
elseif (percentage>75) then
tilemap:updateMap(levelManager.exitPos,8)
end
end
end
local tile = tilemap:tile(x,y)
-- aankomen onderweg (oppikken)
if (tile == 1) then
if (self.wood < 1) then
self.wood = self.wood + 1
tilemap:updateMap({x=x, y=y}, 0)
--local path = AStar:find({x=x, y=y}, {x=levelManager.homePos.x, y=levelManager.homePos.y})
--self:giveJob("WalkPath", {path=path})
return false
end
elseif (tile == 2) then
if (self.rope < 1) then
self.rope = self.rope + 1
tilemap:updateMap({x=x, y=y}, 0)
--local path = AStar:find({x=x, y=y}, {x=levelManager.homePos.x, y=levelManager.homePos.y})
--self:giveJob("WalkPath", {path=path})
return false
end
end
-- aankomen op vlot
if (tile == 8) then
for n=1, #survivors do
local pos = survivors[n]:tilePos()
if (pos.x~=x or pos.y~=y) then
path = AStar:find(pos, {x=x, y=y})
survivors[n]:giveJob("WalkPath", {path=path})
end
end
end
if (player.wood >= levelManager.winning.wood and player.rope >= levelManager.winning.rope) then
local allOnBoard = true
for x=1, #survivors do
local pos = survivors[x]:tilePos()
if (pos.x ~= levelManager.exitPos.x or pos.y ~= levelManager.exitPos.y) then
allOnBoard = false
end
end
if (allOnBoard) then
player.ignoreClick = true
local pos ={x=x,y=y}
local xMax= gameSettings.resolution.width / (gameSettings.tileWidth * gameSettings.zoom)
local yMax= gameSettings.resolution.height / (gameSettings.tileHeight * gameSettings.zoom)
local xVaarCoord = 20
local yVaarCoord = 12
if ((pos.x > (xMax/2) and pos.y >= (yMax/2)) and pos.x <= pos.y) then
xVaarCoord = pos.x
yVaarCoord = gameSettings.resolution.height / (gameSettings.tileHeight * gameSettings.zoom)
elseif ((pos.x > (xMax/2) and pos.y >= (yMax/2)) and pos.x > pos.y) then
xVaarCoord = gameSettings.resolution.width / (gameSettings.tileWidth * gameSettings.zoom)
yVaarCoord = pos.y
elseif ((pos.x > (xMax/2) and pos.y < (yMax/2)) and ((xMax-pos.x) >= ((yMax/2) -pos.y))) then
xVaarCoord = gameSettings.resolution.width / (gameSettings.tileWidth * gameSettings.zoom)
yVaarCoord = pos.y
elseif ((pos.x > (xMax/2) and pos.y < (yMax/2)) and ((xMax-pos.x) < ((yMax/2) -pos.y))) then
xVaarCoord = pos.x
yVaarCoord = 1
elseif ((pos.x < (xMax/2) and pos.y < (yMax/2)) and pos.x <= pos.y ) then
xVaarCoord = 1
yVaarCoord = pos.y
elseif ((pos.x < (xMax/2) and pos.y < (yMax/2)) and pos.x > pos.y) then
xVaarCoord = pos.x
yVaarCoord = 1
elseif ((pos.x < (xMax/2) and pos.y >= (yMax/2)) and (pos.x <= (yMax -pos.y))) then
xVaarCoord = 1
yVaarCoord = pos.y
elseif ((pos.x < (xMax/2) and pos.y >= (yMax/2)) and (pos.x > (yMax -pos.y))) then
xVaarCoord = pos.x
yVaarCoord = gameSettings.resolution.height / (gameSettings.tileHeight * gameSettings.zoom)
end
path = AStar:find({x=x,y=y}, {x=xVaarCoord, y=yVaarCoord}, {onlyWater=true})
tilemap:updateMap({x=x, y=y}, 3)
survivors = {}
decal = Marsgus.Decal({x=x,y=y})
decals = {decal}
decal:giveJob("WalkPath", {path=path})
return false
end
end
return false
end
}
-- ----------------------------------------------------------------------------------------------------------------------------
Marsgus.Enemy = Class {
__includes = Marsgus.Entity,
init = function(self, pos)
self.normalImage = love.graphics.newImage("tileset/enemy.png")
Marsgus.Entity.init(self, self.normalImage, pos, 4)
end,
update = function(self, dt)
Marsgus.Entity.update(self, dt)
-- collision
local enemyCenter = self.sprite:center()
for x=1, #survivors do
if (survivors[x].sprite:intersect(enemyCenter.x,enemyCenter.y)) then
tilemap:updateMap(survivors[x]:tilePos(), 9)
table.remove(survivors,x)
self:giveJob("Hunt")
break
end
end
-- local randomGetal = love.math.random(1, 100)
-- if (randomGetal < 5) then
-- self:giveJob("Wander")
-- end
if (self.job == nil) then
self:giveJob("Hunt")
end
end,
arrive = function(self, x, y)
end
}
-- ----------------------------------------------------------------------------------------------------------------------------
Marsgus.Decal = Class {
__includes = Marsgus.Entity,
init = function(self, pos)
self.normalImage = love.graphics.newImage("tileset/manopboot.png")
Marsgus.Entity.init(self, self.normalImage, pos, 1)
end,
update = function(self, dt)
Marsgus.Entity.update(self, dt)
if (self.job == nil) then
--self:giveJob("Hunt")
end
end,
arrive = function(self, x, y)
-- aankomen bij einde
if (x == 20 and y == 12) then
levelManager:levelFinished()
end
end
}
-- ----------------------------------------------------------------------------------------------------------------------------
Marsgus.Job = Class {
init = function(self, actor, options)
self.actor = actor
self.cyclesSinceLastUpdate = 0
self.updateDelay = 0.1
self.options = options
end,
update = function(self, dt)
local jobResult = self:process(dt)
if (not jobResult) then return false end
return true
end,
process = function(self, dt)
return false
end
}
Marsgus.WalkPath = Class {
__includes = Marsgus.Job,
init = function(self, actor, options)
Marsgus.Job.init(self, actor, options)
local currentPos = self.actor.sprite.pos
--if (#self.options.path > 1) then table.remove(self.options.path, 1) end
local goalTile = self.options.path[1]
if (currentPos.x == goalTile.pos.x and currentPos.y == goalTile.pos.y) then table.remove(self.options.path, 1) end
self.speed = 150
if (self.options.speed) then self.speed = self.options.speed end
self.actor.sprite:start()
end,
process = function(self, dt)
local currentPos = self.actor.sprite.pos
local goalTile = self.options.path[1]
local goalPos = {
x=(goalTile.pos.x-1)*gameSettings.tileWidth*gameSettings.zoom,
y=(goalTile.pos.y-1)*gameSettings.tileHeight*gameSettings.zoom
}
if currentPos.x==goalPos.x and currentPos.y==goalPos.y then
table.remove(self.options.path,1)
if (#self.options.path == 0) then
self.actor.sprite:stop()
return self.actor:arrive(goalTile.pos.x,goalTile.pos.y)
end
return true
end
local movement = self.speed * dt
if currentPos.x > goalPos.x then
currentPos.x = math.max(currentPos.x-movement, goalPos.x)
end
if currentPos.x < goalPos.x then
currentPos.x = math.min(currentPos.x+movement, goalPos.x)
end
if currentPos.y > goalPos.y then
currentPos.y = math.max(currentPos.y-movement, goalPos.y)
end
if currentPos.y < goalPos.y then
currentPos.y = math.min(currentPos.y+movement, goalPos.y)
end
self.actor.sprite.pos = currentPos
return true
end
}
Marsgus.Hunt = Class {
__includes = Marsgus.Job,
init = function(self, actor, options)
Marsgus.Job.init(self, actor, options)
end,
process = function(self, dt)
if (#survivors>0) then
local survivor = survivors[love.math.random(1, #survivors)]
local survivorPos = survivor:tilePos()
local actorPos = self.actor:tilePos()
possibleMoves = {}
for x=-2,2 do
for y=-2,2 do
local checkPos = {x=actorPos.x+x,y=actorPos.y+y}
local value = math.abs(checkPos.x-survivorPos.x) + math.abs(checkPos.y - survivorPos.y)
table.insert(possibleMoves, {pos=checkPos, value=value})
end
end
table.sort(possibleMoves, function(a,b) return a.value<b.value end)
local top = math.min(5, #possibleMoves)
local randomTop = love.math.random(1,top)
local goalPos = possibleMoves[randomTop].pos
path = AStar:find({x=actorPos.x,y=actorPos.y}, goalPos)
self.actor:giveJob("WalkPath", {path=path,speed=75})
return true
else
levelManager:gameOver()
end
end
}
Marsgus.Wander = Class {
__includes = Marsgus.Job,
init = function(self, actor, options)
Marsgus.Job.init(self, actor, options)
end,
process = function(self, dt)
local actorPos = self.actor:tilePos()
local possiblePos = {
{x=actorPos.x+1,y=actorPos.y},
{x=actorPos.x-1,y=actorPos.y},
{x=actorPos.x,y=actorPos.y+1},
{x=actorPos.x,y=actorPos.y-1}
}
local newPos = possiblePos[love.math.random(1, #possiblePos)]
path = AStar:find({x=actorPos.x,y=actorPos.y}, newPos)
self.actor:giveJob("WalkPath", {path=path,speed=75})
return true
end
}
return Marsgus
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment