Thanks! We'll be in touch in the next 12 hours
Oops! Something went wrong while submitting the form.

Flame Engine : Unleashing Flutter's Game Development Potential

Hemant

Mobile App Development

With Flutter, developers can leverage a single codebase to seamlessly build applications for diverse platforms, including Android, iOS, Linux, macOS, Windows, Google Fuchsia, and the web. The Flutter team remains dedicated to empowering developers of all backgrounds, ensuring effortless creation and publication of applications using this powerful multi-platform UI toolkit.
Flutter simplifies the process of developing standard applications effortlessly. However, if your aim is to craft an extraordinary game with stunning graphics, captivating gameplay, lightning-fast loading times, and highly responsive interactions, Flames emerges as the perfect solution.s
This blog will provide you with an in-depth understanding of Flame. Through the features provided by Flame, you will embark on a journey to master the art of building a Flutter game from the ground up. You will gain invaluable insights into seamlessly integrating animations, configuring immersive soundscapes, and efficiently managing diverse game assets.

1. Flame engine

Flame is a cutting-edge 2D modular game engine designed to provide a comprehensive suite of specialized solutions for game development. Leveraging the powerful architecture of Flutter, Flame significantly simplifies the coding process, empowering you to create remarkable projects with efficiency and precision.

1.1. Setup: 

Run this command with Flutter:

CODE: https://gist.github.com/velotiotech/f86728269be4a977fda3fc9207cee541.js

This will add a line like this to your package's pubspec.yaml (and run an implicit flutter pub get):

CODE: https://gist.github.com/velotiotech/5f26faa301e4d3d2160f09cb92d45027.js

Import it, and now, in your Dart code, you can use:

CODE: https://gist.github.com/velotiotech/2e2af5147996e15389647148db7be1e4.js

1.2. Assets Structure: 

Flame introduces a well-structured assets directory framework, enabling seamless utilization of these resources within your projects.
To illustrate the concepts further, let's delve into a practical example that showcases the application of the discussed principles:

CODE: https://gist.github.com/velotiotech/5518a7d815fd9c57e339e396890c885c.js

When utilizing image and audio assets in Flame, you can simply specify the asset name without the need for the full path, given that you place the assets within the suggested directories as outlined below.


For better organization, you have the option to divide your audio folder into two distinct subfolders: music and sfx

The music directory is intended for audio files used as background music, while the sfx directory is specifically designated for sound effects, encompassing shots, hits, splashes, menu sounds, and more.

To properly configure your project, it is crucial to include the entry of above-mentioned directories in your pubspec.yaml file:

1.3. Support to other platforms: 

As Flame is built upon the robust foundation of Flutter, its platform support is inherently reliant on Flutter's compatibility with various platforms. Therefore, the range of platforms supported by Flame is contingent upon Flutter's own platform support.

Presently, Flame offers extensive support for desktop platforms such as Windows, MacOS, and Linux, in addition to mobile platforms, including Android and iOS. Furthermore, Flame also facilitates game development for the web. It is important to note that Flame primarily focuses on stable channel support, ensuring a reliable and robust experience. While Flame may not provide direct assistance for the dev, beta, and master channels, it is expected that Flame should function effectively in these environments as well.

1.3.1. Flutter web: 

To optimize the performance of your web-based game developed with Flame, it is recommended to ensure that your game is utilizing the CanvasKit/Skia renderer. By leveraging the canvas element instead of separate DOM elements, this choice enhances web performance significantly. Therefore, incorporating the CanvasKit/Skia renderer within your Flame-powered game is instrumental in achieving optimal performance on the web platform.

To run your game using Skia, use the following command:

CODE: https://gist.github.com/velotiotech/adfef57fad00fe800a436288821f738d.js

To build the game for production, using Skia, use the following:

CODE: https://gist.github.com/velotiotech/529610dc233254726c2d151641cd4d1d.js

2. Implementation

2.1 GameWidget: 

To integrate a Game instance into the Flutter widget tree, the recommended approach is to utilize the GameWidget. This widget serves as the root of your game application, enabling seamless integration of your game. You can incorporate a Game instance into the widget tree by following the example provided below:

CODE: https://gist.github.com/velotiotech/31aa95b7ccf7e56f3dbe4b0b055bd2d1.js

By adopting this approach, you can effectively add your Game instance to the Flutter widget tree, ensuring proper execution and integration of your game within the Flutter application structure.

