Fins ara, els nostres components (àrea de joc, bola i pala) eren figures bàsiques (RectangleComponent o CircleComponent); però ens pot interessar fer servir altres formes, en quin cas caldrà emprar el component genèric PositionComponent i definir específicament la forma. Com a aexemple, anem a fer que la pala sigui un rectangle amb les vores arrodonides.
Ara, doncs, la pala es basarà en un PositionComponent i li afegirem un paràmetre que serà el radi de curvatura de les cantonades. Ara les instruccions per pintar el rectangle estaran en una funció a banda (_paint) que s'haurà de cridar al mètode render, que caldrà sobrescriure per tal que el rectangle es representi.
pala.dart
import 'package:flame/collisions.dart'; import 'package:flame/components.dart'; import 'package:flame/effects.dart'; import 'package:flame/events.dart'; import 'package:flutter/material.dart'; import 'package:joc_breakout/breakout.dart'; import 'package:joc_breakout/core/colors.dart';
class Pala extends PositionComponent
with DragCallbacks, HasGameReference<Breakout> {
Pala({
required this.cornerRadius,
required super.position,
required super.size,
}) : super(
anchor: Anchor.center,
children: [RectangleHitbox()]
);
final Radius cornerRadius;
final _paint = Paint()
..color = ColorsApp.pala
..style = PaintingStyle.fill;
@override
void render(Canvas canvas) {
super.render(canvas);
canvas.drawRRect(
RRect.fromRectAndRadius(Offset.zero & size.toSize(), cornerRadius),
_paint,
);
}
@override
void onDragUpdate(DragUpdateEvent event) {
super.onDragUpdate(event);
position.x = (position.x + event.localDelta.x).clamp(0, game.width);
}
void moveBy(double dx) {
add(
MoveToEffect(
Vector2((position.x + dx).clamp(0, game.width), position.y),
EffectController(duration: 0.1),
),
);
}
}
En la definició del joc, caldrà afegir el nou paràmetre.
breakout.dart
import 'dart:async'; import 'dart:math' as math; import 'package:flame/components.dart'; import 'package:flame/events.dart'; import 'package:flame/game.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'components/components.dart'; import 'config.dart';
class Breakout extends FlameGame
with HasCollisionDetection, KeyboardEvents {
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),
));
world.add(
Pala(
size: Vector2(batWidth, batHeight),
cornerRadius: const Radius.circular(ballRadius / 2),
position: Vector2(width / 2, height * 0.95),
),
);
debugMode = true; // Línia provisional
}
@override
KeyEventResult onKeyEvent(
KeyEvent event,
Set<LogicalKeyboardKey> keysPressed,
) {
super.onKeyEvent(event, keysPressed);
switch (event.logicalKey) {
case LogicalKeyboardKey.arrowLeft:
world.children.query<Pala>().first.moveBy(-batStep);
case LogicalKeyboardKey.arrowRight:
world.children.query<Pala>().first.moveBy(batStep);
}
return KeyEventResult.handled;
}
}
A banda de la forma de la pala, el funcionament del joc es manté.

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