持续创作,加速成长!这是我参与「日新计划 6 月更文挑战」的第 13 天,点击查看活动详情


前言

这是一套 张风捷特烈 出品的 Flutter&Flame 系列教程,发布于社区。如果你在其他平台看到本文,可以根据对于链接移步到中查看。因为文章可能会更新、修正,一切canvas下载以文章版canvas网页版本为准。本系列文章一览:

  • 【Flutter&Flame 游戏 – 壹】开启新世界的大门
  • 【Flutter&Flame 游戏初始化电脑 – 贰】操纵杆与角色移动
  • 【Flutter&Flame 游戏 – 叁】键盘事件与手势canvas什么意思操作
  • 【Flutter&Flame 游戏 – 肆】精灵图片加载方式教程魔方
  • 【Flutter&Flame 游戏 – 伍】Canvas 参上 | 角色的血条
  • 【Flu动画片汪汪队tter&Flame 游戏 – 陆】暴击 Dash | 文字构件的使用
  • 【Flutter&Flame 游戏 – 柒动画专业】人随指动 | 动画点触与移动
  • 【Flutter&Flame游戏 – 捌】装弹完毕 | 角色武器发射
  • 【Flutter&Flame游戏 – 玖】初始化电脑探索构件 | Component 是什么
  • 【Flutter&Flame游戏 – 拾】探索构件 | Component 生命周期回调
  • 【Flutter&am源码时代p;Flame游戏 – 拾壹】探索构件 | Component动画片小猪佩奇 使用细节
  • 【Flutter&amcanvas网页版p;Flame游戏 – 拾贰】探索构件 | 角色管理(本文)

1. 管理怪兽

前面把 Monster 全写在 TolyGame 中,看起来很杂乱。一个场景中可能教程之家存在多个怪兽,比如下面六个小怪和一个 Boss 。我们可动画片少儿小猪佩奇以通教程之家过自定义一个 MonsterManager教程画画 构件对这些怪动画片汪汪队兽进行管理:代码详见【12/01】

【Flutter&Flame游戏 - 拾贰】探索构件 | 角色管理


MonsterManager 中通过入参将小怪和 Boss 的序列帧传入,这样可以中使用时自定义序列帧:

class MonsterManager extends PositionComponent with HasGameRef {
  final SpriteSheet bossSpriteSheet;
  final SpriteSheet stoneSpriteSheet;
  MonsterManager({
    required this.bossSpriteSheet,
    required this.stoneSpriteSheet,
  }):super(anchor: Anchor.center);

onLoad 方法中,通过 createBoss 方法创建并添加 Boss 构件,然后通过 createStoneMonster 方法在左源码中的图片右分canvas翻译别遍历三动画片小猪佩奇个小怪。创建和添加 Monster 的方式和前面是一样的,这里就不赘述了,详见源码。

@override
Future<void> onLoad() async {
  createBoss();
  int lineCount =3;
  double step = gameRef.size.y/lineCount ;
  for(int i=1;i<=lineCount;i++){
    final double pY = i*step- 30;
    final double pX = gameRef.size.x - 200;
    createStoneMonster(Vector2(pX, pY));
  }
  for(int i=1;i<=lineCount;i++){
    final double pY = i*step- 30;
    final double pX = 150;
    createStoneMonster(Vector2(pX, pY));
  }
}

2. 怪兽发射子弹

现在怪物站在那傻乎乎的被打很不公平,动画片汪汪队下面看看如何让怪兽发射子弹。这里用来两个序列帧动画作为子弹的资源,如下图所示:代码详初始化游戏启动器失败见【12/02】

【Flutter&Flame游戏 - 拾贰】探索构件 | 角色管理

其实本质上,怪物发射子弹和主角发射子弹本质上是一样的。不同点在于,主角子弹发送是用户控制的,动画头像怪物一般是定时发射子弹。另外,要区分一下子弹的类教程拼音型,是怪物发射的,还是主角发射的。之前角色的弓箭是静态图动画专业片,这里可以定义一个 AnimBullet 来支持序列帧的子弹:

enum BulletType{
  hero,
  monster
}
class AnimBullet extends SpriteAnimationComponent {
  double speed = 200;
  final double maxRange;
  final BulletType type;
  final bool isLeft;
  AnimBullet({
    required SpriteAnimation animation,
    required this.maxRange,
    required this.type,
    required this.speed,
    this.isLeft = true,
  }) : super(animation : animation);
  // 略同...

然后看一下如何通过 Timer 来定时不断发射子弹,这里的 TimerFlame 中封装的,不是 Fluttecanvasr 自带的。如下 Monster 的各个生命周期中对 Timer 进行相关处理:onLoad 方法中教程之家初始化 _timer 对象Canvas,隔 3 s 钟触发一次 addBulcanvas英语let 方法添加子弹。onMount 方法中开启 _timeronRemove 中停止 _timer

---->[Monster]----
late Timer _timer;
@override
Future<void> onLoad() async {
  _timer = Timer(3, onTick: addBullet, repeat: true);
}
@override
void onMount() {
  super.onMount();
  _timer.start();
}
@override
void update(double dt) {
  super.update(dt);
  _timer.update(dt);
}
@override
void onRemove() {
  super.onRemove();
  _timer.stop();
}

如下是 addBullet 方法,和初始化sdk什么意思之前主角发射子弹的逻辑基本一致:

// 添加子弹
void addBullet() {
  AnimBullet bullet = AnimBullet(
    type: BulletType.monster,
    animation: bulletSprite,
    maxRange: attr.attackRange,
    speed: attr.attackSpeed,
    isLeft: isLeft,
  );
  bullet.size = bulletSize;
  bullet.anchor = Anchor.center;
  bullet.priority = 1;
  priority = 2;
  bullet.position = position - Vector2(0, size.y/2);
  gameRef.add(bullet);
}

3.怪兽发射的命中

如下所示,在怪物发射的子弹命中主角时,主角也会受到伤害。生命值降低,并且显示伤教程英语害数值:代码详见【12/03】

【Flutter&Flame游戏 - 拾贰】探索构件 | 角色管理

目前仍是校验 矩形域中心点 的包含关系来判定是否命中。如下,在 update 中通过 _checkAtt初始化失败是怎么解决ackHero 校验是否命中,命中时 p初始化失败是怎么解决layer 触发 loss 方法掉血。

---->[TolyGame#update]----
@override
void update(double dt) {
  super.update(dt);
  _checkAttackMonster();
  _checkAttackHero();
}
void _checkAttackHero() {
  final Iterable<AnimBullet> bullets = children
      .whereType<AnimBullet>()
      .where((AnimBullet e) => e.type == BulletType.monster);
  for (AnimBullet bullet in bullets) {
    if (bullet.shouldRemove) {
      continue;
    }
    if (player.containsPoint(bullet.absoluteCenter) ||
        bullet.containsPoint(player.absoluteCenter)) {
      bullet.removeFromParent();
      player.loss(bullet.attr);
      break;
    }
  }
}

到这里,我们已经完成了 主角怪物 间的基本交互,也基本上对 Component 有了较深的理解。接教程之家提取码下来将进一步探讨 碰撞检测 相关的知识,毕竟现在靠的是 矩形域中心点 的包含关系,并不是非常准确。那本文就到这初始化里,明天见 ~

  • @张风捷特烈 2022.06.06 未允禁转
  • 初始化的 公众号: 编程之王
  • 我的 主页 : 张风捷特烈
  • 我的 B站主页 : 张风捷特烈
  • 我的 github 主页 : toly1994328