2.2 GameWidget:

When developing games in Flutter, it is crucial to utilize a widget that can efficiently handle high refresh rates, speedy memory allocation, and deallocation and provide enhanced functionality compared to the Stateless and Stateful widgets. Flame offers the FlameGame class, which excels in providing these capabilities.

By utilizing the FlameGame class, you can create games by adding components to it. This class automatically calls the update and render methods of all the components added to it. Components can be directly added to the FlameGame through the constructor using the named children argument, or they can be added from anywhere else using the add or addAll methods.

To incorporate the FlameGame into the widget tree, you need to pass its object to the GameWidget. Refer to the example below for clarification:

CODE: https://gist.github.com/velotiotech/6ecb57bfc87519a5c4714ca3025b5afa.js

2.3 Component:

This is the last piece of the puzzle. The smallest individual components that make up the game. This is like a widget but within the game. All components can have other components as children, and all components inherit from the abstract class Component. These components serve as the fundamental entities responsible for rendering and interactivity within the game, and their hierarchical organization allows for flexible and modular construction of complex game systems in Flame. These components have their own lifecycle. 

Component Lifecycle: 


Figure 01

2.3.1. onLoad:

The onLoad method serves as a crucial component within the game's lifecycle, allowing for the execution of asynchronous operations such as image loading. Positioned between the onGameResize and onMount callbacks, this method is strategically placed to ensure the necessary assets are loaded and prepared. In Figure 01 of the component lifecycle, onLoad is set as the initial method due to its one-time execution. It is within this method that all essential assets, including images, audio files, and tmx files, should be loaded. This ensures that these assets are readily available for utilization throughout the game's progression.

2.3.2. onGameResize:

Invoked when new components are added to the component tree or when the screen undergoes resizing, the onGameResize method plays a vital role in handling these events. It is executed before the onMount callback, allowing for necessary adjustments to be made in response to changes in component structure or screen dimensions.

2.3.3. onParentResize:

This method is triggered when the parent component undergoes a change in size or whenever the current component is mounted within the component tree. By leveraging the onParentResize callback, developers can implement logic that responds to parent-level resizing events and ensures the proper rendering and positioning of the component.

2.3.4. onMount:

As the name suggests, the onMount method is executed each time a component is mounted into the game tree. This critical method offers an opportunity to initialize the component and perform any necessary setup tasks before it becomes an active part of the game.

2.3.5. onRemove:

The onRemove method facilitates the execution of code just before a component is removed from the game tree. Regardless of whether the component is removed using the parent's remove method or the component's own remove method, this method ensures that the necessary cleanup actions take place in a single execution.

2.3.6. onChildrenChanged:

The onChildrenChanged method is triggered whenever a change occurs in a child component. Whether a child is added or removed, this method provides an opportunity to handle the updates and react accordingly, ensuring the parent component remains synchronized with any changes in its children.

2.3.7. Render & Update Loop:

The Render method is responsible for generating the user interface, utilizing the available data to create the game screen. It provides developers with canvas objects, allowing them to draw the game’s visual elements. On the other hand, the Update method is responsible for modifying and updating this rendered UI. Changes such as resizing, repositioning, or altering the appearance of components are managed through the Update method. In essence, any changes observed in the size or position of a component can be attributed to the Update method, which ensures the dynamic nature of the game's user interface.

3. Sample Project

To showcase the practical implementation of key classes like GameWidget, FlameGame, and essential Components within the Flame game engine, we will embark on the creation of a captivating action game. By engaging in this hands-on exercise, you will gain valuable insights and hands-on experience in utilizing Flame's core functionalities and developing compelling games. Through this guided journey, you will unlock the knowledge and skills necessary to create engaging and immersive gaming experiences, while harnessing the power of Flame's robust framework.

Let's start with:

3.1. Packages & assets: 

3.1.1. Create a project using the following command:

CODE: https://gist.github.com/velotiotech/1b568c2c0dbaca7c951adbfe61c3ac12.js

3.1.2. Add these under dependencies of pubspec.yaml (and run command flutter pub get):

CODE: https://gist.github.com/velotiotech/f9b5d8b9844d66ee2a2a8d2456d6e391.js

3.1.3. As mentioned earlier in the Asset Structure section, let's create a directory called assets in your project and include an images subdirectory within it. Download assets from here, add both the assets to this  images directory.

Figure 02 

Figure 03

