Blazor GameDev – part 4: moving a sprite
Hi All! Welcome back to part 4 of our Blazor 2d Gamedev series. Today we’re going to refactor the code of part 3 and start moving the sprite across the screen.
The final result will be something like this:
Example 3 and 4 will render exactly the same thing but in Example 4 we’ll start refactoring a bit the code and move away from the procedural style. But let’s do one step at a time. For now, we’re going to focus on Example 3.
So, the first thing that we want to do is to start storing the basic information of our Sprite somewhere:
public class Sprite { public Size Size { get; set; } public ElementReference SpriteSheet { get; set; } }
The next step will be to keep track of where our Sprite instance is (position), what it is looking at (direction) and how fast it is moving (speed). For now, we’re going to store all this info in our Index.razor :
Point _spritePosition = Point.Empty; Point _spriteDirection = new Point(1, 1); float _spriteSpeed = 0.25f; [JSInvokable] public async ValueTask GameLoop(float timeStamp, int screenWidth, int screenHeight) { _gameTime.TotalTime = timeStamp; await Update(screenWidth, screenHeight); await Render(screenWidth, screenHeight); } private async ValueTask Update(int screenWidth, int screenHeight) { if (_spritePosition.X + _sprite.Size.Width >= screenWidth || _spritePosition.X < 0) _spriteDirection.X = -_spriteDirection.X; if (_spritePosition.Y + _sprite.Size.Height >= screenHeight || _spritePosition.Y < 0) _spriteDirection.Y = -_spriteDirection.Y; _spritePosition.X += (int)(_spriteDirection.X * _spriteSpeed * _gameTime.ElapsedTime); _spritePosition.Y += (int)(_spriteDirection.Y * _spriteSpeed * _gameTime.ElapsedTime); }
As you may have noticed, I have decided to split our GameLoop() function into two separate methods, Update() and Render().
Eventually, we’re going to use separate data structures to hold our entities, but we’ll see this in another post.
The logic in Update() is pretty straightforward: every time we hit the screen bounds, we just invert the direction. Easy peasy.
The last step is of course our Render() method:
private async ValueTask Render(int width, int height) { await _context.ClearRectAsync(0, 0, width, height); await _context.DrawImageAsync(_sprite.SpriteSheet, _spritePosition.X, _spritePosition.Y, _sprite.Size.Width, _sprite.Size.Height); }
This is quite similar to how we were rendering the sprite last time, the only difference is that here we’re providing the proper position to DrawImageAsync().
That’s all for now. Next time we’re going to introduce our new best friend: the GameObject!