Aplicacions amb Flutter, Dart i Flame

Tutorial Flutter Flame Projectes   Recursos CITCEA
Exemples Dart Dades pràctiques     Inici

Fem que els totxos siguin sprites

Ara farem que els totxos siguin sprites. Això ens permetrà fer servir un fitxer gràfic i així cada totxo no serà un simple rectangle sinó que li podrem donar l'aspecte que vulguem.

El primer que necessitem és els fitxers amb la imatge dels totxos. Si tenim cinc colors de totxo, ens caldran cinc imatges. Aquestes són les imatges que farem servir, amb el fons transparent. És important que l'objecte, en aquest cas el totxo, 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 rectangular.

Totxo         Totxo         Totxo         Totxo         Totxo

Per baixar-les, pots picar sobre cada imatge amb el botó dret i guardar-la a l'ordinador.

Ara hem de modificar el fitxer totxo.dart per eliminar les coses específiques del RectangleComponent i substituir-les per les de l'sprite. Hi haurà importacions que ja no necessitarem.

totxo.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/config.dart';
import 'bola.dart';
import 'pala.dart';
//class Totxo extends RectangleComponent
class Totxo extends SpriteComponent
    with CollisionCallbacks, HasGameReference<Breakout> {
  // Ara demanem el nom del fitxer de la imatge en lloc del Color
  //Totxo({required super.position, required Color color})
  Totxo({required super.position, required this.imatge})
    : super(
        size: Vector2(brickWidth, brickHeight),
        anchor: Anchor.center,
        //paint: Paint()
          //..color = color
          //..style = PaintingStyle.fill,
        // Eliminem el detector de col·lisions, perquè ara va a un altre lloc
        //children: [RectangleHitbox()],
      );

  // Afegim la variable per al nom de la imatge
  final String imatge;

  // En carregar l'sprite, definim el fitxer i el detector de col·lisions
  @override
  Future<void> onLoad() async {
    super.onLoad();
    // Carrega l'sprite rebut pel constructor
    sprite = await game.loadSprite(imatge);
    // Afegim la caixa de col·lisions
    add(RectangleHitbox());
  }

  @override
  void onCollisionStart(
    Set<Vector2> intersectionPoints,
    PositionComponent other,
  ) {
    super.onCollisionStart(intersectionPoints, other);
    removeFromParent();
    game.punts.value++;
    // Mira si era el darrer totxo
    if (game.world.children.query<Totxo>().length == 1) {
      game.playState = PlayState.guanya;
      game.world.removeAll(game.world.children.query<Bola>());
      game.world.removeAll(game.world.children.query<Pala>());
    }
  }
}

En el fitxer de definició del joc (breakout.dart) hem de definir una llista amb les imatges que farem servir i modificar els bucles per treballar amb imatges en lloc de colors.

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 'package:joc_breakout/core/colors.dart';
import 'components/components.dart';
import 'config.dart';
enum PlayState {inici, jugant, fi, guanya}

// Fem una llista amb les imatges dels totxos
final llistaImatgesTotxos = [
  'totxo_blau.png',
  'totxo_verd.png',
  'totxo_groc.png',
  'totxo_taronja.png',
  'totxo_roig.png',
];

class Breakout extends FlameGame 
    with HasCollisionDetection, KeyboardEvents, TapCallbacks {
  Breakout()
    : super(
        camera: CameraComponent.withFixedResolution(
          width: gameWidth,
          height: gameHeight,
        ),
      );

  final ValueNotifier<int> punts = ValueNotifier(0);
  final rand = math.Random();  // Generador de valors aleatoris
  double get width => size.x;
  double get height => size.y;
  late PlayState _playState;
  PlayState get playState => _playState;
  set playState(PlayState playState) {
    _playState = playState;
    switch (playState) {
      case PlayState.inici:
      case PlayState.fi:
      case PlayState.guanya:
        overlays.add(playState.name);
      case PlayState.jugant:
        overlays.remove(PlayState.inici.name);
        overlays.remove(PlayState.fi.name);
        overlays.remove(PlayState.guanya.name);
    }
  }

  @override
  FutureOr<void> onLoad() async {
    super.onLoad();
    camera.viewfinder.anchor = Anchor.topLeft;
    world.add(PlayArea());
    playState = PlayState.inici;
  }

  void startGame() {
    if (playState == PlayState.jugant) return;
    world.removeAll(world.children.query<Bola>());
    world.removeAll(world.children.query<Pala>());
    world.removeAll(world.children.query<Totxo>());
    playState = PlayState.jugant;
    punts.value = 0;
    world.add(Bola(
      factorDificultat: factorDif,
      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),
      ),
    );
    // Afegim els totxos amb dos bucles
    world.addAll([
      for (var i = 0; i < numTotxosFilera; i++)
        //for (var j = 0; j < ColorsApp.colorsTotxos.length; j++)
        for (var j = 0; j < llistaImatgesTotxos.length; j++)
          Totxo(
            position: Vector2(
              (i + 0.5) * brickWidth + (i + 1) * juntaTotxos,
              (j + 1 + 2.0) * brickHeight + (j + 1) * juntaTotxos,
            ),
            //color: ColorsApp.colorsTotxos[j],
            // Passem el nom del fitxer que correspon a la fila j
            imatge: llistaImatgesTotxos[j],
          ),
    ]);
  }

  @override
  void onTapDown(TapDownEvent event) {
    super.onTapDown(event);
    startGame();
  }

  @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);
      case LogicalKeyboardKey.space:
      case LogicalKeyboardKey.enter:
        startGame();
    }
    return KeyEventResult.handled;
  }

  @override
  Color backgroundColor() => ColorsApp.fons;
}

Ara en el fitxer colors.dart podem eliminar la llista dels colors dels totxos; encara que, si no ho fem, no afecta al funcionament del joc.

Quan executem aquest programa veurem que ara els totxos tenen un aspecte diferent.

 

 

 

 

 

 

 

 

 

 

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