游戏简单控制逻辑 一个轻量级的状态机
2015-04-08 05:01
435 查看
出处:http://blog.csdn.net/u010019717
author:孙广东 时间:2015.3.25
关于状态机这种设计模式不用多介绍了,网上有很多这方面的介绍,特别是FSM。
现在是我实现一个轻量级的状态机。
[csharp] view
plaincopyprint?
using System;
using System.Collections.Generic;
namespace Gamelogic
{
/**
一个轻量级的状态机。
要使用它:
-# 定义您自己的label。枚举Enums可能是最好的选择。
-# 构造一个新的状态机state machin,通常是在 MonoBehaviour 的Start方法中。
-# 添加的各种状态和对应的delegates。
-# 从 MonoBehaviour 的Update方法调用状态机Update方法。
-# 在状态机transition转换状态时调用 ChangeState 方法(你可以调用此方法,从一个state delegates,或任何其他地方)
-# 状态发生变化时,对现有状态执行关闭 OnStop,然后OnStart开启新状态,之后新的状态每帧更新中调用 OnUpdate 方法
*/
public sealed class StateMachine<TLabel>
{
private class State
{
public readonly Action onStart;
public readonly Action onUpdate;
public readonly Action onStop;
public readonly TLabel label;
public State(TLabel label, Action onStart, Action onUpdate, Action onStop)
{
this.onStart = onStart;
this.onUpdate = onUpdate;
this.onStop = onStop;
this.label = label;
}
}
private readonly Dictionary<TLabel, State> stateDictionary;
private State currentState;
/**
Returns the label of the current state.
*/
public TLabel CurrentState
{
get { return currentState.label; }
/**@version1_2*/
set { ChangeState(value); }
}
/**
Constructs a new StateMachine.
*/
public StateMachine()
{
stateDictionary = new Dictionary<TLabel, State>();
}
/**
Adds a state, and the delegates that should run
when the state starts, stops,
and when the state machine is updated.
Any delegate can be null, and wont be executed.
*/
public void AddState(TLabel label, Action onStart, Action onUpdate, Action onStop)
{
stateDictionary[label] = new State(label, onStart, onUpdate, onStop);
}
/**
Changes the state from the existing one to the state with the given label.
*/
private void ChangeState(TLabel newState)
{
if (currentState != null && currentState.onStop != null)
{
currentState.onStop();
}
currentState = stateDictionary[newState];
if (currentState.onStart != null)
{
currentState.onStart();
}
}
/**
This method should be called every frame.
*/
public void Update()
{
if (currentState != null && currentState.onUpdate != null)
{
currentState.onUpdate();
}
}
}
}
使用的例子 很简单,cube的两种状态转换。 每种状态有不同的行为表现:
[csharp] view
plaincopyprint?
using System.Collections;
using UnityEngine;
namespace Gamelogic.Examples
{
public class Cube : MonoBehaviour
{
public enum CubeStates
{
Swivel,
MoveStraight
}
private StateMachine<CubeStates> stateMachine;
private float moveSpeed = 1;
private float switchTime = 3;
private float swivelSpeed = 2;
public void Start()
{
stateMachine = new StateMachine<CubeStates>();
stateMachine.AddState(CubeStates.Swivel, OnSwivelStart, OnSwivelUpdate, OnSwivelStop);
stateMachine.AddState(CubeStates.MoveStraight, null, OnMoveStraightUpdate, null);
stateMachine.CurrentState = CubeStates.MoveStraight;
StartCoroutine(SwitchStates());
}
public IEnumerator SwitchStates()
{
while (true)
{
stateMachine.CurrentState = CubeStates.Swivel;
yield return new WaitForSeconds(switchTime);
stateMachine.CurrentState = CubeStates.MoveStraight;
yield return new WaitForSeconds(switchTime);
}
}
public void Update()
{
stateMachine.Update();
}
public void OnGUI()
{
GUILayout.TextField(stateMachine.CurrentState.ToString());
}
public void OnMoveStraightUpdate()
{
float dx = -Time.deltaTime * moveSpeed;
transform.TranslateX(dx);
}
public void OnSwivelUpdate()
{
float dx = Time.deltaTime*moveSpeed;
float y = Mathf.Sin(swivelSpeed * transform.position.x * 2 * Mathf.PI/switchTime);
transform.TranslateX(dx);
transform.SetY(y);
}
public void OnSwivelStart()
{
GetComponent<Renderer>().material.color = Color.red;
}
public void OnSwivelStop()
{
GetComponent<Renderer>().material.color = Color.green;
transform.SetY(0); //recallibrate
}
}
}
就是这样的很简单的状态机。
author:孙广东 时间:2015.3.25
关于状态机这种设计模式不用多介绍了,网上有很多这方面的介绍,特别是FSM。
现在是我实现一个轻量级的状态机。
[csharp] view
plaincopyprint?
using System;
using System.Collections.Generic;
namespace Gamelogic
{
/**
一个轻量级的状态机。
要使用它:
-# 定义您自己的label。枚举Enums可能是最好的选择。
-# 构造一个新的状态机state machin,通常是在 MonoBehaviour 的Start方法中。
-# 添加的各种状态和对应的delegates。
-# 从 MonoBehaviour 的Update方法调用状态机Update方法。
-# 在状态机transition转换状态时调用 ChangeState 方法(你可以调用此方法,从一个state delegates,或任何其他地方)
-# 状态发生变化时,对现有状态执行关闭 OnStop,然后OnStart开启新状态,之后新的状态每帧更新中调用 OnUpdate 方法
*/
public sealed class StateMachine<TLabel>
{
private class State
{
public readonly Action onStart;
public readonly Action onUpdate;
public readonly Action onStop;
public readonly TLabel label;
public State(TLabel label, Action onStart, Action onUpdate, Action onStop)
{
this.onStart = onStart;
this.onUpdate = onUpdate;
this.onStop = onStop;
this.label = label;
}
}
private readonly Dictionary<TLabel, State> stateDictionary;
private State currentState;
/**
Returns the label of the current state.
*/
public TLabel CurrentState
{
get { return currentState.label; }
/**@version1_2*/
set { ChangeState(value); }
}
/**
Constructs a new StateMachine.
*/
public StateMachine()
{
stateDictionary = new Dictionary<TLabel, State>();
}
/**
Adds a state, and the delegates that should run
when the state starts, stops,
and when the state machine is updated.
Any delegate can be null, and wont be executed.
*/
public void AddState(TLabel label, Action onStart, Action onUpdate, Action onStop)
{
stateDictionary[label] = new State(label, onStart, onUpdate, onStop);
}
/**
Changes the state from the existing one to the state with the given label.
*/
private void ChangeState(TLabel newState)
{
if (currentState != null && currentState.onStop != null)
{
currentState.onStop();
}
currentState = stateDictionary[newState];
if (currentState.onStart != null)
{
currentState.onStart();
}
}
/**
This method should be called every frame.
*/
public void Update()
{
if (currentState != null && currentState.onUpdate != null)
{
currentState.onUpdate();
}
}
}
}
使用的例子 很简单,cube的两种状态转换。 每种状态有不同的行为表现:
[csharp] view
plaincopyprint?
using System.Collections;
using UnityEngine;
namespace Gamelogic.Examples
{
public class Cube : MonoBehaviour
{
public enum CubeStates
{
Swivel,
MoveStraight
}
private StateMachine<CubeStates> stateMachine;
private float moveSpeed = 1;
private float switchTime = 3;
private float swivelSpeed = 2;
public void Start()
{
stateMachine = new StateMachine<CubeStates>();
stateMachine.AddState(CubeStates.Swivel, OnSwivelStart, OnSwivelUpdate, OnSwivelStop);
stateMachine.AddState(CubeStates.MoveStraight, null, OnMoveStraightUpdate, null);
stateMachine.CurrentState = CubeStates.MoveStraight;
StartCoroutine(SwitchStates());
}
public IEnumerator SwitchStates()
{
while (true)
{
stateMachine.CurrentState = CubeStates.Swivel;
yield return new WaitForSeconds(switchTime);
stateMachine.CurrentState = CubeStates.MoveStraight;
yield return new WaitForSeconds(switchTime);
}
}
public void Update()
{
stateMachine.Update();
}
public void OnGUI()
{
GUILayout.TextField(stateMachine.CurrentState.ToString());
}
public void OnMoveStraightUpdate()
{
float dx = -Time.deltaTime * moveSpeed;
transform.TranslateX(dx);
}
public void OnSwivelUpdate()
{
float dx = Time.deltaTime*moveSpeed;
float y = Mathf.Sin(swivelSpeed * transform.position.x * 2 * Mathf.PI/switchTime);
transform.TranslateX(dx);
transform.SetY(y);
}
public void OnSwivelStart()
{
GetComponent<Renderer>().material.color = Color.red;
}
public void OnSwivelStop()
{
GetComponent<Renderer>().material.color = Color.green;
transform.SetY(0); //recallibrate
}
}
}
就是这样的很简单的状态机。
相关文章推荐
- 游戏简单控制逻辑 一个轻量级的状态机
- 游戏手柄(JoyStick)编程控制的一个简单代码(Qt)
- 使用C++与SFML编写一个简单的撞球游戏Part6——添加弹板控制与弹球
- 一步一个记录--简单的jquery轮播图,按钮状态控制,layer弹窗
- 一个简单的游戏源代码
- 一个简单的游戏源代码
- ReportMachine 控制打印走纸的一个简单方法
- .NET20 一种简单的窗口控件UI状态控制方法
- 最简单的游戏回血逻辑实现(包括源代码)
- c#中子线程控制进度条的一个简单例子
- 一个简单的游戏源代码
- .NET20 一种简单的窗口控件UI状态控制方法
- 一个简单的游戏源代码
- 一个简单的游戏--贪吃蛇
- 写了一个简单的对多游标控制的存储过程
- 一个简单的游戏(3)
- 一个采购主管的问题与我的简单回答:交期达成与成本控制[原创]
- 一个使用面向对象方式编写的简单游戏框架
- 一个简单的控制ADSL拨号的小程序
- 一个简单的游戏源代码