local consts = require 'constants'
local tile = require 'tile'
local Entity = {}
Entity.__index = Entity
function Entity:new(state, x, y, name)
local file = io.open('entities/' .. name .. '.lua')
local char_data = load('return' .. file:read('*all'))()
local sprites = {}
for name, sprite in pairs(char_data.sprites) do
sprites[name] = tile.getTile(sprite)
end
local t = {
state = state,
x = x,
y = y,
dx = 0,
dy = 0,
sprites = sprites,
direction = {0, 1},
facing = 'down',
}
return setmetatable(t, Entity)
end
function Entity:checkCollision(dx, dy)
local bx = math.floor((self.x + dx) / consts.tileSize)
local by = math.floor((self.y + dy) / consts.tileSize)
local alignX = ((self.x + dx) % consts.tileSize) == 0
local alignY = ((self.y + dy) % consts.tileSize) == 0
local a = self.state.board:passable(bx, by)
local b = self.state.board:passable(bx + 1, by)
local c = self.state.board:passable(bx, by + 1)
local d = self.state.board:passable(bx + 1, by + 1)
if alignX and alignY then
return a
elseif alignX then
return a and c
elseif alignY then
return a and b
else
return a and b and c and d
end
end
function Entity:goingOffside(dx, dy)
local bx = math.floor((self.x + dx) / consts.tileSize)
local by = math.floor((self.y + dy) / consts.tileSize)
return self.state.board:offside(bx, by) or
self.state.board:offside(bx + 1, by) or
self.state.board:offside(bx, by + 1) or
self.state.board:offside(bx, by + 1)
end
function Entity:getFocus(board)
local gx, gy = self:gameCoords()
local es = board:lookupEntity(gx + self.direction[1],
gy + self.direction[2])
if es then
return es[1]
end
end
function Entity:move(board)
local movement = true
local gX, gY = self:gameCoords()
debug = string.format(' {x=%d, y=%d, gx=%d, gy=%d}\n',
self.x, self.y, gX, gY)
if self.dx == 0 and self.dy == 0 then
return
end
if self.dx > 0 then
self.direction[1] = 1
self.facing = 'right'
elseif self.dx < 0 then
self.direction[1] = -1
self.facing = 'left'
elseif self.dy ~= 0 then
self.direction[1] = 0
end
if self.dy > 0 then
self.direction[2] = 1
self.facing = 'down'
elseif self.dy < 0 then
self.direction[2] = -1
self.facing = 'up'
elseif self.dx ~= 0 then
self.direction[2] = 0
end
local off = self:goingOffside(self.dx, self.dy)
if off and self.state.board[off] then
print('loading areas/' .. self.state.board[off] .. '.lua')
self.state:loadMap(self.state.board[off])
if off == 'south' then
self.y = 0
elseif off == 'north' then
self.y = consts.tileSize * (consts.boardHeight - 1)
elseif off == 'west' then
self.x = consts.tileSize * (consts.boardWidth - 1)
elseif off == 'east' then
self.x = 0
end
end
if self:checkCollision(self.dx, self.dy) then
self.x = self.x + self.dx
self.y = self.y + self.dy
elseif self:checkCollision(self.dx, 0) then
self.x = self.x + self.dx
elseif self:checkCollision(0, self.dy) then
self.y = self.y + self.dy
else
movement = false
end
if movement then
if self.dx ~= 0 and self.dy ~= 0 then
-- nothing
elseif self.dy ~= 0 then
local xm = self.x % consts.halfTile
if 0 < xm and xm < consts.quarterTile and self:checkCollision(-1, 0) then
self.x = self.x - 1
elseif xm >= consts.quarterTile and self:checkCollision(1, 0) then
self.x = self.x + 1
end
elseif self.dx ~= 0 then
local ym = self.y % consts.halfTile
if 0 < ym and ym < consts.quarterTile and self:checkCollision(0, -1) then
self.y = self.y - 1
elseif ym >= consts.quarterTile and self:checkCollision(0, 1) then
self.y = self.y + 1
end
end
end
local nX, nY = self:gameCoords()
if nX ~= gX or nY ~= gY then
self.state.board:enterSquare(nX, nY, self.state)
end
end
function Entity:draw(t)
if self.dx == 0 and self.dy == 0 then
return self.sprites[self.facing]:drawPx(self.x, self.y, t)
else
return self.sprites[self.facing .. 'Moving']:drawPx(self.x, self.y, t)
end
end
function Entity:gameCoords()
return math.floor((self.x + consts.halfTile) / consts.tileSize),
math.floor((self.y + consts.halfTile) / consts.tileSize)
end
function Entity:gameTopCoords()
return math.floor(self.x / consts.tileSize),
math.floor(self.y / consts.tileSize)
end
return {
Entity = Entity
}