策略模式是一种设计模式,它定义了一系列算法,并将每一个算法封装起来,使它们可以互换使用。这种模式使得算法可以独立于使用它们的客户端变化。在游戏开发中,策略模式尤其有用,因为它允许开发者根据不同的游戏状态动态地切换不同的行为或策略。
假设有一个游戏,玩家可以在三种状态之间切换:角色状态(Character State)、汽车状态(Car State)和电影状态(Cinematic State)。每种状态都包含一个策略数组,这些策略根据功能分类,并放置在对应的数组索引中,称为通道(channels)。当在状态之间切换时,这些通道会被激活或停用。一些策略会在玩家状态之间共享。
在当前示例中,策略通道被定义为C#枚举(Enum),整数值也可以使用:
public enum StrategyChannel
{
Camera = 0,
Input = 1,
Controls = 2
}
每个通道策略可以有任何实现,在当前示例中被定义为接口:
public interface IStrategyChannel
{
StrategyChannel Channel { get; }
void Activate();
void Deactivate();
}
以下是汽车相机(CarCamera)的IStrategyChannel接口实现示例:
public class CarCamera : IStrategyChannel
{
public StrategyChannel Channel => StrategyChannel.Camera;
public void Activate()
{
Console.WriteLine("Activate CarCamera");
}
public void Deactivate()
{
Console.WriteLine("Deactivate CarCamera");
}
}
在切换到另一个状态时,跟踪每个策略通道中的策略变化,并激活或停用相应的策略(如果有变化发生):
public class PlayerState
{
private const int CHANNELS = 3;
private readonly IStrategyChannel[] _strategyChannels = new IStrategyChannel[CHANNELS];
public void SwitchToState(PlayerState state)
{
for (var i = 0; i < CHANNELS; i++)
{
var currentStrategy = _strategyChannels[i];
var targetStrategy = state._strategyChannels[i];
if (currentStrategy != targetStrategy)
{
if (currentStrategy != null)
{
currentStrategy.Deactivate();
}
if (targetStrategy != null)
{
targetStrategy.Activate();
}
}
}
}
public void SetChannelStrategy(IStrategyChannel strategy)
{
_strategyChannels[(int)strategy.Channel] = strategy;
}
}
PlayerStatesController构建并保持所有状态,跟踪当前状态,并初始化初始状态:
public class PlayerStatesController
{
private PlayerState _currentState;
public readonly PlayerState CharacterState;
public readonly PlayerState CarState;
public readonly PlayerState CinematicState;
public PlayerStatesController()
{
CharacterState = new PlayerState();
CarState = new PlayerState();
CinematicState = new PlayerState();
var playerInput = new PlayerInput();
CharacterState.SetChannelStrategy(new FreeLookCamera());
CharacterState.SetChannelStrategy(playerInput);
CarState.SetChannelStrategy(new CarCamera());
CarState.SetChannelStrategy(playerInput);
CarState.SetChannelStrategy(new CarControl());
CinematicState.SetChannelStrategy(new CinematicCamera());
}
public void ActivateInitialState(PlayerState state)
{
_currentState = state;
_currentState.InitialActivate();
}
public void SwitchToState(PlayerState state)
{
_currentState.SwitchToState(state);
_currentState = state;
}
}
在这个代码示例中,依次激活每个状态,然后切换回第一个状态:
var statesController = new PlayerStatesController();
Console.WriteLine("Activating initial CharacterState:");
statesController.ActivateInitialState(statesController.CharacterState);
Console.WriteLine();
Console.WriteLine("Switching to CarState:");
statesController.SwitchToState(statesController.CarState);
Console.WriteLine();
Console.WriteLine("Switching to CinematicState:");
statesController.SwitchToState(statesController.CinematicState);
Console.WriteLine();
Console.WriteLine("Switching to CharacterState:");
statesController.SwitchToState(statesController.CharacterState);
Console.WriteLine();
执行后,将得到以下输出:
Activating initial CharacterState:
Activate FreeLookCamera
Activate PlayerInput
Switching to CarState:
Deactivate FreeLookCamera
Activate CarCamera
Activate CarControl
Switching to CinematicState:
Deactivate CarCamera
Activate CinematicCamera
Deactivate PlayerInput
Deactivate CarControl
Switching to CharacterState:
Deactivate CinematicCamera
Activate FreeLookCamera
Activate PlayerInput