Room = class("Room") require "player" require "box" require "wall" require "artifact" require "npc" require "art" require "assorted" require "switch" require "door" function Room:initialize(t) self.colorsPlayerHas = {"red", "green", "blue"} self.exits = t.exits self.name = t.name self.player = Player:new(t.player.x, t.player.y, t.player.activeColors) self.switches = { red = {}, green = {}, blue = {} } self.switchMatrices = {} self.collideables = { red = {}, green = {}, blue = {} } self.collidableMatrices = {} --{red = {{...}{...}{...}}, ... self.doors = {} self.activeColors = { red = true, green = true, blue = true } -- for color, coords in pairs(t.player) do -- self.player[color] = Player:new(coords.x, coords.y, color) -- self.activeColors[color] = true -- end for i=1, 3 do local x, y = randomPosition() local door = Door:new(x, y, self.colorsPlayerHas) table.insert(self.doors, door) for color, active in pairs(self.activeColors) do self.collideables[color]["w: " .. x .. ", " .. y] = door end end -- for i=0, 5 do -- local x, y = math.random(1, gridWidth), math.random(1, gridHeight) -- for color, active in pairs(self.activeColors) do -- self.collideables[color]["w: " .. x .. ", " .. y] = Wall:new(x, y, color) -- end -- end 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 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 local x, y = 1, 1 if active then self.collideables[color]["n: " .. x .. ", " .. y] = Ass:new(x, y, color, "tech/processed/", "mac_smaller") end self.collideables[color]["n: " .. x .. ", " .. y]:getOccupiedCells() local x, y = 7, 7 if active then self.collideables[color]["n: " .. x .. ", " .. y] = Ass:new(x, y, color, "tech/processed/", "cd") end end -- self.collideables["green"]["fpp"] = Artifact:new(6, 6, "green") for color, entities in pairs(self.collideables) do self.collidableMatrices[color] = self:createEntityMatrix(entities) end end function Room:update(dt) self.player:update(dt) end function Room:draw() self.player:draw() for color, entityArray in pairs(self.collideables) do for _, entity in pairs(entityArray) do entity:draw() end end for color, switchArray in pairs(self.switches) do for _, switch in pairs(switchArray) do switch:draw() end end end function Room:createCollideablesMatrix() for color, entities in pairs(self.collideables) do self.collidableMatrices[color] = self:createEntityMatrix(entities) end end function Room:createSwitchMatrix() for color, switches in pairs(self.switches) do self.switchMatrices[color] = self:createEntityMatrix(switches) end end function Room:createEntityMatrix(entities) local matrix = {} --lets populate it w/ empty stuff first for i = 1, gridWidth do local row = {} for i = 1, gridHeight do table.insert(row, false) end table.insert(matrix, row) end --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) return matrix end function Room:getCellInMatrix(matrix, cell) return matrix[cell.y][cell.x] end function Room:movePlayer(key) local activeColors = self.player:getActiveColors() local pos = self.player:getGridPos() 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 local move = true local entitiesToPush = { red = {}, green = {}, blue = {} } local entitiesToPull = { red = {}, green = {}, blue = {} } -- PUSHHHHHHHHHHHHHHHHHHHHHH--------------------- 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 if not self:isInBounds(initialTargetCell) then move = true elseif self:getCellInMatrix(self.collidableMatrices["red"], initialTargetCell) and self:getCellInMatrix(self.collidableMatrices["red"], initialTargetCell):canPassOver() then move = true else local targetCells --so the way this worx is.... for _, color in pairs(activeColors) do --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!! if not entitiesToPush[color][entity] then --if the entity hasnt been found already if entity:canMove() then local projectedCells = entity:getOccupiedCells(dir) -- we project the movement here entitiesToPush[color][entity] = entity for _, projectedCell in ipairs(projectedCells) do table.insert(nextTargetCells, projectedCell) end else move = false doneSearching = true end end else --there's nothin there!! table.insert(emptyCells, cell) end else --we are out of bounds now move = false doneSearching = true end end --if every projected cell is empty then we can do the move if #emptyCells == #targetCells then move = true doneSearching = true end targetCells = nextTargetCells end --let's get out of this loop b/c if we can't move one color we can't move at all if move == false then break end end end ---PULL CHEC local initialTargetCell = {x = pos.x - dir.x, y = pos.y - dir.y} local targetCells local pull = {} --so the way this worx is.... for _, color in pairs(activeColors) do --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!! if not entitiesToPull[color][entity] then --if the entity hasnt been found already if entity:canMove() then local projectedCells = entity:getOccupiedCells(dir) -- we project the movement here entitiesToPull[color][entity] = entity for _, projectedCell in ipairs(projectedCells) do table.insert(nextTargetCells, projectedCell) end else pull[color] = false doneSearching = true end end else --there's nothin there!! table.insert(emptyCells, cell) end else pull[color] = true --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 pull[color] = true doneSearching = true end targetCells = nextTargetCells end --let's get out of this loop b/c if we can't move one color we can't move at all if move == false then break end end if move then for color, entities in pairs(entitiesToPush) do for _, entity in pairs(entities) do entity:move(axis, dir[axis]) end end for color, entities in pairs(entitiesToPull) do if pull[color] then for _, entity in pairs(entities) do entity:move(axis, dir[axis]) end end end self.player:move(axis, dir[axis]) self:tick() end end function Room:attemptPush(dirVector) -- should return array of things to push or nil/falsey value end function Room:switchPlayerColor(color) if color == "white" then self.player:setActiveColors({"red", "green", "blue"}) else self.player:setActiveColors({color}) end end function Room:setActiveColor(color, bool) self.activeColors[color] = bool end function Room:tick() for color, entityArray in pairs(self.collideables) do for _, entity in pairs(entityArray) do entity:tick() end end self:createCollideablesMatrix() self:createSwitchMatrix() local setDoorColors = self:switchCheck() for _, door in pairs(self.doors) do print(door) door:setColors(setDoorColors) end self:nextRoomCheck() end function Room:switchCheck() local doorsToUnlock = {} 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 end end if #onSwitches == #switchArray then doorsToUnlock[color] = true else doorsToUnlock[color] = false end print(color, doorsToUnlock[color]) end return doorsToUnlock end 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 function Room:nextRoomCheck() if not self:isInBounds(self.player:getGridPos()) then nextRoom(self.player:getGridPos()) end end 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 currentRoom = Room:new{ player = { x = newPos.x, y = newPos.y, activeColors = currentRoom.player:getActiveColors() } } end