Ara afegirem la detecció de les col·lisions amb les vores de l'àrea de joc. Quan la pilota toqui les vores laterals o la vora superior, rebotarà; és a dir, invertirem el signe de la seva velocitat en el sentit en el qual s'ha provocat el xoc. En el cas de la vora inferior, farem desaparèixer la bola ja que, quan hi hagi la pala, això correspondrà a que el jugador ha fallat.
El primer que hem de fer és activar, en la definició del joc, la detecció de col·lisions.
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 with HasCollisionDetection {
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
}
}
Atès que l'àrea de joc no es mou i tampoc s'ha de modificar en cas de col·lisió, només cal definir-li l'àrea de detecció.
play_area.dart
import 'dart:async'; import 'package:flame/components.dart'; import 'package:flutter/material.dart'; import 'package:flame/collisions.dart'; import 'package:joc_breakout/core/colors.dart'; import '../breakout.dart';
class PlayArea extends RectangleComponent with HasGameReference<Breakout> {
PlayArea() : super(
paint: Paint()
..color = ColorsApp.fons,
children: [RectangleHitbox()],
);
@override
FutureOr<void> onLoad() async {
super.onLoad();
size = Vector2(game.width, game.height);
}
}
En el cas de la pilota, a banda de l'àrea de detecció, cal definir què passa quan hi ha una col·lisió. De moment, només hi ha possibilitat de col·lisions amb l'àrea de joc; però hem deixat a punt una alternativa per quan hi pugui haver més opcions. Quan s'escapa per la part inferior, fem que la bola desaparegui.
bola.dart
import 'package:flame/collisions.dart'; import 'package:flame/components.dart'; import 'package:flutter/material.dart'; import 'package:joc_breakout/breakout.dart'; import 'package:joc_breakout/components/play_area.dart'; import 'package:joc_breakout/core/colors.dart';
class Bola extends CircleComponent
with CollisionCallbacks, HasGameReference<Breakout> {
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,
children: [CircleHitbox()],
);
final Vector2 velocity;
@override
void update(double dt) {
super.update(dt);
position += velocity * dt;
}
@override
void onCollisionStart(
Set<Vector2> intersectionPoints,
PositionComponent other,
) {
super.onCollisionStart(intersectionPoints, other);
if (other is PlayArea) {
if (intersectionPoints.first.y <= 0) {
velocity.y = -velocity.y;
} else if (intersectionPoints.first.x <= 0) {
velocity.x = -velocity.x;
} else if (intersectionPoints.first.x >= game.width) {
velocity.x = -velocity.x;
} else if (intersectionPoints.first.y >= game.height) {
removeFromParent();
}
} else {
debugPrint('collision with $other');
}
}
}

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