In our game, we'll use "Figure 02" as the background image and "Figure 03" as the avatar character who will be walking. If you have separate images for the avatar's different walking frames, you can utilize a sprite generator tool to create a sprite sheet from those individual images.

A sprite generator helps combine multiple separate images into a single sprite sheet, which enables efficient rendering and animation of the character in the game. You can find various sprite generator tools available online that can assist in generating a sprite sheet from your separate avatar images.

By using a sprite sheet, you can easily manage and animate the character's walking motion within the game, providing a smooth and visually appealing experience for the players.

After uploading, your asset structure will look like this: 

Figure 04

3.1.4. To use these assets, we have to register them into pubspect.yaml below assets section: 

CODE: https://gist.github.com/velotiotech/ff248b14f3283250e9473cbc1ebab032.js

3.2. Supporting code: 

3.2.1. Create 3 directories  constants, overlays, and components inside the lib directory.

3.2.2. First, we will start with a constants directory where we have to create 4 files as follows:

   all_constants.dart. 

CODE: https://gist.github.com/velotiotech/44bf75c3fdb5ba7517d88ba4358b6719.js

   assets_constants.dart. 

CODE: https://gist.github.com/velotiotech/ba269c9a615fd0d96b574150c01c28ea.js

   enum_constants.dart. 

CODE: https://gist.github.com/velotiotech/db43c84e2ace17e618ae8566281e10ac.js

   key_constants.dart. 

CODE: https://gist.github.com/velotiotech/51164d859f0186754bae731bc4ae67c4.js

3.2.3. In addition to the assets directory, we will create an overlay directory to include elements that need to be constantly visible to the user during the game. These elements typically include information such as the score, health, or action buttons.

For our game, we will incorporate five control buttons that allow us to direct the gaming avatar's movements. These buttons will remain visible on the screen at all times, facilitating player interaction and guiding the avatar's actions within the game environment.

Organizing these overlay elements in a separate directory makes it easier to manage and update the user interface components that provide vital information and interaction options to the player while the game is in progress.

In order to effectively manage and control the position of all overlay widgets within our game, let's create a dedicated controller. This controller will serve as a centralized entity responsible for orchestrating the placement and behavior of these overlay elements. Create a file named  overlay_controller.dart.

All the files in the overlays directory are common widgets that extend Stateless widget.

CODE: https://gist.github.com/velotiotech/74d392ebab20aa1e61cec1430b83dd2e.js

3.2.5. In our game, all control buttons share a common design, featuring distinct icons and functionalities. To streamline the development process and maintain a consistent user interface, we will create a versatile widget called DirectionButton. This custom widget will handle the uniform UI design for all control buttons.

Inside the overlays directory, create a directory called widgets and add a file called direction_button.dart in that directory. This file defines the shape and color of all control buttons. 

CODE: https://gist.github.com/velotiotech/646ffe690554dfd5a0b0e0ed4d37c34c.js

3.2.4. In the overlay_controller.dart file we can see the ButtonOverlay class as a child. So, let's create that file. button_overlay.dart will have all the 5 control buttons. 

CODE: https://gist.github.com/velotiotech/2cad7b2306cd3fcb8c111adf70650338.js

3.3. Core logic: 

Moving forward, we will leverage the code we have previously implemented, building upon the foundations we have laid thus far:

3.3.1.  The first step is to create a component. As discussed earlier, all the individual elements in the game are considered components, so let’s create 1 component that will be our gaming avatar. For the UI of this avatar, we are going to use assets shown in Figure 03.

For the avatar, we will be using SpriteAnimationComponents as we want this component to animate automatically.

In the components directory, create a file called avatar_component.dart. This file will hold the logic of when and how our game avatar will move. 

In the onLoad() method, we are loading the asset and using it to create animations, and in the update() method, we are using an enum to decide the walking animation.

CODE: https://gist.github.com/velotiotech/c997fe9ebc2dedf953971588089925f2.js

3.1.2. Our Avatar is ready to walk now, but there is no map or world where he can do that. So, let's create a game and add a background to it.  

Create file name walking_game.dart in the lib directory and add the following code.

CODE: https://gist.github.com/velotiotech/c4c6c874a6fab9c59db020a9cf904864.js

First thing in onLoad(), you can see that we are adding an overlay using a key. You can learn more about this key in the main class.

Next is to create background components using SpriteComponent and add it to the world component. For creating the background component, we are using SpriteComponent instead of SpriteAnimationComponent because we do not need any background animation in our game.

