increpare / PuzzleScript

Open Source HTML5 Puzzle Game Engine
MIT License
903 stars 160 forks source link

Safari 12: Audio played during again turns doesn't play until audio is played in another way first #491

Closed chz16 closed 3 years ago

chz16 commented 6 years ago

Safari 12 has new audio autoplay restrictions, similar to Chrome (see #419 / #438), that seem to have caused this thing.

The intro of my game Maera no longer plays sound: there should be some loud whooshes when the water level lowers and a click when the door opens. Once you get into the tutorial level and drop down the first rope, every single one of those noises all play at the same time, and then sound works normally.

I haven't looked at the engine source so this is only a guess, but it seems like what may be happening is that the audio context isn't being resumed before playing any of the sounds in the intro cutscene levels, which all happen through again turns without any user input. If I add a StartGame sound to play a noise when you hit play, then the cutscene works fine. And sound caused by direct player inputs in levels seem to work fine too; the problem only seems to occur specifically for again turns.

chz16 commented 6 years ago

Update on this based on what I've learned fixing my own games:

It seems that, in order to authorize an audio context for playback whenever, you need to "activate" it (either by .resume() or playing something through it) during a handler explicitly called by a user input. I've only personally tested mouse events in my own code but keyboard events seem to work too in others' games.

The important part is that the activation itself has to be in a user input handler. So one of my games was doing this:

  1. Clicking on the game starts async loading the graphics
  2. The load callback on the final image starts async loading the sound effects
  3. The load callback on the final sound effect sets up the audio context

This didn't work because, while the whole process was started by user input, the audio context was being activated inside a loading handler and not a user input handler. When I had the click handler set up the audio context and then just save it for later, everything worked fine.

So, this is all speculation from this point, because I don't know what the PuzzleScript engine is doing, but:

If the engine is processing again turns through either a .requestAnimationFrame() game loop or a .setTimeout()/.setInterval() callback, then that won't satisfy Safari because the sounds aren't being played during a user input handler. It works once the context has been activated through a direct user input, but it doesn't suffice to activate the context on its own.

IF that's a correct diagnosis of the problem, then my suggestion would be to activate the audio context in the main menu when the player selects either start or continue, since that's a required user input. Just making sure the audio context exists and calling .resume() on it would probably work.

increpare commented 3 years ago

Getting around to looking at this, it seems to work ok now? I feel like everything's gotten patched up since I last looked at this report.

(Apologies for not replying sooner...)

increpare commented 3 years ago

(I'll reopen if it's still an issue)

chz16 commented 3 years ago

Unfortunately still doesn't work for me in the latest version of Safari (14.0.3). Made a very simple test case; for me this plays a sound when the level starts in Firefox and Chrome, but in Safari the sound is delayed until you move, after which it works fine if you escape back to the menu and restart the game (until you reload the page): https://www.puzzlescript.net/play.html?p=04a3d63650b56b08115db8b006794131

increpare commented 3 years ago

Ah indeed. Can repro. I'm on it ^^

increpare commented 3 years ago

I think it's good now? (you may need to hit reload)

chz16 commented 3 years ago

Yep, audio plays at level start for me too! 👍

increpare commented 3 years ago

Thanks for checking!

<3 S