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


theme: cyanosis

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


前言

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

第一季完结,谢谢支持 ~


1. 管理怪兽

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


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

dart 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 方法在左右分别遍历三个小怪。创建和添加 Monster 的方式和前面是一样的,这里就不赘述了,详见源码。

dart @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】

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

```dart 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 中封装的,不是 Flutter 自带的。如下 Monster 的各个生命周期中对 Timer 进行相关处理:onLoad 方法中初始化 _timer 对象,隔 3 s 钟触发一次 addBullet 方法添加子弹。onMount 方法中开启 _timeronRemove 中停止 _timer

```dart ---->[Monster]---- late Timer _timer;

@override Future 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 方法,和之前主角发射子弹的逻辑基本一致:

dart // 添加子弹 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】

目前仍是校验 矩形域中心点 的包含关系来判定是否命中。如下,在 update 中通过 _checkAttackHero 校验是否命中,命中时 player 触发 loss 方法掉血。

```dart ---->[TolyGame#update]---- @override void update(double dt) { super.update(dt); _checkAttackMonster(); _checkAttackHero(); }

void _checkAttackHero() { final Iterable bullets = children .whereType () .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 有了较深的理解。接下来将进一步探讨 碰撞检测 相关的知识,毕竟现在靠的是 矩形域中心点 的包含关系,并不是非常准确。那本文就到这里,明天见 ~

\

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值