[Development Notes for Aircraft Wars Based on Flutter&Flame] Bullet upgrades and supplies

foreword

敌机ComponentAfter the reconstruction, the basic capabilities of aircraft warfare are basically formed. This article will make an upgrade, add bullet props子弹Component in the game , and deal with collisions with it .战机Component

The author has included this series of articles in the following columns, and interested students are welcome to read:

Development Notes for Aircraft Wars Based on Flutter&Flame

bullet characteristics

The front is just a simple definition of a class Bullet1, 子弹Componentaccording to the existing attributes, a bullet can be defined 父类Bullet, continue to use the abstract class here.

abstract class Bullet extends SpriteAnimationComponent with CollisionCallbacks {
  Bullet({required this.speed, required this.attack})
      : super(size: Vector2(5, 11));

  double speed;
  int attack;

  Future<SpriteAnimation> bulletAnimation();

  @override
  Future<void> onLoad() async {
    animation = await bulletAnimation();

    add(MoveEffect.to(
        Vector2(position.x, -size.y), EffectController(speed: speed),
        onComplete: () {
      removeFromParent();
    }));
    
    add(RectangleHitbox());
  }

  void loss() {
    removeFromParent();
  }
}
复制代码

The definition is relatively simple

  • Bullets have their own speed speedand damage attack.
  • fixed size = 5 * 11.
  • Since the textures of different bullets are different , define an abstract method to bulletAnimation()be loaded by subclasses.
  • Use to MoveEffectreplace the previous s = v * tcontrol movement, which was mentioned earlier. Here it is moved from the initial position (usually 战机Componentthe head) to the top of the screen .
  • loss()method is 敌机Componentcalled when a collision occurs with.

The above list is the common characteristics of current bullets.

upgrade bullet

In the game, you 战机Componentwill obtain enhanced bullets for a short time by obtaining props . expressed here类Bullet2

class Bullet2 extends Bullet {
  Bullet2({required super.speed, required super.attack});

  @override
  Future<SpriteAnimation> bulletAnimation() async {
    List<Sprite> sprites = [];
    sprites.add(await Sprite.load('bullet/bullet2.png'));
    final SpriteAnimation spriteAnimation =
        SpriteAnimation.spriteList(sprites, stepTime: 0.15);
    return spriteAnimation;
  }
}
复制代码

Here another texture will be loaded as the bullet's style.

Let's take a look at the final effect

VID_20220711191853_.gif

ammo supply

如上面的效果,游戏中会随机生成子弹补给。这里定义一个抽象类Supply补给Component的效果是匀速向下移动并带有小幅度的晃动

  • 匀速向下移动继续采用MoveEffect的方式。
  • 小幅度的晃动需要使用RotateEffect做一个小幅度的旋转。由于需要一个吊起来来回晃动的效果,所以我们还需要将锚点设置为topCenter,令旋转支点为上方居中的位置。

故最后的逻辑为

abstract class Supply extends SpriteComponent with HasGameRef {
  Supply({position, size})
      : super(position: position, size: size, anchor: Anchor.topCenter);

  @override
  Future<void> onLoad() async {
    add(MoveEffect.to(
        Vector2(position.x, gameRef.size.y), EffectController(speed: 40.0),
        onComplete: () {
      removeFromParent();
    }));

    add(RotateEffect.by(15 / 180 * pi,
        EffectController(duration: 2, reverseDuration: 2, infinite: true)));

    add(RectangleHitbox()..debugMode = true);
  }
}
复制代码
  • 移动距离是从屏幕最上方向屏幕最下方移动
  • 旋转角度是弧度,这里是(15 / 180)pi,需要来回晃动,所以这里设置了正反方向的持续时间且效果是无限循环的
  • 最后需要添加RectangleHitbox,作为与战机Component的碰撞检测。ps:碰撞检测的逻辑在子类实现,这里目前是类BulletSupply

子类的逻辑几乎只有碰撞检测,这个在下文会讲到,先来看看这个实现的效果 Record_2022-07-11-17-25-45_13914082904e1b7ce2b619733dc8fcfe_.gif

升级与恢复

子弹补给Component中,碰撞检测与战机Component发生碰撞后

  • 会触发其upgradeBullet()方法,此时会变更bulletType,即子弹类型。
  • 添加一个0.15sColorEffect,作为子弹升级的反馈
  • Turn on one Timer, timed 5s, as the bullet returns to normal timing . ps: _bulletUpgradeTimerset autoStart = false, do not allow automatic opening . When called start(), the progress will be reset , which can be understood as the timing of continuously obtaining supplies will be reset.
// class BulletSupply
@override
void onCollisionStart(
    Set<Vector2> intersectionPoints, PositionComponent other) {
  super.onCollisionStart(intersectionPoints, other);
  if (other is Player) {
    other.upgradeBullet();
    removeFromParent();
  }
}

// class Player
int bulletType = 1;

_bulletUpgradeTimer = Timer(5, onTick: _downgradeBullet, autoStart: false);

void upgradeBullet() {
  bulletType = 2;
  add(ColorEffect(Colors.blue.shade900, const Offset(0.3, 0.0),
      EffectController(duration: 0.15)));

  _bulletUpgradeTimer.start();
}

void _downgradeBullet() {
  bulletType = 1;
}

// timer.dart
/// Start the timer from 0.
void start() {
  reset();
  resume();
}
复制代码

Since 战机Componentit 类Playerhas a timer for firing bullets, after the bullet type is bulletTypemodified, the logic for the next bullet firing needs to be changed .

// class Player
void _addBullet() {
  if (bulletType == 2) {
    final Bullet2 bullet2 = Bullet2(speed: 400, attack: 2);
    bullet2.priority = 1;
    bullet2.position = Vector2(position.x + size.x / 2 - 10, position.y + 10);

    final Bullet2 bullet2a = Bullet2(speed: 400, attack: 2);
    bullet2a.priority = 1;
    bullet2a.position =
        Vector2(position.x + size.x / 2 + 10, position.y + 10);

    gameRef.add(bullet2);
    gameRef.add(bullet2a);
  } else {
    final Bullet1 bullet1 = Bullet1(speed: 200, attack: 1);
    bullet1.priority = 1;
    bullet1.position = Vector2(position.x + size.x / 2, position.y);
    gameRef.add(bullet1);
  }
}
复制代码

Supply generation

Remember that 敌机生成器EnemyCreator? Here temporarily through its timing to generate supplies

// class EnemyCreator
void _createEnemy() {
  final width = gameRef.size.x;
  double x = _random.nextDouble() * width;
  final double random = _random.nextDouble();
  if (random < 0.05) {
    final size = Vector2(60, 75);
    if (width - x < size.x / 2) {
      x = width - size.x / 2;
    } else if (x < size.x / 2) {
      x = size.x / 2;
    }
    final enemySupply =
        BulletSupply(position: Vector2(x, -size.y), size: size);

    add(enemySupply);
    return;
  }
  。。。
复制代码

It should be noted that since 补给Componentthe anchor point of ' is modified totopCenter , positionthe position of ' ' has also been moved totopCenter . The boundary calculation here needs to be adapted according to this situation.

at last

This article records the expansion of bullet types, the effect and generation of bullet supply, and战机Component the logic of bullet upgrades . So far, the functions of the aircraft war have basically been realized, and the remaining functions such as additional props, scoring system and health value system. In the future, we will consider modifying the structure of the entire project with reference to official blocexamples.

Guess you like

Origin juejin.im/post/7119401685138538510