<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
		>
<channel>
	<title>Comments on: Strategy &amp; State：條件判斷式的消除者</title>
	<atom:link href="http://blog.monkeypotion.net/gameprog/pattern/strategy-and-state/feed" rel="self" type="application/rss+xml" />
	<link>http://blog.monkeypotion.net/gameprog/pattern/strategy-and-state</link>
	<description>遊戲開發‧遊戲程式‧遊戲設計</description>
	<lastBuildDate>Sun, 05 Feb 2012 11:54:53 +0000</lastBuildDate>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
	<item>
		<title>By: 半路</title>
		<link>http://blog.monkeypotion.net/gameprog/pattern/strategy-and-state/comment-page-1#comment-2013</link>
		<dc:creator>半路</dc:creator>
		<pubDate>Tue, 24 Mar 2009 08:49:12 +0000</pubDate>
		<guid isPermaLink="false">http://blog.monkeypotion.net/?p=1185#comment-2013</guid>
		<description>@Milo:
談到 FSM State 類別的創建，的確無須使用 Factory 範式就可以達成目的。我個人的習慣是使用 enum 來指定要轉換的 State 類別，並且把資料儲存在 Context 物件中以達成 Stateless 的狀態類別設計。如此一來，就不需要在其他的 State 實作檔中 include 其他（或所有）的 State 表頭檔，而且也僅需具現化一份 State 的實作體即可。

在腳本語言中撰寫 FSM 的相關程式碼真的容易許多！事實上我在&lt;a href=&quot;http://blog.monkeypotion.net/gamedev/journal/dev-journal-of-crystal-guardian&quot; rel=&quot;nofollow&quot;&gt;《水晶守護者》&lt;/a&gt;中，就是利用 Lua 的威力，才能夠很迅速地完成玩家與敵人角色的狀態邏輯。但相對要付出的代價，就是程式碼比較難以維護，稍不留意就很容易會形成一片混亂的狀態。

