From c92c0f6ff73f08d5566f28f77017a6f2813e368c Mon Sep 17 00:00:00 2001 From: Your Name Date: Fri, 7 Aug 2026 20:56:42 -0400 Subject: [PATCH] fix state thigns and port to love11 --- _helpers.lua | 13 +-- color.lua | 11 +-- conf.lua | 6 +- level_editor/editor.lua | 4 +- level_editor/gui.lua | 2 +- level_editor/object_attributes.lua | 6 +- main.lua | 21 ++++- player.lua | 4 +- room.lua | 17 +++- rooms/world.sav | 136 ++++++++++++++--------------- world.lua | 6 +- 11 files changed, 130 insertions(+), 96 deletions(-) diff --git a/_helpers.lua b/_helpers.lua index b07f791..77d9807 100644 --- a/_helpers.lua +++ b/_helpers.lua @@ -58,7 +58,8 @@ function clearRuntimeSaveData(roomName) end local function removeTree(path) - if love.filesystem.isDirectory(path) then + local info = love.filesystem.getInfo(path) + if info and info.type == "directory" then for _, child in ipairs(love.filesystem.getDirectoryItems(path)) do removeTree(path .. "/" .. child) end @@ -109,16 +110,18 @@ function cellShapeFromBox(box) return cells end --- Which 16x16 cells of a sprite are non-empty, for multi-cell collision shapes. -function getCellsFromSprite(sprite) - local w, h = sprite:getWidth(), sprite:getHeight() +-- Which 16x16 cells of an image are non-empty, for multi-cell collision +-- shapes. LÖVE 11 no longer exposes Image:getData(), so inspect ImageData +-- directly instead of creating a GPU Image first. +function getCellsFromSprite(spritePath) + local img = love.image.newImageData(spritePath) + local w, h = img:getWidth(), img:getHeight() local box = {w = w / 16, h = h / 16} local boxCells = cellShapeFromBox(box) if box.w < 1 or box.h < 1 then return boxCells end - local img = sprite:getData() local cellsToRemove = {} for _, cell in pairs(boxCells) do diff --git a/color.lua b/color.lua index bf55340..274d882 100644 --- a/color.lua +++ b/color.lua @@ -4,10 +4,11 @@ Color = class("Color") Color.static.list = { - red = {r = 255, g = 0, b = 0, a = 255}, - green = {r = 0, g = 255, b = 0, a = 255}, - blue = {r = 0, g = 0, b = 255, a = 255}, - white = {r = 255, g = 255, b = 255, a = 255} + -- LÖVE 11 represents color components as normalized floats, not bytes. + red = {r = 1, g = 0, b = 0, a = 1}, + green = {r = 0, g = 1, b = 0, a = 1}, + blue = {r = 0, g = 0, b = 1, a = 1}, + white = {r = 1, g = 1, b = 1, a = 1} } function Color:initialize(inColor) @@ -27,4 +28,4 @@ end function randomColor() local colors = {"red", "green", "blue"} return colors[math.random(1, 3)] -end \ No newline at end of file +end diff --git a/conf.lua b/conf.lua index aa708e6..6128aad 100644 --- a/conf.lua +++ b/conf.lua @@ -1,8 +1,12 @@ function love.conf(t) + -- This project uses the normalized-color and ImageData APIs introduced in + -- LÖVE 11. Pinning the intended runtime also gives a useful warning when a + -- player tries to launch it with an older installation. + t.version = "11.5" t.window.width = 900 t.window.height = 640 t.window.title = "CHROMA SOLSTICE" t.window.resizable = true t.window.minwidth = 700 t.window.minheight = 500 -end \ No newline at end of file +end diff --git a/level_editor/editor.lua b/level_editor/editor.lua index 72f2c52..a8fc5cf 100644 --- a/level_editor/editor.lua +++ b/level_editor/editor.lua @@ -136,14 +136,14 @@ local function drawWorldSidebar() love.graphics.rectangle("line", worldSearchBox.x, worldSearchBox.y, worldSearchBox.w, worldSearchBox.h) love.graphics.printf("SEARCH: " .. worldSearchText, worldSearchBox.x + 6, worldSearchBox.y + 7, worldSearchBox.w - 12, "left") for _, button in ipairs(worldRoomButtons) do - love.graphics.setColor(button.name == selectedRoom and 255 or 100, button.name == selectedRoom and 255 or 100, button.name == selectedRoom and 255 or 100, 255) + love.graphics.setColor(button.name == selectedRoom and 1 or 100 / 255, button.name == selectedRoom and 1 or 100 / 255, button.name == selectedRoom and 1 or 100 / 255, 1) love.graphics.rectangle("line", button.x, button.y, button.w, button.h) gameWorld:drawRoomPreview(button.name, button.x + 4, button.y + 4, button.h - 8) love.graphics.setColor(gColor.white:set()) love.graphics.printf(button.name, button.x + button.h + 4, button.y + 21, button.w - button.h - 8, "left") end for _, control in ipairs(worldControls) do - love.graphics.setColor(255, 255, 255, 255) + love.graphics.setColor(1, 1, 1, 1) love.graphics.rectangle("line", control.x, control.y, control.w, control.h) love.graphics.printf(control.text, control.x, control.y + 9, control.w, "center") end diff --git a/level_editor/gui.lua b/level_editor/gui.lua index e7264f4..d5260fd 100644 --- a/level_editor/gui.lua +++ b/level_editor/gui.lua @@ -1,6 +1,6 @@ GUI = class("level_editor/gui") -GUI.static.pressSound = love.audio.newSource("sounds/ui/button.wav") +GUI.static.pressSound = love.audio.newSource("sounds/ui/button.wav", "static") GUI.static.defaultCallbac = function() print("this button has not been configured") end diff --git a/level_editor/object_attributes.lua b/level_editor/object_attributes.lua index c9083da..2ab6257 100644 --- a/level_editor/object_attributes.lua +++ b/level_editor/object_attributes.lua @@ -34,7 +34,7 @@ function getAllAssets() -- class comes from a .meta sitting next to the art -- (authoritative); default to immoveable if none exists local metaPath = topFolder .. "/" .. folder .. "/" .. name .. ".meta" - if love.filesystem.exists(metaPath) then + if love.filesystem.getInfo(metaPath, "file") then globalAssetProperties[name].class = TSerial.unpack(love.filesystem.read(metaPath)).class elseif not globalAssetProperties[name].class then globalAssetProperties[name].class = "immoveable" @@ -45,7 +45,7 @@ function getAllAssets() if not globalAssetProperties[name].cells or reanalyzeCells then globalAssetProperties[name].cells = {} - globalAssetProperties[name].cells[color] = getCellsFromSprite(love.graphics.newImage(sprite)) + globalAssetProperties[name].cells[color] = getCellsFromSprite(sprite) end end end @@ -54,4 +54,4 @@ function getAllAssets() end return globalAssetProperties -end \ No newline at end of file +end diff --git a/main.lua b/main.lua index 12d9044..3caf642 100644 --- a/main.lua +++ b/main.lua @@ -29,8 +29,12 @@ function love.load() inputTimer = Timer.new() + -- Resume the game: prefer the runtime autosave so the last saved position is + -- restored, falling back to the authored source level. Editor room-opens go + -- through their own (source-only) load path, so this only affects resume. currentRoom = Room:new{ - name = gameWorld.lastRoom or "start" + name = gameWorld.lastRoom or "start", + runtime = true } gameWorld:setLastRoom(currentRoom.name) setEditorRoomName(currentRoom.name) @@ -38,6 +42,15 @@ function love.load() response = "" end +-- Autosave on close so a position reached by moving within a room (short of a +-- room-to-room transition, which already autosaves in nextRoom) survives. +function love.quit() + if currentRoom then + currentRoom:save() + if gameWorld then gameWorld:setLastRoom(currentRoom.name) end + end +end + function love.update(dt) if editorView == "world" then Input:stopMoveRepeat() @@ -70,7 +83,7 @@ function love.draw() love.graphics.push() for i = 1, samples do - local c = 65 / (i * 1.75) + local c = 65 / 255 / (i * 1.75) love.graphics.setColor(c, c, c) love.graphics.scale(scaleCoefficient, scaleCoefficient) love.graphics.translate((width / 2 - (width * scaleCoefficient) / 2) + 2, (width / 2 - (height * scaleCoefficient) / 2) + 2) @@ -78,7 +91,7 @@ function love.draw() end love.graphics.pop() - love.graphics.setColor(255, 255, 255) + love.graphics.setColor(1, 1, 1) love.graphics.draw(gameCanvas, 0, 0) love.graphics.setCanvas() @@ -88,7 +101,7 @@ function love.draw() love.graphics.setCanvas() love.graphics.setBlendMode("alpha") - love.graphics.setColor(255, 255, 255, 255) + love.graphics.setColor(1, 1, 1, 1) love.graphics.draw(finalCanvas, 0, 0) love.graphics.draw(sideBarCanvas, sideBarBox.x, sideBarBox.y) love.graphics.print("Current FPS: "..tostring(love.timer.getFPS( )), 10, 10) diff --git a/player.lua b/player.lua index 85b8686..b1b8914 100644 --- a/player.lua +++ b/player.lua @@ -3,8 +3,8 @@ require "entity" Player = class("Player", Entity) Player.static.sounds = { - switchFail = love.audio.newSource("sounds/switch_fail.wav"), - switchSuccess = love.audio.newSource("sounds/switch_success.wav") + switchFail = love.audio.newSource("sounds/switch_fail.wav", "static"), + switchSuccess = love.audio.newSource("sounds/switch_success.wav", "static") } function Player:initialize(x, y, color) diff --git a/room.lua b/room.lua index 22a5707..e06f7a6 100644 --- a/room.lua +++ b/room.lua @@ -130,7 +130,7 @@ function Room:draw() -- npcs (old "sages") are markers for now: a "?" tinted to the player's channels local cellW, cellH = width / gridWidth, height / gridHeight - love.graphics.setColor(has.red and 255 or 0, has.green and 255 or 0, has.blue and 255 or 0) + love.graphics.setColor(has.red and 1 or 0, has.green and 1 or 0, has.blue and 1 or 0) for _, npc in ipairs(self.npcs) do love.graphics.print("?", (npc.x - 1) * cellW + cellW * 0.3, (npc.y - 1) * cellH + cellH * 0.1, 0, 2, 2) end @@ -698,6 +698,12 @@ end function Room:deserialize(saveTable) for _, obj in ipairs(saveTable.objects or {}) do self:createEntity(obj.class, obj.color, obj.x, obj.y) + -- createEntity turns every loaded player on; honour a saved active flag so + -- copies that were off at save time stay off (older savs lack the field and + -- keep the old all-on behaviour). + if obj.class == "player" and obj.active ~= nil then + self:setActiveColor(obj.color, obj.active) + end end end @@ -752,7 +758,14 @@ function Room:serialize(includePlayers) if includePlayers ~= false then for color, player in pairs(self.player) do - emit("player", color, player) + local pos = player:getGridPos() + -- Persist which copies were active so a resume restores exactly the + -- channels that were on at save time. A colour deactivated during play + -- (see playerJoinCheck) must come back as an inactive copy, not turn on. + table.insert(objects, { + class = "player", color = color, x = pos.x, y = pos.y, + active = self.activeColors[color] and true or false, + }) end end diff --git a/rooms/world.sav b/rooms/world.sav index 52b48e2..08012aa 100644 --- a/rooms/world.sav +++ b/rooms/world.sav @@ -1,152 +1,152 @@ { -width=18, -height=18, rooms={ { - x=9, name="start", - y=11 + y=11, + x=9 }, { - x=10, name="3", - y=10 + y=10, + x=10 }, { - x=11, - name="4", - y=10 - }, - { - x=12, name="5", - y=10 + y=10, + x=12 }, { - x=12, name="village_1", - y=9 + y=9, + x=12 }, { - x=12, name="village_2", - y=8 + y=8, + x=12 }, { - x=13, name="village_3", - y=8 + y=8, + x=13 }, { - x=11, name="village_4", - y=8 + y=8, + x=11 }, { - x=11, name="yellow_1", - y=7 + y=7, + x=11 }, { - x=11, name="yellow_3", - y=6 + y=6, + x=11 }, { - x=12, name="yellow_2", - y=7 + y=7, + x=12 }, { - x=11, name="yellow_4", - y=5 + y=5, + x=11 }, { - x=11, name="yellow_5", - y=4 + y=4, + x=11 }, { - x=10, name="yellow_6", - y=5 + y=5, + x=10 }, { - x=1, name="default", - y=1 + y=1, + x=1 }, { - x=3, name="old_yellow_3", - y=1 + y=1, + x=3 }, { - x=5, name="test_patt", - y=1 + y=1, + x=5 }, { - x=7, name="test_patt_update", - y=1 + y=1, + x=7 }, { - x=9, name="white_asymmetrical", - y=1 + y=1, + x=9 }, { - x=11, name="white_ok", - y=1 + y=1, + x=11 }, { - x=13, name="white_primary", - y=1 + y=1, + x=13 }, { - x=15, name="yellow_arches", - y=1 + y=1, + x=15 }, { - x=17, name="yellow_asymmetrical", - y=1 + y=1, + x=17 }, { - x=1, name="yellow_cc_moustache", - y=3 + y=3, + x=1 }, { - x=3, name="yellow_color_changing_levvel_1", - y=3 + y=3, + x=3 }, { - x=5, - name="yellow_skull", - y=3 - }, - { - x=7, name="yellow_smile", - y=3 + y=3, + x=7 }, { - x=9, name="2", - y=10 + y=10, + x=9 }, { - x=11, name="room_11_09", - y=9 + y=9, + x=11 + }, + { + name="4", + y=3, + x=5 + }, + { + name="yellow_skull", + y=3, + x=9 } }, -lastRoom="yellow_skull" -} \ No newline at end of file +lastRoom="start", +width=18, +height=18 +} diff --git a/world.lua b/world.lua index e31a1ac..7204cb1 100644 --- a/world.lua +++ b/world.lua @@ -156,7 +156,7 @@ function World:drawRoomPreview(name, x, y, size) love.graphics.setScissor(x, y, size, size) for _, object in ipairs(room.objects or {}) do if object.class == "npc" then - love.graphics.setColor(255, 255, 255, 255) + love.graphics.setColor(1, 1, 1, 1) love.graphics.print("?", x + (object.x - 1) * 16 * scale, y + (object.y - 1) * 16 * scale, 0, scale, scale) else local props = globalAssetProperties[object.class] @@ -182,14 +182,14 @@ end function World:draw() local cell = width / self.width - love.graphics.setColor(12, 12, 20, 255) + love.graphics.setColor(12 / 255, 12 / 255, 20 / 255, 1) love.graphics.rectangle("fill", 0, 0, width, height) for y = 1, self.height do for x = 1, self.width do local screenX, screenY = (x - 1) * cell, (y - 1) * cell local name = self:roomAt(x, y) if name then self:drawRoomPreview(name, screenX, screenY, cell) end - love.graphics.setColor(name and 255 or 70, name and 255 or 70, name and 255 or 90, 255) + love.graphics.setColor(name and 1 or 70 / 255, name and 1 or 70 / 255, name and 1 or 90 / 255, 1) love.graphics.rectangle("line", screenX, screenY, cell, cell) end end