Created
May 28, 2014 11:17
-
-
Save mgussekloo/309c3463986443048c3d to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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