不同狀態間的組合是個很難處理的問題，一般來說我會利用類似查表的方式來解決，要不然就得實作出階層式的 FSM 才行了。雖然 FSM 很簡單易用，但也不適合用來處理太複雜的條件轉換邏輯哪。</description>
		<content:encoded><![CDATA[<p>@Milo:<br />
談到 FSM State 類別的創建，的確無須使用 Factory 範式就可以達成目的。我個人的習慣是使用 enum 來指定要轉換的 State 類別，並且把資料儲存在 Context 物件中以達成 Stateless 的狀態類別設計。如此一來，就不需要在其他的 State 實作檔中 include 其他（或所有）的 State 表頭檔，而且也僅需具現化一份 State 的實作體即可。</p>
<p>在腳本語言中撰寫 FSM 的相關程式碼真的容易許多！事實上我在<a href="http://blog.monkeypotion.net/gamedev/journal/dev-journal-of-crystal-guardian" rel="nofollow">《水晶守護者》</a>中，就是利用 Lua 的威力，才能夠很迅速地完成玩家與敵人角色的狀態邏輯。但相對要付出的代價，就是程式碼比較難以維護，稍不留意就很容易會形成一片混亂的狀態。</p>
<p>不同狀態間的組合是個很難處理的問題，一般來說我會利用類似查表的方式來解決，要不然就得實作出階層式的 FSM 才行了。雖然 FSM 很簡單易用，但也不適合用來處理太複雜的條件轉換邏輯哪。</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Milo</title>
		<link>http://blog.monkeypotion.net/gameprog/pattern/strategy-and-state/comment-page-1#comment-1978</link>
		<dc:creator>Milo</dc:creator>
		<pubDate>Sat, 21 Mar 2009 05:34:56 +0000</pubDate>
		<guid isPermaLink="false">http://blog.monkeypotion.net/?p=1185#comment-1978</guid>
		<description>關於 snowmantw 的問題，我覺得是不用使用 Factory 的。如果把一個State當作一個普通變數，你也必定要給它一個初始值，之後在 State transition 的時候改變它的值。

void Game::SetCurrentState(State *state) {
    delete mCurrentState;
    mCurrentState = state;
}

//遊戲開始時
game.SetCurrentState(new GameInitState(/**/));

如果所有 State 的洐生類別都是 Stateless 的，更可以使用 Singleton，而不需要每次 new/delete:

game.SetCurrentState(GameInitState::Instance());

除非你希望用一個 enum 把各個 state classes 的實作藏起來 (減少編譯期的 coupling?)，才需要 Factory。


對於 AI 方面來說，用腳本會比較有彈性。我覺得如何利用腳本語言的動態能力，是一個值得探討的問題。和靜態語言 C++ 相比，所需的 &quot;Design Pattern&quot; 會很不同。以 State Pattern 為例，動態腳本裡可以在執行期改變一個 function 的內容，例如 charater.Tick = character.Combat，而不用另外設立類別。


State Pattern 用來實現 AI，應該可以當作是 Finite State Machine (FSM) 的一種實現方式。以前想過做一個 Editor 可視化編輯 FSM，不過在實憏的遊戲中，很多時候會遇到一些狀態組合的問題，例如上半身和下半身的動作狀態是分開的，又或加入其他屬性(痲痺、中毒、祝福...)，單個 FSM 往往很難處理。到最後，好像還是看情況用不同的編程方式處理比較可行。</description>
		<content:encoded><![CDATA[<p>關於 snowmantw 的問題，我覺得是不用使用 Factory 的。如果把一個State當作一個普通變數，你也必定要給它一個初始值，之後在 State transition 的時候改變它的值。</p>
<p>void Game::SetCurrentState(State *state) {<br />
    delete mCurrentState;<br />
    mCurrentState = state;<br />
}</p>
<p>//遊戲開始時<br />
game.SetCurrentState(new GameInitState(/**/));</p>
<p>如果所有 State 的洐生類別都是 Stateless 的，更可以使用 Singleton，而不需要每次 new/delete:</p>
<p>game.SetCurrentState(GameInitState::Instance());</p>
<p>除非你希望用一個 enum 把各個 state classes 的實作藏起來 (減少編譯期的 coupling?)，才需要 Factory。</p>
<p>對於 AI 方面來說，用腳本會比較有彈性。我覺得如何利用腳本語言的動態能力，是一個值得探討的問題。和靜態語言 C++ 相比，所需的 &#8220;Design Pattern&#8221; 會很不同。以 State Pattern 為例，動態腳本裡可以在執行期改變一個 function 的內容，例如 charater.Tick = character.Combat，而不用另外設立類別。</p>
<p>State Pattern 用來實現 AI，應該可以當作是 Finite State Machine (FSM) 的一種實現方式。以前想過做一個 Editor 可視化編輯 FSM，不過在實憏的遊戲中，很多時候會遇到一些狀態組合的問題，例如上半身和下半身的動作狀態是分開的，又或加入其他屬性(痲痺、中毒、祝福&#8230;)，單個 FSM 往往很難處理。到最後，好像還是看情況用不同的編程方式處理比較可行。</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: 半路</title>
		<link>http://blog.monkeypotion.net/gameprog/pattern/strategy-and-state/comment-page-1#comment-1768</link>
		<dc:creator>半路</dc:creator>
		<pubDate>Sun, 01 Mar 2009 16:38:45 +0000</pubDate>
		<guid isPermaLink="false">http://blog.monkeypotion.net/?p=1185#comment-1768</guid>
		<description>@snowmantw:
可以運用 std::map 結構的查表法來做。即使是在創建物件時，也同樣能夠免除條件判斷式喔～</description>
		<content:encoded><![CDATA[<p>@snowmantw:<br />
可以運用 std::map 結構的查表法來做。即使是在創建物件時，也同樣能夠免除條件判斷式喔～</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: snowmantw</title>
		<link>http://blog.monkeypotion.net/gameprog/pattern/strategy-and-state/comment-page-1#comment-1753</link>
		<dc:creator>snowmantw</dc:creator>
		<pubDate>Sat, 28 Feb 2009 01:29:46 +0000</pubDate>
		<guid isPermaLink="false">http://blog.monkeypotion.net/?p=1185#comment-1753</guid>
		<description>這麼作的確能解決 ProcessInput() 等函式內部大量條件判斷式的缺點。不過個人想了一下，應該還是有一個類似條件判斷式的程式，來決定現在餵給 ProcessInput() 等函式進行判斷的 m_CurrentState 是屬於哪種 class 的衍生物吧？比如

//遊戲開始時
m_CurrentState = StateFactory::create(StateFactory::GameInitState);

//遊戲主選單
m_CurrentState = StateFactory::create(StateFactory::GameMenuState);

個人猜想這個判斷應該是無法避免的？</description>
		<content:encoded><![CDATA[<p>這麼作的確能解決 ProcessInput() 等函式內部大量條件判斷式的缺點。不過個人想了一下，應該還是有一個類似條件判斷式的程式，來決定現在餵給 ProcessInput() 等函式進行判斷的 m_CurrentState 是屬於哪種 class 的衍生物吧？比如</p>
<p>//遊戲開始時<br />
m_CurrentState = StateFactory::create(StateFactory::GameInitState);</p>
<p>//遊戲主選單<br />
m_CurrentState = StateFactory::create(StateFactory::GameMenuState);</p>
<p>個人猜想這個判斷應該是無法避免的？</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: 半路</title>
		<link>http://blog.monkeypotion.net/gameprog/pattern/strategy-and-state/comment-page-1#comment-1741</link>
		<dc:creator>半路</dc:creator>
		<pubDate>Thu, 26 Feb 2009 14:37:36 +0000</pubDate>
		<guid isPermaLink="false">http://blog.monkeypotion.net/?p=1185#comment-1741</guid>
		<description>@Rich:
沒錯沒錯，比起功用單純的函式，物件擁有非常大的彈性，而這也是使用函式指標與 Strategy/State 範式最大的差異點。

謝謝你幫忙補充，我是半路不是猴子大～ XD</description>
		<content:encoded><![CDATA[<p>@Rich:<br />
沒錯沒錯，比起功用單純的函式，物件擁有非常大的彈性，而這也是使用函式指標與 Strategy/State 範式最大的差異點。</p>
<p>謝謝你幫忙補充，我是半路不是猴子大～ XD</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Rich</title>
		<link>http://blog.monkeypotion.net/gameprog/pattern/strategy-and-state/comment-page-1#comment-1736</link>
		<dc:creator>Rich</dc:creator>
		<pubDate>Wed, 25 Feb 2009 14:54:09 +0000</pubDate>
		<guid isPermaLink="false">http://blog.monkeypotion.net/?p=1185#comment-1736</guid>
		<description>@zii: 函數指標除了猴子大提到的型別安全問題 最大的不同就是 Strategy或是State是物件(如果是&quot;Interface&quot;那更好)...物件能提供無限的可能性壓(可以包裝任何資料 可以透過繼承介面實做的方式讓無限其他種類的物件都可以為成為State或Strategy)</description>
		<content:encoded><![CDATA[<p>@zii: 函數指標除了猴子大提到的型別安全問題 最大的不同就是 Strategy或是State是物件(如果是&#8221;Interface&#8221;那更好)&#8230;物件能提供無限的可能性壓(可以包裝任何資料 可以透過繼承介面實做的方式讓無限其他種類的物件都可以為成為State或Strategy)</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: 半路</title>
		<link>http://blog.monkeypotion.net/gameprog/pattern/strategy-and-state/comment-page-1#comment-1730</link>
		<dc:creator>半路</dc:creator>
		<pubDate>Tue, 24 Feb 2009 05:23:42 +0000</pubDate>
		<guid isPermaLink="false">http://blog.monkeypotion.net/?p=1185#comment-1730</guid>
		<description>@Michael:
的確，UML 的結構圖只是個參考指引而已。不要只是照圖硬套，結果反而曲解了範式存在與應用的本意。

@Rich:
之前我也有使用過以 Command 範式實作出來的網路協定機制，真的能夠省下很多不必要的 switch-case 程式碼累贅，也可以讓剛接觸網路系統的程式設計者，更容易理解系統的整體流程與架構。五、六千行的 switch-case + if-else……真是太要命啦～ 囧rz

在 &lt; 和 &gt; 之間的字被吃掉了，我猜你應該是想指《重構——改善既有程式的設計》這本書吧？ XD

@jbyu:
Strategy 和 State 範式，也可以和 Factory Method 範式一起混搭使用，效果會更好！

謝謝你的文章～

@zii:
如果沒有虛擬函式存在，C++ 語言就等同於廢掉了一半武功。所以即使需要付出一些代價，我們還是得瞭解怎麼合理運用虛擬與多型機制才行哪。

@gino:
對於已經用習慣的人來說，會覺得使用 Strategy 和 State 範式是很自然的事情。可是對其他比較不熟悉設計模式的人來說，常常不能理解為什麼我們要這樣做啊。 XD

@Wxy:
在遊戲的程式系統中，Observer 也是個超級實用的好傢伙！（是不是該介紹它出場哩？）

我也同意幾乎可以不用操心存取 vtable 的花費這樣的看法，但我發現對於很多從 ASM 與 C 語言時代走來的人而言，很難說服他們接受「以微小效能影響換取大幅程式碼可讀性」的觀念。

我在上個週末已經買了《The Art of Game Design》。目前找不到合適的詞彙來形容內心的激動與衝擊，正在享受沈浸於這本書中的樂趣，Having new eyes！

@zii:
沒錯！你所提出的函式指標作法，就是從前在 C 語言的環境下經常會使用的一種技巧。然而函式指標有個小缺陷，在於它無法保證提供型別安全的約束力。所以在 C# 以及其他比較新穎的程式語言中，就會提供像是 delegate 這類程式語法，以進一步改善函式指標的問題。

@路人甲:
是的，這篇文章所要傳達的訊息，並不是要叫大家把所有的 switch-case 敘述句都換成 Strategy 範式，只是想提醒我們自己，在工具箱裡除了殺雞小刀可以使用之外，別忘了還有青龍偃月刀可以幫助我們。

我有稍微涉獵過 OGRE 引擎的設計模式，也很喜歡它在許多面向中的架構設計，詳細內容請見&lt;a href=&quot;http://blog.monkeypotion.net/gameprog/note/ogre-dev-intro&quot; rel=&quot;nofollow&quot;&gt;這篇文章&lt;/a&gt;。

@vamper:
先畫出 Use Case 是個好習慣～ 如果在撰寫程式碼之前，每次都能先從 User 端的角度出發設想，那麼要選擇哪一把工具就會不是太困難的問題了。


非常感謝以上各位的寶貴意見與迴響。 ：）</description>
		<content:encoded><![CDATA[<p>@Michael:<br />
的確，UML 的結構圖只是個參考指引而已。不要只是照圖硬套，結果反而曲解了範式存在與應用的本意。</p>
<p>@Rich:<br />
之前我也有使用過以 Command 範式實作出來的網路協定機制，真的能夠省下很多不必要的 switch-case 程式碼累贅，也可以讓剛接觸網路系統的程式設計者，更容易理解系統的整體流程與架構。五、六千行的 switch-case + if-else……真是太要命啦～ 囧rz</p>
<p>在 &lt; 和 &gt; 之間的字被吃掉了，我猜你應該是想指《重構——改善既有程式的設計》這本書吧？ XD</p>
<p>@jbyu:<br />
Strategy 和 State 範式，也可以和 Factory Method 範式一起混搭使用，效果會更好！</p>
<p>謝謝你的文章～</p>
<p>@zii:<br />
如果沒有虛擬函式存在，C++ 語言就等同於廢掉了一半武功。所以即使需要付出一些代價，我們還是得瞭解怎麼合理運用虛擬與多型機制才行哪。</p>
<p>@gino:<br />
對於已經用習慣的人來說，會覺得使用 Strategy 和 State 範式是很自然的事情。可是對其他比較不熟悉設計模式的人來說，常常不能理解為什麼我們要這樣做啊。 XD</p>
<p>@Wxy:<br />
在遊戲的程式系統中，Observer 也是個超級實用的好傢伙！（是不是該介紹它出場哩？）</p>
<p>我也同意幾乎可以不用操心存取 vtable 的花費這樣的看法，但我發現對於很多從 ASM 與 C 語言時代走來的人而言，很難說服他們接受「以微小效能影響換取大幅程式碼可讀性」的觀念。</p>
<p>我在上個週末已經買了《The Art of Game Design》。目前找不到合適的詞彙來形容內心的激動與衝擊，正在享受沈浸於這本書中的樂趣，Having new eyes！</p>
<p>@zii:<br />
沒錯！你所提出的函式指標作法，就是從前在 C 語言的環境下經常會使用的一種技巧。然而函式指標有個小缺陷，在於它無法保證提供型別安全的約束力。所以在 C# 以及其他比較新穎的程式語言中，就會提供像是 delegate 這類程式語法，以進一步改善函式指標的問題。</p>
<p>@路人甲:<br />
是的，這篇文章所要傳達的訊息，並不是要叫大家把所有的 switch-case 敘述句都換成 Strategy 範式，只是想提醒我們自己，在工具箱裡除了殺雞小刀可以使用之外，別忘了還有青龍偃月刀可以幫助我們。</p>
<p>我有稍微涉獵過 OGRE 引擎的設計模式，也很喜歡它在許多面向中的架構設計，詳細內容請見<a href="http://blog.monkeypotion.net/gameprog/note/ogre-dev-intro" rel="nofollow">這篇文章</a>。</p>
<p>@vamper:<br />
先畫出 Use Case 是個好習慣～ 如果在撰寫程式碼之前，每次都能先從 User 端的角度出發設想，那麼要選擇哪一把工具就會不是太困難的問題了。</p>
<p>非常感謝以上各位的寶貴意見與迴響。 ：）</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: vamper</title>
		<link>http://blog.monkeypotion.net/gameprog/pattern/strategy-and-state/comment-page-1#comment-1724</link>
		<dc:creator>vamper</dc:creator>
		<pubDate>Mon, 23 Feb 2009 16:31:29 +0000</pubDate>
		<guid isPermaLink="false">http://blog.monkeypotion.net/?p=1185#comment-1724</guid>
		<description>我的習慣是先畫出use case，再決定是否要用Design Pattern。

殺雞用牛刀只是浪費開發成本；當牛刀一出便殺個片甲不流。</description>
		<content:encoded><![CDATA[<p>我的習慣是先畫出use case，再決定是否要用Design Pattern。</p>
<p>殺雞用牛刀只是浪費開發成本；當牛刀一出便殺個片甲不流。</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: 路人甲</title>
		<link>http://blog.monkeypotion.net/gameprog/pattern/strategy-and-state/comment-page-1#comment-1723</link>
		<dc:creator>路人甲</dc:creator>
		<pubDate>Mon, 23 Feb 2009 12:26:10 +0000</pubDate>
		<guid isPermaLink="false">http://blog.monkeypotion.net/?p=1185#comment-1723</guid>
		<description>有時候 switch 還是需要的, 因為殺雞不需用牛刀.
有時間可以看看 Ogre3D 的 OO, 寫的非常的漂亮.</description>
		<content:encoded><![CDATA[<p>有時候 switch 還是需要的, 因為殺雞不需用牛刀.<br />
有時間可以看看 Ogre3D 的 OO, 寫的非常的漂亮.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: zii</title>
		<link>http://blog.monkeypotion.net/gameprog/pattern/strategy-and-state/comment-page-1#comment-1722</link>
		<dc:creator>zii</dc:creator>
		<pubDate>Mon, 23 Feb 2009 08:06:23 +0000</pubDate>
		<guid isPermaLink="false">http://blog.monkeypotion.net/?p=1185#comment-1722</guid>
		<description>突然想到用c一样可以避免条件判断，用函数指针的数组。
#define STATE_INIT 0
#define STATE_INGAME 1
#define STATE_END 2

typedef int (*loopfunc) (double);

int g_state = 0;

int state_init (double dtime) {}
int state_ingame (double dtime) {}
int state_end (double dtime) {}

loopfunc g_statepool[] = {state_init, state_ingame, state_end};

int gameloop (double dtime)
{
  g_statepool[g_state] (dtime);
}</description>
		<content:encoded><![CDATA[<p>突然想到用c一样可以避免条件判断，用函数指针的数组。<br />
#define STATE_INIT 0<br />
#define STATE_INGAME 1<br />
#define STATE_END 2</p>
<p>typedef int (*loopfunc) (double);</p>
<p>int g_state = 0;</p>
<p>int state_init (double dtime) {}<br />
int state_ingame (double dtime) {}<br />
int state_end (double dtime) {}</p>
<p>loopfunc g_statepool[] = {state_init, state_ingame, state_end};</p>
<p>int gameloop (double dtime)<br />
{<br />
  g_statepool[g_state] (dtime);<br />
}</p>
]]></content:encoded>
	</item>
</channel>
</rss>

