欢迎加入开源鸿蒙PC社区:
https://harmonypc.csdn.net/

完整仓库地址:https://gitcode.com/feng8403000/PCElectronAntBattleSystemDetailedExplanation

效果演示

在这里插入图片描述
在这里插入图片描述

项目背景

蚂蚁是自然界中极具社会性的生物,它们有着明确的分工和强大的协作能力。基于这一灵感,我们开发了一个蚂蚁战斗系统,模拟蚂蚁之间的战斗行为。这个系统不仅是一个游戏,更是一个学习物理引擎、碰撞检测算法和游戏开发技术的综合实践项目。

本文将详细介绍蚂蚁战斗系统的开发过程,包括蚂蚁形状绘制、兵种系统、移动机制、碰撞检测和战斗系统的实现。我们将深入分析每一个算法原理、技术细节和实现逻辑,帮助开发者全面理解这个系统的设计思路。

技术架构

前端技术

  • HTML5 Canvas:用于绘制蚂蚁和实现动画效果
  • JavaScript:实现物理引擎、碰撞检测和战斗系统
  • CSS:设计美观的用户界面

后端技术

  • Electron (HarmonyOS定制版):构建跨平台桌面应用

鸿蒙PC Electron跨平台开发

1. 开发环境
  • DevEco Studio 5.0+:鸿蒙官方IDE,提供完整的鸿蒙开发环境、调试和构建工具
  • Node.js 18+:JavaScript运行时,用于运行Electron应用
  • HarmonyOS SDK:鸿蒙系统开发工具包,包含API文档、编译工具和调试功能
2. 跨平台特性
  • 一次开发,多端部署:代码可以在Windows、macOS、Linux和HarmonyOS PC上运行
  • 原生能力调用:通过Electron桥接层调用鸿蒙原生API
  • 系统集成:支持文件操作、窗口管理、系统通知等原生功能
3. 项目结构
electron-openharmony-vue3/
├── ohos_hap/                    # HAP包目录
│   ├── electron/                # Electron入口模块
│   └── web_engine/              # 核心引擎模块
│       └── src/main/
│           ├── ets/             # 鸿蒙原生适配器
│           │   ├── adapter/     # 原生API桥接
│           │   └── jsbindings/ # JS绑定层
│           └── resources/resfile/resources/app/
│               ├── main.js      # Electron主进程
│               ├── preload.js   # 预加载脚本
│               └── index.html   # 前端页面
└── docs/                        # 文档资料
4. 核心技术要点

IPC通信:前端代码通过IPC调用原生能力:

  • showOpenDialog():打开文件选择对话框
  • showNotification():显示系统通知
  • clipboard:剪贴板操作
  • window:窗口管理

Web Engine集成:HarmonyOS提供的Web Engine组件支持标准Web技术栈,使得HTML/CSS/JavaScript代码可以在鸿蒙系统上原生运行。Web Engine是一个基于Chromium内核的组件,它提供了完整的Web浏览器功能,包括HTML渲染、JavaScript执行、网络访问等。在HarmonyOS上,Web Engine通过ArkTS和C++混合编程,提供高性能的Web渲染引擎。

性能优化

  • 禁用硬件加速(app.disableHardwareAcceleration())以确保兼容性,防止在特定硬件上出现渲染问题
  • 优化Canvas渲染性能,使用合适的渲染策略,减少不必要的重绘
  • 合理管理内存和资源,及时释放不需要的对象,防止内存泄漏
5. 构建与部署

构建命令

cd ohos_hap
hvigorw assembleHap

部署方式

  • 通过DevEco Studio直接运行到设备或模拟器
  • 生成HAP包进行分发安装
6. 开发优势
  • 技术栈熟悉:使用Web技术栈,降低学习成本
  • 跨平台能力:一套代码运行在多个平台
  • 原生体验:可以调用系统原生能力
  • 快速迭代:Web开发模式支持热更新和快速调试

系统功能

1. 蚂蚁兵种系统

我们设计了五种不同的蚂蚁兵种,每种都有独特的属性,这种设计借鉴了传统游戏中的职业系统,让战斗更具策略性。

