格ゲーコマンドをどのように解析しようか?
http://d.hatena.ne.jp/bake_3572/20051108/1131378056#c
にて、ちょっと話題になった。私なりのアプローチをここに記そうと思う。(久々のプログラミングだ・・・)
ちょっと草稿ですが、以下にもっさりと載せておきます。(コンパイル出来ません)
今の状態ではキー同時おしには対応していません。
でも、キーの同時おしを判定するとなると毎フレームごとに256byte + α使うことになって。
1秒で60フレームとするととりあえず、10秒ほど保存で153600byte + αくらいが必要になるのかな?多いなぁ〜(泣)
キー入力定義を有限状態オートマトンなC言語のコードに変換できるものを作ったほうがイイのかな?
(http://d.hatena.ne.jp/studiokingyo/20051129にて新作発表中)
/** つくりかけスマン */ #ifndef DKUTIL_HELPER_KEY_INPUT_COMMAND_JUDGEMENT_HPP #define DKUTIL_HELPER_KEY_INPUT_COMMAND_JUDGEMENT_HPP #include <deque> #include <multiset> namespace dkutil{ class CKeyInputCommandJudgement{ public: typedef unsigned char key_data; typedef std::deque<key_data> queue_type; typedef std::vector<key_data> command_difinition; struct command_judgement_container{ ///command definition vector command_definition mDef; ///unique id int mUID; //state command_definition::iterator mIt; bool operator==(key_data x){ return mDef[0] == x; } bool state_compare(key_data x){ return (*mIt) == x; } bool operator<(const command_judgement_container &x){ return mDef[0] < x.mDef[0]; } }; typedef std::multiset<command_judgement_container> container_type; typedef std::pair<container_type::iterator, bool> container_result; protected: container_type mC; queue_type mKeyQueue; ///内部ステートを初期化する。 void command_judgement_container_state_init(){ container_type::iterator it = mC.begin(); for(;it != mC.end();it++) { (*it).mIt = (*it).mDef.begin(); } } typedef std::vector<container_type::iterator> sit_container; public: CKeyInputCommandJudgement(){} ~CKeyInputCommandJudgement(){} void claer(){ mC.clear(); mKeyQueue.clear(); } bool reset(){ } bool insert_command(command_definition &x,int unique_id){ command_judgement_container c; c.mDef = x; c.mUID = unique_id; container_result r = mC.insert(x); return r.second; } /** @param front_move_count[in] 多いほど解析する先頭をずらす 普通は0で @param get_id[out] 解析した結果をunique idとして返す @return trueでコマンドが見つかった。すなわちget_idは有効 @note たとえばqwerとqweいうコマンドがあったとして 解析される優先順位が高いのはqweの方である。 多分、それで不自由しないからよしとする。 */ bool check_command(int front_move_count,int *get_id) { int i; //先頭をずらす queue_type::iterator it = mKeyQueue.begin(); for(i=0:;i<font_move_count;it++,i++) { if(it == mKeyQueue.end()){ return false; } } container_type::iterator sit = mC.find((*it)); //コマンドが存在しない。 if(mC.end()==sit) return false; //コマンドが同じらしきものへの参照(iteratorとして)を保存。 sit_container tc; for(;sit != mC.end();sit++){ if((*sit) == (*it)){ tc.push_back((*sit)); }else break; } //解析開始 command_judgement_container_state_init(); sit_container::iterator tcit = tc.begin(); for(;tcit != tc.end();tcit++) { if(it == mKeyQueue.end()) return false; //比較して同じだった。 if((*tcit).state_compare(*it)) { //次の状態へ (*tcit).mIt++; if((*tcit).mIt == (*tcit).mDef.end()){ *get_id = (*tcit).mUID;//idを保存 return true; } } //key queueも次へ it++; } return false; } //以下キュー操作 void push_queue(key_data x){ mKeyQueue.push_back(x); } key_data front()const{ return mKeyQueue.front(); } key_data back()const{ return mKeyQueue.back(); } void pop_queue(){ mKeyQueue.pop_front(); } queue_type get_key_queue(){ return mKeyQueue; } }; } #endif