Create a Breakout Game With Flame and Forge2D – Part 2

Learn how to create a Flutter version of the classic Breakout game using Flame and Forge2D. By Michael Jordan.

Leave a rating/review
Download materials
Save for later
Share
You are currently viewing page 3 of 3 of this article. Click here to view the first page.

Creating a Prismatic Joint

Now you're going to limit the paddle’s movement to the horizontal plane with PrismaticJoint.

The MouseJoint is associated with the drag event, and it is created and destroyed when the user drags the paddle. You need something more durable than that.

The PrismaticJoint is valid for the life of the paddle body and can be created just once after the paddle body is mounted. That sounds more viable, no?

Open paddle.dart and add the following onMount method to the Paddle class:

 @override
 void onMount() {
  super.onMount();

  // 1
  final worldAxis = Vector2(1.0, 0.0);

  // 2
  final travelExtent = (gameRef.size.x / 2) - (size.width / 2.0);

  // 3
  final jointDef = PrismaticJointDef()
   ..enableLimit = true
   ..lowerTranslation = -travelExtent
   ..upperTranslation = travelExtent
   ..collideConnected = true;

  // 4
  jointDef.initialize(body, ground.body, body.worldCenter, worldAxis);
  final joint = PrismaticJoint(jointDef);
  world.createJoint(joint);
 }

Step through the code:

  1. Set the worldAxis to restrict the paddle's movement to the x-axis.
  2. Set the extent that the paddle can move. The paddle movement is relative to the origin of the paddle, which is at its center. Set travelExtent to a distance of half the width of the game area minus half the width of the paddle to keep the movement within the arena.
  3. Create the prismatic joint definition with the movement limits.
  4. Create the joint then add it to the game world.

Build and run. The paddle movement is now limited to moving from side to side.

Prismatic Joint Restricting the Paddle

Cool! Your game is beginning to look like the Breakout game. Now you need to add some logic so you can destroy those bricks.

Adding Collision Detection

To destroy a brick, you must know when the ball collides with a brick. Your Forge2D collision detection code must uniquely identify the rigid bodies that have come in contact.

To determine the bodies involved in a given collision, you need to add userData to the body definition to identify the bodies uniquely.

Open ball.dart then set the userData property to reference this instance of the ball, like this:

  final bodyDef = BodyDef()
   ..userData = this
   ..type = BodyType.dynamic
   ..position = position;

Now, open brick.dart and add a similar userData property for the bricks:

  final bodyDef = BodyDef()
   ..userData = this
   ..type = BodyType.static
   ..position = position
   ..angularDamping = 1.0
   ..linearDamping = 1.0;

Your new this reference makes it so each brick in the wall is uniquely identified from other bricks. When a ball collides with a brick, Forge2D will use this data to identify the rigid bodies.

When a collision between the ball and a brick happens, the brick is responsible for recording the collision. Then, when the game loop updates, the brick wall checks for destroyed bricks and removes them from the Forge2D world.

In brick.dart, add the mixin ContactCallbacks to the Brick class.

class Brick extends BodyComponent<Forge2dGameWorld> with ContactCallbacks {

This mixin provides access to the contact methods.

Now, add the below:

 var destroy = false;

 @override
 void beginContact(Object other, Contact contact) {
  if (other is Ball) {
   destroy = true;
  }
 }

You just added a flag to indicate if this brick collided with the ball —beginContact sets the flag and is one of the ContactCallbacks Forge2D provides to alert you to collisions between bodies.

Add the below to brick.dart:

import 'ball.dart';

Your code needs this to import the Ball class.

The ball may collide with one or more bricks in a game loop cycle. The brick wall component is an excellent place to check the status of and remove destroyed bricks.

Open brick_wall.dart then add the following update method:

 @override
 void update(double dt) {
  // Check for bricks in the wall that have been flagged for removal.
  // Note: this is a destructive process so iterate over a copy of
  // the elements and not the actual list of children and fixtures.
  //
  for (final child in [...children]) {
   if (child is Brick && child.destroy) {
    for (final fixture in [...child.body.fixtures]) {
     child.body.destroyFixture(fixture);
    }
    gameRef.world.destroyBody(child.body);
    remove(child);
   }
  }

  super.update(dt);
 }

The above code helps us verify which of our bridges have been marked for removal, then destroys their fixtures and bodies. Remember that, when removing bodies from Forge2D, you must first remove the body's fixtures then you can remove the body.

Build and run and see if you can smash some bricks now.

Destroying Bricks

Another round of congratulations is in order!

You've created a ball, paddle and wall of bricks. The user can control the paddle to bounce the ball into the bricks and destroy them.

Where to Go From Here?

You can download the completed project files by clicking the Download Materials button at the top or bottom of the tutorial.

During part two of this series, you learned how to:

  • Create a custom Flame Component for the brick wall.
  • Add Draggable user input controls to Forge2D rigid bodies.
  • Move bodies in Forge2D using setTransform and MouseJoint.
  • Constrain the movement of a rigid body using a PrismaticJoint.
  • Detect collisions between rigid bodies using ContactCallbacks.

When you're ready to deep dive into Forge2D joints, visit this article: Box2D C++ tutorials - Joints - overview.

The third and final part of the Create A Breakout Game With Flame and Forge2D tutorial series will show you how to complete your Breakout game.

Right now, you have all the mechanics needed for a Breakout game, but it is a lawless land. It's missing rules and logic to enforce them.

Your game also lacks visual appeal — everything is black and white.

By the end of part three, these issues will be addressed and you'll have a beautiful, addictive game to play when you're bored: Create A Breakout Game With Flame and Forge2D - Part 3

We hope you enjoyed this tutorial, and if you have any questions or comments, please join the forum discussion below!