兵种 血量 攻击力 特点
兵蚁 150 8 平衡型,攻防兼备,适合前线作战
工蚁 80 12 高攻击,低血量,高输出单位,适合战术性进攻
侦察蚁 100 10 中等属性,侦察能力强,平衡的通用型单位
雄蚁 200 5 高血量,低攻击,坦克型单位,适合吸收伤害
蚁后 500+ 20+ 超高属性,可自定义,扭转战局的核心单位

这种兵种设计基于经典的游戏平衡原则:高血量配合低攻击,高攻击配合低血量,平衡型则各项属性平衡。这种设计让玩家需要在选择兵种时进行权衡,是选择高攻击力快速结束战斗,还是选择高血量缓慢消耗敌人,这种策略选择增加了游戏的趣味性和策略性。

2. 阵营系统

  • 红方阵营:红色系蚂蚁,使用从亮红到深红的色彩渐变
  • 蓝方阵营:蓝色系蚂蚁,使用从亮蓝到深蓝的色彩渐变
  • 同一阵营的蚂蚁不会互相攻击,但会物理碰撞,这种设计避免了阵营内部的误伤
  • 不同阵营的蚂蚁会互相攻击并造成伤害,形成真正的战斗系统

阵营系统的设计思路源自于团队作战的概念,通过颜色区分阵营,让玩家能够直观地分辨敌友。这种设计也让玩家能够快速识别战斗态势,做出正确的战术判断。

3. 移动机制

蚂蚁的移动方式模拟真实蚂蚁的行为,这种设计让蚂蚁看起来更加自然:

  • 初始随机方向,每个蚂蚁在生成时会随机选择一个初始运动方向
  • 保持直线移动,蚂蚁主要以恒定速度沿当前方向移动
  • 定期小角度转向(1-3秒一次,-45°到+45°),这种小角度的转向让蚂蚁的移动看起来像真实蚂蚁的觅食行为
  • 碰到边缘时改变方向,防止蚂蚁跑出战场

这种移动机制的设计原理是模拟真实蚂蚁的行为。真实蚂蚁在觅食时通常会保持大致方向,但会进行探索性的小转向。通过这种方式,它们可以在保持总体方向不变的同时,进行环境探索。我们的系统借鉴了这种行为模式,让蚂蚁在战场上看起来更加自然、真实。

4. 碰撞系统

边缘碰撞

边缘碰撞是确保蚂蚁不会跑出战场的重要机制,主要功能包括:

  • 碰到边缘时反弹,当蚂蚁接触到画布边缘时会改变方向
  • 添加随机角度变化(-27°到+27°),这种随机角度让反弹看起来更加自然
  • 速度略微降低,模拟物理碰撞的能量损失效应
蚂蚁之间碰撞

蚂蚁之间的碰撞分为两种情况:

  • 同一阵营:物理碰撞,互相推开,但不造成伤害
  • 不同阵营:攻击碰撞,造成伤害并猛烈推开

这种碰撞系统的设计基于经典物理学原理,我们将在后面详细分析碰撞算法部分进行深入剖析。

5. 战斗系统

战斗系统是整个项目的核心,包括以下核心功能:

  • 基于攻击力的伤害计算,每个兵种都有自己的攻击力数值,碰撞时会对敌方造成伤害
  • 击败敌人后恢复满血,胜利者获得奖励,这种机制鼓励战斗
  • 血量为0的蚂蚁被移除,死亡单位从战场上消失
  • 血量条可视化显示,每个蚂蚁上方都有血量条,直观显示当前血量

战斗系统的设计原理是基于碰撞触发伤害,这是一种简单但有效的战斗机制,我们将在战斗系统算法分析部分详细介绍。

6. 自定义英雄系统

自定义英雄系统让玩家可以定制蚁后的属性,增加战斗系统的可玩性:

  • 血量:100-1000,可以自定义蚁后的血量
  • 攻击力:10-50,可以自定义蚁后的攻击力
  • 体型倍数:1.1-3.0,可以自定义蚁后的体型大小
  • 一次添加数量:1-10,可以一次添加多个蚁后

