Bodies and sprites
This article will teach us how to draw sprites on top of our Forge2D bodies.
Let's start by creating a Forge2D scene in which a box or a ball will appear at the top of the screen each time we click the screen.
We start by creating the class Box
:
class Box extends BodyComponent {
Body createBody() {
final bodyDef = BodyDef(
position: Vector2(worldSize.x / 2, 0),
type: BodyType.dynamic,
);
final shape = PolygonShape()..setAsBoxXY(.25, .25);
final fixtureDef = FixtureDef(shape)
..density = 5
..friction = .5
..restitution = .5;
return world.createBody(bodyDef)
..createFixture(fixtureDef)
..angularVelocity = radians(180);
}
}
Notice that we added an angularVelocity
so the box will rotate on its axis. Everything else is what we have been
doing in previous tutorials.
Now let's create a class Ball
:
class Ball extends BodyComponent {
Body createBody() {
final bodyDef = BodyDef(
position: Vector2(worldSize.x / 2, 0),
type: BodyType.dynamic,
);
final shape = CircleShape()..radius = .25;
final fixtureDef = FixtureDef(shape)
..density = 5
..friction = .5
..restitution = .5;
return world.createBody(bodyDef)
..createFixture(fixtureDef)
..angularVelocity = radians(180);
}
}
Again, there is nothing special in this class. This ball will be rotating on its axis too.
Every time we click the screen, we want to add a ball or box randomly. Let's add this code:
class GameLesson05 extends MyGame with TapDetector {
Future<void> onLoad() async {
super.onLoad();
add(Floor());
}
void onTapDown(TapDownInfo info) {
super.onTapDown(info);
if (Random().nextBool()) {
add(Ball());
} else {
add(Box());
}
}
}
If we run the previous code, the result is this:
Adding sprites
Let's make the scene of white boxes and balls more fun. First, we will add these two images to the assets folder:
Then, we update the pubspec.yaml
file to add the assets' path.
assets:
- assets/images/
We will load the sprites and store them in the cache. On the class GameLesson05
, we add this code to the
onLoad()
function:
Future<void> onLoad() async {
super.onLoad();
await loadSprite('ball.png');
await loadSprite('box.png');
add(Floor());
}
Now we must retrieve the loaded sprites from the cache and add them to the box and the ball.
Let's start by overriding the onLoad()
function from the Ball
class:
Future<void> onLoad() async {
await super.onLoad();
final sprite = Sprite(gameRef.images.fromCache('ball.png'));
add(
SpriteComponent(
sprite: sprite,
size: Vector2(.5, .5),
anchor: Anchor.center,
),
);
}
The previous code retrieves the image from the cache and creates a new Sprite
, then creates a new SpriteComponent
that will be in charge of drawing the image on top of the ball.
Updating the box code is very similar to the ball code. Let's take a look:
Future<void> onLoad() async {
await super.onLoad();
final sprite = Sprite(gameRef.images.fromCache('box.png'));
add(
SpriteComponent(
sprite: sprite,
size: Vector2(.5, .5),
anchor: Anchor.center,
),
);
}
Running the updated code will give us the following result:
Looks better right? Notice how Flame draws the sprites on top of the bodies, including updating the position, rotation, etc.