当前位置: 首页 > 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.zskr.cn/news/1312489.html

相关文章:

  • Zotero文献元数据自动修正:告别混乱格式,让学术管理更高效
  • 别再混淆了!一文搞懂蓝牙经典(BT)的Inquiry和BLE的Advertising到底有啥区别
  • OpenDAN个人AI操作系统:从零构建智能体协作框架
  • 【网络安全】CTF 入门超详细教程|零基础到进阶,一篇封神!
  • 【NotebookLM数学研究辅助终极指南】:20年数学计算专家亲授5大高阶用法,90%研究者至今未发现
  • Kali Linux 基本命令|超全合集,新手直接抄
  • 瑞德克斯平台:多元化产品体系的综合呈现
  • CareUEyes电脑屏幕护眼软件神器
  • 【2026年拼多多暑期实习/春招- 5月17日-第四题- 多多的道路修建Ⅱ】(题目+思路+JavaC++Python解析+在线测试)
  • GanttProject完全指南:如何用免费开源甘特图软件高效管理项目?
  • Python钉钉机器人SDK实战:自动化通知与监控告警集成指南
  • 基于GCP部署开源语音数据采集站:从零构建定制化语音数据集
  • 深度解析REFramework架构原理与RE引擎游戏兼容性优化方案
  • Atmel Studio 6系统内调试实战:从硬件接口到高级技巧全解析
  • 边走边聊 Python 3.8:Chapter 20:测试与调试
  • java小题练习
  • Mac清理终极指南:3步彻底卸载应用残留,Pearcleaner免费开源解决方案
  • 别再手动点选了!用Python脚本5分钟搞定Abaqus批量加载节点力(附完整代码)
  • 2026嵌入式培训怎么选?一个工程师的3条硬核判断标准
  • 基于大语言模型的AI代理:自主循环执行系统任务的技术解析与实践
  • Arm架构文档版本控制与嵌入式开发实践
  • 工业眼睛:05 机器视觉能做什么?缺陷检测、OCR、3D 全解析
  • 04-内存管理
  • Node.js服务端项目如何集成Taotoken管理多模型调用与成本
  • 高速PCB设计中反射问题的量化分析与工程实践
  • 面向对象设计与构造-对于PTA作业1-3的总结与思考 - 彭梓鑫
  • Kubernetes etcd备份恢复
  • Git核心工作流解析:从快照原理到高效版本控制实践
  • VSCode MCP输出阅读器:AI编程工作流的效率倍增器
  • 大模型API成本优化:基于语义缓存与提示压缩的Token节省方案