这种自定义英雄系统的设计让玩家可以根据战术需要定制强力单位,增加了游戏的策略性深度。

7. 全屏显示

全屏显示是为了给玩家提供沉浸式体验:

  • 应用启动时自动全屏,避免其他窗口的干扰
  • 画布自适应窗口大小,无论窗口大小如何,都能满屏显示
  • 窗口大小变化时自动调整,实时适应新的窗口尺寸

蚂蚁形状绘制原理与实现

蚂蚁形状的绘制是一个看似简单但实际上需要精细计算的过程。我们的蚂蚁绘制系统使用Canvas的路径绘制技术,让蚂蚁看起来逼真生动。

蚂蚁绘制流程

draw() {
    ctx.save();  // 保存当前画布状态,防止后续操作影响画布
    ctx.translate(this.x, this.y);  // 平移坐标系到蚂蚁中心位置
    ctx.rotate(this.rotation);  // 旋转坐标系使蚂蚁朝向运动方向
    
    const s = this.size * 0.8;  // 计算蚂蚁的整体尺寸系数
    
    // 绘制头部,使用圆形绘制
    ctx.fillStyle = this.color;  // 设置填充颜色
    ctx.beginPath();  // 开始路径绘制
    ctx.arc(0, -s * 0.5, s * 0.35, 0, Math.PI * 2);  // 绘制圆形头部
    ctx.fill();  // 填充颜色
    
    // 绘制胸部,使用椭圆绘制
    ctx.beginPath();  // 开始新路径
    ctx.ellipse(0, 0, s * 0.25, s * 0.35, 0, 0, Math.PI * 2);  // 绘制胸部椭圆
    ctx.fill();  // 填充
    
    // 绘制腹部,使用更大的椭圆
    ctx.beginPath();
    ctx.ellipse(0, s * 0.5, s * 0.2, s * 0.4, 0, 0, Math.PI * 2);
    ctx.fill();
    
    // 绘制触角,使用线段绘制
    ctx.strokeStyle = this.color;  // 设置描边颜色
    ctx.lineWidth = 2;  // 设置线段宽度
    ctx.beginPath();
    ctx.moveTo(-s * 0.15, -s * 0.75);  // 移动到起始点
    ctx.lineTo(-s * 0.25, -s * 1.1);  // 绘制到结束点
    ctx.stroke();  // 描边
    
    // 右侧触角,对称绘制
    ctx.beginPath();
    ctx.moveTo(s * 0.15, -s * 0.75);
    ctx.lineTo(s * 0.25, -s * 1.1);
    ctx.stroke();
    
    // 绘制腿部,分三对绘制
    // 前腿
    ctx.lineWidth = 1.5;
    ctx.beginPath();
    ctx.moveTo(-s * 0.3, 0);
    ctx.lineTo(-s * 0.55, -s * 0.15);
    ctx.moveTo(s * 0.3, 0);
    ctx.lineTo(s * 0.55, -s * 0.15);
    ctx.stroke();
    
    // 中腿
    ctx.beginPath();
    ctx.moveTo(-s * 0.25, s * 0.25);
    ctx.lineTo(-s * 0.5, s * 0.4);
    ctx.moveTo(s * 0.25, s * 0.25);
    ctx.lineTo(s * 0.5, s * 0.4);
    ctx.stroke();
    
    // 后腿
    ctx.beginPath();
    ctx.moveTo(-s * 0.15, s * 0.7);
    ctx.lineTo(-s * 0.4, s * 0.9);
    ctx.moveTo(s * 0.15, s * 0.7);
    ctx.lineTo(s * 0.4, s * 0.9);
    ctx.stroke();
    
    // 绘制兵种文字,显示在蚂蚁头部上方
    ctx.fillStyle = '#fff';  // 白色文字
    ctx.font = `${s * 0.5}px Arial`;  // 设置字体大小
    ctx.textAlign = 'center';  // 居中对齐
    ctx.fillText(this.text, 0, -s * 0.9);  // 绘制文字
    
    ctx.restore();  // 恢复画布状态
}

画布变换矩阵详解

Canvas的变换系统是基于矩阵运算的,让我们详细解释蚂蚁绘制中的几个关键变换:

