[閒聊] 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