鸿蒙6.1特性实战之fps60下的任务行走战斗过程模拟演示
·
项目地址:https://atomgit.com/feng8403000/fps60-renwuduizhan


一、项目概述
本项目基于 HarmonyOS 6.1 开发了一款 PC 端人物战斗游戏,实现了流畅的 60fps 人物行走动画、键盘控制系统、敌人对战系统以及完整的游戏交互逻辑。
1.1 核心功能特性
| 功能模块 | 功能描述 | 技术实现 |
|---|---|---|
| 人物动画 | 60fps流畅行走动画,包含身体摆动、手臂摆动、腿部摆动 | 三角函数驱动的相位计算 |
| 键盘控制 | A/D移动、U攻击、I跳跃 | 事件监听与状态机管理 |
| 敌人系统 | 敌对角色、血槽显示、战败躺下动画 | 状态管理与条件渲染 |
| 攻击系统 | 攻击波发射、碰撞检测、伤害计算 | 动画帧更新与边界检测 |
| 跳跃系统 | 物理跳跃效果、重力模拟 | 抛物线运动方程 |
| 边界处理 | 全屏移动范围、自动限制 | 坐标边界检测 |
1.2 游戏操作指南
| 按键 | 功能 | 按钮显示 |
|---|---|---|
| A | 向左移动 | A-后退 |
| D | 向右移动 | D-前进 |
| U | 发射攻击波 | U-发波 |
| I | 跳跃 | I-跳跃 |
二、核心架构设计
2.1 整体架构图
┌─────────────────────────────────────────────────────────────┐
│ 游戏主页面 (Entry) │
├─────────────────────────────────────────────────────────────┤
│ ┌───────────────┐ ┌───────────────┐ ┌───────────────┐ │
│ │ 状态管理层 │ │ 动画计算层 │ │ 事件处理层 │ │
│ │ (@State) │ │ (Phase) │ │ (KeyEvent) │ │
│ └──────┬────────┘ └──────┬────────┘ └──────┬────────┘ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ 渲染层 (Builders) │ │
│ │ buildWalkingCharacter | buildEnemy | buildAttackWave│ │
│ │ buildHealthBars | buildGround | buildInfoPanel │ │
│ └──────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
2.2 状态管理设计
// 核心状态变量设计
@State characterX: number = 50; // 玩家X坐标
@State isWalking: boolean = false; // 是否行走
@State moveDirection: string = 'none'; // 移动方向
@State walkPhase: number = 0; // 行走相位(0-360°)
@State jumpHeight: number = 0; // 跳跃高度
@State isJumping: boolean = false; // 是否跳跃
@State attackWaveVisible: boolean = false; // 攻击波可见
@State attackWaveX: number = 0; // 攻击波X坐标
@State enemyHealth: number = 100; // 敌人血量
@State playerHealth: number = 100; // 玩家血量
@State enemyDefeated: boolean = false; // 敌人是否战败
状态设计原则:
- 分离关注点:位置、动作、状态各自独立
- 单向数据流:状态变化驱动UI更新
- 最小化状态:只存储必要的游戏状态
三、60fps 流畅动画实现
3.1 动画驱动机制
// 动画帧更新定时器
private animationTimer: number = 0;
private frameCount: number = 0;
onPageShow() {
// 60fps = 16.67ms 间隔
this.animationTimer = setInterval(() => {
this.updateAnimation();
this.frameCount++;
}, 16) as unknown as number;
}
updateAnimation() {
// 更新行走相位
if (this.isWalking) {
this.walkPhase += 12; // 每帧增加12度
if (this.walkPhase >= 360) {
this.walkPhase = 0;
}
// 根据方向移动
if (this.moveDirection === 'left') {
this.characterX = Math.max(0, this.characterX - 5);
} else if (this.moveDirection === 'right') {
this.characterX = Math.min(850, this.characterX + 5);
}
}
// 更新跳跃物理
if (this.isJumping) {
this.jumpVelocity -= 0.8;
this.jumpHeight += this.jumpVelocity;
if (this.jumpHeight <= 0) {
this.jumpHeight = 0;
this.isJumping = false;
this.jumpVelocity = 0;
}
}
// 更新攻击波
if (this.attackWaveVisible) {
this.attackWaveX += this.moveDirection === 'left' ? -15 : 15;
// 检测与敌人碰撞
if (this.attackWaveX >= this.enemyX - 30 &&
this.attackWaveX <= this.enemyX + 30) {
this.enemyHealth = Math.max(0, this.enemyHealth - 10);
this.attackWaveVisible = false;
if (this.enemyHealth <= 0) {
this.enemyDefeated = true;
}
}
// 超出边界
if (this.attackWaveX < -50 || this.attackWaveX > 950) {
this.attackWaveVisible = false;
}
}
}
3.2 人物动画参数计算
// 手臂摆动角度计算
get leftArmAngle(): number {
return Math.sin(this.walkPhase * Math.PI / 180) * 30;
}
// 腿部摆动角度计算
get leftLegAngle(): number {
return Math.sin((this.walkPhase - 90) * Math.PI / 180) * 25;
}
// 身体上下摆动
get bodyBob(): number {
return Math.sin(this.walkPhase * Math.PI / 180) * 5;
}
// 方向文本获取
getDirectionText(): string {
if (this.moveDirection === 'left') return '后退';
if (this.moveDirection === 'right') return '前进';
return '静止';
}
动画流畅性保障:
- 使用
setInterval以 16ms 间隔更新(约60fps) - 相位增量控制:每帧增加12度,30帧完成一个周期
- 三角函数计算:使用 sin 函数实现平滑摆动
四、键盘事件处理系统
4.1 事件监听与处理
// 键盘事件处理
handleKeyEvent(event: Object): void {
let eventObj: Record<string, string | number> = event as Record<string, string | number>;
let keyText: string = eventObj['keyText'] ? eventObj['keyText'] as string : '';
let eventType: number = eventObj['type'] as number;
// 按键按下事件
if (eventType === 1) {
switch (keyText.toUpperCase()) {
case 'A':
this.moveDirection = 'left';
this.isWalking = true;
break;
case 'D':
this.moveDirection = 'right';
this.isWalking = true;
break;
case 'U':
this.attack();
break;
case 'I':
this.jump();
break;
}
}
// 按键释放事件
if (eventType === 0) {
if (keyText.toUpperCase() === 'A' && this.moveDirection === 'left') {
this.isWalking = false;
}
if (keyText.toUpperCase() === 'D' && this.moveDirection === 'right') {
this.isWalking = false;
}
}
}
4.2 攻击与跳跃方法
// 攻击方法
attack(): void {
if (!this.attackWaveVisible) {
this.attackWaveVisible = true;
this.attackWaveX = this.characterX + (this.moveDirection === 'left' ? -10 : 40);
this.attackWavePhase = 0;
}
}
// 跳跃方法
jump(): void {
if (!this.isJumping) {
this.isJumping = true;
this.jumpVelocity = 12;
}
}
键盘控制特点:
- 支持按键按下和释放事件
- 持续按住 A/D 可连续移动
- 支持大小写不敏感的按键识别
- 使用
keyText而非keyCode提高兼容性
五、敌人对战系统
5.1 敌人状态管理
@State enemyX: number = 700; // 敌人初始位置
@State enemyY: number = 0;
@State enemyHealth: number = 100; // 敌人血量
@State enemyDefeated: boolean = false; // 战败状态
5.2 敌人渲染逻辑
@Builder
buildEnemy() {
Stack({ alignContent: Alignment.Bottom }) {
if (this.enemyDefeated) {
// 战败状态:躺下
Column({ space: 0 }) {
Row({ space: 0 }) {
Circle()
.width(30)
.height(30)
.fill('#FF6B6B');
Rect()
.width(35)
.height(24)
.fill('#8B0000')
.borderRadius(5)
.translate({ y: 3 });
Stack({ alignContent: Alignment.Top }) {
Rect()
.width(30)
.height(10)
.fill('#1a1a1a')
.borderRadius(3);
}
.width(30)
.height(30);
}
}
.rotate({ x: 0, y: 0, z: 1, angle: 90 })
.translate({ y: -50 });
} else {
// 正常状态:站立
Column({ space: 0 }) {
// 头部、身体、四肢渲染...
}
.translate({ y: -this.bodyBob });
}
}
.width(50)
.height(120)
.translate({ x: this.enemyX, y: -330 });
}
5.3 血槽面板实现
@Builder
buildHealthBars() {
Row({ space: 40 }) {
// 玩家血槽
Column({ space: 4 }) {
Text('玩家')
.fontSize(12)
.fontColor('#ffffff');
Stack({ alignContent: Alignment.Start }) {
Rect()
.width(200)
.height(15)
.fill('rgba(255,255,255,0.2)')
.borderRadius(7);
Rect()
.width(this.playerHealth * 2)
.height(15)
.fill('#22c55e')
.borderRadius(7);
}
.width(200);
}
// 敌人血槽
Column({ space: 4 }) {
Text('敌人')
.fontSize(12)
.fontColor('#ffffff');
Stack({ alignContent: Alignment.Start }) {
Rect()
.width(200)
.height(15)
.fill('rgba(255,255,255,0.2)')
.borderRadius(7);
Rect()
.width(this.enemyHealth * 2)
.height(15)
.fill('#ef4444')
.borderRadius(7);
}
.width(200);
}
}
.padding({ top: 30, left: 50 });
}
六、碰撞检测与边界处理
6.1 攻击波碰撞检测
// 在 updateAnimation() 中执行
if (this.attackWaveVisible) {
this.attackWaveX += this.moveDirection === 'left' ? -15 : 15;
// 碰撞检测:攻击波与敌人重叠
if (this.attackWaveX >= this.enemyX - 30 &&
this.attackWaveX <= this.enemyX + 30) {
this.enemyHealth = Math.max(0, this.enemyHealth - 10);
this.attackWaveVisible = false;
// 判断敌人是否战败
if (this.enemyHealth <= 0) {
this.enemyDefeated = true;
}
}
// 边界检测:攻击波超出屏幕
if (this.attackWaveX < -50 || this.attackWaveX > 950) {
this.attackWaveVisible = false;
}
}
6.2 人物移动边界限制
// 移动时进行边界检查
if (this.moveDirection === 'left') {
this.characterX = Math.max(0, this.characterX - 5); // 左边界
} else if (this.moveDirection === 'right') {
this.characterX = Math.min(850, this.characterX + 5); // 右边界
}
边界处理策略:
- 使用
Math.max/min实现边界钳制 - 攻击波使用独立的边界检查
- 敌人位置固定,玩家可全屏移动
七、UI布局与交互设计
7.1 信息面板布局
@Builder
buildInfoPanel() {
Row({ space: 30 }) {
// 左侧:动画参数
Row({ space: 20 }) {
Column({ space: 4 }) {
Text('姿态').fontSize(10).fontColor('rgba(255,255,255,0.5)');
Text(this.walkPhase.toFixed(0) + '°').fontSize(11).fontColor('#22c55e');
}
Column({ space: 4 }) {
Text('位置').fontSize(10).fontColor('rgba(255,255,255,0.5)');
Text(this.characterX.toFixed(0) + 'px').fontSize(11).fontColor('#3b82f6');
}
Column({ space: 4 }) {
Text('跳跃').fontSize(10).fontColor('rgba(255,255,255,0.5)');
Text(this.jumpHeight.toFixed(0) + 'px').fontSize(11).fontColor('#a855f7');
}
Column({ space: 4 }) {
Text('方向').fontSize(10).fontColor('rgba(255,255,255,0.5)');
Text(this.getDirectionText()).fontSize(11).fontColor(this.getDirectionColor());
}
}
// 右侧:控制按钮
Row({ space: 6 }) {
Button('A-后退')
.width(60)
.height(30)
.fontSize(12)
.backgroundColor('rgba(59,130,246,0.3)')
.fontColor('#3b82f6')
.border({ width: 1, color: '#3b82f6' })
.onClick(() => { this.moveDirection = 'left'; this.isWalking = true; });
// D、U、I 按钮...
}
}
.width('100%')
.justifyContent(FlexAlign.SpaceBetween)
.padding({ top: 10, bottom: 15, left: 20, right: 20 })
.translate({ y: -300 });
}
7.2 场景布局结构
@Builder
buildAnimationScene() {
Stack({ alignContent: Alignment.Bottom }) {
// 天空背景
this.buildClouds();
this.buildSun();
this.buildMountains();
// 游戏UI
this.buildHealthBars();
// 游戏角色
this.buildWalkingCharacter();
this.buildEnemy();
// 特效
this.buildAttackWave();
// 地面
this.buildGround();
}
.width('100%')
.height('75%')
.clip(true)
.borderRadius(20)
.margin({ left: 20, right: 20 });
}
八、技术难点与解决方案
8.1 键盘事件兼容问题
问题描述:
HarmonyOS PC 端键盘事件处理与移动设备不同,keyCode 返回 <private>,无法直接使用。
解决方案:
// 使用 keyText 而非 keyCode
let keyText: string = eventObj['keyText'] ? eventObj['keyText'] as string : '';
// 处理逻辑
if (keyText.toUpperCase() === 'A') {
// 左移
}
8.2 动画同步问题
问题描述:
人物、敌人、攻击波的位置需要保持在同一视觉平面。
解决方案:
// 统一使用 translate({ y: -330 }) 向上偏移
.translate({ x: this.characterX, y: -330 - this.jumpHeight }); // 玩家
.translate({ x: this.enemyX, y: -330 }); // 敌人
.translate({ x: this.attackWaveX, y: -330 - this.jumpHeight }); // 攻击波
8.3 性能优化策略
| 优化项 | 实现方式 | 效果 |
|---|---|---|
| 60fps 帧率 | setInterval(16ms) |
流畅动画 |
| 状态合并 | 批量更新状态 | 减少重绘次数 |
| 条件渲染 | if(this.attackWaveVisible) |
避免无效渲染 |
| 数学计算 | 使用 Math.sin/cos |
GPU加速 |
九、项目结构总结
9.1 文件结构
entry/
└── src/
└── main/
└── ets/
└── pages/
└── CharacterWalking.ets # 主页面
docs/
└── HarmonyOS_Character_Combat_Game.md # 技术文档
9.2 核心方法清单
| 方法名 | 功能描述 | 调用位置 |
|---|---|---|
buildWalkingCharacter() |
渲染玩家角色 | buildAnimationScene |
buildEnemy() |
渲染敌人角色 | buildAnimationScene |
buildAttackWave() |
渲染攻击波 | buildAnimationScene |
buildHealthBars() |
渲染血槽面板 | buildAnimationScene |
buildGround() |
渲染地面 | buildAnimationScene |
buildInfoPanel() |
渲染信息面板 | build |
updateAnimation() |
更新动画帧 | setInterval |
handleKeyEvent() |
处理键盘事件 | onKeyEvent |
attack() |
执行攻击 | 按键/按钮触发 |
jump() |
执行跳跃 | 按键/按钮触发 |
十、扩展功能建议
10.1 可扩展功能
| 功能 | 描述 | 实现复杂度 |
|---|---|---|
| 敌人AI | 敌人自动移动和攻击 | 中 |
| 多敌人系统 | 支持多个敌人 | 中 |
| 技能系统 | 多种攻击技能 | 高 |
| 等级系统 | 血量、攻击力升级 | 低 |
| 音效系统 | 攻击、跳跃音效 | 低 |
| 存档系统 | 保存游戏进度 | 中 |
10.2 性能优化方向
- 使用
@Builder复用组件:减少重复代码 - 状态懒加载:只在需要时计算
- GPU渲染优化:使用硬件加速
- 对象池:复用攻击波对象
十一、总结
本项目基于 HarmonyOS 6.1 实现了一个完整的 PC 端人物战斗游戏,包含:
- 流畅的 60fps 动画系统:基于三角函数的相位计算
- 完整的键盘控制系统:支持 A/D/U/I 按键
- 敌人对战系统:血槽、伤害、战败动画
- 物理模拟:跳跃重力效果
- 边界检测:全屏移动范围限制
项目代码结构清晰,状态管理合理,可扩展性强,是学习 HarmonyOS ArkUI 开发的优秀示例。
技术栈:HarmonyOS 6.1 / ArkTS / ArkUI
开发工具:DevEco Studio
更多推荐


所有评论(0)