Category Archives: Blazor

Creating a Game in Blazor – Part 2 – Gravity, and Controls

In this post I started the process of writing a very vague approximation of Jet Set Willy, in an effort to regain my youth.

Here, we’re going to take those very vague foundations, and allow left and right controls, along with a jump function. As a caveat, I’m going to state here that I expect quite large swathes of this code to change significantly before I declare it complete; and, as another caveat, there were 60 rooms in the original Jet Set Willy. I’ll be surprised if this series of posts manages to replicate the bathroom (which is the first room).

From the first post, we have a Game.razor, and all the code for this post will go into there. You can simply view that code here.

I’ve introduced a game loop here, which calls an update and then a draw method. Currently, the game loop is just a crude timer:

    private void TimerElapsed(Object source, System.Timers.ElapsedEventArgs e)
    {
        Update();
        Draw();
    }

This gets registered in the OnInitializedAsync method:

    protected override Task OnInitializedAsync()
    {
        _timer = new Timer();
        _timer.Interval = 16;
        _timer.Elapsed += TimerElapsed;
        _timer.AutoReset = true;
        _timer.Enabled = true;        

        return base.OnInitializedAsync();
    }

The Draw method is, in fact, just a single line:

private void Draw() => this.StateHasChanged();  

The reason for this is that Blazor doesn’t always automatically refresh state – updating bound objects on a timer is one of the times when it doesn’t. The Update method has a little more to it:

    private void Update()
    {
        ApplyGravity();
        _top -= _forceUp;

        if (_top > FLOOR)
        {
            _top = FLOOR;
            _forceUp = 0;
        }

        if (_left <= 0 && _forceRight < 0) _forceRight = 0;

        _left += _forceRight;
    }

Anything in caps is just a constant. The rest of the code basically takes care of the left, right, and jump.

Next, we’ll need to modify the HandleKeyDown method:

    private void HandleKeyDown(KeyboardEventArgs e)
    {
        switch (e.Code)
        {
            case "ArrowLeft": // Left
                if (_forceUp == 0)
                {
                    Walk(-SPEED);
                }
                break;
            case "ArrowUp": // Up
                Jump();
                break;
            case "ArrowRight": // Right
                if (_forceUp == 0)
                {
                    Walk(SPEED);
                }
                break;
            default:
                break;
        }
    }

As you can see, we’ve added Jump and Walk methods. All the logic has moved into those methods:

    private void Walk(int amt) => _forceRight = amt;

    private void Jump()
    {
        if (_forceUp == 0)
        {
            _forceUp += JUMP_FORCE;
        }
    }

Since Walk needs to be immediate, we just set the _forceRight to whatever value it’s passed; similarly with the jump, although we can’t allow a double jump, so we determine if a jump is in progress first.

Finally, we’ve added a HandleKeyUp: this stop walking when the key is released.

    private void HandleKeyUp(KeyboardEventArgs e)
    {
        switch (e.Code)
        {
            case "ArrowLeft": // Left
                Walk(0);
                break;

            case "ArrowRight": // Right
                Walk(0);
                break;

            default:
                break;
        }
    }

If you run this, you should now be able to walk “test” around the screen, and cause him to jump.

What’s Next?

For the next steps, I’m going to add a platform, and try to use some graphics. I’ll also try to refactor a little, as the main form is becoming a little large.

References

https://docs.microsoft.com/en-us/aspnet/core/blazor/components/event-handling?view=aspnetcore-5.0

https://www.pmichaels.net/2019/06/03/creating-a-car-game-in-react-part-1-drawing-and-moving/

https://stackoverflow.com/questions/58920461/how-to-detect-key-press-without-using-an-input-tag-in-blazor

Creating a Game in Blazor – Part 1 – Moving Objects

By now, writing games in frameworks that were clearly not designed for such things is becoming something of a habit for me. Here I created a poor-man’s version of Trans-Am (the hugely popular Spectrum game) in React, and here I attempted something along the lines of Daley Thompson’s Decathlon in Vue. I even created a catch game and a snake game in a .Net console app.

In this post, I’m going to attempt to create a game in Blazor. I’m hoping I can get a vague approximation of a platform game, such as Jet Set Willy. Obviously, this will not be as advanced (nor will I be able to offer a helicopter ride as a prize for finishing, as the creators originally did), but I can hopefully get some semblance of something moving across the screen, and the ability to jump over obstacles.

For part one, we’ll just explore how we would move an object. To start, let’s create a default Blazor client side application.

If you’d like to see the finished product from this post, you’ll find it here.

We’ll start in the Counter.razor file. We’ll simply replace the existing code with the following:

@page "/counter"

<h1>Counter</h1>

<button class="btn btn-primary" @onclick="IncrementLeft">Across</button>
<button class="btn btn-primary" @onclick="IncrementTop">Down</button>

<div style="top: @(top)px; left: @(left)px; position: absolute">test</div>

@code {
private int top = 0;
private int left = 0;

private void IncrementLeft()
{
left += 10;
}

private void IncrementTop()
{
top += 10;
}

}

All we’re really doing here is binding the position of the div to the variables left and top and then changing them on the button presses. Each time they are updated, they trigger a refresh of the screen.

You should now see the word test (very vaguely) in the top left hand corner of the screen. Pressing the Across and Down buttons move the text – if you move it far enough, you should be able to see it clearly against the white background.

Tidy Up

Now that this is working, let’s remove some of the cruft – our game doesn’t need a menu, or a FetchData screen; the following files can be removed:

Index.razor
NavMenu.razor
FetchData.razor

In Counter.razor we can change the routing:

@page "/"

Finally, change the code in MainLayout.razor to the following:

@inherits LayoutComponentBase

<div class="page">
<div class="main">
<div class="content px-4">
@Body
</div>
</div>
</div>

What’s left is just the counter screen: which can now be renamed to something more appropriate – I’ve changed mine to Game.razor.

What’s Next

We now have something moving around the screen – the next step will be to make this work using key presses, and add an actual platform for our game.

Simple binding in Blazor

A while back, I asked on Dev about moving my blog from WordPress to … well, not WordPress anymore. My main critera was to Markdown instead of whatever the WordPress format is called. The main issue being that you need to replace the code tags.

I resolved to create a tool to do it for me. I’m doing so in Blazor.

The first task was to create a very simple data binding scenario, so I could handle all the view logic in the View Model. I’ve previously written about using view models. This post covers the scenario where you want to bind text boxes and a button.

Let’s see the View Model first:

    public class MainViewModel
    {
        public string WpText { get; set; }
        public string MdText { get; set; }

        public void ConvertText()
        {
            MdText = $"Converted {WpText}";
        }
    }

Okay, so we have two strings, and a method that populates the second string with the first. As per the linked post, the plumbing for the view model is very simple; first, it’s registered in ConfigureServices:

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddTransient<MainViewModel, MainViewModel>();
        }

Then it’s injected into the Razor view:

@page "/"
@inject ViewModels.MainViewModel MainViewModel

In fact, the next part is much simpler than I thought it would be. To bind a view model property to the view, you just use the syntax bind:

<div class="container">
    <div class="row">
        <div class="form-group col-md-6">
            <label for="WpText">Wordpress Text</label>
            <input type="text" @[email protected] class="form-control" id="WpText" name="WpText"/>
        </div>

        <div class="form-group col-md-6">
            <label for="MdText">Markdown</label>
            <input type="text" @[email protected] class="form-control" id="MdText" name="MdText"/>
        </div>
    </div>
    <div class="row">
        <div class="form-group col-md-12">
            <input type="button" value="Convert" @[email protected](() => MainViewModel.ConvertText()) class="form-control" id="Submit" />
        </div>
    </div>
</div>

Just to point out one thing that tripped me up before I leave this: the event handlers that relate to Blazor must be prefixed with an at symbol (@).

References

https://www.nativoplus.studio/blog/blazor-data-binding-2/

Using Blazor Components

Imagine that you’re writing a Blazor application – maybe it’s similar to this one. Now, imagine that you have a large chunk of HTML in your main view. You might think: I wish I was using React, then I could separate this into its own component.

You can also do this in Blazor. Here’s how.

Components in Blazor

Let’s start with moving your code. The first step is to cut your HTML and paste it into a new Razor Component:

The format of your new component, from scratch, will be:

&lt;h3&gt;Component Name&lt;/h3&gt;

@code {

}

Your existing code should go beneath, or instead of:

&lt;h3&gt;Component Name&lt;h3&gt;

Parameters

The @code section allows you to put all kinds of crazy C# code in a code behind type model – so you probably don’t want to use that, except for passing parameters; for example:

@code {
    [Parameter]
    private string MyParameter { get; set; }
}

This allows you to pass a string into your component; for example (in your main view):

&lt;MyComponent MyParameter=&quot;test&quot; /&gt;

Complex Parameters

So far so good. But what if you need a complex type? You could, for example, pass a View Model into your component:

[Parameter]
private MyViewModel MyViewModel { get; set; }

You can pass this into the component as though it were a primitive type:

&lt;MyComponent MyViewModel=&quot;@MyViewModel&quot; /&gt;

This means that you can lift and shift the code with no changes.

Using External Namespaces

As with standard C#, you can access anything within the current namespace. Should you need any classes that are not in your current namespace, you can declare them at the top of the file, like this:

@using MVVMShirt

&lt;h3&gt;My Component&lt;/h3&gt;

Summary

Blazor is still in its infancy, but hopefully, adding actual code to these @code sections will become as frowned upon as code-behind.

Adding Logging to Client Side Blazor

Whilst there are some pre-built libraries for this, I seemed to be getting Mono linking errors. What finally worked for me was to install the pre-release versions of:

Install-Package Microsoft.Extensions.Logging -Version 3.0.0-preview6.19304.6
Install-Package Microsoft.Extensions.Logging.Console -Version 3.0.0-preview6.19304.6

Now, in your View Model, accept the Logger:

public MyViewModel(ILogger<MyViewModel> logger)

Then you can log as normal:

_logger.LogInformation("Hello, here's a log message");

You should now see the debug message in the F12 console.

You might be wondering why you don’t need to explicitly inject the logging capability; the reason is that:

BlazorWebAssemblyHost.CreateDefaultBuilder()            

Does that for you.

Using View Models in Blazor

Being new to Blazor (and Razor), the first thing that tripped me up was that the view seemed divorced from the rest of the application. In fact, this is actually quite a nice design, as it forces the use of DI.

For example, say you wanted to create a View Model for your view, you could register that ViewModel in the Startup:

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddTransient<MyViewModel, MyViewModel>();
        }

Note here that you don’t need an interface. If you’re only creating an interface for the purpose of this then that abstraction provides no benefit. That isn’t to say there may not be a reason for having an interface, but if you have one and this is the only place it’s used, you probably should reconsider.

The views in Razor / Blazor (at the time of writing) are *.razor files. In order to resolve the dependency inside the view, you would use the following syntax:

@page "/"
@inject ViewModels.MyViewModel MyViewModel

(Note that @page “/” is only in this snippet to orientate the code.)

You can call initialisation in the view model using something like:

@code {

    protected override async Task OnInitAsync()
    {
        await MyViewModel.Init();
    }    
}

And, within your HTML, you can reference the view model like this:

<div>@MyViewModel.MyData</div>

Magic. Hopefully more to come on Blazor soon.