从零开发游戏需要学习的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);

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

相关推荐
落寞的星星3 小时前
这个对象就包含了已经转换好的DFA和各种词法分析器运转所需要的参数。下一步,我们就可以用ScannerInfo对象创建出Scanner对象,请看下面的代码:
开发语言·c#
聪慧的水蜜桃7 小时前
【YFIOs】用C#开发硬件之设备上云
开发语言·c#
星幻元宇VR8 小时前
公共安全实训展厅设备【人防知识学习系统】
科技·学习·安全
心中有国也有家11 小时前
AtomGit Flutter 鸿蒙客户端:情绪日记的时间线实现
学习·flutter·华为·harmonyos
hixiong12312 小时前
TensorRT转换工具分享
人工智能·计算机视觉·ai·c#
百里香酚兰12 小时前
【python学习笔记】pyttsx3库疑似只播报一次语音
笔记·python·学习
恣逍信点13 小时前
《凌微经》助读:本体论根基——“无之自悖”与“形性一体”
人工智能·科技·学习·程序人生·生活·交友·哲学
莫生灬灬14 小时前
DY联系人聊天Web面板支持获取联系人/聊天记录/发送消息
前端·chrome·websocket·c#
vivo互联网技术14 小时前
当 AI 进入推荐系统:从“推什么”到“怎么选”
人工智能·游戏·产品
chh56315 小时前
C++--string
java·开发语言·网络·c++·学习