Then we add AvatarComponent in the same world component where we added the background component. To keep the camera fixed on the AvatarComponent, we are using 1 extra component, which is called CameraComponent.

Lastly, we are adding both world & CameraComponents in our game by using addAll() method.

3.1.3. Finally, we have to create the main.dart file. In this example, we are wrapping a GameWidget with MaterialApp because we want to use some features of material themes like icons, etc., in this project. If you do not want to do that, you can pass GameWidget to the runApp() method directly.
Here we are not only adding the WalkingGame into GameWidget but also adding an overlay, which will show the control buttons. The key mentioned here for the overlay is the same key we added in walking_game.dart file’s onLoad() method.

CODE: https://gist.github.com/velotiotech/400f3eab2a3bba0880a6227de4c34631.js

After all this, our game will look like this, and with these 5 control buttons, we can tell your avatar to move and/or stop.

4. Result

For your convenience, the complete code for the project can be found here. Feel free to refer to this code repository for a comprehensive overview of the implementation details and to access the entirety of the game's source code.

5. Conclusion

Flame game engine alleviates the burden of crucial tasks such as asset loading, managing refresh rates, and efficient memory management. By taking care of these essential functionalities, Flame allows developers to concentrate on implementing the core functionality and creating an exceptional game application.

By leveraging Flame's capabilities, you can maximize your productivity and create an amazing game application that resonates with players across various platforms, all while enjoying the benefits of a unified codebase.

6. References

  1. https://docs.flutter.dev/
  2. https://pub.dev/packages/flame
  3. https://docs.flame-engine.org/latest
  4. https://medium.flutterdevs.com/flame-with-flutter-4c6c3bd8931c
  5. https://supabase.com/blog/flutter-real-time-multiplayer-game
  6. https://www.kodeco.com/27407121-building-games-in-flutter-with-flame-getting-started
  7. https://blog.codemagic.io/flutter-flame-game-development/
  8. https://codelabs.developers.google.com/codelabs/flutter-flame-game
Get the latest engineering blogs delivered straight to your inbox.
No spam. Only expert insights.
Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.
Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.

Did you like the blog? If yes, we're sure you'll also like to work with the people who write them - our best-in-class engineering team.

We're looking for talented developers who are passionate about new emerging technologies. If that's you, get in touch with us.

Explore current openings

Flame Engine : Unleashing Flutter's Game Development Potential

With Flutter, developers can leverage a single codebase to seamlessly build applications for diverse platforms, including Android, iOS, Linux, macOS, Windows, Google Fuchsia, and the web. The Flutter team remains dedicated to empowering developers of all backgrounds, ensuring effortless creation and publication of applications using this powerful multi-platform UI toolkit.
Flutter simplifies the process of developing standard applications effortlessly. However, if your aim is to craft an extraordinary game with stunning graphics, captivating gameplay, lightning-fast loading times, and highly responsive interactions, Flames emerges as the perfect solution.s
This blog will provide you with an in-depth understanding of Flame. Through the features provided by Flame, you will embark on a journey to master the art of building a Flutter game from the ground up. You will gain invaluable insights into seamlessly integrating animations, configuring immersive soundscapes, and efficiently managing diverse game assets.

1. Flame engine

Flame is a cutting-edge 2D modular game engine designed to provide a comprehensive suite of specialized solutions for game development. Leveraging the powerful architecture of Flutter, Flame significantly simplifies the coding process, empowering you to create remarkable projects with efficiency and precision.

1.1. Setup: 

Run this command with Flutter:

CODE: https://gist.github.com/velotiotech/f86728269be4a977fda3fc9207cee541.js

This will add a line like this to your package's pubspec.yaml (and run an implicit flutter pub get):

CODE: https://gist.github.com/velotiotech/5f26faa301e4d3d2160f09cb92d45027.js

Import it, and now, in your Dart code, you can use:

CODE: https://gist.github.com/velotiotech/2e2af5147996e15389647148db7be1e4.js

1.2. Assets Structure: 

Flame introduces a well-structured assets directory framework, enabling seamless utilization of these resources within your projects.
To illustrate the concepts further, let's delve into a practical example that showcases the application of the discussed principles:

CODE: https://gist.github.com/velotiotech/5518a7d815fd9c57e339e396890c885c.js

When utilizing image and audio assets in Flame, you can simply specify the asset name without the need for the full path, given that you place the assets within the suggested directories as outlined below.


