Here what I have to say. First about the hard parts, the next post in this topic - for requests on WEB platform.
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
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 , for example I added a Backspace to duplicate âexitingâ function, which on desktop is done by Escape
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.
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.
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) :
obviously I wait WebAudio 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 Letâs maybe discuss
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.
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;
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.
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.
Also confirmed 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
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.
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! So, this makes me happy, weâre going in a good direction.
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
Sorry this is still not finished + merged. I have definitely too many tasks and too little time lately
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 Bear with me please until then So I just wanted to make a note that these, WebAudio and TCastleDownload+http on web, is very much on TODO list.
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.
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.
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
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 ). Can be seen in server repo on github
Note that the audio playback will be in a suspended state when loading the page in modern web browsers. This is a feature, the idea is that user should manually enable audio because it would be annoying if newly opened page could automatically play some sound. So we can only start audio in response to user interaction with a page, which in practice means: after a press (touch, mouse press, key press on focused canvas). Our engine handles the activation automatically, but you need to design your UX to encourage player to click on anything to start the playback. A button like âStart the gameâ will do the trick.
(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 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).
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 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
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
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
I pushed to the webaudio branch more work â Iâm close to finishing this
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)
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 !
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
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.
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â
Ok, some more time has passed, less intense work on the project bc of job and reality
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
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 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