Ara afegirem la bola i farem que es mogui per la pantalla. Després hi afegirem la detecció de col·lisions.
És molt recomanable definir les dimensions principals dels components en valors relatius a les dimensions de l'àrea de joc; així, si canviem les dimensions d'aquesta, els elements s'hi adaptaran automàticament.
config.dart
const gameWidth = 820.0; const gameHeight = 1600.0; const ballRadius = gameWidth * 0.02;
També hem de definir el color de la bola.
colors.dart
import 'dart:ui';
class ColorsApp {
static const Color fons = Color(0xFFFFEECC);
static const Color bola = Color(0xFFFF6699);
}
A la carpeta components creem el fitxer bola.dart on posarem un CircleComponent on definirem l'aspecte de la bola, indicarem que les coordenades de posició corresponen al seu centre i establirem com canvia la posició a partir de la velocitat. La velocitat es defineix com un vector, perquè cal establir-ne la direcció.
bola.dart
import 'package:flame/components.dart'; import 'package:flutter/material.dart'; import 'package:joc_breakout/core/colors.dart';
class Bola extends CircleComponent {
Bola({
required this.velocity,
required super.position, // El paràmetre accedirà directament a l'original
required double radius,
}) : super(
radius: radius,
anchor: Anchor.center,
paint: Paint()
..color = ColorsApp.bola
..style = PaintingStyle.fill,
);
final Vector2 velocity;
@override
void update(double dt) {
super.update(dt);
position += velocity * dt;
}
}
Un cop definida la bola, l'haurem d'afegir en el fitxer de components.
components.dart
export 'bola.dart'; export 'play_area.dart';
Per tal que es vegi, l'haurem d'incorporar al joc. La posició inicial és al centre de l'àrea de joc, la velocitat vertical és un valor constant calculat a partir de l'alçada i la velocitat horitzontal és un valor amb signe calculat a partir de l'amplada i d'un nombre aleatori. El paràmetre (en aquest cas, 0.2) normalment es defineix a base de fer proves. Un cop tenim el vector, el normalitzem (el reduïm a un vector de mòdul unitari) i després l'escalem a un quart de l'alçada de l'àrea de lloc.
En aquest cas, a més, hem activat el mode de depuració, de manera que, al costat de la bola, hi veurem les seves coordenades.
breakout.dart
import 'dart:async'; import 'dart:math' as math; import 'package:flame/components.dart'; import 'package:flame/game.dart'; import 'components/components.dart'; import 'config.dart';
class Breakout extends FlameGame {
Breakout()
: super(
camera: CameraComponent.withFixedResolution(
width: gameWidth,
height: gameHeight,
),
);
final rand = math.Random(); // Generador de valors aleatoris
double get width => size.x;
double get height => size.y;
@override
FutureOr<void> onLoad() async {
super.onLoad();
camera.viewfinder.anchor = Anchor.topLeft;
world.add(PlayArea());
world.add(Bola(
radius: ballRadius,
position: size / 2, // Centre de l'àrea de joc
velocity: Vector2(
(rand.nextDouble() - 0.5) * width,
height * 0.2,
).normalized()..scale(height / 4),
));
debugMode = true; // Línia provisional
}
}
Quan executem aquest programa veurem aparèixer la pilota al mig i es desplaçarà cap avall però amb una direcció diferent cada vegada.

Aquesta obra d'Oriol Boix està llicenciada sota una llicència no importada Reconeixement-NoComercial-SenseObraDerivada 3.0.