Fixed quitting playstate

This commit is contained in:
entar 2025-05-31 15:22:04 +07:00
parent 94bac4afaa
commit 85f50b2537
2 changed files with 308 additions and 274 deletions

View File

@ -38,6 +38,7 @@ function love.update(dt)
curState = state(curSong, curDiff)
curState.quit = function()
curState = nil
stateLoaded = false
myTypes.destroyAllSprites()
end
curState.load()

View File

@ -1,324 +1,357 @@
return function(songName, songDifficulty)
local state = {}
local state = {} -- Returns needed functions for the state to work after loading it properly
local Height = 0
local Width = 0
-- I NEED THEM IMPORTS
local myMath = require("modules.math")
local myTypes = require("modules.types")
local conductor = require("modules.conductor")
local json = require("modules.json")
local files = require("modules.files")
local logger = require("modules.logging")
local socket = require("socket")
local logging= require("modules.logging")
-- I NEED THEM IMPORTS
local myMath = require("modules.math")
local myTypes = require("modules.types")
local conductor = require("modules.conductor")
local json = require("modules.json")
local files = require("modules.files")
local logger = require("modules.logging")
local socket = require("socket")
local logging= require("modules.logging")
local startTime = 0
local newVector2 = myTypes.Vector2(10, 10)
local chartString = files.read_file(string.format("charts/%s/%s-%s.json", songName, songName, songDifficulty))
if not chartString then
error("Chart couldn't be loaded!")
end
local startTime = 0
local chart = json.parse(chartString).song
local chartString = files.read_file(string.format("charts/%s/%s-%s.json", songName, songName, songDifficulty))
local inst = love.audio.newSource(string.format("songs/%s/Inst.ogg", chart.song), "stream")
local voices = love.audio.newSource(string.format("songs/%s/Voices.ogg", chart.song), "stream")
if not chartString then
error("Chart couldn't be loaded!")
end
local chart = json.parse(chartString).song
local miss = love.audio.newSource("sounds/missnote1.ogg", "static")
local inst = love.audio.newSource(string.format("songs/%s/Inst.ogg", chart.song), "stream")
local voices = love.audio.newSource(string.format("songs/%s/Voices.ogg", chart.song), "stream")
local miss = love.audio.newSource("sounds/missnote1.ogg", "static")
conductor:setBpm(chart.bpm)
conductor:mapBpmChanges(chart)
conductor:setBpm(chart.bpm)
conductor:mapBpmChanges(chart)
local step = 0
local beat = 0
local step = 0
local beat = 0
local zoom = 1
local playing = false
local playing = false
local characters = {}
local stage = json.parse(files.read_file("stages/stage.json"))
local unspawnedNotes = {}
local notes = {}
local stage = json.parse(files.read_file("stages/stage.json"))
local directions = {
"LEFT",
"DOWN",
"UP",
"RIGHT"
}
local unspawnedNotes = {}
local notes = {}
local pressed = {
false,
false,
false,
false
}
local holded = {
false,
false,
false,
false
}
local characters = {}
local receptors = {
}
local directions = {
"LEFT",
"DOWN",
"UP",
"RIGHT"
}
local keyBinds = {}
local pressed = {
false,
false,
false,
false,
false
}
local holded = {
false,
false,
false,
false
}
local function quit()
inst:stop()
inst:release()
local receptors = {}
voices:stop()
voices:release()
local keyBinds = {} -- loaded from settings.json, if anything's wrong then check your settings.json
miss:stop()
miss:release()
local paused = false
state.quit()
end
local pauseTime = 0 -- the global amount of time the song has been paused
local pauseStart = 0 -- the start of the latest pause (for pauseTime calculation)
local zoom = 1
local function quit()
playing = false
local function checkNote(dir)
if pressed[dir] or holded[dir] then
pressed[dir] = false
holded[dir] = true
if receptors[dir].animation ~= string.lower(directions[dir]).." confirm" then
receptors[dir]:PlayAnimation(string.lower(directions[dir]).." press", 25, false)
end
return -- You dont check if you are already holding and not just pressing
end
pressed[dir] = true
for index, note in next, notes do
if note.position - conductor.songPosition < 200 then
if note.mustPress and not note.pressed and note.direction == dir then
characters.bf:PlayAnimation("sing"..directions[note.direction])
note.pressed = true
receptors[dir]:PlayAnimation(string.lower(directions[dir]).." confirm", 25, false)
table.remove(notes, index)
note:destroy()
end
end
end
end
inst:stop()
inst:release()
inst = nil
local elapsed = 0
voices:stop()
voices:release()
voices = nil
function state.update(dt)
if not playing then return end
miss:stop()
miss:release()
local currentTime = socket.gettime()
state.quit()
end
elapsed = (currentTime - startTime) * 1000
conductor.songPosition = elapsed
local oldStep = step
local oldBeat = beat
step = conductor:getStepRounded(elapsed)
beat = conductor:getBeatRounded(elapsed)
if beat ~= oldBeat then
if beat % 2 == 0 then
-- gf:PlayAnimation("BF NOTE LEFT", 30, false)
for name, character in next, characters do
if not character.singing then
if name == "gf" then
if beat % character.beats == 0 then
character:PlayAnimation("danceLeft")
end
else
character:PlayAnimation("idle")
end
end
end
if beat % 4 == 0 then
zoom = zoom + .1
local function checkNote(dir)
if pressed[dir] or holded[dir] then
pressed[dir] = false
holded[dir] = true
if receptors[dir].animation ~= string.lower(directions[dir]).." confirm" then
receptors[dir]:PlayAnimation(string.lower(directions[dir]).." press", 25, false)
end
return -- You dont check if you are already holding and not just pressing
end
pressed[dir] = true
for index, note in next, notes do
if note.position - conductor.songPosition < 200 then
if note.mustPress and not note.pressed and note.direction == dir then
characters.bf:PlayAnimation("sing"..directions[note.direction])
note.pressed = true
receptors[dir]:PlayAnimation(string.lower(directions[dir]).." confirm", 25, false)
table.remove(notes, index)
note:destroy()
end
end
end
end
local section = chart.notes[math.floor(step / 16) + 1]
if section.mustHitSection then
myTypes.cameraTarget = myTypes.Vector2(-stage.camera_boyfriend[1], -stage.camera_boyfriend[2]):Add(characters.bf.stageCamera:Negate()):Add(myTypes.Vector2(0, -200))
else
myTypes.cameraTarget = myTypes.Vector2(stage.camera_opponent[1], stage.camera_opponent[2]):Add(characters.dad.stageCamera:Negate()):Add(myTypes.Vector2(0, -200))
end
myTypes.updateSprites(dt)
if love.keyboard.isDown(keyBinds[1]) then
checkNote(1)
else
holded[1] = false
pressed[1] = false
end
if love.keyboard.isDown(keyBinds[2]) then
checkNote(2)
else
holded[2] = false
pressed[2] = false
end
if love.keyboard.isDown(keyBinds[3]) then
checkNote(3)
else
holded[3] = false
pressed[3] = false
end
if love.keyboard.isDown(keyBinds[4]) then
checkNote(4)
else
holded[4] = false
pressed[4] = false
end
if love.keyboard.isDown("escape") then
state.quit()
end
for index, note in next, notes do
if note.position - conductor.songPosition < 0 then
if note.mustPress then
note:destroy()
miss:stop()
miss:play()
characters.bf:PlayAnimation("sing"..directions[note.direction].."miss")
table.remove(notes, index)
end
end
end
for name, character in next, characters do
if name ~= "gf" and character.sprite.animation ~= "idle" and character.sprite.ended then
character:PlayAnimation("idle")
end
end
for index, note in next, unspawnedNotes do
if note.position - elapsed < 600 and note.mustPress then
note:spawn()
table.remove(unspawnedNotes, index)
table.insert(notes, note)
elseif note.position - elapsed < 600 and not note.mustPress then
table.remove(unspawnedNotes, index)
table.insert(notes, note)
end
end
for index, note in next, notes do
if note.spawned then
note.sprite.position = myTypes.Vector2(400 + 65 * (note.direction - 1), note.position - elapsed - 100)
if note.position - elapsed < -150 then
note:destroy()
table.remove(notes, index)
end
else
if note.position - elapsed < 50 then
table.remove(notes, index)
if section.altAnim or note.altAnim then
characters.dad:PlayAnimation("sing"..directions[note.direction].."-alt")
else
characters.dad:PlayAnimation("sing"..directions[note.direction])
end
note = nil
end
end
end
for index, receptor in next, receptors do
if receptor.ended and receptor.animation ~= "arrow"..directions[index] and receptor.animation ~= "" then
receptor:PlayAnimation("arrow"..directions[index], 25, false)
end
end
if not inst:isPlaying() then
state.quit()
end
zoom = myMath.lerp(zoom, 1, .05)
end
local mainCanvas = love.graphics.newCanvas(1920, 1080)
function state.draw()
love.graphics.setCanvas(mainCanvas)
love.graphics.clear()
love.graphics.circle("fill", 960, 59, 50000)
myTypes.drawSprites()
love.graphics.setCanvas()
love.graphics.draw(mainCanvas, (love.graphics:getHeight() * (4/3) - (love.graphics:getHeight()* (4/3)) * zoom) / 2, (love.graphics:getHeight()- love.graphics:getHeight() * zoom) / 2, 0, ((love.graphics:getHeight() / 1080) * (4/3)) * zoom, (love.graphics:getHeight() / 1080) * zoom)
end
love.window.setMode(1280, 720, { fullscreen = false , resizable = true})
function state.load()
-- GF first so she is below other chars
if chart.gfVersion ~= "none" then
characters.gf = myTypes.character(chart.gfVersion)
characters.gf.stagePosition = myTypes.Vector2(stage.girlfriend[1], stage.girlfriend[2])
end
characters.bf = myTypes.character(chart.player1)
characters.bf.stagePosition = myTypes.Vector2(stage.boyfriend[1], stage.boyfriend[2])
local elapsed = 0
characters.dad = myTypes.character(chart.player2)
characters.dad.stagePosition = myTypes.Vector2(stage.opponent[1], stage.opponent[2])
function state.update(dt)
if not playing then return end
-- playing isn't supposed to work like "paused", it's there to keep the game from working during loading
for index, section in next, chart.notes do
for index, note in next, section.sectionNotes do
local newNote = myTypes.note(note, section.mustHitSection)
table.insert(unspawnedNotes, newNote)
if love.keyboard.isDown(keyBinds[1]) then
checkNote(1)
else
holded[1] = false
pressed[1] = false
end
if love.keyboard.isDown(keyBinds[2]) then
checkNote(2)
else
holded[2] = false
pressed[2] = false
end
if love.keyboard.isDown(keyBinds[3]) then
checkNote(3)
else
holded[3] = false
pressed[3] = false
end
if love.keyboard.isDown(keyBinds[4]) then
checkNote(4)
else
holded[4] = false
pressed[4] = false
end
if love.keyboard.isDown("escape") then
quit()
end
if love.keyboard.isDown("space") then
if pressed[5] then goto evilContinue end
pressed[5] = true
paused = not paused
if paused then
inst:pause()
voices:pause()
pauseStart = socket.gettime() * 1000
else
inst:play()
voices:play()
pauseTime = pauseTime + (socket.gettime() * 1000 - pauseStart)
end
::evilContinue::
else
pressed[5] = false
end
if paused then goto continue end -- if paused then skip this cycle
local currentTime = socket.gettime()
elapsed = (currentTime - startTime) * 1000 - pauseTime
conductor.songPosition = elapsed
local oldStep = step
local oldBeat = beat
step = conductor:getStepRounded(elapsed)
beat = conductor:getBeatRounded(elapsed)
if beat ~= oldBeat then
if beat % 2 == 0 then
-- gf:PlayAnimation("BF NOTE LEFT", 30, false)
for name, character in next, characters do
if not character.singing then
if name == "gf" then
if beat % character.beats == 0 then
character:PlayAnimation("danceLeft")
end
else
character:PlayAnimation("idle")
end
end
end
if beat % 4 == 0 then
zoom = zoom + .1
end
end
end
local section = chart.notes[math.floor(step / 16) + 1]
if section.mustHitSection then
myTypes.cameraTarget = myTypes.Vector2(-stage.camera_boyfriend[1], -stage.camera_boyfriend[2]):Add(characters.bf.stageCamera:Negate()):Add(myTypes.Vector2(0, -200))
else
myTypes.cameraTarget = myTypes.Vector2(stage.camera_opponent[1], stage.camera_opponent[2]):Add(characters.dad.stageCamera:Negate()):Add(myTypes.Vector2(0, -200))
end
myTypes.updateSprites(dt)
for index, note in next, notes do
if note.position - conductor.songPosition < 0 then
if note.mustPress then
note:destroy()
miss:stop()
miss:play()
characters.bf:PlayAnimation("sing"..directions[note.direction].."miss")
table.remove(notes, index)
end
end
end
for name, character in next, characters do
if name ~= "gf" and character.sprite.animation ~= "idle" and character.sprite.ended then
character:PlayAnimation("idle")
end
end
for index, note in next, unspawnedNotes do
if note.position - elapsed < 600 and note.mustPress then
note:spawn()
table.remove(unspawnedNotes, index)
table.insert(notes, note)
elseif note.position - elapsed < 600 and not note.mustPress then
table.remove(unspawnedNotes, index)
table.insert(notes, note)
end
end
for index, note in next, notes do
if note.spawned then
note.sprite.position = myTypes.Vector2(400 + 65 * (note.direction - 1), note.position - elapsed - 100)
if note.position - elapsed < -150 then
note:destroy()
table.remove(notes, index)
end
else
if note.position - elapsed < 50 then
table.remove(notes, index)
if section.altAnim or note.altAnim then
characters.dad:PlayAnimation("sing"..directions[note.direction].."-alt")
else
characters.dad:PlayAnimation("sing"..directions[note.direction])
end
note = nil
end
end
end
for index, receptor in next, receptors do
if receptor.ended and receptor.animation ~= "arrow"..directions[index] and receptor.animation ~= "" then
receptor:PlayAnimation("arrow"..directions[index], 25, false)
end
end
if inst and not inst:isPlaying() then
quit()
end
zoom = myMath.lerp(zoom, 1, .05)
::continue::
end
for i = 0, 3 do
local receptor = myTypes.Sprite("sprites/NOTE_assets.png", "sprites/NOTE_assets.json", false)
receptor:PlayAnimation("arrow"..directions[i+1], 25, false)
local mainCanvas = love.graphics.newCanvas(1920, 1080)
receptor.position = myTypes.Vector2(400 + (65 * i), 0)
function state.draw()
receptor.ui = true -- So it doesnt move with the camera.
love.graphics.setCanvas(mainCanvas)
receptors[i + 1] = receptor
end
state.loaded = true
love.graphics.clear()
myTypes.cameraTarget = myTypes.Vector2()
love.graphics.circle("fill", 960, 59, 50000)
myTypes.drawSprites()
love.graphics.setCanvas()
love.graphics.draw(mainCanvas, (love.graphics:getHeight() * (4/3) - (love.graphics:getHeight()* (4/3)) * zoom) / 2, (love.graphics:getHeight()- love.graphics:getHeight() * zoom) / 2, 0, ((love.graphics:getHeight() / 1080) * (4/3)) * zoom, (love.graphics:getHeight() / 1080) * zoom)
local settings = json.parse(files.read_file("settings.json"))
if not settings then
error("Failed to load settings")
end
keyBinds = settings.Keybinds
love.window.setMode(1280, 720, { fullscreen = false , resizable = true})
end
function state.load()
-- GF first so she is below other chars
if chart.gfVersion ~= "none" then
characters.gf = myTypes.character(chart.gfVersion)
characters.gf.stagePosition = myTypes.Vector2(stage.girlfriend[1], stage.girlfriend[2])
end
function state.finish()
inst:play()
voices:play()
characters.bf = myTypes.character(chart.player1)
characters.bf.stagePosition = myTypes.Vector2(stage.boyfriend[1], stage.boyfriend[2])
while not inst:isPlaying() do
end --waiting till the song actually plays.
characters.dad = myTypes.character(chart.player2)
characters.dad.stagePosition = myTypes.Vector2(stage.opponent[1], stage.opponent[2])
elapsed = 0
playing = true
for index, section in next, chart.notes do
for index, note in next, section.sectionNotes do
local newNote = myTypes.note(note, section.mustHitSection)
table.insert(unspawnedNotes, newNote)
end
end
startTime = socket.gettime()
end
for i = 0, 3 do
local receptor = myTypes.Sprite("sprites/NOTE_assets.png", "sprites/NOTE_assets.json")
receptor:PlayAnimation("arrow"..directions[i+1], 25, false)
return state
receptor.position = myTypes.Vector2(400 + (65 * i), 0)
receptor.ui = true -- So it doesnt move with the camera.
receptors[i + 1] = receptor
end
state.loaded = true
myTypes.cameraTarget = myTypes.Vector2()
local settings = json.parse(files.read_file("settings.json"))
if not settings then
error("Failed to load settings")
end
keyBinds = settings.Keybinds
end
function state.finish()
inst:play()
voices:play()
while not inst:isPlaying() do
end --waiting till the song actually plays.
elapsed = 0
playing = true
startTime = socket.gettime()
end
return state
end