Ara farem que la bola sigui un sprite. Això ens permetrà fer servir un fitxer gràfic i així la bola no serà un simple cercle sinó que li podrem donar l'aspecte que vulguem.
El primer que necessitem és el fitxer amb la imatge de la bola. A l'esquerra tenim la imatge que farem servir, amb el fons transparent, i a la dreta la imatge amb fons gris. És important que l'objecte, en aquest cas la bola, ocupi quasi tot el rectamgle gràfic i escollir un detector de col·lisions apropiat; en cas contrari les col·lisions es veuran estranyes. En aquest cas, ens cal un detector circular.

Per baixar-la, pots picar sobre la imatge de l'esquerra amb el botó dret i guardar-la a l'ordinador.
En aquest cas farem servir el mètode asset per mostrar la imatge; per tant, cal crear una carpeta anomenada assets en l'arrel del projecte i una carpeta images dins d'assets. Per crear la primera carpeta, posarem el cursor en la zona buida que hi ha sota de README.md, picarem amb el botó dret i triarem New Folder...; per crear la segona només cal que ens posem sobre la primera i piquem el botó de nova carpeta que hi ha a la part superior del menú lateral.
Ara haurem d'arrossegar la imatge des de la carpeta de l'ordinador fins deixar-la sobre la carpeta images que acabem de crear; així la tindrem disponible en el nostre projecte.
També cal indicar a quina carpeta trobarà la imatge. Això ho farem editant el fitxer pubspec.yaml, afegint-li dues línies a la part de Flutter, sota les ja existents.
flutter:
uses-material-design: true
assets:
- assets/images/
En aquest fitxer és molt important la sintaxi. Fixem-nos que assets està alineat amb uses. A l'inici de la línia següent hi ha un sagnat, un guió i un espai, després ja ve la ruta.
Ara ja només ens queda modificar el fitxer bola.dart per eliminar les coses específiques del CircleComponent i substituir-les per les de l'sprite.
bola.dart
import 'package:flame/collisions.dart'; import 'package:flame/components.dart'; import 'package:flame/effects.dart'; //import 'package:flutter/material.dart'; import 'package:joc_breakout/breakout.dart'; import 'package:joc_breakout/components/pala.dart'; import 'package:joc_breakout/components/totxo.dart'; import 'package:joc_breakout/components/play_area.dart'; //import 'package:joc_breakout/core/colors.dart';
class Bola extends SpriteComponent
with CollisionCallbacks, HasGameReference<Breakout> {
Bola({
required this.velocity,
required super.position,
required double radius,
required this.factorDificultat,
}) : super(
// Canviem el radi per la mida
//radius: radius,
// Posem el diàmetre (doble del radi) en les dues direccions
size: Vector2.all(radius * 2),
anchor: Anchor.center,
// Eliminem la definició de color i estil, pròpies del cercle
//paint: Paint()
// ..color = ColorsApp.bola
// ..style = PaintingStyle.fill,
// Eliminem el detector de col·lisions, perquè ara va a un altre lloc
//children: [CircleHitbox()],
);
final Vector2 velocity;
final double factorDificultat;
// En carregar l'sprite, definim el fitxer i el detector de col·lisions
@override
Future<void> onLoad() async {
super.onLoad();
// Carrega la imatge de la bola des d'assets/images/bola.png
sprite = await game.loadSprite('bola.png');
// Mantenim el detector de col·lisions circular ajustat a la mida de la imatge
add(CircleHitbox());
}
@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) {
add(
RemoveEffect(
delay: 0.35,
onComplete: () {
game.playState = PlayState.fi;
},
),
);
}
} else if (other is Pala) {
velocity.y = -velocity.y;
velocity.x =
velocity.x +
(position.x - other.position.x) / other.size.x * game.width * 0.3;
} else if (other is Totxo) {
if (position.y < other.position.y - other.size.y / 2) {
velocity.y = -velocity.y;
} else if (position.y > other.position.y + other.size.y / 2) {
velocity.y = -velocity.y;
} else if (position.x < other.position.x) {
velocity.x = -velocity.x;
} else if (position.x > other.position.x) {
velocity.x = -velocity.x;
}
velocity.setFrom(velocity * factorDificultat);
}
}
}
Ara en el fitxer colors.dart podem eliminar el color de la bola; encara que, si no ho fem, no afecta al funcionament del joc.
Quan executem aquest programa veurem que ara la bola té un aspecte diferent.

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