从零开发游戏需要学习的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 里添加:

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);
}

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

相关推荐
在学了加油1 小时前
Inception v1学习笔记
笔记·python·学习
是一个Bug1 小时前
LangChain 入门完全指南:核心概念、学习路线与实战 Demo
学习·langchain
晓梦林2 小时前
EVA靶场学习笔记
android·笔记·学习
AI算法沐枫2 小时前
基于YOLO26深度学习的【果园荔枝检测与计数】系统设计与实现【python源码+Pyqt5界面+数据集+训练代码】
开发语言·人工智能·python·深度学习·qt·学习·机器学习
OBiO20132 小时前
精准靶向心肌细胞的AAV怎么选择?
学习
不羁的木木2 小时前
ArkWeb实战学习笔记02-环境搭建与基础配置
笔记·学习·harmonyos
stars-he2 小时前
SPICE编程与仿真学习笔记:从网表到瞬态分析
笔记·学习·硬件工程
江苏世纪龙科技2 小时前
科鲁兹虚拟系统破解汽车实训“三难“:工位少、组织难、评价弱
学习
小拉达不是臭老鼠2 小时前
Unity数据持久化_Json
学习·unity