3
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

NCCAdvent Calendar 2018

Day 24

Processingで強引にシーン管理

Last updated at Posted at 2018-12-24

TL; DR

  • Processingの仕組みを書き換えて、シーン管理を可能にしてみた
  • 作ったもの: progfay/sceneManager

シーンごとに、コードを書き分けたい

一般的にシーンをかき分ける方法はたくさんあります。

Processingでは以下のようなコードで、シーン別に処理を記述することができます。

void draw () {
    switch (MODE) {
        case 1: // main menu
            drawMainManu();
        case 2: // config menu
            drawConfigMenu();
		// :
    }
}

void mousePressed () {
    switch (MODE) {
		case 1: // main menu
            mousePressedOnMainMenu();
        case 2: // config menu
            mousePressedOnConfigMenu();
        // :
    }
}

しかし、上記のコードでは、問題点がいくつかあります。

  • シーンが追加される度に、 draw()mousePressed などを更新する必要がある
  • 描画やイベント毎に関数を作成しなければならず、まとまりがない
  • frameCountは初期化されず、setup() のような関数の実行もし辛い

そこで、以下のような書き方ができることを理想として、本記事ではそれを目指していきます。

class MainMenuScene {
    void setup () {
        // setup main menu
    }
    
    void draw () {
        // draw main menu
    }
    
    void mousePressed () {
        // mouse pressed on main menu
    }
}

class ConfigMenuScene {
    void setup () {
        // setup config menu
    }
    
    void draw () {
        // draw config menu
    }
    
    void mousePressed () {
        // mouse pressed on config menu
    }
}

Processingの仕組みを書き換える

Processing では、 handleDraw() をOverrideすることで draw()setup() などの仕組みをハックすることができます。 (参考: Processingの仕組みを覗いてみる )

試しに、以下のコードを実行すると、 "handleDraw" の出力が繰り返されるだけで、 setup()draw() は実行されません。

@Override
void handleDraw() {
    println("handle draw");
}

void setup() {
    println("setup");
}

void draw() {
    println("draw");
}

handleDraw() にシーン管理処理を組み込む

handleDraw() をOverrideして、シーン管理のための処理を組み込んでしまえば、理想のシーン管理が実現できます!

以下のコードみたいな雰囲気で組み込みます。

@Override
public void handleDraw () {

    // :

	if (frameCount == 0) {
		currentScene.setup();
	} else {
        
        // : 
        
		currentScene.draw();
        
        // :

	}

    // :

	frameCount++;
}

これだけでは mousePressed などのイベント系が使えないので、そちらは別の方法で対処します。

Processingに組み込まれているイベントは高々11個なので、以下のような処理を書くことで対応できます。

@Override
  void mousePressed() {
  currentScene.mousePressed();
}

適当に作った

GitHub: progfay/sceneManager

  • シーン作成は Scene クラスを継承して、普段どおりに setup()draw() , mousePressed() などを書く

  • SceneManager.set(sceneName, Scene): シーンをセットする

  • SceneManager.changeScene(sceneName): セットしたシーンに遷移する

その他のAPIはコードを読んでください。 (https://github.com/progfay/sceneManager/blob/master/src/SceneManager.pde)

終わりに

この方法では、Processingの仕組みを書き換えてしまっているため、意図せぬ挙動をする可能性があります。

本記事で伝えたかったのは、Processingは仕組みを書き換えても許してくれるような寛大な心を持っているということです。

非常にニッチな知識ですが、様々なことに応用できることを祈っています。

3
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?