For better organization, you have the option to divide your audio folder into two distinct subfolders: music and sfx

The music directory is intended for audio files used as background music, while the sfx directory is specifically designated for sound effects, encompassing shots, hits, splashes, menu sounds, and more.

To properly configure your project, it is crucial to include the entry of above-mentioned directories in your pubspec.yaml file:

1.3. Support to other platforms: 

As Flame is built upon the robust foundation of Flutter, its platform support is inherently reliant on Flutter's compatibility with various platforms. Therefore, the range of platforms supported by Flame is contingent upon Flutter's own platform support.

Presently, Flame offers extensive support for desktop platforms such as Windows, MacOS, and Linux, in addition to mobile platforms, including Android and iOS. Furthermore, Flame also facilitates game development for the web. It is important to note that Flame primarily focuses on stable channel support, ensuring a reliable and robust experience. While Flame may not provide direct assistance for the dev, beta, and master channels, it is expected that Flame should function effectively in these environments as well.

1.3.1. Flutter web: 

To optimize the performance of your web-based game developed with Flame, it is recommended to ensure that your game is utilizing the CanvasKit/Skia renderer. By leveraging the canvas element instead of separate DOM elements, this choice enhances web performance significantly. Therefore, incorporating the CanvasKit/Skia renderer within your Flame-powered game is instrumental in achieving optimal performance on the web platform.

To run your game using Skia, use the following command:

CODE: https://gist.github.com/velotiotech/adfef57fad00fe800a436288821f738d.js

To build the game for production, using Skia, use the following:

CODE: https://gist.github.com/velotiotech/529610dc233254726c2d151641cd4d1d.js

2. Implementation

2.1 GameWidget: 

To integrate a Game instance into the Flutter widget tree, the recommended approach is to utilize the GameWidget. This widget serves as the root of your game application, enabling seamless integration of your game. You can incorporate a Game instance into the widget tree by following the example provided below:

CODE: https://gist.github.com/velotiotech/31aa95b7ccf7e56f3dbe4b0b055bd2d1.js

By adopting this approach, you can effectively add your Game instance to the Flutter widget tree, ensuring proper execution and integration of your game within the Flutter application structure.

2.2 GameWidget:

When developing games in Flutter, it is crucial to utilize a widget that can efficiently handle high refresh rates, speedy memory allocation, and deallocation and provide enhanced functionality compared to the Stateless and Stateful widgets. Flame offers the FlameGame class, which excels in providing these capabilities.

By utilizing the FlameGame class, you can create games by adding components to it. This class automatically calls the update and render methods of all the components added to it. Components can be directly added to the FlameGame through the constructor using the named children argument, or they can be added from anywhere else using the add or addAll methods.

To incorporate the FlameGame into the widget tree, you need to pass its object to the GameWidget. Refer to the example below for clarification:

CODE: https://gist.github.com/velotiotech/6ecb57bfc87519a5c4714ca3025b5afa.js

2.3 Component:

This is the last piece of the puzzle. The smallest individual components that make up the game. This is like a widget but within the game. All components can have other components as children, and all components inherit from the abstract class Component. These components serve as the fundamental entities responsible for rendering and interactivity within the game, and their hierarchical organization allows for flexible and modular construction of complex game systems in Flame. These components have their own lifecycle. 

Component Lifecycle: 


Figure 01

2.3.1. onLoad:

The onLoad method serves as a crucial component within the game's lifecycle, allowing for the execution of asynchronous operations such as image loading. Positioned between the onGameResize and onMount callbacks, this method is strategically placed to ensure the necessary assets are loaded and prepared. In Figure 01 of the component lifecycle, onLoad is set as the initial method due to its one-time execution. It is within this method that all essential assets, including images, audio files, and tmx files, should be loaded. This ensures that these assets are readily available for utilization throughout the game's progression.

2.3.2. onGameResize:

Invoked when new components are added to the component tree or when the screen undergoes resizing, the onGameResize method plays a vital role in handling these events. It is executed before the onMount callback, allowing for necessary adjustments to be made in response to changes in component structure or screen dimensions.

2.3.3. onParentResize:

This method is triggered when the parent component undergoes a change in size or whenever the current component is mounted within the component tree. By leveraging the onParentResize callback, developers can implement logic that responds to parent-level resizing events and ensures the proper rendering and positioning of the component.

2.3.4. onMount:

As the name suggests, the onMount method is executed each time a component is mounted into the game tree. This critical method offers an opportunity to initialize the component and perform any necessary setup tasks before it becomes an active part of the game.

2.3.5. onRemove:

The onRemove method facilitates the execution of code just before a component is removed from the game tree. Regardless of whether the component is removed using the parent's remove method or the component's own remove method, this method ensures that the necessary cleanup actions take place in a single execution.

2.3.6. onChildrenChanged:

The onChildrenChanged method is triggered whenever a change occurs in a child component. Whether a child is added or removed, this method provides an opportunity to handle the updates and react accordingly, ensuring the parent component remains synchronized with any changes in its children.

2.3.7. Render & Update Loop:

The Render method is responsible for generating the user interface, utilizing the available data to create the game screen. It provides developers with canvas objects, allowing them to draw the game’s visual elements. On the other hand, the Update method is responsible for modifying and updating this rendered UI. Changes such as resizing, repositioning, or altering the appearance of components are managed through the Update method. In essence, any changes observed in the size or position of a component can be attributed to the Update method, which ensures the dynamic nature of the game's user interface.

3. Sample Project

To showcase the practical implementation of key classes like GameWidget, FlameGame, and essential Components within the Flame game engine, we will embark on the creation of a captivating action game. By engaging in this hands-on exercise, you will gain valuable insights and hands-on experience in utilizing Flame's core functionalities and developing compelling games. Through this guided journey, you will unlock the knowledge and skills necessary to create engaging and immersive gaming experiences, while harnessing the power of Flame's robust framework.

Let's start with:

3.1. Packages & assets: 

3.1.1. Create a project using the following command:

CODE: https://gist.github.com/velotiotech/1b568c2c0dbaca7c951adbfe61c3ac12.js

3.1.2. Add these under dependencies of pubspec.yaml (and run command flutter pub get):

CODE: https://gist.github.com/velotiotech/f9b5d8b9844d66ee2a2a8d2456d6e391.js

3.1.3. As mentioned earlier in the Asset Structure section, let's create a directory called assets in your project and include an images subdirectory within it. Download assets from here, add both the assets to this  images directory.

Figure 02 

Figure 03

In our game, we'll use "Figure 02" as the background image and "Figure 03" as the avatar character who will be walking. If you have separate images for the avatar's different walking frames, you can utilize a sprite generator tool to create a sprite sheet from those individual images.

A sprite generator helps combine multiple separate images into a single sprite sheet, which enables efficient rendering and animation of the character in the game. You can find various sprite generator tools available online that can assist in generating a sprite sheet from your separate avatar images.

By using a sprite sheet, you can easily manage and animate the character's walking motion within the game, providing a smooth and visually appealing experience for the players.

After uploading, your asset structure will look like this: 

Figure 04

3.1.4. To use these assets, we have to register them into pubspect.yaml below assets section: 

CODE: https://gist.github.com/velotiotech/ff248b14f3283250e9473cbc1ebab032.js

3.2. Supporting code: 

3.2.1. Create 3 directories  constants, overlays, and components inside the lib directory.

3.2.2. First, we will start with a constants directory where we have to create 4 files as follows:

   all_constants.dart. 

CODE: https://gist.github.com/velotiotech/44bf75c3fdb5ba7517d88ba4358b6719.js

   assets_constants.dart. 

CODE: https://gist.github.com/velotiotech/ba269c9a615fd0d96b574150c01c28ea.js

   enum_constants.dart. 

CODE: https://gist.github.com/velotiotech/db43c84e2ace17e618ae8566281e10ac.js

   key_constants.dart. 

CODE: https://gist.github.com/velotiotech/51164d859f0186754bae731bc4ae67c4.js

3.2.3. In addition to the assets directory, we will create an overlay directory to include elements that need to be constantly visible to the user during the game. These elements typically include information such as the score, health, or action buttons.

For our game, we will incorporate five control buttons that allow us to direct the gaming avatar's movements. These buttons will remain visible on the screen at all times, facilitating player interaction and guiding the avatar's actions within the game environment.

Organizing these overlay elements in a separate directory makes it easier to manage and update the user interface components that provide vital information and interaction options to the player while the game is in progress.

In order to effectively manage and control the position of all overlay widgets within our game, let's create a dedicated controller. This controller will serve as a centralized entity responsible for orchestrating the placement and behavior of these overlay elements. Create a file named  overlay_controller.dart.

