基于文本的冒险游戏。

我在这个夏天一直在学C#,现在感觉像从我迄今为止所做的那样做出一个小型项目。 我已经决定了一种基于文本的冒险游戏。

游戏的基本结构将涉及多个部门(或房间)。 进入房间后,会输出描述并提供一些您可能采取的措施; 能够检查,拿起,使用那个房间里的东西; 可能是一个战斗系统等等。一个扇区最多可连接4个其他扇区。

无论如何,在论文中如何为此设计代码涂写想法,我正在摸索我的部分代码结构。

我已经决定了一个玩家类,和一个代表等级/地下城/区域的'等级'类。 这个级别的班级将由一些相互关联的“部门”组成。 在任何时候,玩家都会出现在关卡中的某个特定区域。

所以这是混乱:

从逻辑上讲,人们会期望一种方法,如player.Move(Dir d)
这种方法应该改变关卡对象中的'当前部门'字段。 这意味着班级玩家需要了解班级。 嗯。 Level可能需要操纵Player对象(例如,玩家进入房间,被某物埋伏,从库存中丢失某些东西)。所以现在Level还需要持有对Player对象的引用?

这不舒服; 所有的东西都必须提及其他所有东西。

在这一点上,我记得阅读了我正在使用的书中的代表。 虽然我知道C ++中的函数指针,但是关于代表的章节中给出了一些基于事件的编程观点的例子,对此我没有多少启发。

这给了我设计类的想法如下:

玩家:

class Player
{
    //...

    public delegate void Movement(Dir d);   //enum Dir{NORTH, SOUTH, ...}

    public event Movement PlayerMoved;

    public void Move(Dir d)
    {        
        PlayerMoved(d);

        //Other code...
    }

}

水平:

class Level
{
    private Sector currSector;
    private Player p;
    //etc etc...

    private void OnMove(Dir d)
    {
        switch (d)
        {
            case Dir.NORTH:
                //change currSector
                //other code
                break;

                //other cases
        }
    }

    public Level(Player p)
    {
        p.PlayerMoved += OnMove;  
        currSector = START_SECTOR;
        //other code
    }

    //etc...
}

这是一个好方法吗?
如果代表章节没有按照这种方式呈现,我就不会想到使用这种“事件”。 那么如何在不使用回调的情况下实现这个功能呢?

我有一个制作非常详细的帖子的习惯......对不起v__v


对于像游戏者和当前房间这样的大部分信息的'游戏'类来说呢? 对于诸如移动玩家的操作,游戏类可以根据房间的等级图将玩家移动到不同的房间。

游戏课程将管理游戏各个组件之间的所有交互。

使用类似事件的事件带来的危险是您的事件会纠结。 如果你不小心,最终会发生事件互相触发并导致堆栈溢出,这会导致在特殊情况下标志会关闭事件,并且程序不易理解。

UDPATE:

为了使代码更易于管理,可以将主类之间的某些交互作为类自身进行建模,例如Fight类。 使用接口使您的主类能够执行某些交互。 (请注意,我冒昧地在游戏中发明了一些你可能不想要的东西)。

例如:

// Supports existance in a room.
interface IExistInRoom { Room GetCurrentRoom(); }

// Supports moving from one room to another.
interface IMoveable : IExistInRoom { void SetCurrentRoom(Room room); }

// Supports being involved in a fight.
interface IFightable
{
  Int32 HitPoints { get; set; }
  Int32 Skill { get; }
  Int32 Luck { get; }
}

// Example class declarations.
class RoomFeature : IExistInRoom
class Player : IMoveable, IFightable
class Monster : IMoveable, IFightable

// I'd proably choose to have this method in Game, as it alters the
// games state over one turn only.
void Move(IMoveable m, Direction d)
{
  // TODO: Check whether move is valid, if so perform move by
  // setting the player's location.
}

// I'd choose to put a fight in its own class because it might
// last more than one turn, and may contain some complex logic
// and involve player input.
class Fight
{
  public Fight(IFightable[] participants)

  public void Fight()
  {
    // TODO: Logic to perform the fight between the participants.
  }
}

在你的问题中,你确定了这样的事实,即如果你在播放器类中插入了类似Move方法的东西,你将有许多类必须知道对方。 这是因为类似移动的东西既不属于玩家也不属于一个房间 - 移动同时影响两个对象。 通过建模主对象之间的“交互”,可以避免很多这些依赖关系。


听起来像我经常使用Command类或Service类的场景。 例如,我可能会创建一个MoveCommand类来执行Levels和Persons之间的操作和协调。

这种模式具有进一步强化单一责任主体(SRP)的优势。 SRP表示,一个班级只能有一个改变的理由。 如果Person类负责移动,那么毫无疑问会有一个以上的理由需要改变。 通过将Move的逻辑分解成它自己的类,它会更好地封装。

有几种实现Command类的方法,每种方法都能更好地适应不同的场景。 命令类可以有一个Execute方法,它接受所有必要的参数:

 public class MoveCommand {
    public void Execute(Player currentPlayer, Level currentLevel) { ... }
 }

 public static void Main() {
     var cmd = new MoveCommand();
     cmd.Execute(player, currentLevel);
}

或者,有时候我发现它更直接,更灵活,可以在命令对象上使用属性,但它使得客户端代码可以通过忘记设置属性来更容易地滥用类 - 但优点是您具有相同的函数签名对所有命令类执行,因此您可以为该方法创建一个接口并使用抽象命令:

 public class MoveCommand {
    public Player CurrentPlayer { get; set; } 
    public Level CurrentLevel { get; set; }
    public void Execute() { ... }
 }

 public static void Main() {
     var cmd = new MoveCommand();
     cmd.CurrentPlayer = currentPlayer;
     cmd.CurrentLevel = currentLevel;
     cmd.Execute();
}

最后,您可以将参数作为构造函数参数提供给Command类,但我将放弃该代码。

无论如何,我发现使用命令或服务是一种非常强大的方式来处理操作,例如Move。


对于基于文本的游戏,几乎肯定会有一个CommandInterpretor(或类似的)对象,用于评估用户输入的命令。 通过这种抽象级别,您不必在Player对象上实现所有可能的操作。 您的解释器可能会向您的Player对象(“show inventory”)推送某些类型的命令,一些命令指向当前占用的Sector对象(“列表退出”),一些命令给Level对象(“move player North”),一些对特殊对象的命令(“攻击”可能会被推送到CombatManager对象)。

通过这种方式,Player对象变得更像是Character,而CommandInterpretor更多地体现了坐在键盘上的真人玩家。

链接地址: http://www.djcxy.com/p/32025.html

上一篇: based Text Adventure Game.

下一篇: Correct combination of sensor management and camera on android