2015-03-11 20:11:29 -04:00
|
|
|
Room = class("Room")
|
2015-03-11 21:41:02 -04:00
|
|
|
|
2015-03-16 09:06:51 -04:00
|
|
|
require "libs/TSerial"
|
2015-03-11 21:08:15 -04:00
|
|
|
require "player"
|
2015-03-12 03:04:09 -04:00
|
|
|
require "box"
|
|
|
|
|
require "wall"
|
2015-03-12 05:13:04 -04:00
|
|
|
require "artifact"
|
2015-03-14 05:36:02 -04:00
|
|
|
require "npc"
|
|
|
|
|
require "art"
|
|
|
|
|
require "assorted"
|
2015-03-15 05:26:47 -04:00
|
|
|
require "switch"
|
2015-03-15 07:08:35 -04:00
|
|
|
require "door"
|
2015-03-17 02:15:28 -04:00
|
|
|
require "dialogue_manager"
|
2015-03-25 01:38:53 -04:00
|
|
|
require "generic_moveable"
|
|
|
|
|
require "generic_unmoveable"
|
2015-03-11 20:11:29 -04:00
|
|
|
|
2015-03-11 21:08:15 -04:00
|
|
|
function Room:initialize(t)
|
2015-03-15 15:34:17 -04:00
|
|
|
self.player = {}
|
2015-03-15 05:26:47 -04:00
|
|
|
self.switches = { red = {}, green = {}, blue = {} }
|
2015-03-16 10:17:06 -04:00
|
|
|
self.doors = {}
|
2015-03-15 05:26:47 -04:00
|
|
|
self.collideables = { red = {}, green = {}, blue = {} }
|
2015-03-17 01:59:14 -04:00
|
|
|
self.activeColors = {red = false, green = false, blue = false}
|
|
|
|
|
self.colorsPlayerHas = {}
|
|
|
|
|
|
|
|
|
|
if t.name then
|
|
|
|
|
print("loaded!!")
|
|
|
|
|
self:load(t.name)
|
2015-03-25 01:38:53 -04:00
|
|
|
print(t.name)
|
|
|
|
|
if t.player then
|
|
|
|
|
for _, color in ipairs(t.player.activeColors) do
|
|
|
|
|
self:registerPlayer(Player:new(t.player.x, t.player.y, color), color)
|
|
|
|
|
self:setActiveColor(color, true)
|
|
|
|
|
end
|
|
|
|
|
else
|
|
|
|
|
for color, active in pairs(self.activeColors) do
|
|
|
|
|
self:registerPlayer(Player:new(1, 1, color), color)
|
|
|
|
|
self:setActiveColor(color, true)
|
|
|
|
|
end
|
2015-03-17 01:59:14 -04:00
|
|
|
end
|
|
|
|
|
self.exits = t.exits
|
|
|
|
|
self.name = t.name
|
|
|
|
|
else
|
|
|
|
|
self.colorsPlayerHas = {"red", "green", "blue"}
|
|
|
|
|
|
2015-03-12 03:04:09 -04:00
|
|
|
|
2015-03-17 01:59:14 -04:00
|
|
|
for _, color in ipairs(t.player.activeColors) do
|
|
|
|
|
self.player[color] = Player:new(t.player.x, t.player.y, color)
|
|
|
|
|
end
|
2015-03-15 15:34:17 -04:00
|
|
|
|
2015-03-17 01:59:14 -04:00
|
|
|
self.activeColors = {}
|
|
|
|
|
for _, color in ipairs(t.player.activeColors) do self.activeColors[color] = true end
|
2015-03-11 21:08:15 -04:00
|
|
|
|
2015-03-17 01:59:14 -04:00
|
|
|
-- for color, coords in pairs(t.player) do
|
|
|
|
|
-- self.player[color] = Player:new(coords.x, coords.y, color)
|
|
|
|
|
-- self.activeColors[color] = true
|
|
|
|
|
-- end
|
2015-03-15 04:52:18 -04:00
|
|
|
|
2015-03-25 01:38:53 -04:00
|
|
|
-- for i=1, 1 do
|
|
|
|
|
-- local x, y = randomPosition()
|
|
|
|
|
-- -- local door = Door:new(x, y, self.colorsPlayerHas)
|
|
|
|
|
-- -- table.insert(self.doors, door)
|
2015-03-11 20:11:29 -04:00
|
|
|
|
2015-03-25 01:38:53 -04:00
|
|
|
-- for color, active in pairs(self.activeColors) do
|
|
|
|
|
-- table.insert(self.collideables[color], Wall:new(x, y, color))
|
|
|
|
|
-- end
|
|
|
|
|
-- end
|
2015-03-12 05:13:04 -04:00
|
|
|
|
2015-03-25 01:38:53 -04:00
|
|
|
-- for i=0, 5 do
|
2015-03-17 01:59:14 -04:00
|
|
|
-- local x, y = randomPosition()
|
2015-03-25 01:38:53 -04:00
|
|
|
-- for color, active in pairs(self.activeColors) do
|
|
|
|
|
-- table.insert(self.collideables[color], Box:new(x, y, color))
|
|
|
|
|
-- end
|
2015-03-17 01:59:14 -04:00
|
|
|
-- end
|
2015-03-15 05:26:47 -04:00
|
|
|
|
2015-03-25 01:38:53 -04:00
|
|
|
for i = 0, 5 do
|
|
|
|
|
local x, y = randomPosition()
|
|
|
|
|
print(x, y)
|
|
|
|
|
local c = randomColor()
|
|
|
|
|
table.insert(self.switches[c], Switch:new(x, y, c))
|
|
|
|
|
end
|
|
|
|
|
|
2015-03-17 01:59:14 -04:00
|
|
|
for color, active in pairs(self.activeColors) do
|
|
|
|
|
local x, y = 6, 3
|
|
|
|
|
-- if active then self.collideables[color]["n: " .. x .. ", " .. y] = Ass:new(x, y, color, "animals/processed/", "me_rach") end
|
2015-03-14 05:36:02 -04:00
|
|
|
|
2015-03-17 01:59:14 -04:00
|
|
|
local x, y = 1, 1
|
2015-03-25 01:38:53 -04:00
|
|
|
-- if active then table.insert(self.collideables[color], Ass:new(x, y, color, "nature/", "palm_scaled_reduced")) end
|
2015-03-14 05:36:02 -04:00
|
|
|
|
2015-03-17 01:59:14 -04:00
|
|
|
-- local x, y = 7, 7
|
|
|
|
|
-- if active then self.collideables[color]["n: " .. x .. ", " .. y] = Ass:new(x, y, color, "food/processed/", "beer_mug") end
|
2015-03-14 05:36:02 -04:00
|
|
|
|
2015-03-17 01:59:14 -04:00
|
|
|
-- self.collideables[color]["fpp"] = Artifact:new(6, 6, color)
|
|
|
|
|
end
|
2015-03-15 04:52:18 -04:00
|
|
|
end
|
2015-03-14 05:36:02 -04:00
|
|
|
|
2015-03-17 01:59:14 -04:00
|
|
|
self.switchMatrices = {}
|
|
|
|
|
self.collidableMatrices = {} --{red = {{...}{...}{...}}, ...
|
|
|
|
|
self:createSwitchMatrix()
|
|
|
|
|
self:createCollideablesMatrix()
|
2015-03-11 20:11:29 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
2015-03-11 21:41:02 -04:00
|
|
|
function Room:update(dt)
|
2015-03-15 15:34:17 -04:00
|
|
|
for color, player in pairs(self.player) do
|
|
|
|
|
player:update(dt)
|
|
|
|
|
end
|
2015-03-11 20:11:29 -04:00
|
|
|
end
|
|
|
|
|
|
2015-03-11 21:41:02 -04:00
|
|
|
function Room:draw()
|
2015-03-15 04:52:18 -04:00
|
|
|
|
2015-03-15 15:34:17 -04:00
|
|
|
for color, player in pairs(self.player) do
|
|
|
|
|
player:draw()
|
|
|
|
|
end
|
2015-03-12 03:04:09 -04:00
|
|
|
for color, entityArray in pairs(self.collideables) do
|
|
|
|
|
for _, entity in pairs(entityArray) do
|
|
|
|
|
entity:draw()
|
|
|
|
|
end
|
|
|
|
|
end
|
2015-03-15 05:26:47 -04:00
|
|
|
for color, switchArray in pairs(self.switches) do
|
|
|
|
|
for _, switch in pairs(switchArray) do
|
|
|
|
|
switch:draw()
|
|
|
|
|
end
|
|
|
|
|
end
|
2015-03-12 03:04:09 -04:00
|
|
|
end
|
|
|
|
|
|
2015-03-15 05:44:30 -04:00
|
|
|
function Room:createCollideablesMatrix()
|
2015-03-15 04:52:18 -04:00
|
|
|
for color, entities in pairs(self.collideables) do
|
|
|
|
|
self.collidableMatrices[color] = self:createEntityMatrix(entities)
|
|
|
|
|
end
|
2015-03-12 03:04:09 -04:00
|
|
|
end
|
2015-03-15 05:44:30 -04:00
|
|
|
|
|
|
|
|
function Room:createSwitchMatrix()
|
|
|
|
|
for color, switches in pairs(self.switches) do
|
|
|
|
|
self.switchMatrices[color] = self:createEntityMatrix(switches)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2015-03-15 04:52:18 -04:00
|
|
|
function Room:createEntityMatrix(entities)
|
|
|
|
|
local matrix = {}
|
2015-03-12 03:04:09 -04:00
|
|
|
|
2015-03-15 04:52:18 -04:00
|
|
|
--lets populate it w/ empty stuff first
|
|
|
|
|
for i = 1, gridWidth do
|
|
|
|
|
local row = {}
|
|
|
|
|
for i = 1, gridHeight do
|
|
|
|
|
table.insert(row, false)
|
2015-03-12 03:04:09 -04:00
|
|
|
end
|
2015-03-15 04:52:18 -04:00
|
|
|
table.insert(matrix, row)
|
2015-03-12 03:04:09 -04:00
|
|
|
end
|
2015-03-15 04:52:18 -04:00
|
|
|
|
2015-03-17 01:59:14 -04:00
|
|
|
|
2015-03-15 04:52:18 -04:00
|
|
|
--assumes that entities table is set up li_e {index = ent1, anotherIndex = ent2, ...}
|
|
|
|
|
for _, entity in pairs(entities) do
|
|
|
|
|
for _, occupiedCells in pairs(entity:getOccupiedCells()) do
|
|
|
|
|
--we store a table reference so we can call a method on it during a chec_
|
|
|
|
|
matrix[occupiedCells.y][occupiedCells.x] = entity
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
-- printMatrix(matrix)
|
2015-03-17 01:59:14 -04:00
|
|
|
|
2015-03-15 04:52:18 -04:00
|
|
|
return matrix
|
2015-03-12 03:04:09 -04:00
|
|
|
end
|
|
|
|
|
|
2015-03-15 04:52:18 -04:00
|
|
|
function Room:getCellInMatrix(matrix, cell)
|
|
|
|
|
return matrix[cell.y][cell.x]
|
2015-03-12 03:04:09 -04:00
|
|
|
end
|
|
|
|
|
|
2015-03-15 04:52:18 -04:00
|
|
|
function Room:movePlayer(key)
|
|
|
|
|
|
2015-03-15 15:34:17 -04:00
|
|
|
local moved = false
|
2015-03-16 08:47:08 -04:00
|
|
|
local previousPositions = {} --these are so we can perform the overlap chec_
|
|
|
|
|
local newPositions = {}
|
2015-03-15 15:34:17 -04:00
|
|
|
|
|
|
|
|
for _, color in pairs(self:getActiveColors()) do
|
|
|
|
|
local entitiesToPush, entitiesToPull = {}, {}
|
|
|
|
|
local pos = self.player[color]:getGridPos()
|
2015-03-16 08:47:08 -04:00
|
|
|
previousPositions[color] = pos
|
2015-03-15 15:34:17 -04:00
|
|
|
local x, y = pos.x, pos.y
|
|
|
|
|
local dir = {x = 0, y = 0}
|
|
|
|
|
local axis
|
|
|
|
|
|
|
|
|
|
if key == "up" then
|
|
|
|
|
dir.y, axis = -1, "y"
|
|
|
|
|
elseif key == "down" then
|
|
|
|
|
dir.y, axis = 1, "y"
|
|
|
|
|
elseif key == "left" then
|
|
|
|
|
dir.x, axis = -1, "x"
|
|
|
|
|
elseif key == "right" then
|
|
|
|
|
dir.x, axis = 1, "x"
|
|
|
|
|
end
|
2015-03-15 04:52:18 -04:00
|
|
|
|
2015-03-15 15:34:17 -04:00
|
|
|
local move = true
|
|
|
|
|
-- PUSHHHHHHHHHHHHHHHHHHHHHH---------------------
|
2015-03-12 03:04:09 -04:00
|
|
|
|
2015-03-15 15:34:17 -04:00
|
|
|
local initialTargetCell = {
|
|
|
|
|
x = pos.x + dir.x, y = pos.y + dir.y
|
|
|
|
|
} -- this is for reference for each color as we change the targetCells table
|
2015-03-12 03:04:09 -04:00
|
|
|
|
2015-03-16 07:43:02 -04:00
|
|
|
local initialTargetEntity
|
2015-03-17 01:59:14 -04:00
|
|
|
|
2015-03-16 09:06:51 -04:00
|
|
|
if self:isInBounds(initialTargetCell) then
|
|
|
|
|
initialTargetEntity = self:getCellInMatrix(self.collidableMatrices[color], initialTargetCell)
|
|
|
|
|
end
|
|
|
|
|
|
2015-03-16 07:43:02 -04:00
|
|
|
if initialTargetEntity then initialTargetEntity:bump() end
|
2015-03-16 07:39:54 -04:00
|
|
|
|
2015-03-15 15:34:17 -04:00
|
|
|
if not self:isInBounds(initialTargetCell) then
|
2015-03-16 07:39:54 -04:00
|
|
|
-- let's us move out of bounds to Change Rooms without pulling a bloc_
|
2015-03-15 15:34:17 -04:00
|
|
|
move = true
|
2015-03-16 07:43:02 -04:00
|
|
|
elseif initialTargetEntity and initialTargetEntity:canPassOver() then
|
2015-03-16 07:39:54 -04:00
|
|
|
--we should put this in the else statement actually
|
2015-03-15 15:34:17 -04:00
|
|
|
move = true
|
|
|
|
|
else
|
|
|
|
|
local targetCells
|
2015-03-15 05:26:47 -04:00
|
|
|
|
|
|
|
|
targetCells = {initialTargetCell} -- ...we start with our attempted movement...
|
|
|
|
|
local doneSearching
|
|
|
|
|
while not doneSearching do
|
|
|
|
|
nextTargetCells = {} -- ...then we create this array to save our next group of cells
|
|
|
|
|
local emptyCells = {}
|
|
|
|
|
for _, cell in pairs(targetCells) do
|
|
|
|
|
if self:isInBounds(cell) then
|
|
|
|
|
local entity = self:getCellInMatrix(self.collidableMatrices[color], cell)
|
|
|
|
|
if entity then
|
|
|
|
|
--something is here!!
|
2015-03-15 15:34:17 -04:00
|
|
|
if not entitiesToPush[entity] then --if the entity hasnt been found already
|
2015-03-15 05:26:47 -04:00
|
|
|
if entity:canMove() then
|
|
|
|
|
local projectedCells = entity:getOccupiedCells(dir) -- we project the movement here
|
2015-03-15 15:34:17 -04:00
|
|
|
entitiesToPush[entity] = entity
|
2015-03-15 05:26:47 -04:00
|
|
|
for _, projectedCell in ipairs(projectedCells) do
|
|
|
|
|
table.insert(nextTargetCells, projectedCell)
|
|
|
|
|
end
|
|
|
|
|
else
|
|
|
|
|
move = false
|
|
|
|
|
doneSearching = true
|
2015-03-15 04:52:18 -04:00
|
|
|
end
|
|
|
|
|
end
|
2015-03-15 05:26:47 -04:00
|
|
|
else
|
|
|
|
|
--there's nothin there!!
|
|
|
|
|
table.insert(emptyCells, cell)
|
2015-03-15 04:52:18 -04:00
|
|
|
end
|
2015-03-15 05:26:47 -04:00
|
|
|
else
|
|
|
|
|
--we are out of bounds now
|
|
|
|
|
move = false
|
|
|
|
|
doneSearching = true
|
2015-03-15 04:52:18 -04:00
|
|
|
end
|
2015-03-15 05:26:47 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
|
|
--if every projected cell is empty then we can do the move
|
|
|
|
|
if #emptyCells == #targetCells then
|
|
|
|
|
move = true
|
2015-03-15 04:52:18 -04:00
|
|
|
doneSearching = true
|
|
|
|
|
end
|
|
|
|
|
|
2015-03-15 05:26:47 -04:00
|
|
|
targetCells = nextTargetCells
|
2015-03-15 04:52:18 -04:00
|
|
|
end
|
2015-03-15 05:26:47 -04:00
|
|
|
--let's get out of this loop b/c if we can't move one color we can't move at all
|
2015-03-15 04:52:18 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
2015-03-15 15:34:17 -04:00
|
|
|
---PULL CHEC
|
2015-03-15 04:52:18 -04:00
|
|
|
|
2015-03-15 15:34:17 -04:00
|
|
|
local initialTargetCell = {x = pos.x - dir.x, y = pos.y - dir.y}
|
2015-03-15 04:52:18 -04:00
|
|
|
|
2015-03-15 15:34:17 -04:00
|
|
|
local targetCells
|
2015-03-15 04:52:18 -04:00
|
|
|
|
2015-03-15 18:45:24 -04:00
|
|
|
local pull
|
2015-03-15 04:52:18 -04:00
|
|
|
--for each color...
|
|
|
|
|
targetCells = {initialTargetCell} -- ...we start with our attempted movement...
|
|
|
|
|
local doneSearching
|
|
|
|
|
while not doneSearching do
|
|
|
|
|
nextTargetCells = {} -- ...then we create this array to save our next group of cells
|
|
|
|
|
local emptyCells = {}
|
|
|
|
|
for _, cell in pairs(targetCells) do
|
|
|
|
|
if self:isInBounds(cell) then
|
|
|
|
|
local entity = self:getCellInMatrix(self.collidableMatrices[color], cell)
|
|
|
|
|
if entity then
|
|
|
|
|
--something is here!!
|
2015-03-15 15:34:17 -04:00
|
|
|
if not entitiesToPull[entity] then --if the entity hasnt been found already
|
2015-03-15 04:52:18 -04:00
|
|
|
if entity:canMove() then
|
|
|
|
|
local projectedCells = entity:getOccupiedCells(dir) -- we project the movement here
|
2015-03-15 15:34:17 -04:00
|
|
|
entitiesToPull[entity] = entity
|
2015-03-15 04:52:18 -04:00
|
|
|
for _, projectedCell in ipairs(projectedCells) do
|
|
|
|
|
table.insert(nextTargetCells, projectedCell)
|
|
|
|
|
end
|
|
|
|
|
else
|
2015-03-15 18:45:24 -04:00
|
|
|
pull = false
|
2015-03-15 04:52:18 -04:00
|
|
|
doneSearching = true
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
else
|
|
|
|
|
--there's nothin there!!
|
|
|
|
|
table.insert(emptyCells, cell)
|
|
|
|
|
end
|
|
|
|
|
else
|
|
|
|
|
--we are out of bounds now
|
|
|
|
|
doneSearching = true
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
--if every projected cell is empty then we can do the move
|
|
|
|
|
if #emptyCells == #targetCells then
|
2015-03-15 18:45:24 -04:00
|
|
|
pull = true
|
2015-03-15 04:52:18 -04:00
|
|
|
doneSearching = true
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
targetCells = nextTargetCells
|
|
|
|
|
end
|
|
|
|
|
|
2015-03-15 15:34:17 -04:00
|
|
|
if move then
|
|
|
|
|
for _, entity in pairs(entitiesToPush) do
|
2015-03-15 04:52:18 -04:00
|
|
|
entity:move(axis, dir[axis])
|
|
|
|
|
end
|
2015-03-15 18:45:24 -04:00
|
|
|
if pull == true then
|
|
|
|
|
for _, entity in pairs(entitiesToPull) do
|
|
|
|
|
entity:move(axis, dir[axis])
|
|
|
|
|
end
|
2015-03-15 04:52:18 -04:00
|
|
|
end
|
2015-03-15 15:34:17 -04:00
|
|
|
self.player[color]:move(axis, dir[axis])
|
|
|
|
|
moved = true
|
2015-03-15 04:52:18 -04:00
|
|
|
end
|
2015-03-16 08:47:08 -04:00
|
|
|
newPositions[color] = self.player[color]:getGridPos()
|
2015-03-15 15:34:17 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
|
|
if moved then
|
2015-03-16 08:47:08 -04:00
|
|
|
self:playerJoinCheck(previousPositions, newPositions)
|
2015-03-15 04:52:18 -04:00
|
|
|
self:tick()
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2015-03-15 08:00:59 -04:00
|
|
|
function Room:switchPlayerColor(color)
|
2015-03-15 15:34:17 -04:00
|
|
|
local canSwitch
|
2015-03-12 03:04:09 -04:00
|
|
|
|
2015-03-15 15:34:17 -04:00
|
|
|
if self:onlyColorIsActive(color) then
|
|
|
|
|
canSwitch = false
|
|
|
|
|
else
|
|
|
|
|
for _, c in pairs(self:getPossibleColors()) do
|
|
|
|
|
if c == color then
|
|
|
|
|
self:setActiveColor(c, true)
|
|
|
|
|
else
|
|
|
|
|
self:setActiveColor(c, false)
|
|
|
|
|
end
|
2015-03-15 08:00:59 -04:00
|
|
|
end
|
|
|
|
|
end
|
2015-03-15 15:34:17 -04:00
|
|
|
|
|
|
|
|
self.player[color]:playSwitchSound(canSwitch)
|
2015-03-15 04:52:18 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function Room:setActiveColor(color, bool)
|
|
|
|
|
self.activeColors[color] = bool
|
2015-03-11 21:08:15 -04:00
|
|
|
end
|
|
|
|
|
|
2015-03-15 15:34:17 -04:00
|
|
|
function Room:getActiveColors()
|
|
|
|
|
local colors = {}
|
|
|
|
|
|
|
|
|
|
for color, active in pairs(self.activeColors) do
|
|
|
|
|
if active then
|
|
|
|
|
table.insert(colors, color)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
return colors
|
|
|
|
|
end
|
|
|
|
|
|
2015-03-16 08:47:08 -04:00
|
|
|
function Room:colorIsActive(color)
|
|
|
|
|
if self.activeColors[color] then
|
|
|
|
|
return true
|
|
|
|
|
end
|
|
|
|
|
return false
|
|
|
|
|
end
|
|
|
|
|
|
2015-03-15 15:34:17 -04:00
|
|
|
function Room:getInactiveColors()
|
|
|
|
|
local colors = {}
|
|
|
|
|
|
|
|
|
|
for color, active in pairs(self.activeColors) do
|
|
|
|
|
if not active then
|
|
|
|
|
table.insert(colors, color)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
return colors
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function Room:getPossibleColors()
|
|
|
|
|
local colors = {}
|
|
|
|
|
|
|
|
|
|
for _, color in ipairs(self.colorsPlayerHas) do
|
|
|
|
|
table.insert(colors, color)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
return colors
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function Room:onlyColorIsActive(color)
|
|
|
|
|
local activeColors = self:getActiveColors()
|
|
|
|
|
if #activeColors == 1 and activeColors[1] == color then
|
|
|
|
|
return true
|
|
|
|
|
else
|
|
|
|
|
return false
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2015-03-11 21:08:15 -04:00
|
|
|
function Room:tick()
|
2015-03-12 03:04:09 -04:00
|
|
|
for color, entityArray in pairs(self.collideables) do
|
|
|
|
|
for _, entity in pairs(entityArray) do
|
|
|
|
|
entity:tick()
|
|
|
|
|
end
|
|
|
|
|
end
|
2015-03-15 04:52:18 -04:00
|
|
|
self:createCollideablesMatrix()
|
2015-03-15 05:44:30 -04:00
|
|
|
self:createSwitchMatrix()
|
2015-03-15 07:08:35 -04:00
|
|
|
local setDoorColors = self:switchCheck()
|
|
|
|
|
for _, door in pairs(self.doors) do
|
|
|
|
|
door:setColors(setDoorColors)
|
2015-03-15 05:44:30 -04:00
|
|
|
end
|
2015-03-11 21:08:15 -04:00
|
|
|
self:nextRoomCheck()
|
|
|
|
|
end
|
|
|
|
|
|
2015-03-16 08:47:08 -04:00
|
|
|
function Room:playerJoinCheck(previousPositions, newPositions)
|
|
|
|
|
local activate = {}
|
|
|
|
|
local deactivate = {}
|
|
|
|
|
local activeColors = self:getActiveColors()
|
|
|
|
|
|
|
|
|
|
for _, color in ipairs(activeColors) do
|
|
|
|
|
if #activeColors > 1 then
|
|
|
|
|
if Entity.positionsAreEqual(previousPositions[color], newPositions[color]) then
|
|
|
|
|
table.insert(deactivate, color)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
2015-03-15 15:34:17 -04:00
|
|
|
|
|
|
|
|
for _, inactiveColor in ipairs(self:getInactiveColors()) do
|
|
|
|
|
local overlapping = 0
|
|
|
|
|
local activeColors = self:getActiveColors()
|
|
|
|
|
local inactivePos = self:getPlayerPos(inactiveColor)
|
|
|
|
|
for _, activeColor in ipairs(activeColors) do
|
|
|
|
|
local activePos = self:getPlayerPos(activeColor)
|
|
|
|
|
if activePos.x == inactivePos.x and activePos.y == inactivePos.y then
|
|
|
|
|
overlapping = overlapping + 1
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
if overlapping == #activeColors then
|
2015-03-16 08:47:08 -04:00
|
|
|
table.insert(activate, inactiveColor)
|
2015-03-15 15:34:17 -04:00
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2015-03-16 08:47:08 -04:00
|
|
|
for _, color in ipairs(activate) do
|
2015-03-15 15:34:17 -04:00
|
|
|
self:setActiveColor(color, true)
|
|
|
|
|
end
|
2015-03-16 08:47:08 -04:00
|
|
|
|
|
|
|
|
for _, color in ipairs(deactivate) do
|
|
|
|
|
self:setActiveColor(color, false)
|
|
|
|
|
end
|
2015-03-15 15:34:17 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function Room:getPlayerPos(color)
|
|
|
|
|
return self.player[color]:getGridPos()
|
|
|
|
|
end
|
|
|
|
|
|
2015-03-16 10:17:06 -04:00
|
|
|
function Room:getPlayerObject(color)
|
|
|
|
|
return self.player[color]
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function Room:getDoors()
|
|
|
|
|
return self.doors
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function Room:getCollideables()
|
|
|
|
|
return self.collideables
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function Room:getSwitches()
|
|
|
|
|
return self.switches
|
|
|
|
|
end
|
|
|
|
|
|
2015-03-15 07:08:35 -04:00
|
|
|
function Room:switchCheck()
|
|
|
|
|
local doorsToUnlock = {}
|
2015-03-15 05:44:30 -04:00
|
|
|
for color, switchArray in pairs(self.switches) do
|
|
|
|
|
local onSwitches = {}
|
|
|
|
|
for _, switch in pairs(switchArray) do
|
|
|
|
|
local targetCell = self:getCellInMatrix(self.collidableMatrices[color], switch:getGridPos())
|
|
|
|
|
if targetCell then
|
|
|
|
|
--switch is on
|
|
|
|
|
switch:activate()
|
|
|
|
|
table.insert(onSwitches, switch) --doesn't rly matter what we put here as long as it's true-y
|
2015-03-15 13:54:47 -04:00
|
|
|
else
|
|
|
|
|
switch:deactivate()
|
2015-03-15 05:44:30 -04:00
|
|
|
end
|
|
|
|
|
end
|
2015-03-15 07:08:35 -04:00
|
|
|
if #onSwitches == #switchArray then doorsToUnlock[color] = true else doorsToUnlock[color] = false end
|
2015-03-15 05:44:30 -04:00
|
|
|
end
|
2015-03-15 07:08:35 -04:00
|
|
|
|
|
|
|
|
return doorsToUnlock
|
2015-03-15 05:44:30 -04:00
|
|
|
end
|
|
|
|
|
|
2015-03-15 04:52:18 -04:00
|
|
|
function Room:isInBounds(cell)
|
|
|
|
|
if cell.x > 0 and cell.x <= gridWidth and
|
|
|
|
|
cell.y > 0 and cell.y <= gridHeight then
|
|
|
|
|
return true
|
|
|
|
|
end
|
|
|
|
|
return false
|
|
|
|
|
end
|
|
|
|
|
|
2015-03-11 21:08:15 -04:00
|
|
|
function Room:nextRoomCheck()
|
2015-03-15 15:34:17 -04:00
|
|
|
for _, color in ipairs(self:getActiveColors()) do
|
|
|
|
|
if not self:isInBounds(self.player[color]:getGridPos()) then
|
|
|
|
|
nextRoom(self.player[color]:getGridPos())
|
|
|
|
|
return
|
|
|
|
|
end
|
2015-03-15 05:26:47 -04:00
|
|
|
end
|
2015-03-11 21:08:15 -04:00
|
|
|
end
|
|
|
|
|
|
2015-03-17 01:59:14 -04:00
|
|
|
|
|
|
|
|
function Room:createEntity(class, color, x, y)
|
|
|
|
|
if class == "Door" then
|
|
|
|
|
self:registerDoor(Door:new(x, y))
|
|
|
|
|
elseif class == "Wall" then
|
|
|
|
|
self:registerCollidable(Wall:new(x, y, color), {color})
|
|
|
|
|
elseif class == "Switch" then
|
|
|
|
|
self.registerSwitch(Switch:new(x, y), color)
|
|
|
|
|
elseif class == "player" then
|
|
|
|
|
self:registerPlayer(Player:new(x, y, color), color)
|
|
|
|
|
elseif class == "Box" then
|
|
|
|
|
self:registerCollidable(Box:new(x, y, color), {color})
|
|
|
|
|
elseif class == "npc" then
|
|
|
|
|
-- do something soon
|
|
|
|
|
elseif class == "Ass" then
|
|
|
|
|
--do this later when we have a more definite schema
|
|
|
|
|
-- self:registerAssorted(Ass:new(x, y, color, name))
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function Room:registerCollidable(entityPointer, colorArray)
|
|
|
|
|
if type(colorArray) ~= "table" then colorArray = {colorArray} end
|
|
|
|
|
for _, color in ipairs(colorArray) do
|
|
|
|
|
table.insert(self.collideables[color], entityPointer)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function Room:registerDoor(entityPointer)
|
|
|
|
|
table.insert(self.doors, entityPointer)
|
|
|
|
|
self:registerCollidable(entityPointer, {"red", "green", "blue"})
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function Room:registerSwitch(entityPointer, color)
|
|
|
|
|
table.insert(self.switches[color], entityPointer)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function Room:registerPlayer(entityPointer, color)
|
|
|
|
|
table.insert(self.colorsPlayerHas, color)
|
|
|
|
|
self.player[color] = entityPointer
|
|
|
|
|
end
|
|
|
|
|
|
2015-03-25 01:38:53 -04:00
|
|
|
function Room:getCellFromMousePos(mouseX, mouseY)
|
|
|
|
|
local cell = {}
|
|
|
|
|
cell.x = math.ceil(mouseX * gridWidth / width)
|
|
|
|
|
cell.y = math.ceil(mouseY * gridHeight / height)
|
|
|
|
|
return cell
|
|
|
|
|
end
|
|
|
|
|
|
2026-08-06 23:54:49 -04:00
|
|
|
function Room:attemptDelete(mouseX, mouseY, color)
|
2015-03-25 01:38:53 -04:00
|
|
|
local cell = self:getCellFromMousePos(mouseX, mouseY)
|
2026-08-06 23:54:49 -04:00
|
|
|
|
|
|
|
|
-- "white" (or nil) deletes every channel; otherwise just the picked one
|
|
|
|
|
local colors
|
|
|
|
|
if not color or color == "white" then
|
|
|
|
|
colors = {"red", "green", "blue"}
|
|
|
|
|
else
|
|
|
|
|
colors = {color}
|
2015-03-25 01:38:53 -04:00
|
|
|
end
|
2026-08-06 23:54:49 -04:00
|
|
|
|
|
|
|
|
for _, c in ipairs(colors) do
|
|
|
|
|
-- player
|
|
|
|
|
if self.player[c] and self.player[c]:occupiesCell(cell) then
|
|
|
|
|
self.player[c] = nil
|
|
|
|
|
self.colorsPlayerHas[c] = false
|
|
|
|
|
end
|
|
|
|
|
-- collidables (iterate backwards so table.remove is safe)
|
|
|
|
|
local entityArray = self.collideables[c]
|
|
|
|
|
for index = #entityArray, 1, -1 do
|
|
|
|
|
if entityArray[index]:occupiesCell(cell) then
|
|
|
|
|
table.remove(entityArray, index)
|
2015-03-25 01:38:53 -04:00
|
|
|
end
|
|
|
|
|
end
|
2026-08-06 23:54:49 -04:00
|
|
|
-- switches
|
|
|
|
|
local switchArray = self.switches[c]
|
|
|
|
|
for index = #switchArray, 1, -1 do
|
|
|
|
|
if switchArray[index]:occupiesCell(cell) then
|
|
|
|
|
table.remove(switchArray, index)
|
2015-03-25 01:38:53 -04:00
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
self:tick()
|
|
|
|
|
end
|
|
|
|
|
|
2026-08-06 23:54:49 -04:00
|
|
|
local placeImageCache = {}
|
|
|
|
|
local function loadPlaceImage(path)
|
|
|
|
|
if not placeImageCache[path] then
|
|
|
|
|
placeImageCache[path] = love.graphics.newImage(path)
|
|
|
|
|
end
|
|
|
|
|
return placeImageCache[path]
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function Room:attemptPlace(name, props, mouseX, mouseY, color)
|
|
|
|
|
if not props or not props.sprites then return end
|
|
|
|
|
local cell = self:getCellFromMousePos(mouseX, mouseY)
|
2015-03-25 01:38:53 -04:00
|
|
|
|
2026-08-06 23:54:49 -04:00
|
|
|
-- "white" (or nil) means every channel; otherwise just the picked channel
|
|
|
|
|
local colors
|
|
|
|
|
if not color or color == "white" then
|
|
|
|
|
colors = {"red", "green", "blue"}
|
|
|
|
|
else
|
|
|
|
|
colors = {color}
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-- one generic entity per placed channel; each lives on its own collision
|
|
|
|
|
-- layer and the additive blend combines them into full color
|
|
|
|
|
for _, c in ipairs(colors) do
|
|
|
|
|
local path = props.sprites[c]
|
|
|
|
|
if path then
|
|
|
|
|
local sprite = loadPlaceImage(path)
|
|
|
|
|
local entity
|
|
|
|
|
if props.class == "moveable" then
|
|
|
|
|
entity = GenericMoveable:new(cell.x, cell.y, c, sprite, name)
|
|
|
|
|
else
|
|
|
|
|
entity = GenericUnmoveable:new(cell.x, cell.y, c, sprite)
|
|
|
|
|
end
|
|
|
|
|
self:registerCollidable(entity, {c})
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
self:tick()
|
2015-03-25 01:38:53 -04:00
|
|
|
end
|
|
|
|
|
|
2015-03-17 01:59:14 -04:00
|
|
|
function Room:load(name)
|
|
|
|
|
local room = love.filesystem.read("rooms/" .. name .. ".sav")
|
2026-08-06 23:54:49 -04:00
|
|
|
if not room then
|
|
|
|
|
-- no save yet: start with a blank room to build in the editor
|
|
|
|
|
print("no save for '" .. name .. "', starting blank")
|
|
|
|
|
return
|
|
|
|
|
end
|
2015-03-17 01:59:14 -04:00
|
|
|
self:deserialize(TSerial.unpack(room))
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function Room:deserialize(saveTable)
|
|
|
|
|
for entityClass, entities in pairs(saveTable) do
|
|
|
|
|
for _, entity in pairs(entities) do
|
|
|
|
|
self:createEntity(entityClass, entity.color, entity.x, entity.y)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2015-03-16 09:06:51 -04:00
|
|
|
function Room:save()
|
2015-03-17 01:59:14 -04:00
|
|
|
local name = self.name or "test"
|
|
|
|
|
local room = TSerial.pack(self:serialize(), nil, true)
|
|
|
|
|
|
|
|
|
|
local success = love.filesystem.write("rooms/" .. name .. ".sav", room)
|
|
|
|
|
if not success then error "great job u fool" end
|
2015-03-16 09:06:51 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function Room:serialize()
|
2015-03-16 10:17:06 -04:00
|
|
|
local level = {}
|
|
|
|
|
|
|
|
|
|
level.player = {}
|
|
|
|
|
for _, color in ipairs(self:getInactiveColors()) do
|
|
|
|
|
level.player[color] = self:getPlayerObject(color):getSerializationTable()
|
|
|
|
|
end
|
|
|
|
|
|
2015-03-17 01:59:14 -04:00
|
|
|
level.door = {}
|
2015-03-16 10:17:06 -04:00
|
|
|
for _, door in pairs(self:getDoors()) do
|
|
|
|
|
table.insert(level.door, doors:getSerializationTable())
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for color, collideableArray in pairs(self:getCollideables()) do
|
|
|
|
|
for _, collideable in pairs(collideableArray) do
|
|
|
|
|
if not collideable:isInstanceOf("Door") then --for now, we might change doors up some
|
2015-03-17 01:59:14 -04:00
|
|
|
local entityClass = collideable:getClass()
|
2015-03-16 10:17:06 -04:00
|
|
|
if not level[entityClass] then level[entityClass] = {} end
|
2015-03-17 01:59:14 -04:00
|
|
|
table.insert(level[entityClass], collideable:getSerializationTable())
|
2015-03-16 10:17:06 -04:00
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2015-03-17 01:59:14 -04:00
|
|
|
level.switch = {}
|
2015-03-16 10:17:06 -04:00
|
|
|
for color, switchArray in pairs(self:getSwitches()) do
|
|
|
|
|
for _, switch in ipairs(switchArray) do
|
2015-03-17 01:59:14 -04:00
|
|
|
table.insert(level.switch, switch:getSerializationTable())
|
2015-03-16 10:17:06 -04:00
|
|
|
end
|
|
|
|
|
end
|
2015-03-16 09:06:51 -04:00
|
|
|
|
2015-03-16 10:17:06 -04:00
|
|
|
return level
|
2015-03-16 09:06:51 -04:00
|
|
|
end
|
|
|
|
|
|
2015-03-15 05:26:47 -04:00
|
|
|
function nextRoom(pos)
|
|
|
|
|
local exit
|
|
|
|
|
local newPos = {x = pos.x, y = pos.y}
|
|
|
|
|
if pos.x > gridWidth then
|
|
|
|
|
exit = "right"
|
|
|
|
|
newPos.x = 1
|
|
|
|
|
elseif pos.x < 1 then
|
|
|
|
|
exit = "left"
|
|
|
|
|
newPos.x = gridWidth
|
|
|
|
|
elseif pos.y > gridHeight then
|
|
|
|
|
exit = "bottom"
|
|
|
|
|
newPos.y = 1
|
|
|
|
|
elseif pos.y < 1 then
|
|
|
|
|
exit = "top"
|
|
|
|
|
newPos.y = gridHeight
|
|
|
|
|
end
|
2015-03-12 03:04:09 -04:00
|
|
|
|
2015-03-16 09:06:51 -04:00
|
|
|
currentRoom:save()
|
|
|
|
|
|
2015-03-17 01:59:14 -04:00
|
|
|
currentRoom = Room:new{
|
2015-03-25 01:38:53 -04:00
|
|
|
-- name = "test",
|
2015-03-15 05:26:47 -04:00
|
|
|
player = {
|
2015-03-15 15:34:17 -04:00
|
|
|
x = newPos.x, y = newPos.y, activeColors = currentRoom:getActiveColors()
|
2015-03-15 05:26:47 -04:00
|
|
|
}
|
|
|
|
|
}
|
2015-03-17 01:59:14 -04:00
|
|
|
|
2015-03-16 09:06:51 -04:00
|
|
|
end
|
|
|
|
|
|