PLAY IT NOW! https://stevedunn.github.io/PacManBlazor/
This is a project I started in order to experiment with Blazor/WebAssembly. I wanted to see if it was feasible to use Blazor to write a game in C# that runs at 60FPS.
Although care was needed with heap allocations in the main game-loop (which has to take less than 16 milliseconds)
The game basically manipulates the HTML 5 canvas from C# code via the interop provided by Blazor.
It uses the .NET NuGet package Blazor.Extensions.Canvas
All drawing is done as on 224x314 canvas. This is upscaled by 3x3 (672/944) 672/944 is a 0.711 aspect ratio
It uses Howler. sound.js
is loaded and exposes SoundPlayer
. In the C# code,
GameSoundPlayer
loads the sound effects via SoundLounder
which interact with Howler via IJSRuntime
.
Each sound in C# is represented by SoundEffect
which again uses IJSRuntime
to call methods on the JS SoundPlayer
,
e.g. _runtime.InvokeVoidAsync("soundPlayer.play", name])
.
When a sound has stopped playing, our end
event on Howler calls back into the C# code.
This is needed to loop things like the sirens and other long playing effects.
It uses Hammer.js.
First, we override OnInitializedAsync
in index.blazor
(which is the Blazor class that derives from ComponentBase
).
In this method, we initialise the C# world and then call setDrawCallback
in the JS code. setDrawCallback
does these things:
- initialises Hammer for input
- registers for
KeyDown
,KeyUp
events onwindow
; the events are fed through to the C# code - calls
requestAnimationFrame
onwindow
; every frame it then calls the C# code
Then, back in Blazor, we override OnAfterRenderAsync
and initialise the canvases. There are 3 canvases used, one is the output canvas that we draw on,
and the other two are canvases for each player's maze (it's a one or two player game).
In JS, at startup, we called requestAnimationFrame
. This means that every frame (60 per second), a JS method is called
and that method calls the C# code. The C# code