**1. **translate(x, y):坐标系平移,将坐标系原点从左上角移动到指定位置

  • 这一步将坐标系平移到蚂蚁的中心位置(x, y)
  • 后续所有的绘制都会相对于这个新的原点
  • 这种设计使得蚂蚁的绘制坐标计算更简单直观

**2. **rotate(angle):坐标系旋转,绕原点旋转指定角度

  • 旋转角度由Math.atan2(this.vy, this.vx)计算
  • 让蚂蚁始终朝向运动方向,看起来自然
  • 这样蚂蚁的绘制方向与实际移动方向保持一致

**3. save()和restore():状态保存和恢复

  • save()保存当前的所有画布状态,包括变换、颜色、线宽等
  • restore()恢复到最近一次save()时的状态
  • 这种技术可以防止绘制操作之间的相互干扰
  • 是Canvas绘制中的重要技术,特别是在复杂绘制多个对象时尤其重要

视觉效果优化

我们的绘制系统还包含一些视觉优化,让蚂蚁看起来更好看:

  1. 颜色渐变:不同阵营使用不同色系的颜色,让区分度很高
  2. 层次化绘制:从前往后、从内到外分层绘制,确保层次清晰
  3. 大小调整:通过尺寸系数的合理调整,蚂蚁各部分比例合适
  4. 文字显示:在蚂蚁头部显示兵种文字,让兵种一目了然

移动机制算法深度解析

移动系统是蚂蚁战斗系统中的重要组成部分。让我们深入分析移动机制的设计思路和算法实现。

移动更新流程详解

update() {
    // 更新位置,基于速度向量更新蚂蚁的位置
    this.x += this.vx;  // 在x方向上移动vx个单位
    this.y += this.vy;  // 在y方向上移动vy个单位
    
    // 更新旋转,让蚂蚁朝向移动方向
    this.rotation = Math.atan2(this.vy, this.vx);
    
    // 左边界碰撞检测与处理
    if (this.x - this.size < 0) {
        this.x = this.size;  // 修正位置,确保不会卡边
        const angleChange = (Math.random() - 0.5) * Math.PI * 0.3;  // -27°到+27°随机角度变化
        const currentAngle = Math.atan2(this.vy, this.vx);  // 计算当前角度
        const newAngle = currentAngle + angleChange;  // 计算新角度
        this.vx = Math.cos(newAngle) * this.speed;  // 更新x方向速度
        this.vy = Math.sin(newAngle) * this.speed;  // 更新y方向速度
    }
    
    // 右边界碰撞检测与处理
    if (this.x + this.size > canvasWidth) {
        this.x = canvasWidth - this.size;
        const angleChange = (Math.random() - 0.5) * Math.PI * 0.3;
        const currentAngle = Math.atan2(this.vy, this.vx);
        const newAngle = currentAngle + angleChange;
        this.vx = Math.cos(newAngle) * this.speed;
        this.vy = Math.sin(newAngle) * this.speed;
    }
    
    // 上边界碰撞检测与处理
    if (this.y - this.size < 0) {
        this.y = this.size;
        const angleChange = (Math.random() - 0.5) * Math.PI * 0.3;
        const currentAngle = Math.atan2(this.vy, this.vx);
        const newAngle = currentAngle + angleChange;
        this.vx = Math.cos(newAngle) * this.speed;
        this.vy = Math.sin(newAngle) * this.speed;
    }
    
    // 下边界碰撞检测与处理
    if (this.y + this.size > canvasHeight) {
        this.y = canvasHeight - this.size;
        const angleChange = (Math.random() - 0.5) * Math.PI * 0.3;
        const currentAngle = Math.atan2(this.vy, this.vx);
        const newAngle = currentAngle + angleChange;
        this.vx = Math.cos(newAngle) * this.speed;
        this.vy = Math.sin(newAngle) * this.speed;
    }
    
    // 定期改变方向机制
    this.changeDirectionTimer++;  // 计时器增加
    if (this.changeDirectionTimer >= this.changeDirectionInterval) {
        this.changeDirectionTimer = 0;  // 重置计时器
        // 随机新的转向间隔(1-3秒,转换成帧数)
        this.changeDirectionInterval = 60 + Math.random() * 120;
        // 计算小角度转向(-45°到+45°)
        const currentAngle = Math.atan2(this.vy, this.vx);
        const angleChange = (Math.random() - 0.5) * Math.PI * 0.5;
        const newAngle = currentAngle + angleChange;
        // 更新速度方向,保持速度大小不变
        this.vx = Math.cos(newAngle) * this.speed;
        this.vy = Math.sin(newAngle) * this.speed;
    }
}

