Excerpts from WEB-build and Itch.io deploy of CGE Project journey

Following the topic of my game Tower Fight, Samurai Arcade for testing math Skills - #4 by michalis

and stealing a good topic naming from topic Excerpts from the Shooter development journey :) - #14 by hal09

Here what I have to say. First about the hard parts, the next post in this topic - for requests on WEB platform.

  1. Do not use MessageYesNo and probably all other dialogs/dialog functions from CastleMessages unit, they contain Blocking of app flow with Application.ProcessMessages, also don’t use ProcessMessages itself, it hangs the Web-page, you even have troubles to close the page. I was using it for sample questions to the user, but had to switch to my custom view-based dialog approach: Remade messagedialog to custom one · phomm/Towerfight@cf6f623 · GitHub
  2. Do not use Keyboard key like Escape, Space, Tab, PgUp, PgDn, maybe even arrow keys, they switch the focus of html-canvas or scroll the page, which makes playing uncomfortable, I knew about Escape, but others I had myself to bump into :sweat_smile:, for example I added a Backspace to duplicate “exiting” function, which on desktop is done by Escape
  3. Use ApplicationProperties.ShowUserInterfaceToQuit from CastleApplicationProperties unit everywhere you can to hide various controls, it make sense not only on mobile, but web as well, I use it to disable Exit button and corresponding controls, also Fullscreen selector, as on Web it is controlled outside: by canvas.requestFullScreen if you use castle standard html-template, or by Itch special fullscreen button, if you post game to itch.
  4. I have a thing that bothers me on Android build, you need to disable orientation-lock to be able to rotate cge-window to landscape. But if you post the game to itch , there is a setting to setup landscape-always, which works even in mobile browser and you don’t need to disable lock.
  5. The standard html-template of cge-web project is not compatible with itch (iframe shows only part of canvas, and in itch-fullscreen-mode the button from castle html template for fullscreen isn’t working), I had to adjust the template, I think @michalis would add such a template as an option. The changes you need - remove the style attribute from canvas element, comment/remove all other elements (button and hrefs), except canvas, bc they could capture the focus from canvas and break the gameplay. Itch kinda requires bare canvas for 100% of iframe and controls fullscreen by its own mechanism and button. for this you need CSS (separate or embedded into style attribute) :
  6. #castle-canvas {
    position:fixed;
    left:0;
    top:0;
    width:100%;
    height:100%;
    }
2 Likes

What I wanted to discuss/request for web platform :slight_smile:

obviously I wait WebAudio :sweat_smile: as a game without it is really different as designed

Also would be nice to have UserConfig flow to store basic settings in user’s storage in browser

My personal (maybe not so important for other devs) is TCastleDownload, because one of soon to be implemented features for the web-game is leaderboard based on server and requests from game-app

As a lazy programmer, I’m always down for automations and really love CI templates provided by Castle to automatically build and publish artifacts to castle releases, and I use this feature for both my games. And even more - I have a custom step in pipeline to upload artifact to google drive. So AFAIK, Itch supports automation, and uploading new build is doable thru the pipeline, which I would love to have. But as I know it is not yet fully prepared in CI template (as requires updating docker image with crossfpc and pas2js). Would be cool to have it eventually.

Those are my expectations/favorites :sweat_smile: Let’s maybe discuss :slight_smile:

From my side - I’m not a JS developer (i’m a .net backend), however I have some experience with JS, and I think with the help of AI something could be achieved. Or , for example the Docker part seems doable to me, as I work with docker from time to time, and also building fpc stuff from sources sometimes.

1 Like

Indeed, on web Application.ProcessMessages will not work, and routines relying on it, like MessageYesNo will also fail.

This is the same situation as with iOS known problems.

Note that you can still use our dialogs, by using views:

  • You can use unit CastleDialogViews (which define views, which are the underlying things inside MessageXxx) and create related views yourself. Like this:
var
  Dlg: TViewDialogOK;
begin
  // open new view with dialog
  Dlg := TViewDialogOK.Create(Self);
  Dlg.Caption := 'Some content to display';
  Container.PushView(Dlg);
end;

This is what e.g. castle-model-viewer-mobile uses, and it works on iOS and web too.

  • You can set MessageOKPushesView to actually make MessageOK(...) do something like above. But naturally it cannot work for routines like MessagesYesNo, so my simpler advise for iOS and web is just to not use CastleMessages unit at all, and not use MessageXxx at all.

Basically, I confirm your advise :slight_smile: I will update known limitations section in “web” docs shortly.

