[闲聊] SUD实作尝试

楼主: poewar (☺☻)   2022-07-09 04:44:26
SUD就是Single User Dungeon啦,相对于MUD是多人连
线,SUD就是单人游玩。如果你要把自己架MUD,然后一
个人玩来当作同样的东西好像也不是不行,不过我还是
想做个无连线的(单机游戏),同时测试一些东西。
主要是类似MUD的文字接口跟操作,单人为主,战斗并
不是主要的成分,可能会是以解谜或互动为主。
因此实作的目标就是:单人、无连线、类MUD的操控。
目前已把最低限度的一些东西完成,稍稍有点东西可以
呈现在画面上。
https://i.imgur.com/rlVG2vM.png
目前完成的简易结构
1. Room/Zone/World 的房间跟区域结构
2. 房间叙述加简易条件限制(例如Str>5才能看到跟执行)
3. 房间描述分文字部分及ANSI部分
4. 简易物品道具/拾取/丢下
5. 角色指令独立物件处理
##
区域架构先简单处理,基本上就一层包一层,每层加上
一个Parent方便往上层取资料,目前只配置几个必要的
物件,很多细项都还不需要加入,因为目前都用不到。
public interface IWorld : IUpdatable
{
IReadOnlyDictionary<int, IZone> Zones { get; }
...
}
public interface IZone : IUpdatable
{
IWorld Parent { get; }
IReadOnlyDictionary<int, IRoom> Rooms { get; }
...
}
public interface IRoom : IUpdatable
{
IZone Parent { get; }
IReadOnlyList<IItem> Items { get; }
IReadOnlyDictionary<Guid, IUnit> Units { get; }
...
}
在Room的地方多设定了Items跟Units,用来作为物品跟
角色的存放,至于场景的描述字串,因为有别的设计,
所以这边就暂时没用string字段。
##
房间描述加条件限制,就是单纯的设定某些情况下可以
看到某些叙述,可能限制是角色身上的属性、游戏中的
时间、或是携带的道具等等。
在Room中配置
List<ICondString> CondStrings { get; }
而ICondString就简单设定一个检查跟一个输出。
public interface ICondString
{
bool Check(IUnit unit);
string ToString(IUnit unit);
}
执行起来就会类似这样:
https://i.imgur.com/ZQt4Qrp.png
这边简单的实作了一个限制Str的字串。
public class StrConstrainString : ICondString
{
public StrConstrainString(int minInclude, int maxExclude) { }
...
}
会想要做这个设计,主要是因为单人游戏,但又想要加
些针对事件可以不同的手段处理的方式,可以因为属性
不同用不同的方式解谜。
不过目前也就只有实作属性达到可以看到不同的环境叙
述而已,尚未有其余功能,后续要怎么做也还没想,就
暂时先这样。
##
房间描述分为文字部分跟ANSI部分。
原本是没打算这样做,后来想想似乎可以加些东西,就
拆了开来,至于为什么分出ANSI部分,是打算做为Scene
来处理,会跟环境的道具或叙述交互作用。
例如:
条件叙述(Perception > 8)
文字部分: [洞察]你发现窗户有些裂痕
ANSI部分: AnsiString() {S = "...", Rect = new Rect(10, 10, 10, 5), Order = 1}
在合并环境描述输出的时候,Room的基本ANSI作为底,
再把条件叙述检验成功的取出,并使用AnsiString物件
中的ANSI去取代指定位置Rect的ANSI资料,最后再输出
至画面上,用此来达到ANSI图不是单纯Room图片而已。
不过目前这边逻辑没做就是了,只是单纯的构思,但是
ANSI图层合并的逻辑,我在我自己做的ANSI绘图软件中
已经验证过是可行,也不会太复杂。
##
因为只有房间跟移动有点无聊,为了要有物品可以操作
,所以加入个简单的物品结构,每个Room就直接用个
IReadOnlyList<IItem>来保存每个Room中的物品,单位
身上也同样需要。
道具就简单设定几个字段,这边同样把文字描述跟ANSI
资料拆分开来。
public interface IItem
{
int ID { get; }
string Name { get; set; }
string DisplayName { get; set; }
string InspectDesc { get; set; }
string InspectANSI { get; set; }
}
简易的拾取物品动作。
https://i.imgur.com/Y5dJO9Q.png
##
至于角色指令独立物件处理,就是每个动作各自继承
IHandler实作逻辑,目前的移动、拾取、Look等都各
自实作逻辑,单位身上需要有一个参照来保存。
Dictionary<string, IHandler<IUnit>> Handlers { get; }
输入动作的时候检查是否有对应的handler,取出并运
作。
public interface IHandler<T>
{
void Process(T o, params string[] args);
}
主要这么做的原因,当初是想说我想要动态配给单位可
执行的指令,也可以动态的移除,例如装备一些道具后
这个道具会Add一个handler,让角色可以执行特定的动
作,移除装备就移除这个动作。
##
基本上往单机游戏方向设计就是了,游戏启动用一个Task
去执行Loop,并且每次Loop呼叫World的Update,并一
层层传递下去,来达到更新。
目前暂时这样吧,很大的机会做不完,后续会不会继续补
完也很难说:P 反正也只是想要来验证一下,确实还算有趣。
作者: tsetsethatha (吉星麦造~~~我来了)   2022-07-14 19:52:00
感谢提供! 收入精华区 z-3-12

Links booklink

Contact Us: admin [ a t ] ucptt.com