Draw a circle in Flame with Flutter

To start developing 2D games with Flutter and Flame, you can follow these tutorials that I bring to your disposal in which we will learn the basic concepts to create 2D games with Flutter.

 

Before going into the matter of image or sprite management, collision detection, tap events... We must start small and initially, we are going to want to draw something on the screen, something primitive like a circle, which is very easy to do; these exercises are essential to understand how to develop more complete components such as sprites, animations and of course, how to interact with all these images according to some user action.

Draw a circle

To draw a circle in Flame with Flutter, you can use the Circle class from the Flame/components.dart package. This class allows you to draw a circle on the canvas based on coordinates that would define its center and size:

Offset(10, 10)

and also the color

BasicPalette.red.paint()

In this example, we will see how to draw a circle with the FlameGame class:

lib/main.dart

import 'package:flame/components.dart';
import 'package:flame/game.dart';
import 'package:flame/palette.dart';
import 'package:flutter/material.dart';

class MyCircle extends PositionComponent {
  MyCircle() : super();

  @override
  Future<void> onLoad() async {}

  @override
  void render(Canvas canvas) {
    canvas.drawCircle(const Offset(10, 10), 10, BasicPalette.red.paint());

    // canvas.drawRect(Rect.fromCircle(center: const Offset(0, 0), radius: 20),
    //     BasicPalette.red.paint());
  }
}

class MyGame extends FlameGame {
  @override
  Future<void> onLoad() async {
    await add(MyCircle());
  }
}

main() {
  runApp(GameWidget(game: MyGame()));
}

In this other example, we have the same application, but using the Game class instead:

lib/main.dart

import 'package:flame/palette.dart';
import 'package:flutter/material.dart';
import 'package:flame/game.dart';

void main() async {
  runApp(GameWidget(game: MyCircle()));
}

class MyCircle with Game {
  @override
  Future<void> onLoad() async {
    super.onLoad();
    // init
  }

  @override
  void render(Canvas canvas) {
    canvas.drawCircle(const Offset(10, 10), 10, BasicPalette.red.paint());

    // canvas.drawRect(Rect.fromCircle(center: const Offset(0, 0), radius: 20),
    //     BasicPalette.red.paint());
  }

  @override
  void update(double deltaTime) {}
}

Either the program with the Game or FlameGame class, if you run the above script, you will see output like the following:

As you can conclude, those approaches that allow us to organize the code in classes, is the approach that allows us to reuse the components more easily, as well as extend them or create others, therefore, these examples reinforce the reason why it is used. the FlameGame class instead of the Game class; Apart from that, with the FlameGame class we have access to other features of the Flame API.

As you saw before, we use the fundamental methods of the GameLoop in Flame, which are. the render function and the update function.

The FlameGame class maintains a list of all game components, and these can be dynamically added to the game as needed; for example, we could add various enemy SpriteComponents to the game and then remove them from the game as the player kills the enemies. The FlameGame class will then iterate over these components telling each component to update and render itself.

The GameWidget class represents the constructor we usually use to instantiate the game in Flame and set it to the widget tree in Flutter.

As a recommendation, click on the FlameGame, Game, PositionComponent, SpriteComponent and the rest classes to see their details, see what properties they implement, as in the case of the Game type classes:

class PositionComponent extends Component
    implements
        AnchorProvider,
        AngleProvider,
        PositionProvider,
        ScaleProvider,
        CoordinateTransform {
  PositionComponent({
    Vector2? position,
    Vector2? size,
    Vector2? scale,
    double? angle,
    this.nativeAngle = 0,
    Anchor? anchor,
    super.children,
***

Or about the functions that you can implement and what parameters you can send and the type, as in the case of Canvas and test them and evaluate the result...

For example, to draw a rectangle, we can do it by defining two points on the screen:

canvas.drawRect(Rect.fromPoints(const Offset(10,10), const Offset(500,500)), BasicPalette.purple.paint());

Or using a circle, but instead of drawing a circle with canvas.drawCircle(), we draw a rectangle:

canvas.drawRect(Rect.fromCircle(center: const Offset(100, 100), radius: 50.0),BasicPalette.brown.paint());

In summary, with these examples, it becomes more clear how Flame works, a structure based on components, which, like widgets, are an element of several of our games, we see how to use the PositionComponent which are basic widgets and that they are inherited from other types of widgets that we will introduce later; elements such as position, size, scale, among other geometric operations, are essential in any game engine, and Flame is no exception.

- Andrés Cruz

En español
Andrés Cruz

Develop with Laravel, Django, Flask, CodeIgniter, HTML5, CSS3, MySQL, JavaScript, Vue, Android, iOS, Flutter

Andrés Cruz In Udemy

I agree to receive announcements of interest about this Blog.