Indeed, browsers capture various keys for their purpose. Our control still receives (some) of them, but the UX is bad when both our game and the browser do some action on these keys.

As above: I will update known limitations section in “web” docs shortly.

Also confirmed :slight_smile: ShowUserInterfaceToQuit is false on web and one should honor it, by not showing the UX (buttons etc.) to user to “Quit” the application, since on web → there’s no quit, users just close their tab / browser window etc.

Hm, you mean in a web browser on Android? There is a way to request that full-screen is forced to landscape? Thank you – added to TODO, we should find it and use too. We could then make screen_orientation from manifest work on web too, so using screen_orientation="landscape" would work on the web.

Thank you – we should indeed introduce some way to provide custom templates, and maybe just provide a ready template to do out-of-the-box something proper for itch.io as you show.

Your post is a great reference for people who want to upload their web games on itch.io, thank you!

I have 2 of above, WebAudio and a TCastleDownload-web backend already in progress :slight_smile:

They work – but WebAudio needs review (parts of it have been generated by Claude Code) and TCastleDownload-web needs rework to be cleaner (here also Claude Code helped, but what it did must be now fixed). You will like our next update :), hopefully this weekend.

Indeed, exactly as you say. Itch.io has butler to upload builds from the command-line (so also from any automated work, CI/CD). We use it e.g. to upload platformer to itch.io.

As you say, to use this from CI/CD, we miss easy way to get all web prerequisites (FPC cross-compiler for WebAssembly, pas2js) in a CI runner (ideally, both in our Docker image and in through our castle-build-ci scripts ).

I want to solve it by zipping the prerequisites in castle-fpc releases. Then the “web prerequisites” could be:

  • placed in Docker image,
  • downloaded by castle-build-ci scripts,
  • but also downloaded easily by CGE editor, so that building for web is just “a simple button press from our editor”.

I agree 100% with all your feature requests. I think they actually match perfectly the things I see as “most priority” for web! :slight_smile: So, this makes me happy, we’re going in a good direction.

2 Likes

Looks like JS ScreenOrientation.lock is the key to do this. Mentioned also here (Managing screen orientation). Added to TODO in our web docs.

1 Like

This is my observation. I configured the game config panel (on itch) , among others there is a selector for Forced landscape mode. When I opened the game on Android inside browser in fullscreen mode (via itch fullscreen button), it preserves landscape despite phone setting to enable/disable rotation of orientation.

Great ! Lovely ! I will proceed with my features so maybe even in sync with cge updates :sweat_smile:

1 Like

Done. I added to “Known Limitations” on web notes about Application.ProcessMessage, CastleMessages, keys, and ShowUserInterfaceToQuit.

1 Like

Sorry this is still not finished + merged. I have definitely too many tasks and too little time lately :slight_smile:

I also made similar apology in this PR: I have a big delay, with pretty much everything, in February and in March likely too, due to personal stuff and the need to finish one job in March. I should have a lot more time working on CGE since April 2026, so in ~3 weeks :slight_smile: Bear with me please until then :slight_smile: So I just wanted to make a note that these, WebAudio and TCastleDownload+http on web, is very much on TODO list.

1 Like

@phomm Downloading HTTP(S) on web is almost ready :slight_smile:

You can already try the engine from branch web-download where TCastleDownload on web should work. I noticed one problem (testing examples/network/asynchronous_download/, where 2 downloads seem to go OK, 1 weirdly fails) – will investigate and fix ASAP, to merge this to master.

Note: CORS will prevent our application on web from downloading things from other domains. This is the same problem as all JS application face.

Stay tuned for finishing and merging this. But if you’re brave, you can try it already with your game and let me know how it goes:)

1 Like

Important fix done, and at least basic downloading works correctly!

This is a screenshot of examples/network/asynchronous_download/ from branch web-download. I added to that example also showing MD5 and SHA-256 checksums of the downloaded contents, to I could easily see in the console that indeed they download 100% correct data.

1 Like

Works cool, merging to master – so, we have TCastleDownload on web:)

Below screenshots from:

1 Like

Started checking the changes. Also noted a compilation error in Android, I fixed it and pushing it along with my Android Request error handling fix PR

regarding web requests - a bit later

1 Like

behold ! :rofl:

Here is working workflow for server-side leader board for the game on itch!

The data is loaded fine and also posted properly (“WEB” name of a leader and by luck on the top of leaderboard on easy difficulty, was sent from web-version of game)

technical details: GET and POST requests are used, for POST httpbody with json content and httpHeader ‘Content-Type: application/json’ are included

Thanks a lot, @michalis !

