上一节课我们让勇者可以通过键盘操控了,这一课我们来丰富一下我们的游戏内容

首先,我们来创建一个金币类

第一步:创建金币类 Coin.cs

using System;

namespace MyGame
{
    class Coin
    {
        public int X { get; set; }
        public int Y { get; set; }
        public bool IsActive { get; set; }  // 是否还在场上
        public int Value { get; private set; }  // 价值

        public Coin(int x, int y)
        {
            X = x;
            Y = y;
            IsActive = true;
            Value = 10;
        }

        public void Draw()
        {
            if (!IsActive) return;  // 已经被捡了就不画

            Console.SetCursorPosition(X, Y);
            Console.ForegroundColor = ConsoleColor.Yellow;
            Console.Write("$");
            Console.ResetColor();
        }

        // 擦除金币(被捡走时调用)
        public void Erase()
        {
            Console.SetCursorPosition(X, Y);
            Console.Write(" ");
        }
    }
}

第二步:创建 UI 类 GameUI.cs

using System;

namespace MyGame
{
    class GameUI
    {
        private int uiLine;  // UI 显示在哪一行

        public GameUI(int mapHeight)
        {
            uiLine = mapHeight + 1;  // 地图下方第一行
        }

        public void Draw(int score, int coinCount, int bagItemCount)
        {
            // 先清空 UI 区域
            Console.SetCursorPosition(0, uiLine);
            Console.Write(new string(' ', Console.WindowWidth));
            Console.SetCursorPosition(0, uiLine + 1);
            Console.Write(new string(' ', Console.WindowWidth));

            // 显示分数
            Console.SetCursorPosition(2, uiLine);
            Console.ForegroundColor = ConsoleColor.White;
            Console.Write($"⭐ 分数:{score}");

            // 显示剩余金币数
            Console.SetCursorPosition(20, uiLine);
            Console.ForegroundColor = ConsoleColor.Yellow;
            Console.Write($"💰 场上金币:{coinCount}");

            // 显示背包物品数
            Console.SetCursorPosition(40, uiLine);
            Console.ForegroundColor = ConsoleColor.Cyan;
            Console.Write($"🎒 背包物品:{bagItemCount}");

            Console.ResetColor();
        }

        public void ShowMessage(string msg)
        {
            Console.SetCursorPosition(2, uiLine + 1);
            Console.ForegroundColor = ConsoleColor.Green;
            Console.Write(msg);
            Console.ResetColor();
        }
    }
}

第三步:改造 Game.cs,加入金币系统

using System;
using System.Collections.Generic;
using System.Threading;

namespace MyGame
{
    class Game
    {
        private static Game instance;
        public static Game Instance
        {
            get
            {
                if (instance == null)
                    instance = new Game();
                return instance;
            }
        }

        private Game() { }

        private bool isRunning;
        private Player player;
        private GameMap map;
        private InputHandler input;
        private GameUI ui;

        // 金币相关
        private List<Coin> coins;
        private int score;
        private int totalCoinsSpawned = 5;

        public void Start()
        {
            Console.CursorVisible = false;
            Console.Title = "控制台RPG";

            map = new GameMap(40, 20);
            player = new Player(map.Width / 2, map.Height / 2);
            input = new InputHandler();
            ui = new GameUI(map.Height);
            isRunning = true;

            score = 0;

            // 初始化金币列表
            coins = new List<Coin>();
            SpawnCoins(totalCoinsSpawned);

            map.Draw();

            // 主循环
            while (isRunning)
            {
                Update();
                Render();
                Thread.Sleep(30);
            }

            Console.SetCursorPosition(0, map.Height + 3);
            Console.WriteLine("游戏结束!按任意键退出...");
            Console.ReadKey();
        }

        private void SpawnCoins(int count)
        {
            Random rng = new Random();

            for (int i = 0; i < count; i++)
            {
                // 在地图边界内随机生成坐标
                int x = rng.Next(1, map.Width - 1);
                int y = rng.Next(1, map.Height - 1);

                coins.Add(new Coin(x, y));
            }
        }

        private void Update()
        {
            InputHandler.Command cmd = input.GetCommand();

            switch (cmd)
            {
                case InputHandler.Command.MoveUp:
                    player.Move(0, -1, 1, 1, map.Width - 2, map.Height - 2);
                    break;
                case InputHandler.Command.MoveDown:
                    player.Move(0, 1, 1, 1, map.Width - 2, map.Height - 2);
                    break;
                case InputHandler.Command.MoveLeft:
                    player.Move(-1, 0, 1, 1, map.Width - 2, map.Height - 2);
                    break;
                case InputHandler.Command.MoveRight:
                    player.Move(1, 0, 1, 1, map.Width - 2, map.Height - 2);
                    break;
                case InputHandler.Command.Quit:
                    isRunning = false;
                    break;
            }

            // ★ 检测玩家是否碰到金币
            CheckCoinCollision();

            // ★ 如果金币被捡完了,重新生成一批
            if (GetActiveCoinCount() == 0)
            {
                SpawnCoins(totalCoinsSpawned);
            }
        }

        private void CheckCoinCollision()
        {
            foreach (Coin coin in coins)
            {
                if (coin.IsActive && coin.X == player.X && coin.Y == player.Y)
                {
                    // 碰到金币!
                    coin.IsActive = false;
                    coin.Erase();
                    score += coin.Value;
                }
            }
        }

        private int GetActiveCoinCount()
        {
            int count = 0;
            foreach (Coin coin in coins)
            {
                if (coin.IsActive) count++;
            }
            return count;
        }

        private void Render()
        {
            // 擦除旧位置的玩家
            player.EraseOld();

            // 画所有活跃的金币
            foreach (Coin coin in coins)
            {
                coin.Draw();
            }

            // 画玩家
            player.Draw();

            // 画 UI
            ui.Draw(score, GetActiveCoinCount(), 0);
        }
    }
}

代码逐段解析

1. 金币生成

csharp

int x = rng.Next(1, map.Width - 1);
int y = rng.Next(1, map.Height - 1);
  • Random.Next(min, max):生成 min(包含)到 max(不包含)之间的随机整数

  • 边界是 1 到 map.Width-1,因为 0 和 map.Width-1 是墙 #

2. 碰撞检测

csharp

if (coin.IsActive && coin.X == player.X && coin.Y == player.Y)
  • 判断金币坐标和玩家坐标是否完全重合

  • 这就是最简单的“碰撞检测”

3. 金币重生

csharp

if (GetActiveCoinCount() == 0)
{
    SpawnCoins(totalCoinsSpawned);
}
  • 场上金币被吃光后,自动刷新一批

  • 保证永远有金币可捡

4. 渲染顺序很重要

text

擦除旧玩家 → 画金币 → 画玩家 → 画 UI
  • 金币在玩家下面,所以先画金币再画玩家

  • 如果先画玩家再画金币,金币会覆盖在玩家身上

  • 黄色 $ 是金币

  • 黄色 @ 是玩家

  • 玩家走到金币上,金币消失,分数 +10

  • 金币吃完后自动刷新

这节课到此为止,关注我下期内容更精彩,我们继续来丰富属于自己的游戏世界!

更多推荐