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

从零开发游戏需要学习的c#模块,第二十六章(多种敌人与基础 AI)

本节课目标创建三种敌人史莱姆慢、骷髅中速追人、蝙蝠快速随机移动敌人有独立的行为逻辑不同敌人有不同外观和属性敌人在地图上自主移动第一步创建敌人基类右键项目 →添加→类文件名Enemy.cscsharpusing Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using System; namespace MY_FIRST_GAME { public enum EnemyType { Slime, // 史莱姆慢速随机移动 Skeleton, // 骷髅追踪玩家 Bat // 蝙蝠快速随机移动 } public class Enemy { public Vector2 Position; public EnemyType Type; public int Hp; public int MaxHp; public int Attack; public int ScoreValue; public float Speed; public bool IsAlive; protected Texture2D texture; protected Color color; protected Random rng; protected float changeTimer; protected float changeInterval; protected Vector2 moveDirection; public Enemy(EnemyType type, Vector2 position, GraphicsDevice graphicsDevice) { Type type; Position position; IsAlive true; rng new Random(); changeTimer 0f; changeInterval (float)(rng.NextDouble() * 2 1); // 根据类型设置属性 switch (type) { case EnemyType.Slime: Hp 30; MaxHp 30; Attack 8; ScoreValue 30; Speed 40f; color Color.Green; break; case EnemyType.Skeleton: Hp 60; MaxHp 60; Attack 15; ScoreValue 80; Speed 80f; color Color.White; break; case EnemyType.Bat: Hp 15; MaxHp 15; Attack 5; ScoreValue 20; Speed 150f; color Color.Purple; break; } // 创建纹理 int size (type EnemyType.Bat) ? 24 : 40; texture new Texture2D(graphicsDevice, size, size); Color[] data new Color[size * size]; if (type EnemyType.Bat) { // 蝙蝠是三角形 for (int y 0; y size; y) for (int x 0; x size; x) { if (Math.Abs(x - size / 2) y * 0.8f y size * 0.7f) data[y * size x] color; else data[y * size x] Color.Transparent; } } else if (type EnemyType.Skeleton) { // 骷髅是菱形 for (int y 0; y size; y) for (int x 0; x size; x) { float dx Math.Abs(x - size / 2f); float dy Math.Abs(y - size / 2f); if (dx dy size / 2f) data[y * size x] color; else data[y * size x] Color.Transparent; } } else { // 史莱姆是圆形 for (int y 0; y size; y) for (int x 0; x size; x) { float dx x - size / 2f; float dy y - size / 2f; if (dx * dx dy * dy (size / 2f) * (size / 2f)) data[y * size x] color; else data[y * size x] Color.Transparent; } } texture.SetData(data); // 初始随机方向 float angle (float)(rng.NextDouble() * Math.PI * 2); moveDirection new Vector2((float)Math.Cos(angle), (float)Math.Sin(angle)); } public virtual void Update(float deltaTime, Vector2 playerPosition, TileMap tileMap) { changeTimer deltaTime; switch (Type) { case EnemyType.Slime: UpdateSlime(deltaTime, tileMap); break; case EnemyType.Skeleton: UpdateSkeleton(deltaTime, playerPosition, tileMap); break; case EnemyType.Bat: UpdateBat(deltaTime, tileMap); break; } } // ★ 史莱姆慢速随机移动 private void UpdateSlime(float deltaTime, TileMap tileMap) { if (changeTimer changeInterval) { changeTimer 0f; changeInterval (float)(rng.NextDouble() * 3 1); float angle (float)(rng.NextDouble() * Math.PI * 2); moveDirection new Vector2((float)Math.Cos(angle), (float)Math.Sin(angle)); } Vector2 newPos Position moveDirection * Speed * deltaTime; if (!tileMap.IsWall(newPos)) Position newPos; else changeTimer changeInterval; // 撞墙就换方向 } // ★ 骷髅追踪玩家 private void UpdateSkeleton(float deltaTime, Vector2 playerPosition, TileMap tileMap) { Vector2 toPlayer playerPosition - Position; if (toPlayer.Length() 0) { moveDirection Vector2.Normalize(toPlayer); } Vector2 newPos Position moveDirection * Speed * deltaTime; if (!tileMap.IsWall(newPos)) Position newPos; } // ★ 蝙蝠快速随机移动频繁换向 private void UpdateBat(float deltaTime, TileMap tileMap) { if (changeTimer changeInterval) { changeTimer 0f; changeInterval (float)(rng.NextDouble() * 0.5 0.3); float angle (float)(rng.NextDouble() * Math.PI * 2); moveDirection new Vector2((float)Math.Cos(angle), (float)Math.Sin(angle)); } Vector2 newPos Position moveDirection * Speed * deltaTime; if (!tileMap.IsWall(newPos)) Position newPos; else changeTimer changeInterval; } public virtual void Draw(SpriteBatch spriteBatch) { spriteBatch.Draw(texture, Position, null, Color.White, 0f, new Vector2(texture.Width / 2, texture.Height / 2), 1f, SpriteEffects.None, 0f); } public Rectangle GetBounds() { return new Rectangle( (int)(Position.X - texture.Width / 2), (int)(Position.Y - texture.Height / 2), texture.Width, texture.Height); } } }第二步改造Game1.cs以下是需要修改的部分。为了节省篇幅我只列出改动的地方你按位置替换即可。1. 替换敌人列表类型// 旧的private ListVector2 enemies default!;// 新的private ListEnemy enemies default!;2. 替换SpawnEnemies方法private void SpawnEnemies(int count) { for (int i 0; i count; i) { Vector2 pos tileMap.GetRandomEmptyPosition(rng); EnemyType type (EnemyType)(rng.Next(3)); // 随机类型 enemies.Add(new Enemy(type, pos, GraphicsDevice)); } }3. 在Update的Game状态下更新敌人 AI// 在 CheckEnemyCollision 之前加 foreach (Enemy enemy in enemies) enemy.Update(deltaTime, player.Position, tileMap);4. 替换CheckEnemyCollision方法private void CheckEnemyCollision() { Rectangle playerRect player.GetBounds(); for (int i enemies.Count - 1; i 0; i--) { if (enemies[i].GetBounds().Intersects(playerRect)) { Enemy enemy enemies[i]; enemies.RemoveAt(i); score enemy.ScoreValue; enemiesDefeatedThisGame; player.Hp - enemy.Attack; particleSystem.EmitHitParticles(enemy.Position); try { hitSound?.Play(); } catch { } } } }5. 替换DrawGameWorld里的敌人绘制foreach (Enemy enemy in enemies) enemy.Draw(_spriteBatch);本节课学习任务到此结束我是魔法阵维护师关注我下期更精彩
http://www.rkmt.cn/news/1408513.html

相关文章:

  • 3秒预览Office文档:QuickLook.Plugin.OfficeViewer-Native终极指南
  • 在stm32物联网项目中集成多模型ai助手的成本控制实践
  • 基于YOLOv8与边缘计算的智能交通信号自适应控制系统实践
  • 13805黄大年茶思屋第138期(基础软件领域第三期)第5题:多内核混部场景下的快速内存弹性伸缩技术
  • 哪家发动机缸盖工厂专业?2026年5月推荐TOP5对比砂眼控制评测适用场景特点 - 品牌推荐
  • 避坑指南:在Ubuntu 20.04上安装PCL 1.8,为什么你的Anaconda环境是最大阻碍?
  • Ubuntu 18.04安装Realtek网卡驱动后,到底需不需要‘禁用旧驱动’?一个操作背后的原理与选择
  • TVA如何准确高效处理各种复杂应用场景?
  • CLoRA:低秩自适应持续学习在语义分割中的应用
  • 配电网单相接地故障保护方法解析【附代码】
  • 高光谱成像技术驱动的水蜜桃果实病害检测【附代码】
  • 构建机器人评估框架:从性能、软件到环境适应性的全面实战指南
  • 面试官总问的‘scheduleAtFixedRate’和‘scheduleWithFixedDelay’区别,这次用代码和日志彻底讲清楚
  • 告别手动同步!用QDataWidgetMapper在Qt中轻松实现表单与数据库的自动绑定
  • 终极免费文档下载脚本指南:如何一键获取百度文库等30+平台资源
  • 终极指南:如何在Android手机上解锁微信双设备登录,实现工作生活分离
  • 从数据手册到实战:剖析74HC4052模拟开关的选型与电路设计
  • CAPL脚本自动化测试进阶 ———— 活用Test Step函数提升测试报告可读性与精准度
  • 使用taotoken聚合api为个人项目构建智能问答助手
  • 深度指南:2026现阶段河北地区专业阳光房实力厂商选择全解析 - 2026年企业资讯
  • 维普4月升级降AI失效?2026年5月仍有效的4款降AI软件实测
  • P16283 [蓝桥杯 2026 省 Python A 组] 平面选点 题解
  • 扇区感知延迟-相位预编码:攻克太赫兹宽带MIMO波束分裂难题
  • 别再手动配环境了!用Docker Compose一键部署TDengine 3.2.2,5分钟搞定时序数据库
  • 对比自行维护多个API与使用Taotoken聚合在运维上的差异
  • 【独家首发】中国首份《生成式AI合同审查白皮书》(工信部信通院联合审定),覆盖12类SaaS场景,仅限本周开放下载
  • STM32CubeMX实战:PWM呼吸灯从配置到代码实现
  • Mac系统下Docker客户端HTTP/HTTPS协议冲突的排查与修复指南
  • 基于社会脆弱性指数与移动数据的飓风疏散目的地预测模型研究
  • 2026年移动厕所厂家推荐榜单:工地/景区/展会/市政临时卫生间的品质之选 - 品牌企业推荐师(官方)