Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Introduction to Game Development in Flutter wit...

GDG Montreal
March 24, 2024
61

Introduction to Game Development in Flutter with Flame

Flutter is a popular and versatile frontend framework that can be ported to any screen imaginable, with decent performance. This makes it an excellent candidate for developing casual games over many platforms at once. We will create a simple platformer in this workshop. Please bring your laptop and preferably install Flutter in advance with the following targets: your desktop OS, Android or iOS, and web. Alternatively, you can use DartPad (an online IDE) but its features might not be sufficient for the workshop.

GDG Montreal

March 24, 2024
Tweet

More Decks by GDG Montreal

Transcript

  1. About me Song Yang Data scientist, Outlier Previously teaching at

    Vanier College + + Game dev hobbyist (portfolio) Currently building a startup! + + Song Yang | LinkedIn
  2. Agenda 1 2 3 4 5 6 Game development basics

    How Flame fits in Flutter Importing art Controls Physics and collisions Making use of Flutter for UI
  3. The 3Cs of game development Character What does your game

    models look like? • 2D ✅ • 2D with physics ✅ • 3D Flame does not support 3D art, yet. - Flutter pinball (article) Controls How intensive are the player controls? • Just clicking around ✅ • Minimal ✅ • Intensive Flame is best for minimal controls. - Platformer - Card games - 2D shooter Camera How is the game presented visually? • Static 2D camera ✅ • Moving 2D camera ✅ • 3D camera The world is treated as a 2D plane in Flame.
  4. Dart Everything is a widget. Widgets are in a tree.

    + + + Flutter Widget Widget … Widget … …
  5. Introduce the GameWidget. The GameWidget has Flame components. + +

    Flutter + Flame Widget Widget … Widget … … GameWidget No Flutter widgets can be a descendant of the GameWidget.* +
  6. Images and sound can be treated like in Flutter. Add

    them to the asset path designated by the pubspec.yaml. By default, every image is in /assets/images. Adding files to the Flutter-Flame project flutter: assets: - assets/images/ Let’s see an example for the platformer game Ember Quest!
  7. import 'package:flame/game.dart'; class EmberQuestGame extends FlameGame { @override Future<void> onLoad()

    async { await images.loadAll([ 'block.png', 'ember.png', 'ground.png', 'heart_half.png', 'heart.png', 'star.png', 'water_enemy.png', ]);
  8. Introduce the camera The camera is part of the extended

    FlameGame. Anchors are similar to their counterparts in Unity. - Anchors help the positioning of components. @override Future<void> onLoad() async { await images.loadAll([ '...', ]); camera.viewfinder.anchor = Anchor.topLeft; }
  9. Loading a sprite animation The sprite is stored as a

    PNG file. (ember.png) All frames of the animation are sequentially positioned from left to right. Assumption: looping animation class EmberPlayer extends SpriteAnimationComponent with HasGameReference<EmberQuestGame> { EmberPlayer({required super.position}) : super(size: Vector2.all(64), anchor: Anchor.center); @override FutureOr<void> onLoad() { animation = SpriteAnimation.fromFrameData( game.images.fromCache('ember.png'), SpriteAnimationData.sequenced( amount: 4, stepTime: 0.12, textureSize: Vector2.all(16), ), ); }
  10. Adding to the world The world is part of the

    extended FlameGame. World coordinates are in 2D. The origin is in the upper left corner. Going to the right is +x. Going down is +y. canvasSize tells the size of the game’s viewport dimension. class EmberQuestGame extends FlameGame { @override Future<void> onLoad() async { await images.loadAll([ '...', ]); camera.viewfinder.anchor = Anchor.topLeft; _ember = EmberPlayer( position: Vector2(128, canvasSize.y - 128), ); add(_ember); }
  11. Flame uses mixins Mixin (Dart concept) A mixin is an

    implemented interface with properties. Like inheritance, but without the need to be inherited. A class can have as many mixins as desired. As such, mixins do not make classes polymorphic. HasKeyboardHandler Components This mixin is added to the FlameGame to enable keyboard events for the game. KeyboardHandler This mixin is added to the classes that respond to keyboard events. class EmberQuestGame extends FlameGame with HasKeyboardHandlerComponents {
  12. class EmberPlayer extends SpriteAnimationComponent with KeyboardHandler { @override bool onKeyEvent(KeyEvent

    event, Set<LogicalKeyboardKey> keysPressed) { horizontalDirection = 0; horizontalDirection += (keysPressed.contains(LogicalKeyboardKey.keyA) || keysPressed.contains(LogicalKeyboardKey.arrowLeft)) ? -1 : 0; horizontalDirection += (keysPressed.contains(LogicalKeyboardKey.keyD) || keysPressed.contains(LogicalKeyboardKey.arrowRight)) ? 1 : 0; return true; }
  13. @override void update(double dt) { velocity.x = horizontalDirection * moveSpeed;

    position += velocity * dt; super.update(dt); } Performing the move Let’s make Ember move! The update method is called each game frame, similar to the update method in a Unity GameObject.
  14. By default, Flame has no physics. You would have to

    implement them. Flame has an ecosystem of bridge packages. Forge2D is a 2D physics package. + + + Physics in Flame +
  15. Collision mixins Hitboxes A hitbox is an area (or surface

    for 3D) around something that takes part in collisions. Flame offers a very simple collision matrix. - Active: collides with everything - Passive: collides only with active HasCollisionDetection This mixin is added to the FlameGame to enable collision detection for the game. CollisionCallback This mixin is added to the classes representing things that can collide with each other. class EmberQuestGame extends FlameGame with HasCollisionDetection
  16. class EmberPlayer extends SpriteAnimationComponent with CollisionCallbacks { @override void onCollision(Set<Vector2>

    intersectionPoints, PositionComponent other) { if (other is GroundBlock || other is PlatformBlock) { ... a bunch of physics, like calculating the normal ...
  17. Flutter + Flame Widget Widget … Widget … … GameWidget

    No Flutter widgets can be a descendant of the GameWidget.* + Flutter widgets can be added to the GameWidget as an overlay. * Widget overlay … … Components This is the way to leverage Flutter for the game’s UI. +
  18. class MainMenu extends StatelessWidget { // Reference to parent game.

    final EmberQuestGame game; const MainMenu({super.key, required this.game}); @override Widget build(BuildContext context) { return Material( ... all the widgets you need ... ElevatedButton( onPressed: () { game.overlays.remove('MainMenu'); },
  19. • Build games for many platforms at once. • Build

    relatively simple games (no 3D or AAA). • Leverage the power of Flutter for UI. • No drag-and-drop GUI (Unity inspector). Repository: https://github.com/songyang-dev/flame_platformer_tutorial Conclusion What is Flame?