当前位置: 首页 > news >正文

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

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

  • 金币吃完后自动刷新

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

http://www.jsqmd.com/news/840889/

相关文章:

  • Nginx CVE-2026-42945
  • Zotero文献元数据自动修正:告别混乱格式,让学术管理更高效
  • 02-进程管理
  • 2026年温州专业测甲醛机构大揭秘,哪家才是你的最佳之选? - 品牌企业推荐师(官方)
  • 别再混淆了!一文搞懂蓝牙经典(BT)的Inquiry和BLE的Advertising到底有啥区别
  • nncase神经网络编译器:从PyTorch模型到K210边缘AI部署全流程详解
  • AI智能体技能库实战:从文档解析到RAG检索的工程化集成
  • 航空器配载与货运管理系统总结Blog
  • 03-处理机调度与死锁
  • 14504黄大年茶思屋145期 难题第四题 块KV复用的交叉注意力修复问题 标准化解题框架
  • 工业眼睛:05 机器视觉能做什么?缺陷检测、OCR、3D 全解析
  • 【NotebookLM数学研究辅助终极指南】:20年数学计算专家亲授5大高阶用法,90%研究者至今未发现
  • 探索DeepMosaics:当AI遇见图像隐私保护与修复的艺术
  • 面向对象设计与构造——航空器配载与货运管理系统单元总结
  • 面向对象程序设计总结(作业一至作业三)
  • 智慧树自动刷课插件:三步实现网课自动化学习的终极秘籍
  • 工业眼睛:04 10 分钟做出你的第一个视觉程序:识别螺丝
  • LabVIEW 8.5多核并行编程实战:榨干老旧CPU性能的底层优化指南
  • 树状数组训练题 - HDU 4217 Data Structure?
  • 【2026年拼多多暑期实习/春招- 5月17日-第四题- 多多的道路修建Ⅱ】(题目+思路+JavaC++Python解析+在线测试)
  • 告别命令行恐惧症:N_m3u8DL-CLI-SimpleG如何让M3U8下载变得像聊天一样简单
  • 14505黄大年茶思屋145期 第五题 面向长期运行LLM Agent的高效记忆构建和查询算法 标准化解题框架
  • ARM Cortex-A55温升实测:从热成像到散热优化的嵌入式设计实践
  • 2026 年全国天津搬家拖运物流怎么选?兴达伟业物流15022082555 - 品牌企业推荐师(官方)
  • Arm架构文档版本控制与嵌入式开发实践
  • 【NotebookLM高阶问答工作流】:从上传→切片→提问→溯源→导出,一整套可复用的SOP模板(含GTD集成方案)
  • 2026 年互联网洗衣靠谱品牌推荐:干洗 / 上门取送 / 衣物家纺洗护选择指南 - 海棠依旧大
  • 基于GCP部署开源语音数据采集站:从零构建定制化语音数据集
  • Atmel Studio 6系统内调试实战:从硬件接口到高级技巧全解析
  • 单例模式深度解析:从基础实现到生产级避坑指南