C# c语言中的状态模式#
我读了一本叫做《游戏编程模式》的书,开始用C#实现其中的一些模式。现在,我正在实现下面的UML类图描述的状态模式 这是我的主要节目。我使用了两个不同的线程,以便不停止键盘用户输入的游戏循环。在hero类中,HandleInput方法调用存储在字段state中的当前状态的HandleInput方法C# c语言中的状态模式#,c#,state-pattern,C#,State Pattern,我读了一本叫做《游戏编程模式》的书,开始用C#实现其中的一些模式。现在,我正在实现下面的UML类图描述的状态模式 这是我的主要节目。我使用了两个不同的线程,以便不停止键盘用户输入的游戏循环。在hero类中,HandleInput方法调用存储在字段state中的当前状态的HandleInput方法 class Program { private static string key; private static Thread t; private static Hero
class Program
{
private static string key;
private static Thread t;
private static Hero hero1;
public delegate void PressDelegate();
public static event PressDelegate OnPress;
static void Main(string[] args)
{
// Creating Hero
hero1 = new Hero("zelda");
// Subscribing to KeyboardInput Event
OnPress += KeyboardInputHandler;
// Game Loop
t = new Thread(new ThreadStart(KeyboardInput));
t.Start();
}
private static void KeyboardInput()
{
while (true)
{
key = Console.ReadLine();
OnPress();
}
}
private static void KeyboardInputHandler()
{
hero1.HandleInput(key);
}
}
}
我的目标是,当用户按空格键时,英雄将其状态更改为JumpingState(假设其默认状态为IDLState),并在1秒后更改回idle(模拟重力效果)。问题是我已经尝试了一些解决方案,比如在IDLState中设置计时器,但是对于每个转换到跳跃状态的状态(例如,一个躲闪状态),我都必须这样做。我还尝试在hero类上使用if语句来实现这一点:(如果state是JumpingState,那么启动计时器,当finish调用SetState(idlstate)时,类似的东西),但我觉得这打破了SetState方法只在状态内部调用,而不在hero上调用的事实
我非常感谢您的帮助:)通常游戏是在游戏循环中运行的。一个非常简单的可以如下所示:
- 你应该处理所有的输入吗?每帧仅最后一次输入?仅当帧开始时按下该键时
- 是否有可能在每帧中多次切换状态?例如,“跳跃”可能会转换为“空闲”,但如果用户按住shift键,则可能会立即转换为“蜷缩”
- 将“状态”和“过渡”分开是很常见的。这有助于使状态机更加抽象。也就是说,您可以使用OnKeyTransition,将输入键和目标状态作为输入,而不是硬编码英雄应该在每个状态下跳转到空格。然后可以将此转换添加到所有应支持跳跃的状态
- 在一个游戏中可以有许多不同类型的状态机。一个高级别可能是,如果玩家正在驾驶汽车、步行、驾驶飞机等。较低级别的状态机可能处理动画。第三种可以用于人工智能。所有这些都有不同的需求,因此需要区别对待
public class State
{
public virtual State Update(ConsoleKey? input, TimeSpan deltaTime) => this;
}
public class IdleState : State
{
public override State Update(ConsoleKey? input, TimeSpan deltaTime)
{
if (input == ConsoleKey.Spacebar)
{
return new JumpingState();
}
return base.Update(input, deltaTime);
}
}
public class JumpingState : State
{
private TimeSpan elapsed = TimeSpan.Zero;
public override State Update(ConsoleKey? input, TimeSpan deltaTime)
{
elapsed += deltaTime;
if (elapsed > TimeSpan.FromSeconds(1))
{
return new IdleState();
}
return base.Update(input, deltaTime);
}
}
public class Game
{
static void Main(string[] args)
{
var game = new Game();
game.StartGame();
}
State currentState = new IdleState();
private TimeSpan frameRate = TimeSpan.FromMilliseconds(30);
public void StartGame()
{
Console.WriteLine("Game Started");
while (true)
{
var input = GetLastKeypress()?.Key;
if (input == ConsoleKey.Escape)
{
Console.WriteLine("Game Over");
return;
}
// Update the state
var nextState = currentState.Update(input, frameRate);
if (nextState != currentState)
{
currentState = nextState;
Console.WriteLine(currentState.GetType().Name);
}
Thread.Sleep(frameRate);
}
}
private ConsoleKeyInfo? GetLastKeypress()
{
ConsoleKeyInfo? info = null;
while (Console.KeyAvailable)
{
info = Console.ReadKey();
}
return info;
}
}
可以为所有将转换回跳跃状态的状态创建一个基类,其中包含计时器逻辑我认为回到空闲状态应该只适用于跳跃状态,而不是所有状态?我说的是所有需要这样做的状态-你在问题中说你有不止一个状态需要这样做。否则我不确定问题出在哪里非常感谢你的回答。它确实回答了我提出的问题,还提供了一些gameloop的基本知识。我认为我犯的错误是没有在state类中包含update方法,这样我就可以在其中运行计时器。再次感谢