flame_behaviors 0.1.0 copy "flame_behaviors: ^0.1.0" to clipboard
flame_behaviors: ^0.1.0 copied to clipboard

Flame Behaviors applies separation of concerns to game logic in the form of Entities and Behaviors, built by Very Good Ventures.

Flame Behaviors #

Very Good Ventures

Developed with 💙 by Very Good Ventures 🦄

ci coverage pub package style: very good analysis License: MIT Powered by Flame


Flame Behaviors was created to make it easier to create scalable, testable games with a well-defined structure. It applies the separation of concerns to the game logic, in the form of Entities and Behaviors.

Imagine you want to build an old school Pong game. At its very core are two objects: a paddle and a ball. If you have a look at the paddle, you could say its game logic is: move up and move down. The ball has the simple game logic of: on collision with a paddle reverse the movement direction.

These objects, paddles and balls, are what we call entities and the game logics we just described are their behaviors. By applying these behaviors to each individual entity we get the core gameplay loop of Pong: hitting balls with our paddles until we win.

By defining what kind of entities our game has and describing what type of behaviors they may hold, we can easily turn a gameplay idea into a structured game that is both testable and scalable.


Installation 💻 #

flutter pub add flame_behaviors

Usage ✨ #

Entity #

The entity is the building block of a game. It represents a visual game object that can hold multiple Behaviors, which in turn define how the entity behaves.

// Define a custom entity by extending `Entity`.
class MyEntity extends Entity {
  MyEntity() : super(behaviors: [MyBehavior()]);
}

Behavior #

A behavior is a component that defines how an entity behaves. It can be attached to an Entity and handle a specific behavior for that entity. Behaviors can either be generic for any entity or you can specify the specific type of entity that a behavior requires:

// Can be added to any type of Entity.
class MyGenericBehavior extends Behavior {
  ...
}

// Can only be added to MyEntity and subclasses of it.
class MySpecificBehavior extends Behavior<MyEntity> {
  ...
}

Each behavior can have its own Components for adding extra functionality related to the behavior. For instance a TimerComponent can implement a time-based behavioral activity:

class MyBehavior extends Behavior {
  @override
  Future<void> onLoad() async {
    await add(TimerComponent(period: 5, repeat: true, onTick: _onTick));
  }

  void _onTick() {
    // Do something every 5 seconds.
  }
}

Note: A Behavioris a non-visual component that describes how a visual component (Entity) behaves. To ensure this rule, a behavior can't have its ownBehavior`s.

Input behaviors

The flame_behaviors package also provides input behaviors. These behaviors are a layer over the existing Flame input mixins for components. These behaviors will trigger when their parent entity is being interacted with by the user. So these events are always relative to the parent entity.

class MyDraggableBehavior extends DraggableBehavior<MyEntity> {
  @override
  bool onDragUpdate(DragUpdateInfo info) {
    // Do something on drag update event.
    return super.onDragUpdate(info);
  }
}

Note: You still need to add the corresponding input mixins to your game class, see the Flame input docs for more information.

Collision detection #

Flame comes with a powerful built-in collision detection system, but this API is not strongly typed. Components always get the colliding component as a PositionComponent and developers need to manually check what type of class it is.

flame_behaviors is all about enforcing a strongly typed API. It provides a special behavior called CollisionBehavior that describes what type of entity it will target for collision. It does not, however, do any real collision detection. That is done by the PropagatingCollisionBehavior.

The PropagatingCollisionBehavior handles the collision detection by registering a hitbox on the parent entity. When that hitbox has a collision, the PropagatingCollisionBehavior checks if the component that the parent entity is colliding with contains the target entity type specified in CollisionBehavior.

By letting the PropagatingCollisionBehavior handle the collision detection we gain two benefits, the first and most important one is performance. By only registering collision callbacks on the entities themselves, the collision detection system does not have to go through any "collidable" behaviors, for which there could be many per entity. We only do that now if we confirm a collision has happened.

The second benefit is that it allows for separation of concerns. Each CollisionBehavior handles a specific collision use case and ensures that the developer does not have to write a bunch of if statements in one big method to figure out what it is colliding with.

A good use case of this collisional behavior pattern can be seen in the flame_behaviors example

class MyEntityCollisionBehavior extends CollisionBehavior<MyCollidingEntity, MyParentEntity> {
  @override
  void onCollisionStart(Set<Vector2> intersectionPoints, MyCollidingEntity other) {
    // We are starting colliding with MyCollidingEntity
  }

  @override
  void onCollisionEnd(MyCollidingEntity other) {
    // We stopped colliding with MyCollidingEntity
  }
}

class MyParentEntity extends Entity {O
  MyParentEntity() : super(
          behaviors: [
            PropagatingCollisionBehavior(RectangleHitbox()),
            MyEntityCollisionBehavior(),
          ],
        );
  
  ...
}
31
likes
0
pub points
90%
popularity

Publisher

verified publisherverygood.ventures

Flame Behaviors applies separation of concerns to game logic in the form of Entities and Behaviors, built by Very Good Ventures.

Repository (GitHub)
View/report issues

License

unknown (LICENSE)

Dependencies

flame, flutter

More

Packages that depend on flame_behaviors