sound and other misc fixes
This commit is contained in:
parent
38eaba2fa6
commit
176216df8e
6 changed files with 97 additions and 15 deletions
|
|
@ -6,6 +6,10 @@
|
|||
Dialogable = {}
|
||||
|
||||
function Dialogable:onBump()
|
||||
if self.book then Dialogue.open(self.book) end
|
||||
if self.book then
|
||||
local wasOpen = Dialogue.isOpen()
|
||||
Dialogue.open(self.book)
|
||||
if Sound and not wasOpen then Sound.jabber() end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
|
|
|||
1
door.lua
1
door.lua
|
|
@ -41,6 +41,7 @@ end
|
|||
function Door:unlock()
|
||||
self.locked = false
|
||||
self.collision = "none"
|
||||
if Sound then Sound.play("doorUnlock") end
|
||||
end
|
||||
|
||||
function Door:lock()
|
||||
|
|
|
|||
31
main.lua
31
main.lua
|
|
@ -10,6 +10,7 @@ require "_helpers"
|
|||
require "input"
|
||||
require "profiler"
|
||||
require "color"
|
||||
require "sound"
|
||||
require "room"
|
||||
require "world"
|
||||
require "world_seed"
|
||||
|
|
@ -26,6 +27,13 @@ narrator = require "narrator.narrator"
|
|||
startSignBook = require "stories.start_sign"
|
||||
jorgeBook = require "stories.jorge"
|
||||
|
||||
-- DEV/DEBUG mode. When on, the level editor is available and rooms with no
|
||||
-- player copy present still render every channel, so whole levels stay visible
|
||||
-- instead of a black screen. Turn it off for a player-facing build; both the
|
||||
-- editor and that all-channels fallback then disappear. Override at launch with
|
||||
-- the DEBUG env var (DEBUG=0 to force off, DEBUG=1 to force on).
|
||||
DEBUG = os.getenv("DEBUG") ~= "0"
|
||||
|
||||
function love.load()
|
||||
globalAssetProperties = {} -- rebuilt from the filesystem (art/ + .meta) by getAllAssets
|
||||
|
||||
|
|
@ -95,9 +103,9 @@ function love.draw()
|
|||
love.graphics.setCanvas(gameCanvas)
|
||||
love.graphics.clear()
|
||||
love.graphics.setBlendMode("screen")
|
||||
if editorView == "world" then
|
||||
if DEBUG and editorView == "world" then
|
||||
gameWorld:draw()
|
||||
elseif editorView == "wire" then
|
||||
elseif DEBUG and editorView == "wire" then
|
||||
gameWorld:drawWireEditor(wireEditorCamera())
|
||||
else
|
||||
currentRoom:draw()
|
||||
|
|
@ -127,7 +135,9 @@ function love.draw()
|
|||
-- Render the sidebar at native panel resolution: the canvas is panel-sized,
|
||||
-- and editorDraw works in the fixed virtual space, scaled up by a transform.
|
||||
-- Blitting the canvas 1:1 afterwards means no rescaling of the final image
|
||||
-- (crisp, nearest-neighbor throughout — nothing is averaged).
|
||||
-- (crisp, nearest-neighbor throughout — nothing is averaged). The editor is a
|
||||
-- DEBUG-only surface, so skip the whole panel in a player-facing build.
|
||||
if DEBUG then
|
||||
love.graphics.setCanvas(sideBarCanvas)
|
||||
-- The gameplay view now intentionally extends beyond its old room bounds.
|
||||
-- Keep the editor panel opaque so that neighbourhood preview never shows
|
||||
|
|
@ -138,6 +148,7 @@ function love.draw()
|
|||
editorDraw()
|
||||
love.graphics.pop()
|
||||
love.graphics.setCanvas()
|
||||
end
|
||||
|
||||
-- Collect every visible layer before the accessibility pass. Applying the
|
||||
-- shader here also covers the editor sidebar, FPS display, and dialogue,
|
||||
|
|
@ -147,7 +158,7 @@ function love.draw()
|
|||
love.graphics.setBlendMode("alpha")
|
||||
love.graphics.setColor(1, 1, 1, 1)
|
||||
love.graphics.draw(finalCanvas, 0, 0)
|
||||
love.graphics.draw(sideBarCanvas, sideBarBox.x, sideBarBox.y)
|
||||
if DEBUG then love.graphics.draw(sideBarCanvas, sideBarBox.x, sideBarBox.y) end
|
||||
love.graphics.print("Current FPS: "..tostring(love.timer.getFPS( )), 10, 10)
|
||||
PerfProfiler:draw()
|
||||
Dialogue.draw()
|
||||
|
|
@ -208,6 +219,9 @@ function love.keypressed(key)
|
|||
-- worldSha = worldSha - 1
|
||||
-- end
|
||||
|
||||
-- Editor text-field controls (room-name entry etc.): DEBUG-only.
|
||||
if not DEBUG then return end
|
||||
|
||||
if key == "return" then
|
||||
response = ""
|
||||
editorCompleteResponse()
|
||||
|
|
@ -225,24 +239,31 @@ function love.keypressed(key)
|
|||
end
|
||||
end
|
||||
|
||||
-- Every mouse/text callback below only ever drives the editor, so they are
|
||||
-- inert outside DEBUG: a player-facing build is keyboard-only.
|
||||
function love.mousepressed(x, y, button)
|
||||
if not DEBUG then return end
|
||||
editorMouseHandler(x, y, button)
|
||||
end
|
||||
|
||||
function love.mousemoved(x, y)
|
||||
if not DEBUG then return end
|
||||
editorMouseMoved(x, y)
|
||||
end
|
||||
|
||||
function love.mousereleased(x, y, button)
|
||||
if not DEBUG then return end
|
||||
editorMouseReleased(x, y, button)
|
||||
end
|
||||
|
||||
function love.textinput(t)
|
||||
if not DEBUG then return end
|
||||
response = response .. t
|
||||
editorTextHandler(response)
|
||||
end
|
||||
|
||||
function love.wheelmoved(dx, dy)
|
||||
if not DEBUG then return end
|
||||
-- Scroll the editor's asset/folder list when the cursor is over the sidebar.
|
||||
if editorView == "room" and love.mouse.getX() > width then
|
||||
editorScrollRoomList(dy)
|
||||
|
|
@ -358,6 +379,8 @@ function cycleAccessibilityMode()
|
|||
end
|
||||
|
||||
function _initSounds()
|
||||
Sound.init()
|
||||
|
||||
staticWave = sfxr.newSound()
|
||||
staticWave.waveform = sfxr.WAVEFORM.NOISE -- was `wavetype = 3`; field renamed in this sfxr
|
||||
staticWave.frequency.start = .1
|
||||
|
|
|
|||
5
room.lua
5
room.lua
|
|
@ -140,6 +140,9 @@ function Room:getRenderChannels()
|
|||
for _, color in ipairs({"red", "green", "blue"}) do
|
||||
if self.player[color] then table.insert(channels, color) end
|
||||
end
|
||||
-- No player copy lives here, so the view would be black. In debug/dev mode
|
||||
-- render every channel instead, letting whole (player-less) levels be seen.
|
||||
if #channels == 0 and DEBUG then return {"red", "green", "blue"} end
|
||||
return channels
|
||||
end
|
||||
|
||||
|
|
@ -456,6 +459,7 @@ function Room:movePlayerLocal(key)
|
|||
end
|
||||
|
||||
if moved then
|
||||
if Sound then Sound.play("playerMove") end
|
||||
if useWorld then gameWorld:playerJoinCheck(self, previousPositions, newPositions)
|
||||
else self:playerJoinCheck(previousPositions, newPositions) end
|
||||
self:tick()
|
||||
|
|
@ -1119,6 +1123,7 @@ function nextRoom(pos)
|
|||
|
||||
local currentName = currentRoom.name
|
||||
local nextName = gameWorld and currentName and gameWorld:getNeighbor(currentName, exit)
|
||||
if Sound and nextName and nextName ~= currentName then Sound.play("levelChange") end
|
||||
currentRoom:save()
|
||||
|
||||
-- Missing map neighbours intentionally wrap back into the room just exited.
|
||||
|
|
|
|||
47
sound.lua
Normal file
47
sound.lua
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
-- Central sound-effect registry. One preloaded Source per named effect; the game
|
||||
-- calls Sound.play("name") to (re)trigger it. Ambient static + music live in
|
||||
-- main.lua's _initSounds; this covers the one-shot gameplay/UI feedback.
|
||||
--
|
||||
-- Top level does NO audio calls on purpose: requiring this under the test love
|
||||
-- stub (which never runs Sound.init) must be side-effect free. Until Sound.init
|
||||
-- runs, Sound.sfx is empty and Sound.play is a harmless no-op.
|
||||
Sound = {}
|
||||
|
||||
Sound.sfx = {} -- name -> Source
|
||||
Sound.jabbers = {} -- pool of npc chatter Sources, picked at random
|
||||
|
||||
local function load(path)
|
||||
return love.audio.newSource(path, "static")
|
||||
end
|
||||
|
||||
function Sound.init()
|
||||
Sound.sfx = {
|
||||
playerMove = load("sounds/player_move.ogg"),
|
||||
switchFail = load("sounds/switch_fail.wav"),
|
||||
switchSuccess = load("sounds/switch_success.wav"),
|
||||
doorUnlock = load("sounds/door_unlock.ogg"),
|
||||
levelChange = load("sounds/level_change.ogg"),
|
||||
uiButton = load("sounds/ui/button.wav"),
|
||||
}
|
||||
Sound.jabbers = {
|
||||
load("sounds/jabber_1.ogg"),
|
||||
load("sounds/jabber_2.ogg"),
|
||||
}
|
||||
end
|
||||
|
||||
-- Restart-and-play a named effect. A static Source only plays one instance at a
|
||||
-- time, so stopping first makes rapid retriggers (e.g. mashing move) audible.
|
||||
function Sound.play(name)
|
||||
local src = Sound.sfx[name]
|
||||
if not src then return end
|
||||
src:stop()
|
||||
src:play()
|
||||
end
|
||||
|
||||
-- Pick a random npc jabber clip and play it. Used when a Dialogable starts talking.
|
||||
function Sound.jabber()
|
||||
if #Sound.jabbers == 0 then return end
|
||||
local src = Sound.jabbers[love.math.random(#Sound.jabbers)]
|
||||
src:stop()
|
||||
src:play()
|
||||
end
|
||||
|
|
@ -707,6 +707,7 @@ function World:movePlayer(room, key)
|
|||
current[color] = player:getGridPos()
|
||||
end
|
||||
if moved then
|
||||
if Sound then Sound.play("playerMove") end
|
||||
self:markDirty(room)
|
||||
self:playerJoinCheck(room, previous, current)
|
||||
self:tick(room)
|
||||
|
|
@ -811,6 +812,7 @@ function World:nextRoom(room, pos)
|
|||
elseif pos.y > gridHeight then exit, entry.y = "bottom", 1
|
||||
elseif pos.y < 1 then exit, entry.y = "top", gridHeight end
|
||||
local nextName = self:getNeighbor(room.name, exit) or room.name
|
||||
if Sound and nextName ~= room.name then Sound.play("levelChange") end
|
||||
local sourceLocation = self:roomLocation(room.name)
|
||||
local destinationLocation = self:roomLocation(nextName)
|
||||
local activeColors = room:getActiveColors()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue