Page 1 of 1

WIP rhythm game's audio bugs out when reading from JSON?

Posted: Fri Mar 19, 2021 10:03 pm
by RAYTRAC3R
Hello! I'm currently working on one of my first games, a rhythm game. I haven't implemented actual gameplay yet, but right now I have an early version of the main menu, and I'm trying to implement an early version of the level loader. I want to make it possible to make custom levels later down the line, so each level is going to be formatted as a json file.

I've gotten the menu to automatically add buttons for new levels added to the songlist file, but whenever I try to enter a level, it plays a distorted version of one specific song, no matter what level I choose. Obviously, each level is supposed to have it's own song, so it should be playing a non-distorted version of each level's respective song. I'm pretty sure it's reading the json file incorrectly, but I barely have any idea what exactly is going wrong.

This is the main section of the code that I think is the problem:

Code: Select all

function danzsongs.enter()

	buttons = {}
	
	for i,k in ipairs(songList) do
		songFile = json.decode(love.filesystem.read(k["Song"]))
		for j,l in ipairs(songFile) do
			buttonTitle = l["songName"]
			songlevel = l["songWav"]
			songBPM = l["songBPM"]
			songOffset = l["songOffset"]
		end
		table.insert(buttons, newButton(
			buttonTitle,
			function()
				print("Starting game")
				love.audio.stop()
				Gamestate.switch(levelface)
				songlevel = songlevel
				songBPM = songBPM
				songCrochet = 60 / songBPM
				songOffset = songOffset
			end))
	end

	table.insert(buttons, newButton(
		"Back",
		function()
			love.audio.stop( )
			Gamestate.switch(menu)
		end))
end

function levelface.draw()
	buttons = {}
	love.graphics.setColor(0.9, 0.8, 0.85, 1.0)
	local tracker = {50, 400, 75, 550, 750, 550, 750, 400}
	love.graphics.polygon('line', tracker)
	levelsong = love.audio.newSource(songlevel, "stream")
	love.audio.play(levelsong)
	songPosition = levelsong:tell("seconds")
	love.graphics.print(
			songPosition,
			font,
			10,
			10
			)
end
I've included the full source code as an attachment. Anyone have any idea what mistake I've made?

EDIT: Uploaded the source code to Github in case people don't want to bother downloading
https://github.com/RAYTRAC3R/DANZ/

EDIT 2: Managed to fix the distortion with help from a user in the Discord, I accidentally set the song source under levelface.draw() rather than levelface.enter()
It still seems to play the wrong song. It always plays the last song in the songlist file.

Re: WIP rhythm game's audio bugs out when reading from JSON?

Posted: Sat Mar 20, 2021 2:51 am
by pgimeno
There seems to be an abuse of globals, and that's part of the problem. The button function does this:

Code: Select all

songlevel = songlevel
but that does basically nothing. The songlevel global variable will retain the last value it was set to, that's why it plays the last loaded level.

As for how to solve it, well, one idea would be to pass the button itself to the button function, and have metadata in the button table.

For example, create the buttons like this:

Code: Select all

function newButton(text, fn, data)
        return {
                text = text,
                fn = fn,
                data = data,

                now = false,
                last = false
        }
end

...

        for i,k in ipairs(songList) do
                songFile = json.decode(love.filesystem.read(k["Song"]))

                local data = {}

                for j,l in ipairs(songFile) do
                        buttonTitle = l["songName"]
                        data.songWav = l["songWav"]
                        data.songBPM = l["songBPM"]
                        data.songOffset = l["songOffset"]
                end
               table.insert(buttons, newButton(
                        buttonTitle,
                        function(self)
                                love.audio.stop()
                                songlevel = self.data.songWav
                                songBPM = self.data.songBPM
                                songCrochet = 60 / songBPM
                                songOffset = self.data.songOffset
                                Gamestate.switch(levelface)
                        end,
                        data))
        end
And call the function like this:

Code: Select all

                        button.fn(button)
or equivalently, with:

Code: Select all

                        button:fn()