Aplicacions amb Flutter, Dart i Flame

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

Incorporem dificultat progressiva

Ara farem que la dificultat vagi augmentant progressivament. En concret, cada cop que s'elimini un totxo la bola anirà una mica més ràpid.

El primer que farem serà definir un coeficient, més gran que la unitat, pel que multiplicarem la velocitat cada vegada que desaparegui un totxo. El valor d'aquest paràmetre s'obté fent proves.

config.dart
const gameWidth = 820.0;
const gameHeight = 1600.0;
const ballRadius = gameWidth * 0.02;
const batWidth = gameWidth * 0.2;
const batHeight = ballRadius * 2;
const batStep = gameWidth * 0.05;
const numTotxosFilera = 10;
const juntaTotxos = gameWidth * 0.015;
final brickWidth = (gameWidth - (juntaTotxos * (numTotxosFilera + 1))) / numTotxosFilera;
const brickHeight = gameHeight * 0.03;
const factorDif = 1.03;

A la bola, hem d'afegir el factor com a paràmetre i modificar la velocitat quan correspongui.

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 CircleComponent 
    with CollisionCallbacks, HasGameReference<Breakout> {
  Bola({
    required this.velocity,
    required super.position,
    required double radius,
    required this.factorDificultat,
  }) : super(
        radius: radius,
        anchor: Anchor.center,
        paint: Paint()
          ..color = ColorsApp.bola
          ..style = PaintingStyle.fill,
        children: [CircleHitbox()],
      );

  final Vector2 velocity;
  final double factorDificultat;

  @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));
      }
    } 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);
    }
  }
}

I en el joc hem de passar el paràmetre a la bola.

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';
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(
      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
    await world.addAll([
      for (var i = 0; i < numTotxosFilera; i++)
        for (var j = 0; j < ColorsApp.colorsTotxos.length; j++)
          Totxo(
            position: Vector2(
              (i + 0.5) * brickWidth + (i + 1) * juntaTotxos,
              (j + 1 + 2.0) * brickHeight + (j + 1) * juntaTotxos,
            ),
            color: ColorsApp.colorsTotxos[j],
          ),
    ]);
    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;
  }
}

 

 

 

 

 

 

 

 

 

 

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