Building A 2D game in Flutter- A Comprehensive Guide

We built a game in Flutter and its awesome!

GeekyAnts
The GeekyAnts Blog

--

It’s been quite some time since Flutter has shown its face in the market, and it stands proud as one of the few frameworks which offer something new every time you try to make something with it. It’s like opening a box of M&M’s and getting a new flavour every time you put your hand in it.

Google’s new SDK is just plain 🔥. We, at GeekyAnts, have been going at it since its Alpha Stage. Enabling cross-platform apps to be built using a single codebase, with modern React style features, readymade usable widgets, all while maintaining high quality standards is the very least of its features. With the latest stable release announced by Google, Flutter is bound to take the app development world by storm.

Thinking about all this, the lightbulb in our heads went berserk with the idea of building a game in Flutter. Is it possible? Is Flutter really powerful enough to build a full-fledged interactive video game for mobile?

What seemed like a bleak possibility, turned out to be the greatest thing we’ve possibly done in a while.

For developers, the concept of building games in a framework they’ve only build generic applications in is an exciting concept. If nothing, it breathes a fresh breath of air in those who are bored of doing the same things over and over again. It’s an exciting thing to explore and, so following our Modus Operandi here at GeekyAnts, we did!

Nice Story… but can we build games or not?

Long story short, yes we can! You can build your own canvas based 2-D game in Flutter.

Why Flutter tho?

The reason why it is suitable for such feats is the fact that it renders frames at a constant 60fps, which is hard to match.

Breaking down a video game.

The first thing that all video games have in common is that they’re interactive. That means that the player can fiddle around with it and perform actions and/or movements. The next three things that you’ll find in every game are-

1. A Game Engine

2. Characters

3. Game Logic

A game engine (Spoiler Alert! That’s what this article is partially about) is essentially a program or a set of programs that contain logics like physics, renders, collisions and so on and so forth.

P.S- A game engine is one of the most important requirement when it comes to making video games. It provides everything elementary to build a game from ground up.

Characters in the game are objects that make up the game world and interact with it using commands issued by the player and Game Logic is the logic around which the game revolves.

Every game has a goal that needs to be achieved, and there’s a certain way of achieving it and that is what a Game Logic comprises of (mainly).

The ‘Flame’ of the game!

A massive shout-out to Luan Nico, who created this amazing Flutter Game engine and named it appropriately because it’s fire! Flame is the engine that we looked towards, when looking for things to use to carry our experiment forward. This engine provides a complete set of utilities, sprites, audio etcetera that you need to build a canvas-based game. It’s easy to understand and use. You can find more details here and its complete documentation here.

Understanding the Game Loop

Basically, every game is built using two main methods-

1. The render method, that makes the canvas ready to draw something over it, maybe a sprite.

2. The update method receives a time input that helps in moving on to the next state.

So, the render and the update method both work in unison to make the game move through states and make it all seem like a seamless process. These states could be a thousand in number and their ability to translate through each of them is where the real magic happens.

Great! What are you building?

Imitation is the sincerest form of flattery.

It was a unanimous decision to take the concept of a classic game and rebuild it. That classic game appeared in the form of ‘Galaxy’. Galaxy is a traditional 8-bit game built in an 8-bit processor where you, the player, controls a spaceship and shoots lasers to kill swarms of aliens the appear on screen. It’s a classic top down-bottom up game and it was perfect for a canvas-based experiment.

Galaxy

The Juice of the Process

Now that the premise is clear, here is a quick walk through the process of building our first game.

After creating the project flutter create galaxygame , the first step is to add the ‘Flame’ dependency in the pubspec.yaml file. Next, navigate to the main function and import the ‘Flame’ package using package:flame/flame.dart;

Now in the main function give the root widget as MyGame().widget

Now that Flame is all set-up, we need to create a base class in order to start our game. This class provides the abstraction necessary to create any game and its game loop. It must be sub-classed so that you are required to implement the basis of any game: an update method, which is called whenever convenient and takes the amount of time passed since last update, and a render method, which has to know how to draw the current state of the game.

Now we have the base for the whole game. The next step is to render something on the screen. Navigate to the render function and first define a string text = "Score: 0"

then use the TextPainter, which is an object that paints a TextSpan tree onto a Canvas.

After giving the painter a text, colour and a font size, it’s time to render it using paint method. It takes the canvas and the exact location of where it should paint. So basically, it paints the text onto the given canvas at a given offset.

The whole code will look something like this:

Now run it using flutter run and you shall see this on the screen.

Setting up the field.

Next, we will render some background and some text to make it more believable. Now that we know how to draw on the screen, we’ll use the SpriteComponent class to draw components or characters of the game. This class is used to represent a single object on the screen.

In the component class we give three methods update, destroy and resize.

The update method receives the delta time in milliseconds since last update and allows you to move the next state.

The resize method is called whenever the screen is resized, and in the beginning once when the component is added via the add method. You need to apply here any changes to the x, y, width and height of your component, or any other changes, due to the screen resizing. You can start these variables here, as the sprite won’t be rendered until everything is set.

The destroy method can be implemented to return true and warn the BaseGame that your object is marked for destruction, and it will be removed after the current update loop. It will then no longer be rendered or updated.

It’s time to add some assets into the game.

You can find the assets we used in our GitHub repository, which is linked at the end.

To add a background image, wrap the root widget to a material app widget. Wrap that to a scaffold and the give a container as body and give the container a background image.

The modified main function looks like this:

Then, take out the dimensions and pass it to the MyGame class.

In runApp method, we use Material app and define home as a Scaffold widget. The child to the container would be a GameWrapper (a stateless widget) which will return game.widget.

So, the new code will look like this:

The Heroes and the Villains.

With an empty screen with some background and some text on it, it’s time to render characters or ‘sprites’ on the screen because you need to be able to shoot something.

The Villain

To do that, first we make a component class that extends base class. Now, in the Base Game class, we define a variable of type double as creationTimer = 0 . We update this logic to make creationTimer 0 again after every 4 seconds. Now, we use the method add which adds a new component to the components list and adds new instances of the component every time.

Next up is the component class. By using

Component(this.dimensions):super.square(ComponentSize,'dragon.png');

We give the characters (components) a face, using an image. Any relevant image can be loaded here in a .jpg or .png format.

Meanwhile, in the update method, we increment the ‘y position’ according to time t with a speed constant. In the resize method, we give the exact position of where the characters should be rendered.

Finally, the whole code should look like this:

Now that we have our ‘characters’ coming down on the screen from the top-corner, we need to make bullets appear from the bottom of the screen to ‘kill’ these characters.

For that, gesture detectors are used and a separate component is created for the bullets. You can explore more of that in the GitHub repository.

To make the bullets collide with the characters and ‘kill’ them, we use Collision Detection. To apply that, in the update method of the Bullet component, we add a Boolean variable and call it remove.

We make remove true when the bullet position coincide with the position of the character, say bottomLeft, bottomCenter and so on. This represents the reference of the bullet class and dragon.toRect represents a reference to the ‘character’ class.

If remove is true, the points in the bottom right is increased by one and both the character and bullet are destroyed.

End Result?

This.

You can find the GitHub repository to the game below.

Canvas based games are a go-go for Flutter but its capabilities may be beyond that. We are on a critical mission to continue exploring Flutter and pushing its limits.

A massive shout-out to SUMANT RAJ and Manoj N Bisarahalli for creating this game and sharing their brainchild for this article. They have put great efforts to make this happen and they deserve all the credit.

--

--