Upload
atsushi-tadokoro
View
3.357
Download
2
Embed Size (px)
DESCRIPTION
Citation preview
Media Art II openFrameworks 複数のシーンの管理・切替え多摩美術大学情報デザイン学科情報芸術コース 2013年11月11日 田所 淳
今日の内容‣ openFrameworksでより実践的なプログラムの構築方法 ‣ 複数のシーンを切替えるにはどうすれば良いのか? ‣ 実際の例を見ながら解説
シーンを切り替える方法‣ 2つの方法を紹介 !
‣ 1: ベースとなるシーンを継承 ‣ ofBaseAppを継承したクラスbaseSceneを作成 ‣ testAppに、baseSceneの配列を用意 ‣ baseSceneを継承したクラスを複数作成し配列に格納 !
‣ 2: ofxStateMachineを使用する ‣ ステイトデザインを利用した複数の状態を管理するためのアドオン
複数シーンの切り替え 1 ベースとなるシーンを継承
‣ 下記のような構成を構築
複数シーンの切替えイメージ
testApp
...
baseSceneSceneA継承
配列(vector)
切替えて表示 setup() update() draw()
SceneB
SceneC
全てのシーンの テンプレート
#pragma once #include "ofMain.h" !class baseScene { !public: //仮想関数 (virtual) として定義する virtual void setup(){}; virtual void update(){}; virtual void draw(){}; virtual void keyPressed (int key){}; virtual void keyReleased(int key){}; virtual void mouseMoved(int x, int y ){}; virtual void mouseDragged(int x, int y, int button){}; virtual void mousePressed(int x, int y, int button){}; virtual void mouseReleased(int x, int y, int button){}; virtual void windowResized(int w, int h){}; };
‣ baseScene.h
シーンのテンプレート:baseSceneクラス
#pragma once !#include "ofMain.h" #include "baseScene.h" !// baseSceneを継承したクラスを定義 class SceneA : public baseScene { void setup(); void update(); void draw(); };
‣ SceneA.h
具体化したシーン例:SceneA
#include "SceneA.h" !void SceneA::setup(){ } !void SceneA::update(){ } !void SceneA::draw(){ ofBackgroundHex(0xFF0000); ofSetHexColor(0xFFFFFF); ofDrawBitmapString("Scene A", 20, 20); }
‣ SceneA.cpp
具体化したシーン例:SceneA
シーンの切替えの実装‣ SceneAクラスと同様にSceneB、SceneC... と作成していく !
‣ 複数のシーンの切替えの仕組みは、testAppで実装する ‣ シーンの集合は、動的配列(vector)として管理する
#pragma once #include "ofMain.h" #include "baseScene.h" #include "SceneA.h" #include "SceneB.h" #include "SceneC.h" !class testApp : public ofBaseApp { public: void setup(); void update(); void draw(); void keyPressed (int key); void keyReleased(int key); void mouseMoved(int x, int y ); void mouseDragged(int x, int y, int button); void mousePressed(int x, int y, int button); void mouseReleased(int x, int y, int button); void windowResized(int w, int h); vector <baseScene *> scenes; //複数のシーンを格納する動的配列 int currentScene; //現在のシーン番号 };
‣ testApp.h
シーン切替え:testApp
#include "testApp.h" !void testApp::setup(){ ofSetFrameRate(60); //シーンを新規の生成し、配列に追加 baseScene * sa = new SceneA(); scenes.push_back(sa); baseScene * sb = new SceneB(); scenes.push_back(sb); baseScene * sc = new SceneC(); scenes.push_back(sc); //現在のシーンを0に currentScene = 0; scenes[currentScene]->setup(); } !void testApp::update(){ //現在表示しているシーンを更新 scenes[currentScene]->update(); }
‣ testApp.cpp (1 of 3)
シーン切替え:testApp
void testApp::draw(){ //現在表示しているシーンを描画 scenes[currentScene]->draw(); } !void testApp::keyPressed(int key){ ! switch (key) { ! case ' ': //シーンの切り替え currentScene++; currentScene %= scenes.size(); scenes[currentScene]->setup(); break; ! case 'f': ofToggleFullscreen(); break; } }
‣ testApp.cpp (2 of 3)
シーン切替え:testApp
!void testApp::keyReleased(int key){ scenes[currentScene]->keyReleased(key); } !void testApp::mouseMoved(int x, int y ){ scenes[currentScene]->mouseMoved(x, y); } !void testApp::mouseDragged(int x, int y, int button){ scenes[currentScene]->mouseDragged(x, y, button); } !void testApp::mousePressed(int x, int y, int button){ scenes[currentScene]->mousePressed(x, y, button); } !void testApp::mouseReleased(int x, int y, int button){ scenes[currentScene]->mouseReleased(x, y, button); } !void testApp::windowResized(int w, int h){ scenes[currentScene]->windowResized(w, h); }
‣ testApp.cpp (3 of 3)
シーン切替え:testApp
‣ スペースキーで、シーンが切り替わる
シーンの切替えの実装
‣ 複数のクラスから成る複雑なシーンを組み合せることも可能
シーンの切替えの実装
複数シーンの切り替え 2 ofxStateMachine を使用
ofxStateMachine を使用‣ State Machine (Finite-state Machine) ‣ 状態と遷移と動作の組み合わせからなる数学的なモデル ‣ (有限個の)状態と、入力による状態の遷移を記述する
!状態 1
!状態 2
!状態 3
遷移1
遷移2
遷移3
遷移4
ofxStateMachine を使用‣ ofxStateMachineでは ‣ ofxStateを継承したシーンを複数作成して、名前をつける ‣ シーンを跨いで共有するデータ、SharedDataを利用できる
SceneA 名前: “scene_a”ofxState
SceneB 名前: “scene_b”
SceneC 名前: “scene_c”
継承
#pragma once #include "ofxState.h" !class TemplateState : public itg::ofxState<> { ! void setup(); void update(); void draw(); ! string getName(); };
ofxStateMachine を使用‣ ofxStateMachine、状態(個別のシーン)のテンプレート
#pragma once #include "ofxState.h" !class TemplateState : public itg::ofxState<> { ! void setup(); void update(); void draw(); ! string getName(); };
ofxStateMachine を使用‣ ofxStateMachine、状態(個別のシーン)のテンプレート
ofxStateを継承する
#pragma once #include "ofxState.h" !class TemplateState : public itg::ofxState<> { ! void setup(); void update(); void draw(); ! string getName(); };
ofxStateMachine を使用‣ ofxStateMachine、状態(個別のシーン)のテンプレート
ofBaseAppの関数は、 そのまま使用可能
#pragma once #include "ofxState.h" !class TemplateState : public itg::ofxState<> { ! void setup(); void update(); void draw(); ! string getName(); };
ofxStateMachine を使用‣ ofxStateMachine、状態(個別のシーン)のテンプレート
状態の名前を返す関数が必須 状態遷移の際に必要となる
#pragma once !#include "ofMain.h" #include "ofxStateMachine.h" !class testApp : public ofBaseApp{ public: void setup(); void update(); void draw(); !(中略) ! itg::ofxStateMachine<> stateMachine; };
ofxStateMachine を使用‣ 作成したシーンを、testAppから呼びだす ‣ testApp.h
#pragma once !#include "ofMain.h" #include "ofxStateMachine.h" !class testApp : public ofBaseApp{ public: void setup(); void update(); void draw(); !(中略) ! itg::ofxStateMachine<> stateMachine; };
ofxStateMachine を使用‣ 作成したシーンを、testAppから呼びだす ‣ testApp.h
ofxStateMachineを インスタンス化
#include "testApp.h" #include "TemplateState.h" !//-------------------------------------------------------------- void testApp::setup(){ // initialise state machine ! stateMachine.addState<TemplateState>(); ! stateMachine.changeState("template"); !} !(後略)
ofxStateMachine を使用‣ 作成したシーンを、testAppから呼びだす ‣ testApp.cpp
#include "testApp.h" #include "TemplateState.h" !//-------------------------------------------------------------- void testApp::setup(){ // initialise state machine ! stateMachine.addState<TemplateState>(); ! stateMachine.changeState("template"); !} !(後略)
ofxStateMachine を使用‣ 作成したシーンを、testAppから呼びだす ‣ testApp.cpp
読み込む状態をインクルード
#include "testApp.h" #include "TemplateState.h" !//-------------------------------------------------------------- void testApp::setup(){ // initialise state machine ! stateMachine.addState<TemplateState>(); ! stateMachine.changeState("template"); !} !(後略)
ofxStateMachine を使用‣ 作成したシーンを、testAppから呼びだす ‣ testApp.cpp
状態をState Machineに追加
#include "testApp.h" #include "TemplateState.h" !//-------------------------------------------------------------- void testApp::setup(){ // initialise state machine ! stateMachine.addState<TemplateState>(); ! stateMachine.changeState("template"); !} !(後略)
ofxStateMachine を使用‣ 作成したシーンを、testAppから呼びだす ‣ testApp.cpp
名前を指定して、状態へ遷移
‣ SharedDataを利用 ‣ 全てのシーンで共有するデータを格納する
ofxStateMachine を使用
SceneA
SceneB
SceneC
SharedData
#pragma once !class SharedData{ public: string sharedMsg; };
ofxStateMachine を使用‣ SharedDataの例、string sharedMsg を追加 ‣ SharedData.h
#pragma once !#include "ofMain.h" #include “ofxStateMachine.h" #include "SharedData.h" !class testApp : public ofBaseApp{ public: void setup(); void update(); void draw(); !(中略) ! itg::ofxStateMachine<SharedData> stateMachine; };
ofxStateMachine を使用‣ SharedDataを読み込めるように、testApp.hを変更 ‣ testApp.h
#pragma once !#include "ofMain.h" #include “ofxStateMachine.h" #include "SharedData.h" !class testApp : public ofBaseApp{ public: void setup(); void update(); void draw(); !(中略) ! itg::ofxStateMachine<SharedData> stateMachine; };
ofxStateMachine を使用‣ SharedData.hをtestAppにインクルード ‣ testApp.h
SharedState.h をインクルード
#pragma once !#include "ofMain.h" #include “ofxStateMachine.h" #include "SharedData.h" !class testApp : public ofBaseApp{ public: void setup(); void update(); void draw(); !(中略) ! itg::ofxStateMachine<SharedData> stateMachine; };
ofxStateMachine を使用‣ ofxStateMachineのインスタンス化を変更 ‣ testApp.h
ofxStateMachineを インスタンス化
#include "testApp.h" #include "TemplateState.h" !//-------------------------------------------------------------- void testApp::setup(){ ! // SharedData stateMachine.getSharedData().sharedMsg = "Hello State Machine!"; // initialise state machine stateMachine.addState<TemplateState>(); stateMachine.changeState("template"); }
ofxStateMachine を使用‣ testApp.cppで、SharedDataにアクセス ‣ testApp.h
#include "testApp.h" #include "TemplateState.h" !//-------------------------------------------------------------- void testApp::setup(){ ! // SharedData stateMachine.getSharedData().sharedMsg = "Hello State Machine!"; // initialise state machine stateMachine.addState<TemplateState>(); stateMachine.changeState("template"); }
ofxStateMachine を使用‣ testApp.cppで、SharedDataにアクセス ‣ testApp.h
SharedData内のsharedMsgに 文字列を代入
‣ キーボードの操作で、シーンを切り替えるサンプル ‣ 詳細はコードで!
ofxStateMachine を使用