All the files in the overlays directory are common widgets that extend Stateless widget.

CODE: https://gist.github.com/velotiotech/74d392ebab20aa1e61cec1430b83dd2e.js

3.2.5. In our game, all control buttons share a common design, featuring distinct icons and functionalities. To streamline the development process and maintain a consistent user interface, we will create a versatile widget called DirectionButton. This custom widget will handle the uniform UI design for all control buttons.

Inside the overlays directory, create a directory called widgets and add a file called direction_button.dart in that directory. This file defines the shape and color of all control buttons. 

CODE: https://gist.github.com/velotiotech/646ffe690554dfd5a0b0e0ed4d37c34c.js

3.2.4. In the overlay_controller.dart file we can see the ButtonOverlay class as a child. So, let's create that file. button_overlay.dart will have all the 5 control buttons. 

CODE: https://gist.github.com/velotiotech/2cad7b2306cd3fcb8c111adf70650338.js

3.3. Core logic: 

Moving forward, we will leverage the code we have previously implemented, building upon the foundations we have laid thus far:

3.3.1.  The first step is to create a component. As discussed earlier, all the individual elements in the game are considered components, so let’s create 1 component that will be our gaming avatar. For the UI of this avatar, we are going to use assets shown in Figure 03.

For the avatar, we will be using SpriteAnimationComponents as we want this component to animate automatically.

In the components directory, create a file called avatar_component.dart. This file will hold the logic of when and how our game avatar will move. 

In the onLoad() method, we are loading the asset and using it to create animations, and in the update() method, we are using an enum to decide the walking animation.

CODE: https://gist.github.com/velotiotech/c997fe9ebc2dedf953971588089925f2.js

3.1.2. Our Avatar is ready to walk now, but there is no map or world where he can do that. So, let's create a game and add a background to it.  

Create file name walking_game.dart in the lib directory and add the following code.

CODE: https://gist.github.com/velotiotech/c4c6c874a6fab9c59db020a9cf904864.js

First thing in onLoad(), you can see that we are adding an overlay using a key. You can learn more about this key in the main class.

Next is to create background components using SpriteComponent and add it to the world component. For creating the background component, we are using SpriteComponent instead of SpriteAnimationComponent because we do not need any background animation in our game.

Then we add AvatarComponent in the same world component where we added the background component. To keep the camera fixed on the AvatarComponent, we are using 1 extra component, which is called CameraComponent.

Lastly, we are adding both world & CameraComponents in our game by using addAll() method.

3.1.3. Finally, we have to create the main.dart file. In this example, we are wrapping a GameWidget with MaterialApp because we want to use some features of material themes like icons, etc., in this project. If you do not want to do that, you can pass GameWidget to the runApp() method directly.
Here we are not only adding the WalkingGame into GameWidget but also adding an overlay, which will show the control buttons. The key mentioned here for the overlay is the same key we added in walking_game.dart file’s onLoad() method.

CODE: https://gist.github.com/velotiotech/400f3eab2a3bba0880a6227de4c34631.js

After all this, our game will look like this, and with these 5 control buttons, we can tell your avatar to move and/or stop.

4. Result

For your convenience, the complete code for the project can be found here. Feel free to refer to this code repository for a comprehensive overview of the implementation details and to access the entirety of the game's source code.

5. Conclusion

Flame game engine alleviates the burden of crucial tasks such as asset loading, managing refresh rates, and efficient memory management. By taking care of these essential functionalities, Flame allows developers to concentrate on implementing the core functionality and creating an exceptional game application.

By leveraging Flame's capabilities, you can maximize your productivity and create an amazing game application that resonates with players across various platforms, all while enjoying the benefits of a unified codebase.

6. References

  1. https://docs.flutter.dev/
  2. https://pub.dev/packages/flame
  3. https://docs.flame-engine.org/latest
  4. https://medium.flutterdevs.com/flame-with-flutter-4c6c3bd8931c
  5. https://supabase.com/blog/flutter-real-time-multiplayer-game
  6. https://www.kodeco.com/27407121-building-games-in-flutter-with-flame-getting-started
  7. https://blog.codemagic.io/flutter-flame-game-development/
  8. https://codelabs.developers.google.com/codelabs/flutter-flame-game

Did you like the blog? If yes, we're sure you'll also like to work with the people who write them - our best-in-class engineering team.

We're looking for talented developers who are passionate about new emerging technologies. If that's you, get in touch with us.

Explore current openings