从零开发游戏需要学习的c#模块,第二十九章(经验值与升级系统)

本节课学习内容

  1. 击杀敌人获得经验值

  2. 经验条显示在血量条下方

  3. 经验满了升级,攻击力提升、血量回满

  4. 升级时屏幕上飘出"LEVEL UP"文字


第一步:升级 Player 类

打开 Player.cs,在类里加上经验值和升级相关的内容:

1. 添加字段:

csharp

复制代码
// 升级系统
public int Level { get; private set; } = 1;
public int Experience { get; private set; } = 0;
public int ExpToNextLevel { get; private set; } = 30;

2. 在构造函数里初始化:

这些字段已经有默认值,不用动构造函数。

3. 在 Player.cs 末尾添加方法:

csharp

复制代码
// 获得经验值,返回 true 表示升级了
public bool GainExperience(int amount)
{
    Experience += amount;
    if (Experience >= ExpToNextLevel)
    {
        LevelUp();
        return true;
    }
    return false;
}

private void LevelUp()
{
    Level++;
    Experience -= ExpToNextLevel;
    ExpToNextLevel = (int)(ExpToNextLevel * 1.5f); // 升级所需经验递增
    Attack += 5;
    MaxHp += 20;
    Hp = MaxHp; // 升级回满血
}

// 获取经验值百分比(用于经验条)
public float GetExpPercent()
{
    return (float)Experience / ExpToNextLevel;
}

第二步:添加飘字效果类

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

cs 复制代码
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using FontStashSharp;

namespace MY_FIRST_GAME
{
    public class FloatingText
    {
        public Vector2 Position;
        public string Text;
        public Color Color;
        public float Lifetime;
        public float MaxLifetime;
        public bool IsAlive => Lifetime > 0;
        private float floatSpeed = -60f; // 向上飘

        public FloatingText(Vector2 position, string text, Color color, float lifetime = 1.5f)
        {
            Position = position;
            Text = text;
            Color = color;
            Lifetime = lifetime;
            MaxLifetime = lifetime;
        }

        public void Update(float deltaTime)
        {
            Lifetime -= deltaTime;
            Position.Y += floatSpeed * deltaTime;
        }

        public void Draw(SpriteBatch spriteBatch, SpriteFontBase font)
        {
            float alpha = Lifetime / MaxLifetime;
            Vector2 textSize = font.MeasureString(Text);
            spriteBatch.DrawString(font, Text, Position - textSize / 2, Color * alpha);
        }
    }
}

第三步:改造 Game1.cs

以下是需要改动的部分,对照着替换即可。

1. 添加字段:

复制代码
private List<FloatingText> floatingTexts = default!;

2. 在 InitializeGame 里初始化列表:

csharp

复制代码
floatingTexts = new List<FloatingText>();

3. 在 CheckBulletEnemyCollision 里,击杀敌人后给经验并生成飘字:

找到击杀敌人的那几行,加上:

csharp

复制代码
if (enemies[j].Hp <= 0)
{
    enemies[j].IsAlive = false;
    score += enemies[j].ScoreValue;
    enemiesDefeatedThisGame++;
    particleSystem.EmitHitParticles(enemies[j].Position);

    // ★ 加经验
    int expGain = enemies[j].ScoreValue / 2 + 5;
    bool leveledUp = player.GainExperience(expGain);
    floatingTexts.Add(new FloatingText(enemies[j].Position, $"+{expGain} EXP", Color.Cyan));

    if (leveledUp)
    {
        floatingTexts.Add(new FloatingText(
            enemies[j].Position + new Vector2(0, -30),
            "LEVEL UP!",
            Color.Gold, 2f));
    }
}

4. 在 Update 中更新飘字:

Game 状态的 Update 里(particleSystem.Update 附近)加上:

csharp

复制代码
foreach (FloatingText ft in floatingTexts)
    ft.Update(deltaTime);
floatingTexts.RemoveAll(ft => !ft.IsAlive);

5. 替换 DrawGameUI 方法(加经验条):

cs 复制代码
private void DrawGameUI()
{
    _spriteBatch.DrawString(font, $"分数:{score}", new Vector2(10, 10), Color.White);
    _spriteBatch.DrawString(font, $"最高分:{saveData.HighScore}", new Vector2(10, 35), Color.Gold);

    // 血量条
    DrawPlayerHealthBar(_spriteBatch, 10, 65, 200, 20);
    _spriteBatch.DrawString(font, $"{player.Hp}/{player.MaxHp}", new Vector2(220, 63), Color.White);

    // ★ 经验条
    DrawExpBar(_spriteBatch, 10, 90, 200, 14);
    _spriteBatch.DrawString(font, $"Lv.{player.Level}", new Vector2(220, 86), Color.Cyan);
    _spriteBatch.DrawString(font, $"{player.Experience}/{player.ExpToNextLevel}", new Vector2(270, 86), Color.LightGray);

    _spriteBatch.DrawString(font, $"敌人:{enemies.Count} | 子弹:{bullets.Count}",
        new Vector2(10, 115), Color.Yellow);
    _spriteBatch.DrawString(font, "WASD移动 | 鼠标瞄准左键射击 | M静音",
        new Vector2(10, 570), Color.LightGray);
}

6. 添加画经验条的方法:

cs 复制代码
private void DrawExpBar(SpriteBatch spriteBatch, int x, int y, int width, int height)
{
    float expPercent = player.GetExpPercent();

    Texture2D pixel = new Texture2D(GraphicsDevice, 1, 1);
    pixel.SetData(new[] { Color.White });

    // 背景
    spriteBatch.Draw(pixel, new Rectangle(x, y, width, height), Color.DarkSlateGray);

    // 经验值
    int currentWidth = (int)(width * expPercent);
    spriteBatch.Draw(pixel, new Rectangle(x, y, currentWidth, height), Color.Cyan);

    // 边框
    spriteBatch.Draw(pixel, new Rectangle(x, y, width, 1), Color.White);
    spriteBatch.Draw(pixel, new Rectangle(x, y + height - 1, width, 1), Color.White);
    spriteBatch.Draw(pixel, new Rectangle(x, y, 1, height), Color.White);
    spriteBatch.Draw(pixel, new Rectangle(x + width - 1, y, 1, height), Color.White);
}

7. 在 DrawGameWorld 末尾加飘字绘制:

player.Draw(_spriteBatch); 后面加上:

csharp

复制代码
foreach (FloatingText ft in floatingTexts)
    ft.Draw(_spriteBatch, font);

我是魔法阵维护师,关注我,下期更精彩!

相关推荐
JaydenAI13 小时前
[MAF预定义ChatClient中间件-04]ReducingChatClient——通过精减对话实施又不丢失基本语义
ai·c#·agent·maf·chatclient管道·对话历史压缩
chenxy0213 小时前
Biopython学习笔记
笔记·学习
小满Autumn13 小时前
WPF 进阶:样式、触发器与控件模板
c#·.net·wpf
wanhengidc13 小时前
云手机 算力终端应用
运维·服务器·网络·游戏·智能手机
光泽雨13 小时前
C# 扩展方法(Extension Method)在语法上的核心灵魂。
开发语言·c#
啄缘之间13 小时前
10.【学习】SPI & UART 验证环境与测试用例
开发语言·经验分享·学习·fpga开发·测试用例·verilog
咸甜适中13 小时前
rust语言学习笔记Trait(十三)Borrow、BorrowMut(借用)
笔记·学习·rust
凌云若寒13 小时前
SENTINEL软件
学习·sentinel·产品经理·制造·软件需求
影寂ldy13 小时前
C#Lambda表达式
开发语言·c#