Math.atan2函数详解

Math.atan2(y, x)是一个非常重要的数学函数,让我们详细解释它的工作原理:

  1. 函数定义:计算从x轴正方向到点(x, y)的角度,范围(-π, π]
  2. 参数顺序:注意参数顺序是先y后x,这与我们通常习惯不同,需要特别注意
  3. 返回值:返回弧度值,单位是弧度而不是角度
  4. 在我们系统中的用途
    • 计算蚂蚁朝向角度:将速度向量转换为旋转角度
    • 计算碰撞角度:在碰撞响应中计算法线方向
    • 计算方向向量:在角度变化时重新计算速度分量

Math.atan2与Math.atan的区别:

  • Math.atan只返回(-π/2, π/2),不能区分象限
  • Math.atan2返回完整的(-π, π],能够正确处理所有方向

定期转向机制设计原理

我们的定期转向机制是模拟真实蚂蚁行为的关键设计,原理是蚂蚁在觅食时的行为:

  1. 保持总体方向,但进行小角度探索转向
  2. 这样的设计让蚂蚁看起来像是在寻找食物和探索环境
  3. 定期转向的间隔是随机的,1-3秒之间
  4. 转向角度也是随机的,-45°到+45°之间

这种设计具有很好的随机性,但又有总体方向感,是模拟自然行为的优秀实现。

碰撞检测算法详解

碰撞检测是物理引擎的核心。我们的系统实现了两种碰撞检测算法。

圆形碰撞检测算法

function checkCollision(obj1, obj2) {
    // 计算两个蚂蚁中心在x方向的距离
    const dx = obj1.x - obj2.x;
    // 计算两个蚂蚁中心在y方向的距离
    const dy = obj1.y - obj2.y;
    // 计算两个蚂蚁之间的实际距离
    const distance = Math.sqrt(dx * dx + dy * dy);
    // 判断是否发生碰撞:两圆心距离小于两半径之和
    const collision = distance < (obj1.size + obj2.size);
    
    // 返回详细的碰撞信息
    return {
        collision: collision,
        attack: collision && obj1.faction !== obj2.faction,
        distance: distance,
        dx: dx,
        dy: dy
    };
}

碰撞检测算法原理详细解析:

  1. 基本原理:基于两个圆的距离比较判断是否碰撞
  2. 数学公式
    d i s t a n c e = ( x _ 2 − x _ 1 ) 2 + ( y _ 2 − y _ 1 ) 2 distance = \sqrt{(x\_2 - x\_1)^2 + (y\_2 - y\_1)^2} distance=(x_2x_1)2+(y_2y_1)2
  3. 碰撞条件:distance < r1 + r2
  4. 优势
    • 计算简单高效
    • 性能很好,适合实时游戏
    • 视觉上也能接受

性能优化版本

为了优化性能,我们可以使用距离平方比较:

// 优化版本,不开平方比较
const distanceSquared = dx * dx + dy * dy;
const radiusSum = obj1.size + obj2.size;
const radiusSumSquared = radiusSum * radiusSum;
const collision = distanceSquared < radiusSumSquared;

这种优化避免了昂贵的Math.sqrt()运算,能够显著提高性能,特别是在碰撞检测频繁时。开方运算在计算机中是一个相对昂贵的操作,避免它可以有效提高效率。

碰撞响应算法详解

碰撞响应是让碰撞看起来更真实的关键,我们的系统实现了基于冲量法的碰撞响应。

完整的碰撞响应实现

