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

从零开发游戏需要学习的c#模块,第三十章(掉落物品 —— 血包与能量)

本节课学习内容

  1. 敌人死亡时概率掉落血包或能量球

  2. 血包恢复血量

  3. 能量球暂时提升攻击力

  4. 掉落物有吸引动画(可选)

第一步:创建掉落物类

右键项目 →添加,文件名Pickup.cs

csharp

using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; namespace MY_FIRST_GAME { public enum PickupType { Health, // 血包:恢复25点血量 Power // 能量球:5秒内攻击力翻倍 } public class Pickup { public Vector2 Position; public PickupType Type; public bool IsAlive = true; public float Lifetime = 10f; // 10秒后消失 public int Value; private Texture2D texture; private float timer; private float floatOffset; private float floatSpeed = 0.5f; public Pickup(Vector2 position, PickupType type, GraphicsDevice graphicsDevice) { Position = position; Type = type; int size = 20; texture = new Texture2D(graphicsDevice, size, size); Color[] data = new Color[size * size]; switch (type) { case PickupType.Health: Value = 25; // 红色十字 for (int y = 0; y < size; y++) for (int x = 0; x < size; x++) { bool horizontal = (y >= size * 0.35f && y <= size * 0.65f); bool vertical = (x >= size * 0.35f && x <= size * 0.65f); if (horizontal || vertical) data[y * size + x] = Color.Red; else data[y * size + x] = Color.Transparent; } break; case PickupType.Power: Value = 5; // 持续5秒 // 黄色闪电 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.Gold; else data[y * size + x] = Color.Transparent; } break; } texture.SetData(data); } public void Update(float deltaTime) { timer += deltaTime; floatOffset = (float)System.Math.Sin(timer * 3) * 5; // 上下浮动 if (timer >= Lifetime) IsAlive = false; } public void Draw(SpriteBatch spriteBatch) { Vector2 drawPos = Position + new Vector2(0, floatOffset); spriteBatch.Draw(texture, drawPos, 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); } } }

第二步:给 Player 类加 BUFF 系统

Player.cs里添加:

// BUFF 相关 private bool isPoweredUp; private float powerTimer; private int originalAttack; // 在构造函数里保存原始攻击力 // 在 Player 构造函数末尾加:originalAttack = Attack; // 添加方法 public void ApplyPowerUp(float duration) { if (!isPoweredUp) { originalAttack = Attack; isPoweredUp = true; } powerTimer = duration; Attack = originalAttack * 2; // 攻击力翻倍 } public void UpdateBuffs(float deltaTime) { if (isPoweredUp) { powerTimer -= deltaTime; if (powerTimer <= 0) { isPoweredUp = false; Attack = originalAttack; // 恢复 } } } public bool HasPowerUp => isPoweredUp; public float PowerUpTimeRemaining => powerTimer;

Player的构造函数最后加一行:

csharp

originalAttack = Attack;

第三步:改造Game1.cs

只列出需要改的地方。

1. 添加字段:

csharp

private List<Pickup> pickups = default!;

2. 在InitializeGame里初始化:

csharp

pickups = new List<Pickup>();

3. 在击杀敌人的地方加掉落逻辑:
CheckBulletEnemyCollision击杀分支里:

csharp

if (enemies[j].Hp <= 0) { // ...原有代码... // ★ 掉落判定 float dropChance = (float)rng.NextDouble(); if (dropChance < 0.4f) // 40%概率掉落 { if (dropChance < 0.25f) // 25%血包 pickups.Add(new Pickup(enemies[j].Position, PickupType.Health, GraphicsDevice)); else // 15%能量球 pickups.Add(new Pickup(enemies[j].Position, PickupType.Power, GraphicsDevice)); } }

4. 在Update的 Game 状态里更新掉落物:

csharp

// 更新掉落物 foreach (Pickup pickup in pickups) pickup.Update(deltaTime); pickups.RemoveAll(p => !p.IsAlive); // 更新玩家 BUFF player.UpdateBuffs(deltaTime); // 检测玩家和掉落物碰撞 CheckPickupCollision();

5. 添加碰撞检测方法:

csharp

private void CheckPickupCollision() { Rectangle playerRect = player.GetBounds(); for (int i = pickups.Count - 1; i >= 0; i--) { if (pickups[i].GetBounds().Intersects(playerRect)) { Pickup pickup = pickups[i]; pickups.RemoveAt(i); switch (pickup.Type) { case PickupType.Health: player.Hp = Math.Min(player.Hp + pickup.Value, player.MaxHp); floatingTexts.Add(new FloatingText(pickup.Position, $"+{pickup.Value} HP", Color.Red)); break; case PickupType.Power: player.ApplyPowerUp(pickup.Value); floatingTexts.Add(new FloatingText(pickup.Position, "攻击力UP!", Color.Gold)); break; } } } }

6. 在DrawGameWorld里画掉落物:

csharp

foreach (Pickup pickup in pickups) pickup.Draw(_spriteBatch);

7. 在DrawGameUI里加 BUFF 提示:
在 UI 最后加:

csharp

if (player.HasPowerUp) { _spriteBatch.DrawString(font, $"⚡ 攻击力UP:{player.PowerUpTimeRemaining:F1}秒", new Vector2(600, 30), Color.Gold); }

好了,本节课学习内容到此结束,关注我,下期更精彩!

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

相关文章:

  • 【PC】《剪映助手悬浮球V2.1》支持最新剪映
  • 2026年北京老家具回收机构排行 靠谱之选盘点 - 优质品牌商家
  • 智能锁怎么选,家用推荐哪个品牌型号?
  • 千问大模型在阿里生态中的实战应用指南
  • 收藏!Python小白必看:从零入门大模型,手把手带你掌握企业级实战能力
  • 2026年网红香薰厂家核心服务及对接联系方式解析 - 优质品牌商家
  • SQL分组查询不会用?手把手教你Group By和聚合函数
  • 告别调包:用NumPy在头歌EduCoder里手动实现CNN的前向传播(含维度计算详解)
  • Windows 10下用IDEA跑通ThingsBoard 3.4源码:保姆级环境配置与编译避坑指南
  • 从PCA到PLS-DA:当你的组学数据‘分不开’时,试试这个有监督的降维利器(附R代码避坑指南)
  • 从零开始:用Python和Scikit-learn搭建你的第一个AI面试助手(附常见问题库)
  • 合作获客平台怎么选?10大渠道深度解析,智能匹配工具成新趋势!
  • 专访 7 名普通职场人:AI 来了之后,你过得还好吗?
  • 面向核电涉密场景的非接触式人员全域定位算法优化方案
  • 2026年q2:美业新商机/美业项目/自主创业项目/连锁品牌加盟/EF时尚假发核心业务与技术体系全解析 - 优质品牌商家
  • 探寻2026年当下广西优秀的四害消杀服务专业提供商 - 2026年企业资讯
  • HanLP RESTful API 实战:如何用Python批量处理社交媒体文本并可视化分析结果?
  • C++23标准几个特性结合使用 学习阶段可能有点过度设计,评论区有源码
  • 告别风扇噪音与高温:FanControl三分钟搞定Windows散热优化
  • Android中Activity,Window,Application,WindowToken,View,Display之间关系用通俗形象的方式介绍下
  • 别再死记硬背Sarsa公式了!用Python手搓一个走迷宫AI,5分钟搞懂On-Policy和Q-learning的区别
  • 从喷头滴漏到AI节水37%:一个Lindy灌溉集群的30天自动化演进日记(含Prometheus监控看板+告警阈值SOP)
  • 2026年AI写作辅助平台深度评测:6款工具专业水准得分排名
  • 基于Arduino与超声波传感器的高尔夫自动喂球器设计与实现
  • 基于Arduino与BNO055陀螺仪的桌面绘图机器人:从传感器融合到G代码解析
  • 2026年圆盘式过滤器行业评测:核心性能横向对比 - 优质品牌商家
  • 别再傻傻分不清!用Python代码5分钟搞懂机器学习里的min和argmin
  • 用Python和SVM给水质‘看相’:手把手教你从200张水色图到水质分类模型
  • 从HDRi到游戏画面:手把手教你用Blender和Python预处理IBL环境贴图(含代码)
  • 工业防爆监控技术解析与山东区域选型实践