Flame with Flutter
The Flame Engine aims to provide a complete set of solutions for most of the common problems that games developer might face in the flutter environment.
This article will deliver a quality introduction to the Flutter Flame game engine. You’ll learn how to build a Flutter Flame game, load sprites, and add animations. In the further project, we shall talk about animations made with Flutter Flame.
Table of Contents :
Introduction:
Flutter is an open-source framework created by Google where we craft various attractive applications for the Android, iOS, web, etc platforms from a single code base. Flutter uses a client-optimized language called Dart that makes faster apps on any platform. It is a much easier approach than traditional methods.
Flutter makes it easy to develop beautiful, interactive, and user-friendly interfaces(UI). Although, Flutter is a framework that is used for both frontend and backend development. But because of its adorable performance in frontend developers mostly use Flutter for Frontend development.
The Flutter team is dedicated to providing the ability to all kinds of developers to build applications in a minimal amount of time and release them effortlessly. For instance, Game developers are now capable of crafting beautiful game apps without taking care of performance issues, load times, and app sizes problems.
Flame:
It is a 2D game engine by which we develop various 2D game applications that run on top of flutter. We get so many useful & amazing features of it such as
- Game loop
- A component/object system(Flame Component System(FCS))
- Collision detection
- Images, sprites, sprite sheets, and animations.
- Input/gestures handling
- General utilities that make development easier.
Installation:-
Initially, you need to install Flame to implement it in your project. For that, we need to add its package with the latest version of it in pubspec.yaml
file:
dependencies:
flame: ^1.6.0
Code Implementation:-
To attach a Game instance in our Flutter tree, we need to give the charge to the widget called GameWidget. Or in simpler words, we will wrap our game with GameWidget at initials.
void main() {
WidgetsFlutterBinding.ensureInitialized();
SystemChrome.setPreferredOrientations(
[DeviceOrientation.landscapeLeft, DeviceOrientation.landscapeRight]);
runApp(GameWidget(game: Game()));
}
Here Game() is the game instance that GameWidget() will render over the screen. “Game” extends the FlameGame class.
class Game extends FlameGame with HasTappables {
@override
Future<void>? onLoad() {
super.onLoad();
}
FlameGame is a more absolute and opinionated implementation of Game. Extending it makes the developer able to add his game logic or he can keep the logic in the child Component.
FlameGame is based on the Flame Component System (also called FCS). This is the base class mostly recommended to use for most games that are made with Flame.
Component:
Everything we see on top of the screen is all components. For instance, background image, all the characters/objects on the screen, etc.
All components get inherited from the abstract class Component
directly or indirectly.
Every Component
has a few methods that you can implement optionally while using FlameGame
the class. If you are not using FlameGame, you can implement these methods on your game loop if you need.
Few generally used components:
- PositionalComponent — This class represents a positioned object over the screen, which could be a floating rectangle or a rotating sprite.
Constructor:-
PositionComponent({
Vector2? position,
Vector2? size,
Vector2? scale,
double? angle,
double nativeAngle = 0,
Anchor? anchor,
Iterable<Component>? children,
int? priority,
})
- FlameGame — It is based on the Flame Component System (FCS). It is the most recommended component to be extended to work with Flame.
Constructor:-FlameGame({
Iterable<Component>? children,
Camera? camera,
})
- SpriteComponent —
SpriteComponent
is the most commonly used implementation ofPositionComponent
, and it can be built with aSprite
.
Constructor:-
SpriteComponent({
Sprite? sprite,
Paint? paint,
Vector2? position,
Vector2? size,
Vector2? scale,
double? angle,
double? nativeAngle,
Anchor? anchor,
Iterable<Component>? children,
int? priority,
})
- SpriteAnimationComponent — This class is used to represent sprites containing Components that run in a single cyclic animation. I’ll be using it in the further project file for the animation making.
Constructor:-
SpriteAnimationComponent({
SpriteAnimation? animation,
bool? removeOnFinish,
bool? playing,
Paint? paint,
Vector2? position,
Vector2? size,
Vector2? scale,
double? angle,
double? nativeAngle,
Anchor? anchor,
Iterable<Component>? children,
int? priority,
})
There are so many other classes that extend Component directly or indirectly and use its methods by overriding it.
Code File:
The project is all about an animated user interface using a flame. All the related file snippets are presented below:
main. dart
void main() {
WidgetsFlutterBinding.ensureInitialized();
SystemChrome.setPreferredOrientations(
[DeviceOrientation.landscapeLeft, DeviceOrientation.landscapeRight]);
runApp(GameWidget(game: GameComponent()));
}
GameComponent.dart
class GameComponent extends FlameGame with HasTappables {
MovementState movementState = MovementState.running;
late SpriteSheet spriteSheet;
late SpriteAnimation spriteAnimation;
DialogButton dialogButton = DialogButton();
final Vector2 buttonSize = Vector2(100.0, 100.0);
SpriteAnimationComponent animationComponent = SpriteAnimationComponent(
size: Vector2(402 * 0.7, 202 * 0.7), position: Vector2(100, 180));
BackgroundComponent backgroundComponent = BackgroundComponent();
@override
Future<void>? onLoad() async {
super.onLoad();
await loadAnimations();
button();
add(backgroundComponent);
add(animationComponent);
add(dialogButton);
}
Future<void> loadAnimations() async {
if (movementState == MovementState.running) {
spriteSheet = SpriteSheet(
image: await images.load("cat_final.png"),
srcSize: Vector2(402, 202));
spriteAnimation =
spriteSheet.createAnimation(row: 0, stepTime: 0.1, from: 0, to: 11);
} else {
spriteSheet = SpriteSheet(
image: await images.load("cat_final.png"),
srcSize: Vector2(402, 202));
spriteAnimation =
spriteSheet.createAnimation(row: 0, stepTime: 0.35, from: 12, to: 18);
}
animationComponent.animation = spriteAnimation;
}
void button() async {
dialogButton
..sprite = await loadSprite("button.png")
..size = buttonSize
..position =
Vector2(size[0] - buttonSize[0] - 10, size[1] - buttonSize[1] - 10);
}
@override
void update(double dt) {
super.update(dt);
if (dialogButton.isTapped) {
// print("Tapped?${dialogButton.isTapped}");
movementState = MovementState.idle;
loadAnimations();
return;
} else {
movementState = MovementState.running;
// loadAnimations();
return;
// }
}
}
}
DialogButton.dart
class DialogButton extends SpriteComponent with Tappable {
MovementState movementState = MovementState.running;
GameComponent? game;
bool isTapped = false;
@override
bool onTapDown(TapDownInfo info) {
try {
print("Pressed");
isTapped = !isTapped;
isTapped ? movementState = MovementState.idle : movementState = MovementState.running;
print(movementState);
return true;
} catch(e) {
print("Something went wrong $e");
return false;
}
}
}
BackgroundComponent.dart
class BackgroundComponent extends SpriteComponent
with HasGameRef<GameComponent> {
@override
Future<void> onLoad() async {
await super.onLoad();
sprite = await gameRef.loadSprite("background.png");
size = gameRef.size;
}
}
You can download sprite sheets and make your animation UI. Few are here.
Final Output:-
When we run the application, we ought to get the screen’s output like the underneath screen video.
As we click the DialogButton component, we are changing the sprite sheet limits from 0–11(running state) to 12–18(sitting state).
Conclusion:-
In this article, we’ve learned how to work will package flame to encounter animation in our application. We commonly use this package for developing 2D games but it’s indeed a good choice for the making of animations too in our applications.
❤ ❤ Thanks for reading this article ❤❤
If I got something wrong? Let me know in the comments. I would love to improve.
Clap 👏 If this article helps you.
Github link:
Find the source code of flame_flutter:
https://github.com/flutter-devs/flame_flutter
Feel free to connect with us:
And read more articles from FlutterDevs.com.
FlutterDevs team of Flutter developers to build high-quality and functionally-rich apps. Hire a Flutter developer for your cross-platform Flutter mobile app project on an hourly or full-time basis as per your requirement! For any flutter-related queries, you can connect with us on Facebook, GitHub, Twitter, and LinkedIn.
We welcome feedback and hope that you share what you’re working on using #FlutterDevs. We truly enjoy seeing how you use Flutter to build beautiful, interactive web experiences.