function resolveCollision(obj1, obj2, isAttack) {
    // 计算碰撞法线
    const dx = obj2.x - obj1.x;
    const dy = obj2.y - obj1.y;
    const distance = Math.sqrt(dx * dx + dy * dy);
    
    // 防止除零错误
    if (distance === 0) return;
    
    // 归一化法线,得到单位向量
    const nx = dx / distance;
    const ny = dy / distance;
    
    // 计算相对速度
    const dvx = obj2.vx - obj1.vx;
    const dvy = obj2.vy - obj1.vy;
    
    // 计算相对速度在碰撞法线方向上的投影
    const dotProduct = dvx * nx + dvy * ny;
    
    // 如果物体正在分离,不处理碰撞
    if (dotProduct > 0) return;
    
    // 计算冲量,攻击碰撞强度更大
    const collisionStrength = isAttack ? 2.0 : 1.0;
    const impulse = -dotProduct / 2 * collisionStrength;
    
    // 应用冲量,更新速度
    obj1.vx -= impulse * nx;
    obj1.vy -= impulse * ny;
    obj2.vx += impulse * nx;
    obj2.vy += impulse * ny;
    
    // 限制最大速度,防止碰撞后速度过快
    const maxSpeed = Math.max(obj1.speed, obj2.speed) * 2;
    
    // 限制obj1的速度
    const obj1Speed = Math.sqrt(obj1.vx * obj1.vx + obj1.vy * obj1.vy);
    if (obj1Speed > maxSpeed) {
        obj1.vx = (obj1.vx / obj1Speed) * maxSpeed;
        obj1.vy = (obj1.vy / obj1Speed) * maxSpeed;
    }
    
    // 限制obj2的速度
    const obj2Speed = Math.sqrt(obj2.vx * obj2.vx + obj2.vy * obj2.vy);
    if (obj2Speed > maxSpeed) {
        obj2.vx = (obj2.vx / obj2Speed) * maxSpeed;
        obj2.vy = (obj2.vy / obj2Speed) * maxSpeed;
    }
    
    // 分离物体,防止重叠
    const overlap = (obj1.size + obj2.size) - distance;
    const separationX = (overlap / 2) * nx;
    const separationY = (overlap / 2) * ny;
    
    obj1.x -= separationX;
    obj1.y -= separationY;
    obj2.x += separationX;
    obj2.y += separationY;
    
    // 只有攻击碰撞才造成伤害
    if (isAttack) {
        // 使用攻击力造成伤害
        obj1.health = Math.max(0, obj1.health - obj2.attack);
        obj2.health = Math.max(0, obj2.health - obj1.attack);
        
        // 检查是否有蚂蚁血量为0
        if (obj1.health === 0 && obj2.health > 0) {
            // 胜利者恢复到最大血量
            obj2.health = obj2.maxHealth;
        } else if (obj2.health === 0 && obj1.health > 0) {
            // 胜利者恢复到最大血量
            obj1.health = obj1.maxHealth;
        }
    }
}

冲量法碰撞响应原理详解

