room changes
This commit is contained in:
parent
8fae34b803
commit
38eaba2fa6
7 changed files with 2333 additions and 2108 deletions
4
main.lua
4
main.lua
|
|
@ -306,6 +306,10 @@ function _initCanvases()
|
||||||
gameCanvas = love.graphics.newCanvas()
|
gameCanvas = love.graphics.newCanvas()
|
||||||
finalCanvas = love.graphics.newCanvas()
|
finalCanvas = love.graphics.newCanvas()
|
||||||
presentationCanvas = love.graphics.newCanvas()
|
presentationCanvas = love.graphics.newCanvas()
|
||||||
|
-- Reused for each cardinal neighbour's alternate real-colour view at the
|
||||||
|
-- porous room boundary. Full-screen dimensions keep it pixel-aligned with
|
||||||
|
-- the gameplay canvas during shader compositing.
|
||||||
|
porousRoomCanvas = love.graphics.newCanvas()
|
||||||
sideBarCanvas = love.graphics.newCanvas(math.max(1, sideBarBox.w), math.max(1, sideBarBox.h))
|
sideBarCanvas = love.graphics.newCanvas(math.max(1, sideBarBox.w), math.max(1, sideBarBox.h))
|
||||||
sideBarCanvas:setFilter("nearest", "nearest") -- never average when sampled
|
sideBarCanvas:setFilter("nearest", "nearest") -- never average when sampled
|
||||||
end
|
end
|
||||||
|
|
|
||||||
25
room.lua
25
room.lua
|
|
@ -130,17 +130,30 @@ function Room:update(dt)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function Room:draw()
|
-- A room's view is defined by the colour player copies that are in that room,
|
||||||
|
-- independent of which of those copies is currently being controlled. A caller
|
||||||
|
-- may supply another set for World's porous boundary without altering sprites
|
||||||
|
-- or colour blending.
|
||||||
|
function Room:getRenderChannels()
|
||||||
|
if gameWorld and gameWorld.roomBrowseMode then return {"red", "green", "blue"} end
|
||||||
|
local channels = {}
|
||||||
|
for _, color in ipairs({"red", "green", "blue"}) do
|
||||||
|
if self.player[color] then table.insert(channels, color) end
|
||||||
|
end
|
||||||
|
return channels
|
||||||
|
end
|
||||||
|
|
||||||
|
function Room:draw(drawChannels)
|
||||||
if gameWorld and gameWorld.levels and gameWorld.levels[self.name] == self and
|
if gameWorld and gameWorld.levels and gameWorld.levels[self.name] == self and
|
||||||
not gameWorld.drawingRoomNeighborhood then
|
not gameWorld.drawingRoomNeighborhood then
|
||||||
return gameWorld:drawRoomNeighborhood(self)
|
return gameWorld:drawRoomNeighborhood(self)
|
||||||
end
|
end
|
||||||
self:drawWiresAt(0, 0, width / gridWidth, nil, false)
|
drawChannels = drawChannels or self:getRenderChannels()
|
||||||
|
self:drawWiresAt(0, 0, width / gridWidth, nil, false, drawChannels)
|
||||||
|
|
||||||
-- draw only the channels the player has. Each object just exposes sprites per
|
-- Draw only the channels active in this view. Each object just exposes sprites per
|
||||||
-- channel via Entity:draw(channel); a door registered on all three channels
|
-- channel via Entity:draw(channel); a door registered on all three channels
|
||||||
-- naturally draws its red sprite on the red pass, etc. No per-object logic.
|
-- naturally draws its red sprite on the red pass, etc. No per-object logic.
|
||||||
local drawChannels = gameWorld and gameWorld.roomBrowseMode and {"red", "green", "blue"} or self.colorsPlayerHas
|
|
||||||
for _, channel in ipairs(drawChannels) do
|
for _, channel in ipairs(drawChannels) do
|
||||||
if self.player[channel] then self.player[channel]:draw(channel) end
|
if self.player[channel] then self.player[channel]:draw(channel) end
|
||||||
for _, entity in pairs(self.collideables[channel]) do entity:draw(channel) end
|
for _, entity in pairs(self.collideables[channel]) do entity:draw(channel) end
|
||||||
|
|
@ -190,7 +203,7 @@ function Room:removeWire(cell, circuitId)
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function Room:drawWiresAt(originX, originY, cellSize, selectedCircuit, editorColors)
|
function Room:drawWiresAt(originX, originY, cellSize, selectedCircuit, editorColors, renderChannels)
|
||||||
local ids = {}
|
local ids = {}
|
||||||
for _, row in pairs(self.wires) do
|
for _, row in pairs(self.wires) do
|
||||||
for _, tracks in pairs(row) do
|
for _, tracks in pairs(row) do
|
||||||
|
|
@ -205,7 +218,7 @@ function Room:drawWiresAt(originX, originY, cellSize, selectedCircuit, editorCol
|
||||||
local showAllChannels = gameWorld and gameWorld.roomBrowseMode
|
local showAllChannels = gameWorld and gameWorld.roomBrowseMode
|
||||||
local visibleColors = {red = showAllChannels, green = showAllChannels, blue = showAllChannels}
|
local visibleColors = {red = showAllChannels, green = showAllChannels, blue = showAllChannels}
|
||||||
if not showAllChannels then
|
if not showAllChannels then
|
||||||
for _, color in ipairs(self.colorsPlayerHas or {}) do visibleColors[color] = true end
|
for _, color in ipairs(renderChannels or self:getRenderChannels()) do visibleColors[color] = true end
|
||||||
end
|
end
|
||||||
local editorIsOn = editorView ~= nil and editorView ~= "off"
|
local editorIsOn = editorView ~= nil and editorView ~= "off"
|
||||||
for _, circuitId in ipairs(ordered) do
|
for _, circuitId in ipairs(ordered) do
|
||||||
|
|
|
||||||
1799
rooms/room_13_14.sav
1799
rooms/room_13_14.sav
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
38
shaders.lua
38
shaders.lua
|
|
@ -128,6 +128,44 @@ wireNeonShader = love.graphics.newShader[[
|
||||||
}
|
}
|
||||||
]]
|
]]
|
||||||
|
|
||||||
|
-- World renders a neighbouring room twice for the porous seam: once through
|
||||||
|
-- its own active channels and once through the current room's channels. This
|
||||||
|
-- shader only controls the alpha of that second, already-authored render, so
|
||||||
|
-- it never approximates the game's literal RGB colour treatment.
|
||||||
|
porousRoomBoundaryShader = love.graphics.newShader[[
|
||||||
|
extern number porousTime;
|
||||||
|
extern vec4 porousRoomRect;
|
||||||
|
extern vec2 porousDirection;
|
||||||
|
extern number porousDepth;
|
||||||
|
|
||||||
|
float porousWave(vec2 point) {
|
||||||
|
float broad = sin(point.x * 0.095 + point.y * 0.071 + porousTime * 1.45);
|
||||||
|
float fine = sin(point.x * 0.231 - point.y * 0.187 - porousTime * 2.20);
|
||||||
|
return broad * 0.105 + fine * 0.050;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec4 effect(vec4 color, Image texture, vec2 textureCoords, vec2 screenCoords) {
|
||||||
|
vec4 alternateView = Texel(texture, textureCoords) * color;
|
||||||
|
vec2 local = screenCoords - porousRoomRect.xy;
|
||||||
|
vec2 size = porousRoomRect.zw;
|
||||||
|
if (local.x < 0.0 || local.y < 0.0 || local.x > size.x || local.y > size.y)
|
||||||
|
return vec4(0.0);
|
||||||
|
|
||||||
|
float depth;
|
||||||
|
if (porousDirection.x > 0.5) depth = local.x;
|
||||||
|
else if (porousDirection.x < -0.5) depth = size.x - local.x;
|
||||||
|
else if (porousDirection.y > 0.5) depth = local.y;
|
||||||
|
else depth = size.y - local.y;
|
||||||
|
|
||||||
|
float towardSeam = 1.0 - smoothstep(0.0, porousDepth, depth);
|
||||||
|
// Animated fingers soften the fifty-fifty transition across the visible
|
||||||
|
// overlap while preserving the pixels of the real alternate room render.
|
||||||
|
float mask = smoothstep(0.18, 0.82, towardSeam + porousWave(screenCoords));
|
||||||
|
alternateView.a *= mask;
|
||||||
|
return alternateView;
|
||||||
|
}
|
||||||
|
]]
|
||||||
|
|
||||||
function drawGoopySprite(sprite, x, y, scale)
|
function drawGoopySprite(sprite, x, y, scale)
|
||||||
local w, h = sprite:getWidth(), sprite:getHeight()
|
local w, h = sprite:getWidth(), sprite:getHeight()
|
||||||
local time = love.timer.getTime()
|
local time = love.timer.getTime()
|
||||||
|
|
|
||||||
53
world.lua
53
world.lua
|
|
@ -963,20 +963,61 @@ function World:drawRoomNeighborhood(room)
|
||||||
local transform = self:roomNeighborhoodTransform(room)
|
local transform = self:roomNeighborhoodTransform(room)
|
||||||
if not transform then return end
|
if not transform then return end
|
||||||
self.drawingRoomNeighborhood = true
|
self.drawingRoomNeighborhood = true
|
||||||
|
local currentChannels = room:getRenderChannels()
|
||||||
|
local roomWidth, roomHeight = width * transform.zoom, height * transform.zoom
|
||||||
|
|
||||||
|
local function drawAt(offsetX, offsetY, level, channels)
|
||||||
|
love.graphics.push()
|
||||||
|
love.graphics.translate(transform.originX + (offsetX + transform.cameraX) * roomWidth,
|
||||||
|
transform.originY + (offsetY + transform.cameraY) * roomHeight)
|
||||||
|
love.graphics.scale(transform.zoom, transform.zoom)
|
||||||
|
level:draw(channels)
|
||||||
|
love.graphics.pop()
|
||||||
|
end
|
||||||
|
|
||||||
for roomY = -1, 1 do
|
for roomY = -1, 1 do
|
||||||
for roomX = -1, 1 do
|
for roomX = -1, 1 do
|
||||||
local name = self:roomAt(transform.location.x + roomX, transform.location.y + roomY)
|
local name = self:roomAt(transform.location.x + roomX, transform.location.y + roomY)
|
||||||
local adjacent = name and self.levels[name]
|
local adjacent = name and self.levels[name]
|
||||||
if adjacent then
|
if adjacent then
|
||||||
love.graphics.push()
|
drawAt(roomX, roomY, adjacent)
|
||||||
love.graphics.translate(transform.originX + (roomX + transform.cameraX) * width * transform.zoom,
|
|
||||||
transform.originY + (roomY + transform.cameraY) * height * transform.zoom)
|
|
||||||
love.graphics.scale(transform.zoom, transform.zoom)
|
|
||||||
adjacent:draw()
|
|
||||||
love.graphics.pop()
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Each cardinal neighbour receives a second, real render through the active
|
||||||
|
-- colours in the current room. The shader only chooses a wispy portion of
|
||||||
|
-- the shared visible margin, preserving all literal RGB passes and sprites.
|
||||||
|
if porousRoomCanvas and porousRoomBoundaryShader and #currentChannels > 0 then
|
||||||
|
local targetCanvas = love.graphics.getCanvas()
|
||||||
|
local directions = {
|
||||||
|
{ x = -1, y = 0 }, { x = 1, y = 0 }, { x = 0, y = -1 }, { x = 0, y = 1 },
|
||||||
|
}
|
||||||
|
for _, direction in ipairs(directions) do
|
||||||
|
local name = self:roomAt(transform.location.x + direction.x, transform.location.y + direction.y)
|
||||||
|
local adjacent = name and self.levels[name]
|
||||||
|
if adjacent then
|
||||||
|
love.graphics.setCanvas(porousRoomCanvas)
|
||||||
|
love.graphics.clear(0, 0, 0, 0)
|
||||||
|
drawAt(direction.x, direction.y, adjacent, currentChannels)
|
||||||
|
|
||||||
|
love.graphics.setCanvas(targetCanvas)
|
||||||
|
local roomLeft = transform.originX + (direction.x + transform.cameraX) * roomWidth
|
||||||
|
local roomTop = transform.originY + (direction.y + transform.cameraY) * roomHeight
|
||||||
|
porousRoomBoundaryShader:send("porousTime", love.timer.getTime())
|
||||||
|
porousRoomBoundaryShader:send("porousRoomRect", {roomLeft, roomTop, roomWidth, roomHeight})
|
||||||
|
porousRoomBoundaryShader:send("porousDirection", {direction.x, direction.y})
|
||||||
|
-- Exactly the amount of the neighbour exposed by the zoom-out.
|
||||||
|
porousRoomBoundaryShader:send("porousDepth", (1 - transform.zoom) * width / 2)
|
||||||
|
love.graphics.setBlendMode("alpha")
|
||||||
|
love.graphics.setColor(1, 1, 1, 1)
|
||||||
|
love.graphics.setShader(porousRoomBoundaryShader)
|
||||||
|
love.graphics.draw(porousRoomCanvas, 0, 0)
|
||||||
|
love.graphics.setShader()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
love.graphics.setBlendMode("screen")
|
||||||
|
end
|
||||||
self.drawingRoomNeighborhood = false
|
self.drawingRoomNeighborhood = false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue