Hi All! Welcome back to part 6 of our Blazor 2d Gamedev series. Today we’ll see how we can start detecting user interaction and mouse input.

Last time we started the real refactoring towards a more reusable structure and introduced the concept of composition through the GameObject class.

The goal for today’s exercise is to be able to detect when the mouse cursor is over the Blazor logo and stop it when the left button is clicked.

Take your time, check the example, I’ll wait.

Done? OK. So, the first step is to update index.html and register few callbacks:

window.initGame = (instance) => {
    // some init code here...
    if (window.game.canvas) {
        window.game.canvas.onmousemove = (e) => {
            game.instance.invokeMethodAsync('OnMouseMove', e.clientX, e.clientY);
        };
        window.game.canvas.onmousedown = (e) => {
            game.instance.invokeMethodAsync('OnMouseDown', e.button);
        };
        window.game.canvas.onmouseup = (e) => {
            game.instance.invokeMethodAsync('OnMouseUp', e.button);
        };
    }
    // some more init code here...
};

We’ll be using the same method we use for our render loop to invoke C# methods, passing the mouse position or the id of the clicked button. Let’s add them to Index.razor :

[JSInvokable]
public async ValueTask OnMouseMove(int mouseX, int mouseY)
{
    InputSystem.Instance.MouseCoords.X = mouseX;
    InputSystem.Instance.MouseCoords.Y = mouseY;
}

[JSInvokable]
public async ValueTask OnMouseDown(MouseButtons button)
{
    InputSystem.Instance.SetButtonState(button, ButtonStates.Down);
}

[JSInvokable]
public async ValueTask OnMouseUp(MouseButtons button)
{
    InputSystem.Instance.SetButtonState(button, ButtonStates.Up);
}

We’re almost there. Now we have to define the InputSystem class. It’s “only” purpose will be to keep track of the state of our input peripherals (for now just the mouse) and expose a get operation.

At the bare minimum should look something like this:

public class InputSystem
{
    public Point MouseCoords;
    public static InputSystem Instance;
    
    public void SetButtonState(MouseButtons button, ButtonStates state) ;
    public ButtonStates GetButtonState(MouseButtons button);
}

The last step now is to update the “brain” component of the Blazor logo and handle the input:

public override async ValueTask Update(GameContext game)
{
    var isOver = _transform.BoundingBox.Contains(InputSystem.Instance.MouseCoords);

    _renderComponent.DrawBoundingBox = isOver;

     _speed = InputSystem.Instance.GetButtonState(MouseButtons.Left) == ButtonStates.Down && (isOver || _speed == 0f)
                ? 0
                : DefaultSpeed;
}

We’ll simply render a bounding box if the mouse is hovering our logo and zero out the speed if we’re clicking.

That’s all for today! Next time we’ll see how we can display some nice animations using spritesheets. Stay tuned!