从零开发游戏需要学习的c#模块,第十二章(rpg小游戏入门,中篇,金币收集与ui显示)

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

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

第一步:创建金币类 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

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(不包含)之间的随机整数

  • 边界是 1map.Width-1,因为 0map.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

  • 金币吃完后自动刷新

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

相关推荐
小宋加油啊18 小时前
学习机械臂相关知识
学习
kaikaile199519 小时前
数字全息图处理系统(C# 实现)
开发语言·c#
漫友也是程序猿20 小时前
ddraw.dll异常排查:旧游戏图形接口、兼容性模式和DirectX组件检查
程序人生·游戏·电脑
十月的皮皮21 小时前
C语言学习笔记20260606- 求月份天数三种写法
c语言·笔记·学习
马士兵教育21 小时前
Java还有前景吗?Java+AI大模型学习路线及项目?
java·人工智能·python·学习·机器学习
lizhihai_991 天前
股市学习心得-AI 产业链核心标的梳理清单
大数据·服务器·人工智能·科技·学习
吃好睡好便好1 天前
说说科学爬山
学习·生活
lunzi_08261 天前
【学习笔记】《Python编程 从入门到实践》第8章:函数定义、参数传递与模块导入
笔记·python·学习
wearegogog1231 天前
C# .NET 文件比较工具 WinForms
开发语言·c#·.net