前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【Flutter&Flame 游戏 - 叁】手势操作与键盘事件

【Flutter&Flame 游戏 - 叁】手势操作与键盘事件

作者头像
张风捷特烈
发布2022-09-20 10:18:37
1.2K0
发布2022-09-20 10:18:37
举报

前言

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


1. 键盘事件

Flutter 作为跨平台的开发框架,本身有键盘的监听行为。Flame 中的键盘事件也只是对 Flutter 原生的一层封装而已,还是非常好理解的。这里我们先来实现如下的效果:按 Y 键时,让角色以自身中心沿 y 轴 反转; 按 X 键时,让角色以自身中心沿 x 轴 反转:代码在 【03/01】


首先介绍一下 Flame 对键盘事件的封装,可以看出是以 mixin 的方式提供回调实现的。注意一点,因为只是 on Game ,示意只有 Game 一族的类才可以混入。


前面知道 FlameGame 中混入了 Game ,所以是 Game 一族。这里 TolyGame 就可以混入 KeyboardEvents 。然后通过覆写 onKeyEvent 方法,来监听键盘事件。其中 RawKeyEvent 有两种类型:RawKeyDownEvent 表示按键按下;RawKeyUpEvent 表示按键抬起,代码如下:

代码语言:javascript
复制
---->[03/01]----
class TolyGame extends FlameGame with KeyboardEvents{
  late final HeroComponent player;

  @override
  Future<void> onLoad() async {
    player = HeroComponent();
    add(player);
  }

  @override
  KeyEventResult onKeyEvent(
      RawKeyEvent event,
      Set<LogicalKeyboardKey> keysPressed,
      ) {
    final isKeyDown = event is RawKeyDownEvent;
    if (event.logicalKey == LogicalKeyboardKey.keyY&amp;&amp;isKeyDown) {
                    //TODO 反转Y
    }
    if (event.logicalKey == LogicalKeyboardKey.keyX&amp;&amp;isKeyDown) {
              //TODO 反转X
    }
    return super.onKeyEvent(event, keysPressed);
  }
}

2. 角色的镜像反转

上一篇介绍过角色的 移动旋转 ,这里来看一下通过 缩放 来实现沿轴的 镜像反转 。其实思路很简单,对于点来说,沿 Y 轴镜像是保持 y 坐标不变,x 坐标取相反数。scale 的本质就是对坐标在横纵分量上的乘积,所以 scale(-1,1) 表示的是将 x 坐标。

如下,在 HeroComponent 构建中添加 flip 方法,默认沿 y 轴镜像反转:

代码语言:javascript
复制
---->[03/01/HeroComponent]----
void flip({
  bool x = false,
  bool y = true,
}) {
  scale = Vector2(scale.x * (y ? -1 : 1), scale.y * (x ? -1 : 1));
}

接下来,只要在按键监听中,触发 flip 方法即可。这样就实现了通过按键,控制对角色进行镜像反转的效果,代码如下:

代码语言:javascript
复制
---->[03/01/TolyGame$onKeyEvent]----
if (event.logicalKey == LogicalKeyboardKey.keyY &amp;&amp; isKeyDown) {
  player.flip(y: true);
}
if (event.logicalKey == LogicalKeyboardKey.keyX &amp;&amp; isKeyDown) {
  player.flip(x: true);
}

同理,结合上一章的内容,我们也可以通过键盘按键来控制角色的移动,如下所示,通过 上下左右WSAD 键进行移动:代码在 【03/02】

代码如下,其中 step 表示按一下的偏移量:

代码语言:javascript
复制
final double step = 10;

if (event.logicalKey == LogicalKeyboardKey.keyY &amp;&amp; isKeyDown) {
  player.flip(y: true);
}
if (event.logicalKey == LogicalKeyboardKey.keyX &amp;&amp; isKeyDown) {
  player.flip(x: true);
}
if ((event.logicalKey == LogicalKeyboardKey.arrowUp
    || event.logicalKey == LogicalKeyboardKey.keyW)
    &amp;&amp; isKeyDown) {
  player.move(Vector2(0, -step));
}
if ((event.logicalKey == LogicalKeyboardKey.arrowDown
    || event.logicalKey == LogicalKeyboardKey.keyS)
    &amp;&amp; isKeyDown) {
  player.move(Vector2(0, step));
}
if ((event.logicalKey == LogicalKeyboardKey.arrowLeft
    || event.logicalKey == LogicalKeyboardKey.keyA)
    &amp;&amp; isKeyDown) {
  player.move(Vector2(-step, 0));
}
if ((event.logicalKey == LogicalKeyboardKey.arrowRight
    || event.logicalKey == LogicalKeyboardKey.keyD)
    &amp;&amp; isKeyDown) {
  player.move(Vector2(step, 0));
}

通过这两个小例子就简单认识了在 Flame 中如何监听键盘事件,下面来看一下手势事件,比如点击、拖拽、长按等。


