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

  • 金币吃完后自动刷新

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

相关推荐
阳光九叶草LXGZXJ1 小时前
达梦数据库-堆栈看问题-01-asmapi_asm_extent_load
linux·运维·数据库·sql·学习
号码认证服务1 小时前
公司号码认证怎么申请?提交企业资质开通名片,建立高效外呼体系
游戏·金融·健康医疗·传媒·零售·教育电商·交通物流
魔法阵维护师1 小时前
从零开发游戏需要学习的c#模块,第十九章(在游戏画面里显示文字 —— FontStashSharp)
学习·游戏·c#
PNP Robotics1 小时前
PNP机器人亮相南京学术论坛,分享具身智能多模态数据采集前沿成果
人工智能·深度学习·学习·机器学习·virtualenv
毕小宝1 小时前
AI 编程应用:实现 npm CLI 工具 scp-upload
学习
清钟沁桐1 小时前
mlir 编译器学习笔记之十 -- 数据类型
笔记·学习·mlir
red_redemption1 小时前
自由学习记录(190)
学习
Pizza_Lawson1 小时前
spinningup学习笔记(二)
笔记·学习
名字不好奇1 小时前
大模型如何训练?猜词游戏如何炼成智能大脑
深度学习·游戏·机器学习