当前位置: 首页 > news >正文

Flutter for OpenHarmony 实战:双控制系统实现(按钮+键盘)

Flutter for OpenHarmony 实战:双控制系统实现(按钮+键盘)

一、前言

为了提供良好的用户体验,我们实现了双控制系统:屏幕触控按钮和键盘控制。触控按钮方便移动端操作,键盘控制适合PC端开发调试。本文将详细讲解两种控制方式的实现。

二、屏幕按钮控制

2.1 按钮布局设计

采用经典的D-Pad布局(十字方向键):

if(!isGameOver)Container(padding:constEdgeInsets.all(20),child:Column(children:[// 上按钮(单独一行)Row(mainAxisAlignment:MainAxisAlignment.center,children:[_buildControlButton(Icons.arrow_upward,(){_changeDirection(Direction.up);}),],),constSizedBox(height:10),// 左、暂停、右按钮(一行三个)Row(mainAxisAlignment:MainAxisAlignment.center,children:[_buildControlButton(Icons.arrow_back,(){_changeDirection(Direction.left);}),constSizedBox(width:20),_buildControlButton(isPaused?Icons.play_arrow:Icons.pause,(){setState((){isPaused=!isPaused;});},),constSizedBox(width:20),_buildControlButton(Icons.arrow_forward,(){_changeDirection(Direction.right);}),],),constSizedBox(height:10),// 下按钮(单独一行)Row(mainAxisAlignment:MainAxisAlignment.center,children:[_buildControlButton(Icons.arrow_downward,(){_changeDirection(Direction.down);}),],),],),),

布局特点:

  • 上按钮:居中独占一行
  • 中间行:左、暂停、右三个按钮
  • 下按钮:居中独占一行
  • 形成十字键布局

2.2 圆形按钮样式

Widget_buildControlButton(IconDataicon,VoidCallbackonPressed){returnContainer(width:60,height:60,decoration:BoxDecoration(color:Colors.green,borderRadius:BorderRadius.circular(12),),child:IconButton(icon:Icon(icon,color:Colors.white,size:30),onPressed:onPressed,),);}

样式特点:

  • 尺寸:60×60像素
  • 颜色:绿色背景、白色图标
  • 圆角:12像素
  • 图标大小:30像素

2.3 点击事件处理

_buildControlButton(Icons.arrow_upward,(){_changeDirection(Direction.up);})

事件流程:

  1. 用户点击按钮
  2. 触发onPressed回调
  3. 调用_changeDirection()
  4. 更新nextDirection
  5. 下次_update()时应用新方向

三、KeyboardListener键盘监听

3.1 KeyboardListener组件使用

KeyboardListener(focusNode:_focusNode,onKeyEvent:_handleKeyEvent,child:Scaffold(// 游戏内容),)

组件说明:

  • focusNode:焦点控制器
  • onKeyEvent:键盘事件回调
  • child:子组件(游戏界面)

3.2 KeyEvent事件类型

Flutter中KeyEvent有两种类型:

void_handleKeyEvent(KeyEventevent){if(eventisKeyDownEvent){// 按键按下// 处理按键}if(eventisKeyUpEvent){// 按键抬起// 一般不处理}}

事件类型:

  • KeyDownEvent:按键按下时触发
  • KeyUpEvent:按键抬起时触发
  • 我们只处理KeyDownEvent

3.3 FocusNode焦点管理

latefinalFocusNode_focusNode;@overridevoidinitState(){super.initState();_focusNode=FocusNode();_focusNode.requestFocus();// 请求焦点}@overridevoiddispose(){_focusNode.dispose();// 释放焦点super.dispose();}

FocusNode作用:

  • 管理组件焦点状态
  • requestFocus():获取焦点
  • 有焦点才能接收键盘事件

重要提示:

  • 必须调用requestFocus()
  • 否则键盘事件无法触发

四、多键位兼容实现

4.1 WASD键位映射

caseLogicalKeyboardKey.keyW:_changeDirection(Direction.up);return;caseLogicalKeyboardKey.keyS:_changeDirection(Direction.down);return;caseLogicalKeyboardKey.keyA:_changeDirection(Direction.left);return;caseLogicalKeyboardKey.keyD:_changeDirection(Direction.right);return;

WASD布局:

W A S D
  • W:上
  • S:下
  • A:左
  • D:右

4.2 方向键映射

caseLogicalKeyboardKey.arrowUp:_changeDirection(Direction.up);return;caseLogicalKeyboardKey.arrowDown:_changeDirection(Direction.down);return;caseLogicalKeyboardKey.arrowLeft:_changeDirection(Direction.left);return;caseLogicalKeyboardKey.arrowRight:_changeDirection(Direction.right);return;

方向键布局:

↑ ← ↓ →

4.3 LogicalKeyboardKey使用

Flutter的LogicalKeyboardKey枚举提供跨平台的按键映射:

import'package:flutter/services.dart';switch(event.logicalKey){caseLogicalKeyboardKey.keyW:caseLogicalKeyboardKey.arrowUp:_changeDirection(Direction.up);return;// ...}

优势:

  • 跨平台统一API
  • 自动处理不同键盘布局
  • 支持物理键盘和软键盘

五、辅助功能实现

5.1 空格暂停/继续

caseLogicalKeyboardKey.space:setState((){isPaused=!isPaused;});return;

功能说明:

  • 按下空格键
  • 切换暂停状态
  • true→false或false→true
  • 定时器在_update()中检查isPaused

5.2 R键重新开始

caseLogicalKeyboardKey.keyR:if(isGameOver){_initGame();}return;

功能说明:

  • 游戏结束时才有效
  • 按R键重新开始
  • 调用_initGame()重置状态

5.3 焦点自动获取

@overridevoidinitState(){super.initState();_focusNode=FocusNode();_focusNode.requestFocus();// 自动获取焦点_initGame();}

为什么需要自动获取焦点?

  • 应用启动后,焦点可能不在游戏组件
  • 没有焦点就无法接收键盘事件
  • requestFocus()确保游戏能接收输入

六、完整代码实现

class_GameHomePageStateextendsState<GameHomePage>{latefinalFocusNode_focusNode;@overridevoidinitState(){super.initState();_focusNode=FocusNode();_focusNode.requestFocus();_initGame();}void_changeDirection(DirectionnewDirection){if((direction==Direction.up&&newDirection!=Direction.down)||(direction==Direction.down&&newDirection!=Direction.up)||(direction==Direction.left&&newDirection!=Direction.right)||(direction==Direction.right&&newDirection!=Direction.left)){nextDirection=newDirection;}}void_handleKeyEvent(KeyEventevent){if(eventisKeyDownEvent){switch(event.logicalKey){caseLogicalKeyboardKey.keyW:caseLogicalKeyboardKey.arrowUp:_changeDirection(Direction.up);return;caseLogicalKeyboardKey.keyS:caseLogicalKeyboardKey.arrowDown:_changeDirection(Direction.down);return;caseLogicalKeyboardKey.keyA:caseLogicalKeyboardKey.arrowLeft:_changeDirection(Direction.left);return;caseLogicalKeyboardKey.keyD:caseLogicalKeyboardKey.arrowRight:_changeDirection(Direction.right);return;caseLogicalKeyboardKey.space:setState((){isPaused=!isPaused;});return;caseLogicalKeyboardKey.keyR:if(isGameOver){_initGame();}return;}}}@overridevoiddispose(){gameTimer?.cancel();_focusNode.dispose();super.dispose();}@overrideWidgetbuild(BuildContextcontext){returnKeyboardListener(focusNode:_focusNode,onKeyEvent:_handleKeyEvent,child:Scaffold(body:Column(children:[// 游戏画面Expanded(child:CustomPaint(painter:GamePainter(...),),),// 控制按钮if(!isGameOver)Container(padding:constEdgeInsets.all(20),child:Column(children:[Row(mainAxisAlignment:MainAxisAlignment.center,children:[_buildControlButton(Icons.arrow_upward,(){_changeDirection(Direction.up);}),],),constSizedBox(height:10),Row(mainAxisAlignment:MainAxisAlignment.center,children:[_buildControlButton(Icons.arrow_back,(){_changeDirection(Direction.left);}),constSizedBox(width:20),_buildControlButton(isPaused?Icons.play_arrow:Icons.pause,(){setState((){isPaused=!isPaused;});},),constSizedBox(width:20),_buildControlButton(Icons.arrow_forward,(){_changeDirection(Direction.right);}),],),constSizedBox(height:10),Row(mainAxisAlignment:MainAxisAlignment.center,children:[_buildControlButton(Icons.arrow_downward,(){_changeDirection(Direction.down);}),],),constSizedBox(height:10),Text('或使用 WASD / 方向键控制',style:TextStyle(fontSize:14,color:Colors.grey[400],),),],),),],),),);}Widget_buildControlButton(IconDataicon,VoidCallbackonPressed){returnContainer(width:60,height:60,decoration:BoxDecoration(color:Colors.green,borderRadius:BorderRadius.circular(12),),child:IconButton(icon:Icon(icon,color:Colors.white,size:30),onPressed:onPressed,),);}}

七、功能演示

操作演示:

  1. 启动游戏,蛇自动向右移动
  2. 点击上按钮或按W键:蛇向上移动
  3. 点击暂停按钮或按空格键:游戏暂停
  4. 游戏结束后,按R键:重新开始

双系统优势:

  • 触控按钮:移动端友好
  • 键盘控制:PC端开发高效
  • 可同时使用,互不冲突

八、总结

本文讲解了双控制系统实现:

  1. 触控按钮:十字布局,绿色圆角样式
  2. KeyboardListener:监听键盘事件
  3. WASD+方向键:多种键位兼容
  4. 辅助功能:空格暂停、R键重开

关键要点:

  • FocusNode必须requestFocus()
  • KeyEvent分为KeyDown和KeyUp
  • 多键位兼容提升用户体验

下篇预告:《Flutter for OpenHarmony 实战:开发调试中的三个典型Bug》

社区支持

欢迎加入开源 OpenHarmony 跨平台社区,获取更多技术支持和资源:

  • 社区论坛:开源 OpenHarmony 跨平台开发者社区
  • 技术交流:参与社区讨论,分享开发经验

如果本文对您有帮助,欢迎点赞、收藏和评论。您的支持是我持续创作的动力!

http://www.jsqmd.com/news/310040/

相关文章:

  • 【计算机毕业设计案例】基于springboot的城市轨道交通安全管理系统(程序+文档+讲解+定制)
  • 【毕业设计】基于springboot的台球厅管理系统(源码+文档+远程调试,全bao定制等)
  • 【计算机毕业设计案例】基于spark的买菜推荐系统设计与实现基于SpringBoot+Spark的买菜推荐系统设计与实现(程序+文档+讲解+定制)
  • Flutter for OpenHarmony 实战:食物生成算法与难度递增系统
  • KAIST团队突破视频生成瓶颈:让AI学会“自我反思“修正动作错误
  • Flutter for OpenHarmony 实战:CustomPainter游戏画面渲染详解
  • 上海AI实验室ImgCoder:AI实现科学手绘图精准生成
  • YOLO26改进 - 注意力机制 | ParNet并行子网络:多分支协同优化特征表达,增强模型判别能
  • 北大腾讯团队只改一行代码,让AI图像生成效果提升20%!
  • 苏州大学突破:新型注意力机制赋能AI语境适应性对话
  • 腾讯突破:AI实现对话到电影的完整自动化制作
  • 清华大学等多所顶尖院校联手揭秘智能数据准备革命
  • 网络工程师必看:11个协议端口号形象记忆法,看完再也忘不掉(附记忆宫殿地图)
  • Agentic AI的“责任边界”:提示工程架构师必须明确的5个问题
  • 探索H6型PFC源代码实现:意想不到的效果
  • 永磁无刷电机(PMSM)Simulink模型搭建与解析
  • 探索 MATLAB/Simulink 中 1.5MW 并网型双馈风力发电机的魅力
  • 光伏系统遮阴下的MPPT最大功率跟踪:粒子群算法(PSO)的奇妙应用
  • 计算机Java毕设实战-基于AI功能+大数据可视化分析+Spark的买菜推荐系统设计与实现基于spark的买菜推荐系统设计与实现【完整源码+LW+部署说明+演示视频,全bao一条龙等】
  • Java计算机毕设之基于SpringBoot+Spark的买菜推荐系统设计与实现基于spark的买菜推荐系统设计与实现(完整前后端代码+说明文档+LW,调试定制等)
  • Maven 核心
  • 近屿智能发现:年终奖背后的IT赛道秘密
  • 【阵列】低旁瓣稀疏同心环阵列优化Matlab实现
  • 昇腾与Jetson核心疑问解析:结合某高校自研国产盒子的实际场景说明
  • 从理论到代码:实现AI原生应用中的知识抽取
  • SpringBoot配置文件加载顺序:一场配置界的权力游戏
  • 一种电梯高峰归底系统的分层模块化设计方案,包含时间调度层、状态感知层、指令执行层和外部交互层四大核心模块。系统通过时间调度自动切换高峰模式,状态感知层实时监测电梯运行状态,指令执行层实现归底控制逻辑
  • 2026必备!专科生论文神器TOP8:开题报告文献综述全测评
  • 神经网络之感知机(Perceptron)
  • JAVA毕业设计中前后端交互功能的实现方案