A small side-note, I implemented easily the CORS support on server (as noted by Michalis earlier), with .net it is quite simple. then I just rebuild the docker image from latest master and rerun the container on a server (bc there was a question in game topic about why .net :slight_smile: ). Can be seen in server repo on github

1 Like

Audio playback on the web is also close to being done:)

Right now on branch webaudio (not master).

Initial notes:

Tested on examples:

  • platformer game
    • (SOLVED) though note initial menu music doesn’t play
  • audio/doppler_demo
    • though note TODOs: Doppler effect is not done by WebAudio

Some TODOs before I merge this:

  • (DONE) Playing non-WAV formats (like OggVorbis) right when the buffer was loaded (e.g. playing iniital game music) will fail with Cannot play sound "%s" because it is still decoding. . We must handle this better, start playback once the OggVorbis finished decoding, instead of aborting.

    This causes the “initial menu music doesn’t play” problem for platformer now.

  • (DONE) We use JS promises in naive way but that’s not good: We need to make sure that we cancel the promise (building a mechanism on top of JS to cancel any promise, maybe just ignoring result), as we must cancel a promise if the Pascal instance interested in the promise no longer exists (which may happen e.g. if you switch views before a promise was realized).

    From what I see, various example JS code snippets using promises or async/await have this TODO too :slight_smile: It will not crash in garbage-collected languages, but still may do all sorts of weird things.

    One needs to remember that application keeps working, possibly changing state, while we wait for promise to be delivered. Our WebAudio backend should account for it, to not crash in edge-cases when promises succeed/fail with large delay.

    This affects now decodeAudioData done asynchronously. In theory, you can crash it, changing views fast after staring to load OggVorbis. We should secure from it.

  • (DONE) platformer weird shot.wav playback must be investigated and fixed.

  • (WORKAROUNDED, issue not related to audio) game_3d_sound crashes (for reasons unrelated to audio, it seems?).

  • (DONE) play_sounds crashes.

  • (POSTPONED after merge in the end) Support other audio formats, like MP3. Also FMOD supports them. IOW, we are not limited to WAV / OggVorbis formats on some audio backends, and we should expose more audio formats, just with warning (that they are not cross-platform supported by CGE).

2 Likes

I have tested audio from webaudio branch.

It worked for me with Wav files. unfortunately, as mentioned with Ogg files it was throwing errors (about decoding). Ofc, it would be great to have ogg files support, as wav files make data.zip really bloated, I was thinking that they are at least well compressible, but seems not :slight_smile: it increased the size of data.zip by 3+ times, ~20→~70

I didn’t try MP3, as didn’t want to add more dependencies (FMOD)

What I noticed, that with Wav files (the only option I have), this detail about “preparing” user for audio and not auto-starting sounds right away, it was actually working, sounds started without any need for adjustments. Not sure if it is my browser setup, or wav-specifics, or smth, just noticed.

Also maybe I did smth wrong when I was converting ogg→wav, it resulted in mono-channel sound on web-page(I hear it in headphones), but the file itself is played as stereo (in media-player). I will try to convert with attention to channels details and retry

Indeed. I’ll get OggVorbis working (fix that Cannot play sound "%s" because it is still decoding error) ASAP, hopefully today in the evening :slight_smile:

Note that I think that we can get MP3 support also with WebAudio. So we would have two sound backends supporting MP3 (and other audio formats, beyond Wav and OggVorbis): FMOD and WebAudio,

More possibilities :slight_smile:

Although the recommendation will remain to limit to Wav and OggVorbis, to work with OpenAL + VorbisFile libraries (which we distribute with CGE out-of-the-box, on Windows, as DLLs).

So sound played for you without the need for any clicks? Huh, interesting. It is depending on the browser, and may be per-website.

For me, both latest FireFox and Vivaldi (Chrome-based) did require initial click to play anything.

You can set global LogSoundLoading to true from unit CastleInternalSoundFile to see in the log some details about loaded sounds, in particular whether they are loaded as mono or stereo. Maybe this will help in investigation :slight_smile:

1 Like

I pushed to the webaudio branch more work – I’m close to finishing this :slight_smile:

  • No more Cannot play sound ... because it is still decoding errors, playing OggVorbis works now reliably.
  • Minor sound API improvements: Channels:Cardinal (we are ready for sounds with > 2 channels), more hidden SampleFormat (we are ready for formats decompressed + played without CGE needing to look at them, like more FMOD and WebAudio formats)
  • Using JS promises in safe way, through utilities in CastleInternalWebUtils.
  • Tested mostly on examples/2d_games/platformer/ and examples/audio/play_sounds/ examples.
2 Likes

