C#学习-魔塔项目记录(2021.11.30)
作者:互联网
项目要求:
1、使用C#控制台实现,
2、至少3个场景,且场景数据从文件中读取加载
3、玩家可以按键控制移动,碰到障碍物停止
3、UI显示玩家信息数据
4、怪物信息可以编辑,txt,xml或者json
5、有简单的框架支撑,且设计合理。使用封装、继承、多态。
6、可以战斗
C#快学完了,做一个魔塔的项目,今天开始记录下每天的进度,也是帮助自己回顾一下流程。
搭建框架(用到了观察者模式)
1、先把需要的几个类建好(目前就这么多)
- GameManager 管理游戏
- GameMap 地图类
- Player 玩家类
- Program Mian函数入口
- Singlton 单例泛型类,接入别的类,就可以实现单例的效果
2、看下各个类里有什么
首先是Singlton里,是一个带约束的泛型抽象类,功能是只要接入别的类就可以相应实现单例效果,项目里就不用反复写单例了。
abstract class Singlton<T> where T : new()
{
private static T instance;
public static T Instance
{
get
{
if(instance == null)
{
instance = new T();
}
return instance;
}
}
}
然后是GameManager
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
namespace Mota
{
class GameManager :Singlton<GameManager>
{
Player Player;
GameMap gameMap;
public void Init()
{
InputManager.Instance.Init();//输入管理的初始化
gameMap = new GameMap("Map.txt");//实例化一个地图对象,把文件路径传进去
gameMap.PrintMap();
Player = new Player();
Player.Init();
while (true)
{
Update();
Render();
Thread.Sleep(1000 / 30);//游戏帧率控制
}
}
public void Update()
{
InputManager.Instance.Update();
Player.Update();
}
public void Render()
{
}
}
}
简单的框架:
Init 方法初始化整个游戏
Update 方法更新数据
Render 方法渲染画面
在 Init 里用一个while循环调用Update和Render方法,
然后在框架里加上各种模块实现各种功能,目前只做了Player和GameaMap的几个简单功能
先看下Player
using Mota;
using System;
using System.Collections.Generic;
using System.Text;
namespace Mota
{
enum Direction
{
None,
Up,
Down,
left,
right
}//各个方向移动的枚举
class Player :IKeyDown//这里是输入管理的接口
{
Direction dir = Direction.None;
public void Init()
{
InputManager.Instance.AddObserverList(this);
}//把自己加入观察者数组
public void Update()
{
Move();
}
//player自己的Update,更新自己的各项数据,
//最后GameManager里只要调用这个玩家的Update就可以实现玩家的功能了
public void Move()
{
switch (dir)
{
case Direction.None:
break;
case Direction.Up:
Console.WriteLine("向上走");//检测下功能
break;
case Direction.Down:
break;
case Direction.left:
break;
case Direction.right:
break;
default:
break;
dir = Direction.None;
}
}//移动的逻辑
public void ObserverOnKeyDown(ConsoleKey Key)
{
switch (Key)
{
case ConsoleKey.W:
dir = Direction.Up;
break;
case ConsoleKey.S:
dir = Direction.Down;
break;
case ConsoleKey.A:
dir = Direction.left;
break;
case ConsoleKey.D:
dir = Direction.right;
break;
default:
break;
}
}//玩家作为键盘输入的观察者,按 W A S D 控制玩家移动
}
}
然后是GameMap
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
namespace Mota
{
class GameMap
{
int[,] mapDate;//定义一个二维数组接收地图数据
int row;//地图的行数
int col;//地图的列数
public GameMap(string path)
{
string[] lines = File.ReadAllLines(path);
//调用 File 类里的 ReadAllLines 方法,
//读取文件里的内容传入一个string数组(文件路径以参数形式,后面 new 的时候传入)
string[] line0 = lines[0].Split(",");//第零行按照“,”分隔,来读取地图行列
row = int.Parse(line0[0]);
col = int.Parse(line0[1]);
mapDate = new int[row, col];
for (int i = 0; i < row; i++)
{
string curLine = lines[i + 1];
string[] datas = curLine.Split(",");
//从第一行开始按照“,”分割来读取数据,一共有roe行
//读取后把每一行的所有数据数据存入 datas 数组备用
for (int j = 0; j < col; j++)
{
mapDate[i, j] = int.Parse(datas[j]);
//把datas 数组里的数据返回给mapData
}
}
}
/*
public void Init()
{
InputManager.Instance.AddObserverList(this);
}//把地图添加为观察者,暂时用不到
*/
StringBuilder sb = new StringBuilder();
//建一个 StringBuilder 打印地图(性能要比直接用 string 字符串打印好)
public void PrintMap()
{
sb.Clear();
for (int i = 0; i < mapDate.GetLength(0); i++)
{
for (int j = 0; j < mapDate.GetLength(1); j++)
{
if (mapDate[i, j] == 0)
{
sb.Append(" ");
}
else if (mapDate[i, j] == 10)
{
sb.Append("■");
}
else if (mapDate[i, j] == 46)
{
sb.Append("◇");
}
else if (mapDate[i, j] == 38)
{
sb.Append("△");
}
}
sb.Append("\n");
}
Console.WriteLine(sb);
}//根据mapDate里的数据,往sb里追加各种地图元素,现在地图还不完整
public override string ToString()
{
return sb.ToString();
}//改写 ToString 方法用于打印地图
}
}
地图数据是这样的:(用Tiled软件画出来可以直接保存成txt文档)
然后看下 InputManager 输入管理类
using System;
using System.Collections.Generic;
using System.Text;
namespace Mota
{
class InputManager : Singlton<InputManager>//继承单例类,实现单例功能
{
//观察者的本质,就是维护一个容器,里面放了所有观察者的对象
//当被观察的对象发生变化,那么会遍历这个容器,对所有观察者发出通知
List<IKeyDown> ObserverKeyList; //新建一个List容器
public void AddObserverList(IKeyDown Observer)
{
ObserverKeyList.Add(Observer);
}//往容器里追加对象的方法
public void RemoveObserverList(IKeyDown Observer)
{
ObserverKeyList.Remove(Observer);
}//往容器里移除对象的方法
public void Init()
{
ObserverKeyList = new List<IKeyDown>();
}//InputManager 的初始化(比较low...只有实例化一个对象出来,哈哈)
public void Update()
{
while (Console.KeyAvailable)//当按下按键时
{
ConsoleKey Key = Console.ReadKey(true).Key;//接收按键
foreach (var item in ObserverKeyList)
{
item.ObserverOnKeyDown(Key);
}//foreach 循环,把按键通知给观察者数组里的所有观察者
}
}//InputManager的数据更新
}
interface IKeyDown //按键的接口
{
public void ObserverOnKeyDown(ConsoleKey Key)
{
}
}
}
第一天项目就做到这里啦~未完待续。。。。。。
标签:Direction,2021.11,C#,void,30,System,break,using,public 来源: https://blog.csdn.net/Erenlui/article/details/121644466