持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第 14 天,点击查看活动详情
前言
这是一套 张风捷特烈 出品的 Flutter&Flame
系列教程,发布于掘金社区。如果你在其他平台看到本文,可以根据对于链接移步到掘金中查看。因为文章可能会更新、修正,一切以掘金文章版本为准。本系列源码于 【toly_game】 ,如果本系列对你有所帮助,希望点赞支持,本系列文章一览:
- 【Flutter&Flame 游戏 - 壹】开启新世界的大门
- 【Flutter&Flame 游戏 - 贰】操纵杆与角色移动
- 【Flutter&Flame 游戏 - 叁】键盘事件与手势操作
- 【Flutter&Flame 游戏 - 肆】精灵图片加载方式
- 【Flutter&Flame 游戏 - 伍】Canvas 参上 | 角色的血条
- 【Flutter&Flame 游戏 - 陆】暴击 Dash | 文字构件的使用
- 【Flutter&Flame 游戏 - 柒】人随指动 | 动画点触与移动
- 【Flutter&Flame 游戏 - 捌】装弹完毕 | 角色武器发射
- 【Flutter&Flame 游戏 - 玖】探索构件 | Component 是什么
- 【Flutter&Flame 游戏 - 拾】探索构件 | Component 生命周期回调
- 【Flutter&Flame 游戏 - 拾壹】探索构件 | Component 使用细节
- 【Flutter&Flame 游戏 - 拾贰】探索构件 | 角色管理
- 【Flutter&Flame 游戏 - 拾叁】碰撞检测 | CollisionCallbacks
- 【Flutter&Flame 游戏 - 拾肆】碰撞检测 | 之前代码优化
- 【Flutter&Flame 游戏 - 拾伍】粒子系统 | ParticleSystemComponent
- 【Flutter&Flame 游戏 - 拾陆】粒子系统 | 粒子的种类
- 【Flutter&Flame 游戏 - 拾柒】构件特效 | 了解 Effect 体系
- 【Flutter&Flame 游戏 - 拾捌】构件特效 | ComponentEffect 一族
- 【Flutter&Flame 游戏 - 拾玖】构件特效 | 了解 EffectController 体系
- 【Flutter&Flame 游戏 - 贰拾】构件特效 | 其他 EffectControler
- 【Flutter&Flame 游戏 - 贰壹】视差组件 | ParallaxComponent
- 【Flutter&Flame 游戏 - 贰贰】菜单、字体和浮层
未完待续
~
1. 碰撞检测场景搭建
前面我们 矩形域
和 中心点
的包含关系校验是否碰撞,这样会有很大的误差。Flame
中提供了 CollisionCallbacks
,对碰撞检测进行了封装,支持两个形状间的配置检测。本文我们就来认识一下该如何使用这个 mixin
。
为了更好地说明碰撞,这里先用图形进行简单示意,本文将在这个场景的基础上进行测试。如下所示,定义一个 Cilrcle
构件和 Line
构件,其中 Line
的位置可以随着触点的拖动而更新:代码详见 【13/01】
https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/6a53412be96245fd8e13ba6e2cf0fd4c~tplv-k3u1fbpfcp-zoom-in-crop-mark:1304:0:0:0.awebp?
如下 TolyGame
中有 Line
和 Circle
两个角色,混入 PanDetector
。覆写 onPanUpdate
方法,在触点更新时,增加 line
的位移。 另外目前 Circle
和 Line
两个构件都只是覆写 render
方法,进行绘制而已,没什么要点,代码就不贴了,详见源码。
class TolyGame extends FlameGame with PanDetector{
late Line line;
late Circle circle;
@override
Future<void> onLoad()async{
circle = Circle(radius: 40, position: size/2);
line = Line(lineWidth: 80,position: size/2-Vector2(140,0));
add(circle);
add(line);
}
@override
void onPanUpdate(DragUpdateInfo info) {
line.position =info.delta.global;
}
}
复制代码
2. 如何让构件支持碰撞检测
如下所示,直线代表 矩形域
,圆形代表 圆形域
,当两个区域发成重叠时,则发生碰撞。代码详见【13/02】
https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/ff2f7b5f6c6a4a8c895100ab27b2d7c8~tplv-k3u1fbpfcp-zoom-in-crop-mark:1304:0:0:0.awebp?
首先说明一点:顶层的 TolyGame
需要混入 HasCollisionDetection
才可以支持碰撞检测。
class TolyGame extends FlameGame with HasCollisionDetection,PanDetector{
复制代码
另外,想让某个 Compoment
支持碰撞检测,需要三个步骤:
1. 混入 `CollisionCallbacks` :
代码语言:javascript复制class Circle extends PositionComponent with CollisionCallbacks{
复制代码
代码语言:txt复制1. 添加检测区域 `Hitbox` : 这个区域就是代表着当前构建件的命中区域。
代码语言:javascript复制late ShapeHitbox hitbox;
@override
Future<void> onLoad() async {
hitbox = CircleHitbox();
add(hitbox);
}
复制代码
- 3.覆写碰撞检测回调方法:
CollisionCallbacks
中有三个碰撞回调的方法,可以监听到碰撞开始、碰撞结束、发生碰撞三个事件。
如下,在 Circle
构件中,覆写 onCollisionStart
方法,当开始发送碰撞时,将圆的颜色置为 blue
;碰撞结束时,将圆的颜色置为 white
。
@override
void onCollisionStart(
Set<Vector2> intersectionPoints,
PositionComponent other,
) {
super.onCollisionStart(intersectionPoints, other);
_paint.color = Colors.blue;
}
@override
void onCollisionEnd(PositionComponent other) {
super.onCollisionEnd(other);
_paint.color = Colors.white;
}
复制代码
3.碰撞形状
其实这样看来,碰撞检测最重要的还是碰撞区域的确定。在 Flame
的 collisions/hitboxes
中只提供了一些常用的形状,比如 圆形
、多边形
、矩形
、屏幕
。感觉还是挺有局限性的,如果能加上 Path
自定义形状就好了。
其中我们在之前已经见识过了 RectangleHitbox
,提供将它的 debugMode
置为 true
,就可以看到边界信息。其实本质上就是为该构件确定一个碰撞检测的区域:
下面我们通过一个案例来测试一下 多边形
和 屏幕边界
的碰撞检测:【13/03】
https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/3ccb979755574670b093c7ac21c3e991~tplv-k3u1fbpfcp-zoom-in-crop-mark:1304:0:0:0.awebp?
如下定义一个菱形的 PolygonHitbox
,主要就是根据顶点,确定多边形。这样当一个 CollisionCallbacks
的角色和其碰撞,就可以接收到 onCollisionXXX
的回调。
---->[Polygon]----
late ShapeHitbox hitbox;
@override
Future<void> onLoad() async {
hitbox = PolygonHitbox([
Vector2(size.x, size.y/2),
Vector2(size.x/2, size.y),
Vector2(0, size.y/2),
Vector2(size.x/2, 0),
]);
add(hitbox);
}
复制代码
最后看一下 ScreenHitbox
,它本质上非常简单,就是在最外层添加一个 RectangleHitbox
而已。
总得来说,通过 CollisionCallbacks
实现碰撞的检测,本质就是定义碰撞物的区域。然后根据碰撞的回调处理逻辑而已,其实 CollisionCallbacks
也是比较有局限性的。但相比于之前的 矩形域
和 中心点
的包含关系,可以说上升了一个维度,支持了 域
和 域
之间的碰撞。
本文介绍了一下 Flame
中通过 CollisionCallbacks
实现碰撞检测的方式,下一篇我们将基于这种方式来对前面的案例进行优化。那本文就到这里,明天见 ~
@张风捷特烈 2022.06.07 未允禁转
我的 掘金主页
: 张风捷特烈我的 B站主页
: 张风捷特烈我的 github 主页
: toly1994328