I Tested the web-build from updated webaudio branch. I removed wav files and kept only ogg.

Tower-fight by phomm same link to the game

It works fine! Tried in incognito on chrome and edge on windows to test it fresh, works without any need of clicking something. Same on incognito chrome on android, works good with music sounding right when app is loaded and menu shown !

I’m happy and grateful, thanks a lot, @michalis !

1 Like

Thank you for testing, I’m happy it’s all good!

And it’s now merged to engine’s master branch:)

Changes since my last post:

  • Fixed WebAudio TCastlePlayingSound.Offset when you change TCastlePlayingSound.Pitch while playback (can be tested with play_sounds example)
  • Fixed WebAudio playback of 8-bit PCM data (play_sounds example has examples)
  • Fix displaying duration of loaded OggVorbis in play_sounds
  • API improvement: TCastleSound.Frequency is now float (both FMOD and WebAudio may report there fractional parts)
  • Docs added to Web Target | Manual | Castle Game Engine
  • examples/audio/game_3d_sound works now (workarounded unrelated rendering issue on web: 16-bit PNG textures don’t work; this will be fixed properly, for now just workarounded as unrelated to sound support)
  • Fixed edge-cases when sound stops playing, we should reliably know about this on engine side now

The page about web target links to ready builds of 2 audio examples (play_sounds, game_3d_sound), also the linked platformer build there is updated – all 3 demos should play audio nicely now.

I left one task post-merge: enabling MP3 and other formats playback on WebAudio and FMOD backends, Since this is kind of “bonus”, and not recommended anyway (for cross-platform apps, stick with Wav and OggVorbis that we guarantee to support everywhere), I’ll tackle it later.

1 Like

For me, your game also plays sound immediately, without the need for any special clicks. Although the audio context is initially suspended (log shows Web Audio context is suspended....) but then it just plays immediately. Something / somehow must resume the audio context in your case magically:)

Maybe the <iframe with allow=autoplay... (I understand this is standard wrapper by itch.io) does the trick?

I’m testing this in FireFox, same browser where e.g. my example platformer requires a click before music is heard.

I guess, kudos to itch.io for wrapping games in HTML that makes it “just work” :slight_smile:

1 Like

Ok, some more time has passed, less intense work on the project bc of job and reality :sweat_smile:

however I was able to prepare new big feature (interactive tutorial) , quite important for future public release.

And here what’s seen from the my progress so far:

1 for this workflow/feature I somewhat rely on the Castle User Config feature, bc I save the fact of completing tutorial to the device-stored-config (same as with sound volume level and others, but those are not so critical for UX), and leaving the implementation as is will bring inconvenience, as every page restart would propose to run tutorial again. For now I’ve overcome this by assigning triggering tutorial to other button than main-game-start-button (this will allow to start game normally, not bumping into tutorial every time page reloaded, but still some users will be confused with “how-to-play” question, bc they wouldn’t know they need to click some other button for tutorial).

So, the feature of storing userconfigs to local storage in browser is patiently awaited :innocent:

2. Couple of issues found : as long as the game is provided on itch, I would say it is naturally possible that players will play the variety of browsers, incl. mobile. The tests on mobile browsers shown most things work well, That’s great! However couple of things would be nice to address:

most important: android keyboard is not activated for textboxes( for my game , for example it is rather important, as user inputs the name for the record table), ofc I set it up for android target and it is tested and working.

less important (to my view): I mentioned earlier that I use ShowUserInterfaceToQuit and IFDEF WASI conditional, but it is kinda tricky to separate the logic (for example I use it to hide some UI block), as both mobile and desktop browsers behave the same way for any of combination of these means, disallowing to configure granularly, i.e. I’m hiding a block about keyboard controls for mobile, but show it for web (as on desktop it is also ok to play with keys), but for mobile web would be nice to hide as well.

I’m describing this not as a bug, but a thing to consider :slight_smile: it might be not so wide use case to worry about.

one more not important thing, I noted when I tried to debug android keyboard (I was trying to launch web build on pc locally from editor, while attempting to connect from android phone to the IP:port). I got an error for line this.RegisterGlobalObject(caches,“cashes”); in the resulting game.js, that caches is not defined, it resulted the game to stop loading (so it works when you access localhost:3000 or 127.0.0.1:3000, but fails for local_network_device_IPv4:3000), I searched entire js file, didn’t find any other mention of caches, commented it, relaunched the game without recompile and it started working with IP:port . I’m not sure if that Register line comes from pas2js or somehow controlled from castle, just a thing I found, maybe not even worth to consider :sweat_smile:

2 Likes