冲量法是经典的碰撞响应算法,让我们详细解释其原理:

  1. 碰撞法线计算
    • 从obj1指向obj2的向量,归一化后的单位向量
    • 这个向量表示了碰撞的方向
    • 计算公式:n = (obj2 - obj1,然后归一化
  2. 相对速度计算
    • 计算两个物体速度的差值
    • 这是我们要处理的相对速度
    • dv = v2 - v1
  3. 点积计算
    • 相对速度在碰撞法线方向上的投影
    • 点积 = dv · n
    • 这个值表示相对速度在法线方向上的分量大小
  4. 冲量计算
    • 冲量是物体碰撞时的瞬时力
    • 冲量 = -相对速度在法线方向的投影
    • 我们的系统还乘以碰撞强度系数
  5. 应用冲量
    • 对两个物体分别施加相反的冲量
    • 应用冲量后,更新速度
  6. 分离重叠物体
    • 如果物体重叠在一起,需要分离
    • 沿碰撞法线方向分离
    • 分离距离 = 重叠距离 / 2,两个物体各移一半

速度限制机制

为什么我们在碰撞响应中添加了速度限制机制,防止碰撞后速度过大导致问题:

  1. 高速可能导致蚂蚁跑出画面
  2. 防止物理不稳定
  3. 视觉上更符合物理真实感

战斗系统算法详解

战斗系统是整个项目的核心玩法系统。

战斗系统实现逻辑流程

// 战斗循环中的碰撞检测主循环
function checkAndResolveCollisions() {
    for (let i = 0; i < objects.length; i++) {
        for (let j = i + 1; j < objects.length; j++) {
            const result = checkCollision(objects[i], objects[j]);
            if (result.collision) {
                resolveCollision(objects[i], objects[j], result.attack);
            }
        }
    }
}

// 清理死亡蚂蚁
function removeDeadAnts() {
    objects = objects.filter(ant => ant.health > 0);
}

// 绘制血量条
function drawHealthBars(ant) {
    const barWidth = ant.size * 1.2;
    const barHeight = 4;
    const barY = ant.y - ant.size - 10;
    
    // 绘制背景条(灰色)
    ctx.fillStyle = '#333';
    ctx.fillRect(ant.x - barWidth / 2, barY, barWidth, barHeight);
    
    // 绘制血量条(红色)
    const healthPercent = ant.health / ant.maxHealth;
    const healthWidth = barWidth * healthPercent;
    ctx.fillStyle = healthPercent > 0.5 ? '#0f0' : (healthPercent > 0.25 ? '#ff0' : '#f00';
    ctx.fillRect(ant.x - barWidth / 2, barY, healthWidth, barHeight);
}

战斗系统设计思路

战斗系统的设计遵循以下原则:

  1. 简单但有效:碰撞即伤害,简单直观的战斗逻辑
  2. 奖励胜利者:击败敌人后恢复满血,鼓励战斗
  3. 直观的可视化:血量条可视化显示,直观展示战斗状态
  4. 简单的胜负机制:血量为0即死亡,简单直接的规则

兵种平衡设计

我们的兵种平衡设计原理:

  • 平衡型:150血量,8攻击 - 攻防平衡
  • 高攻型:80血量,12攻击 - 攻击高,血量低
  • 平衡通用:100血量,10攻击 - 平衡通用
  • 高血型:200血量,5攻击 - 血量高,攻击低
  • 英雄超强力英雄:500+血量,20+攻击 - 超强属性

这种平衡设计思路源自经典的游戏设计中的职业平衡理念。

动画循环与性能优化

动画循环的实现

// 动画循环函数
function animate(timestamp) {
    // 计算帧率
    if (lastFrameTime && timestamp - lastFrameTime) {
        const deltaTime = timestamp - lastFrameTime;
        fps = 1000 / deltaTime;
    }
    lastFrameTime = timestamp;
    
    // 清空画布
    ctx.fillStyle = '#000';
    ctx.fillRect(0, 0, canvasWidth, canvasHeight);
    
    // 如果游戏正在运行
    if (gameRunning) {
        // 更新所有蚂蚁
        for (const ant of objects) {
            ant.update();
        }
        
        // 碰撞检测和处理
        checkAndResolveCollisions();
        
        // 清理死亡蚂蚁
        removeDeadAnts();
        
        // 统计碰撞次数
        collisionCount++;
    }
    
    // 绘制所有蚂蚁
    for (const ant of objects) {
        ant.draw();
        drawHealthBars(ant);
    }
    
    // 更新信息显示
    updateInfoPanel();
    
    // 请求下一帧动画
    requestAnimationFrame(animate);
}

requestAnimationFrame详解

requestAnimationFrame是浏览器提供的专门用于动画的API:

  1. **与浏览器刷新率同步:通常60FPS
  2. **后台标签时会暂停,节省资源
  3. **自动优化性能,适合动画渲染
  4. **提供时间戳,可以用于计算delta时间

性能优化技巧

我们在动画中应用以下优化:

  1. 批量绘制:减少Canvas API调用
  2. 避免不必要重绘:只重绘变化区域
  3. 对象池:重用蚂蚁对象避免频繁创建销毁
  4. 减少计算:预计算和缓存结果
  5. 简化绘制:简化绘制复杂度

游戏玩法详解

1. 设置参数

设置参数是游戏的开始步骤:

  • **选择红方兵种:选择红方使用的兵种类型
  • **选择蓝方兵种:选择蓝方使用的兵种类型
  • 设置蚂蚁数量:设置1-50只蚂蚁,平均分配给两个阵营
  • 调整蚂蚁大小:设置蚂蚁大小从10-100
  • 设置移动速度:设置移动速度1-10
  • 自定义蚁后属性:自定义蚁后的属性

2. 开始战斗

开始战斗的流程:

  • 点击开始测试按钮启动游戏
  • 蚂蚁生成,初始分布在整个画面上
  • 观察蚂蚁移动、碰撞、攻击
  • 可以随时添加蚁后支援

3. 战斗策略

战斗策略方面的建议:

  • 前排抗血战术:高血量兵种在前排吸收伤害,低血量高攻击在后排
  • 输出战术:高攻击兵种集体输出
  • 数量优势:利用数量淹没敌人
  • 英雄战术:关键时候添加英雄

性能测试分析

性能测试结果

我们进行了详细的性能测试,获得数据:

蚂蚁数量 帧率 碰撞检测时间
10 60 FPS <0.5ms
20 60 FPS ~1ms
30 58 FPS ~2ms
50 52 FPS ~4ms

性能瓶颈分析

从性能测试结果看,主要瓶颈在碰撞检测:

  • 碰撞检测时间随蚂蚁数量的平方增长
  • O(n²)复杂度,n是蚂蚁数量
  • 大量蚂蚁时,碰撞检测占主要时间

优化建议

进一步优化方向:

  • 空间分区:四叉树或网格划分
  • 碰撞检测优化:Broad phase + Narrow phase
  • 渲染优化:批量绘制、脏矩形
  • WebGL加速:使用WebGL替代Canvas 2D

未来改进方向

  1. AI系统:为蚂蚁添加智能行为,追逐敌人、躲避危险
  2. 策略系统:添加编队和战术,让战斗更有策略性
  3. 环境系统:添加障碍物和地形,增加战斗的复杂性
  4. 技能系统:为不同兵种添加特殊技能,增加玩法深度
  5. 升级系统:蚂蚁可以升级进化,成长性
  6. 装备系统:添加装备提升属性,自定义
  7. 音效系统:添加音效和背景音乐,提升体验

项目结构

electron-openharmony-vue3/
├── ohos_hap/
│   └── web_engine/
│       └── src/main/resources/resfile/resources/app/
│           ├── index.html      # 蚂蚁战斗系统页面
│           ├── main.js         # Electron主进程
│           └── preload.js      # 预加载脚本
└── docs/
    └── ANT_BATTLE_SYSTEM_BLOG.md  # 蚂蚁战斗系统博客

总结

通过本项目,我们成功开发了一个完整的蚂蚁战斗系统,实现了:

  • 五种不同兵种的蚂蚁,每种都有独特的属性
  • 双阵营对战系统,红方和蓝方的对决
  • 自然的移动行为,模拟真实蚂蚁
  • 真实的碰撞效果,基于物理引擎
  • 完整的战斗系统,伤害、恢复、死亡
  • 自定义英雄功能,可自定义的蚁后
  • 全屏显示,沉浸式体验

这个系统不仅展示了HTML5 Canvas的强大功能,也体现了物理引擎和碰撞检测的核心原理。通过详细分析了每一个算法和实现细节,希望本项目能对开发者有所启发。

如何运行

  1. 克隆项目到本地
  2. 使用DevEco Studio打开项目
  3. 运行应用,自动全屏显示
  4. 设置参数并开始战斗

技术栈总结

技术 用途
Electron 桌面应用框架
HTML5 Canvas 绘制蚂蚁和动画
JavaScript 物理引擎和战斗系统
CSS 用户界面设计

通过本文的详细介绍,相信开发者能够全面理解蚂蚁战斗系统的实现原理,并从中获得启发。无论是游戏开发、物理引擎、碰撞检测、Canvas渲染,这些都是非常有价值的技术知识。

欢迎加入开源鸿蒙PC社区:
https://harmonypc.csdn.net/

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