3. 手势检测 - 点击事件

同样,Flame 中的手势检测也是基于 Flutter 的一层封装,通过 mixin 实现监听功能。另外,注意一点,这也也都是 on Game ,也就是说只有 Game 一族的类才能使用这些手势检测器。

这些手势检测器和 Flutter 中的含义基本一致,就不一一赘述了。使用方式都是混入后,通过覆写方法进行监听,这里主要对 点击 TapDetector拖拽 PanDetector 进行介绍。


如下的小例子中,每次点击屏幕时,角色会顺时针旋转 90° ,而且按下后会显示角色的边界信息,抬手后会消失。代码在 【03/03】

实现也非常简单,将 TolyGame 混入 TapDetector ,然后覆写相关方法进行即可。其中旋转通过 _counter 进行计数,每次点击时加一,然后旋转到 _counter * pi / 2 角度即可。角色的边框信息,通过添加 RectangleHitbox 即可,当其 debugModetrue ,就会显示,代码处理如下:

代码语言:javascript
复制
class TolyGame extends FlameGame with TapDetector {
  late final HeroComponent player;
  late final RectangleHitbox box;

  @override
  Future<void> onLoad() async {
    player = HeroComponent();
    box = RectangleHitbox()..debugMode = false;
    player.add(box);
    add(player);
  }

  final double step = 10;

  double _counter = 0;

  @override
  void onTap() {
    _counter++;
    player.rotateTo(_counter * pi / 2);
  }

  @override
  void onTapCancel() {
    box.debugMode = false;
  }

  @override
  void onTapDown(TapDownInfo info) {
    box.debugMode = true;
  }

  @override
  void onTapUp(TapUpInfo info) {
    box.debugMode = false;
  }
}

4.手势检测 - 拖拽事件

其实上一章中介绍的操作杆,本质上就是基于拖拽事件实现的,只不过限定拖拽区域而言。如下是通过 PanDetector 实现的移动,在 onPanUpdate 回调中可以监听到鼠标的移位量: 【03/04】

代码如下,通过 onPanUpdate 回调的 DragUpdateInfo 对象中的 info.delta.global 可以得到相对于全局的鼠标偏移量:

代码语言:javascript
复制
class TolyGame extends FlameGame with PanDetector {
  // 略同...

  @override
  void onPanDown(DragDownInfo info) {
    box.debugMode = true;
  }

  @override
  void onPanStart(DragStartInfo info) {}

  @override
  void onPanUpdate(DragUpdateInfo info) {
    player.move(info.delta.global);
  }

  @override
  void onPanEnd(DragEndInfo info) {
    box.debugMode = false;
  }

  @override
  void onPanCancel() {
    box.debugMode = false;
  }
}

5. Component 的手势与键盘监听

前面说过,上面的监听都是只能被混入到 Game 一族中,也就是说 Component 构件不能混入,更像是一个全局的手势、事件检测。那么如果只想对某个 Component 进行监听,又该怎么办呢?Flame 源码中在 components/mixin 中提供了 Component 专属的键盘、手势检测混入类。


如下是一个小案例,当鼠标移入角色区域时,边框信息呈绿色,按下时边框变红,且角色顺时针旋转 90° ;鼠标移出区域或抬起时,边框信息取消。这里使用了 TappableHoverable 两个 mixin ,代码详见: 【03/05】

处理方式和前面基本一致,这里就不赘述了。另外说明一点,如果某个 Component 混入了 Tappable ,那么最外层的 TolyGame 就要混入 HasTappables ;同理:

事件类型

Component 混入

XXXGame 需混入

单击

Tappable

HasTappables

悬浮

Hoverable

HasHoverables

键盘

KeyboardHandler

HasKeyboardHandlerComponents

拖拽

Draggable

HasDraggables

代码语言:javascript
复制
class TolyGame extends FlameGame  with HasTappables,HasHoverables {
  // 略...
}

class HeroComponent extends SpriteAnimationComponent with HasGameRef, Tappable,Hoverable {
  // 略...
}

到这里,基本的键盘事件和手势操作就已经介绍完了,这些和 Flutter 原生的事件基本一致。这里来简单瞄一眼单击事件 onTap 的触发,可以看出本质上还是 GestureDetectoronTap 中触发 game.onTap 方法的。所以这里的手势和键盘事件也不是什么新知识。

主要需要注意的是:Flame 中对事件检测封装了两套 mix :一套是基于 Game 的,用于全局的事件检测。另一套是基于 Component 的,用于某个构件角色的事件检测。这里只是简单介绍一下事件的使用,在后面还会经常使用。那本文就到这里,明天见 ~


\

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2022-05-28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 1. 键盘事件
  • 2. 角色的镜像反转
  • 3. 手势检测 - 点击事件
  • 4.手势检测 - 拖拽事件
  • 5. Component 的手势与键盘监听
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档