Book Image

Building Games with Flutter

By : Paul Teale
Book Image

Building Games with Flutter

By: Paul Teale

Overview of this book

With its powerful tools and quick implementation capabilities, Flutter provides a new way to build scalable cross-platform apps. In this book, you'll learn how to build on your knowledge and use Flutter as the foundation for creating games. This game development book takes a hands-on approach to building a complete game from scratch. You'll see how to get started with the Flame library and build a simple animated example to test Flame. You'll then discover how to organize and load images and audio in your Flutter game. As you advance, you'll gain insights into the game loop and set it up for fast and efficient processing. The book also guides you in using Tiled to create maps, add sprites to the maps that the player can interact with, and see how to use tilemap collision to create paths for a player to walk on. Finally, you'll learn how to make enemies more intelligent with artificial intelligence (AI). By the end of the book, you'll have gained the confidence to build fun multiplatform games with Flutter.
Table of Contents (17 chapters)
1
Part 1: Game Basics
5
Part 2: Graphics and Sound
11
Part 3: Advanced Games Programming

Using Dart

In this section, we will discuss Dart and the language features that make it a great fit for game development. We will discuss how Dart is compiled, and how it uses threads and garbage collection. We will also discuss great features such as how hot reload aids us in developing code fast.

Compilation types

Computer programming languages can be either static or dynamic. A static language will be compiled into machine code before it runs, such as C++. A dynamic language is executed by an interpreter, so it does not need to be compiled before running (such as JavaScript).

As programming languages evolved, virtual machines were invented, which made it easier to port a language to a new hardware platform. The code is converted to bytecode, which is then run on the virtual machine. Java is an example of a language that uses bytecode.

The virtual machine imitates hardware in software and can be ported to run on different hardware platforms, making the code portable.

As compiler technology evolved, just-in-time (JIT) compilers were invented, which improved the performance of code running on virtual machines by compiling the code on the fly.

Compiling a program into machine code before running became known as ahead-of-time (AOT) compilation. Dart is unique in that it supports both JIT and AOT compilation types, which provides a massive advantage for developers. Developers can distribute the app compiled with AOT for maximum speed and performance, which helps games run smoothly.

When running in JIT compilation mode, Flutter and Dart have an amazing feature called stateful hot reload that cuts down development time.

Hot reload

Flutter uses the JIT compiler to allow you to reload and run code in less than a second. This allows you to change code and see the changes reflected on the emulator or web browser instantly, while retaining the internal state of the game.

This is great for game development as you can modify code and see the effect of the change, which speeds up development massively. It feels like painting with code!

For instance, you might reposition a graphic by a few pixels or change a color. In traditional development, you would have to rebuild the code (which could take many minutes) to see the change, but in Flutter, this is instant.

Native bridge

Dynamic languages such as JavaScript communicate with the native code on the platform over a bridge, which is very slow. They do this for things such as drawing the native components of the platform they are running on.

The native bridge is used to provide an interface between dynamic code and native code for all code, sending state information for user interface (UI) components.

In Flutter, instead of this, Skia draws all the components on a canvas (and makes them look and feel like native components), so it bypasses the need for a native bridge.

This is massive because with a native bridge you also need to pass the state of the UI components before they can be drawn, which slows everything down and can cause your UI to skip frames instead of keeping the animation smooth.

Garbage collection

Dart uses an advanced garbage collection system that quickly handles short-lived objects in memory.

As Flutter rebuilds the widget tree every frame, it throws away the old objects and recreates new objects. In a language such as Java, this would cause issues, but Dart is optimized to handle this very quickly.

Most languages require the use of locks to access shared memory, but Dart can perform its garbage collection most of the time without using locks. This fast garbage collection results in very smooth graphics performance, which greatly enhances our game.

Thread control

The developer has more control over code execution in Dart due to the way threads are implemented. Because Dart doesn't usually require locks for accessing shared memory, unlike most other languages, we have more control over the execution of the code.

Without locks, we avoid a type of call called a race condition, which can happen when separate threads want access to the shared resource (in this case, memory) and it can't be accessed because some other thread has locked access and the lock has to be released before other threads can access it.

In this section, we have discussed how the features of the Dart language help us to write fast games. In the next section, we will summarize what you will learn throughout the book.