I was beyond excited to discover that there was already an extension for Blazor to be able to interact with an HTML5 canvas called Blazor Extensions Canvas. So I spun up Visual Studio and created a new Blazor client project and begin to strip away all the bloat.
After getting rid of most of the bloat, my App.razor was now just:
<div class="container">
<BECanvas Width="640" Height="480" @ref="_canvasReference"></BECanvas>
</div>
You can find the full source code at my Github here, but I’ll show some pertinent bits below. The first being that in the javascript side I have a main game loop that calls back into the C# code using InvokeMethodAsync
:
function gameLoop(timeStamp) {
window.requestAnimationFrame(gameLoop);
game.instance.invokeMethodAsync('GameLoop',
timeStamp,
game.canvas.width,
game.canvas.height);
}
And then on the C# side I’ve got the GameLoop
function as such with calls being made to populate the canvas:
[JSInvokable]
public async ValueTask GameLoop(float timeStamp, int width, int height)
{
...
await _context.BeginBatchAsync();
await context.SetFillStyleAsync("green");
await context.FillRectAsync(x, y, 50, 50);
...
await _context.EndBatchAsync();
}
Pretty soon I had a rectangle bouncing around the screen and an FPS counter! It was chilling at a rock solid 60FPS and I thought this was going to be my new tool to develop games for games jams to be played in the browser. So next I bumped it up to 20 rectangles just to make sure everything was still smooth and I noticed the FPS dropping a bit sometimes, I chalked it up to being run in debug and kept going with structuring the code.
Soon though I remembered reading that this wasn’t great for performance and so I dropped down 200 rectangles and to my horror it was maxing out at 22 FPS on a machine with a 1080Ti.
After verifying that hardware acceleration in chrome was in fact enabled, and opening up a more “native” wasm project that I had worked on before that could handle 10s of thousand sprites at once, I learned that the JSInterop was killing this dream.
The back and fourth between JS and C# is just to big of an overhead right now, I might experiment with “rendering” all of the images onto a surface of sorts and only calling a canvas draw function once per frame, but for now Blazor does not seem like a great candidate for game development.