processingで脱出ゲームを作るときのリファレンス

#概要

あとから追記します

Processingでゲームを作るときに混乱するところを一つの記事に纏めて書いておきます

processing ver.3.3.5 使用

前提として、例に使う脱出ゲームの構造は以下のようにします

![image.jpg](https://qiita-image-store.s3.amazonaws.com/0/159270/b4a0e20a-b539-f382-d4fd-3c362bd6f95f.jpeg)


- 三部屋は特定の場面（ドア）からのみ行き来できる。
- 脱出の為にはテキストボックスに正しい答えを入れる必要がある
- テキストボックスは特定の場面でのみ出現する
- 各部屋の場面は一枚の画像を使って表示する

#画面遷移-1つの部屋の中を移動する
配列と後述のフラグを使って実装します

部屋ごとに配列を作って場面ごとの画像を格納します

```
PImage[] room1 = new PImage[4];
PImage[] room2 = new PImage[4];
PImage[] room3 = new PImage[4];

room1[0] = loadImage("00.png");

...

```
画像ファイルの名前を規則的に命名することで`loadImage`命令を簡潔にできます

部屋の中で場面を切り替える場合には`image()`で表示させる配列画像のインデックスを操作します


```processing:例
for (int i=0 ; i<4;i++){
image(room[i],0,0);
}
```
ここではaおよびdで部屋の中を移動すると設定しますので`keyPressed`関数でインデックスを操作します

```
void keyPressed() {
  switch(key) {

  case 'a' :
    //bamen idou key
    //bamenNo  manage
    if (bamenNo != 3) {
      bamenNo +=1;
    } else {
      bamenNo = 0;
    }

    break;

  case 'd' :
    //bamen idou key

    if (bamenNo == 0) {
      bamenNo =3;
    } else {
      bamenNo -= 1;
    }
    break;
```

変更したインデックスは以下の画像表示管理関数での表示に反映されます
if文の中の関数にそれぞれimage();などが格納されてます

```
void mainroom() {
  reset();
  if (check_whereRoom == 0) {
    gameStart();
  } else if (check_whereRoom == 1) game();
  else if (check_whereRoom == 2) gameClear();
  else {
    text("noRoom", 60, 30);
  }
}
```

#フラグ管理-部屋と部屋間を移動する
フラグを使って管理します


##戻り値を持つ関数を使ってフラグ管理する

戻り値のある関数は`void`ではなく戻り値の型を関数名の前に置きます

```
void setup(){
}

void draw(){
  print(nibai());
　//関数nibaiを実行すると戻り値tの値が帰ってくる
　//
}

int nibai(){ //int型の戻り値を持つ関数nibai
int t = 10;
 t = t*2; //tを2倍してtに代入する
 return t;　//int型　tの値を戻り値として渡す
//この場合最初のtの中身は10なので戻り値は2倍された20となる
}
```
これを使って「今部屋移動できる場面にいるか判定し、移動できるならtrue、できなければfalseと返す関数」を用意する

```
boolean checkFlag2() {
  boolean Cflag = false;
  if (check_whereRoom ==0 && bamenNo == 2) {
    Cflag = true;
  }else if (check_whereRoom ==1 && bamenNo == 3) {
    Cflag = true;
  } else if (check_whereRoom ==2 && bamenNo == 0) {
    Cflag = true;
  } else Cflag = false;

  return Cflag;
}
```
部屋を移動するときは「今どの部屋にいるかを格納する関数」と組み合わせて使う

```
...
 case ' ' :
    //room idou key
    if (check_whereRoom == 0 && checkFlag2() == true ) {
      check_whereRoom = 1;
      bamenNo = 1;
    } else if (checkFlag2()== true&&check_whereRoom == 1) {
      check_whereRoom = 2;
    } else if (checkFlag2()== true&&check_whereRoom == 2) {
      check_whereRoom = 0;
    }
...
```

##古い方のフラグ管理関数

  部屋移動可能な場面に居るかを2つのフラグで判定する関数

```
void checkFlag() {
  if (check_whereRoom ==0) {
//今どの部屋にいるか
    check_game= false;
    check_clear = false;
    if (bamenNo == 2) check_start = true;
//どの場面にいるか
    else check_start = false;
  } 
else if (check_whereRoom ==1) {
    check_start= false;
    check_clear = false;
    if (bamenNo == 3) check_game = true;
    else check_game = false;
  } 
else if (check_whereRoom ==2) {
    check_start= false;
    check_game = false;
    if (bamenNo == 0) check_clear = true;
    else check_clear= false;
  }
}
``` 

``` 
  case ' ' :
    //room idou key
    if (check_start == true) {
      check_whereRoom = 1;
      bamenNo = 1;
    } else if (check_game == true) {
      check_whereRoom = 2;
    } else if (check_clear == true) {
      check_whereRoom = 0;
    }
   
    break;
``` 


#テキストボックス
Interfasciaというライブラリを使います

##サンプルコードを見る
```processing:textfield
import interfascia.*;

GUIController c;
IFTextField t;
IFLabel l;
```
IFTextFieldはテキストボックスを表示させるための型
IFLabel　はテキストボックスのラベルに関わる型です

```
void setup() {
  size(200, 100);
  background(200);
  
  c = new GUIController(this);
  t = new IFTextField("Text Field", 25, 30, 150);
  l = new IFLabel("", 25, 70);
//IFTextField("テキストボックスの名前",左上のX座標,左上のY座標,ボックスの幅);

  c.add(t);
  c.add(l);
//.addで画面上に当該オブジェクトを表示、機能をスタートさせる.
//IFTextField型のオブジェクトだけはsetup関数以外の場所で
//実行しようとするとフリーズしてしまう。なぜだ
  t.addActionListener(this);
}


void draw() {
  background(200);
}

void actionPerformed(GUIEvent e) {
  if (e.getMessage().equals("Completed")) {
//e.getMessage()の中身がCompletedだったとき
    l.setLabel(t.getValue());
//テキストボックスのラベル名をt.getValue()（=ボックスに入力した文字）にする
  }
}
```
`e.getMessage()`は現在のところ「ボックスに文字を打ったときの"Modified"」「ボックス内でエンターキーを押した瞬間の"Completed"」の2つの状態を取ることが確認できる

##任意の文字列を入れたときにラベルを表示するためには

```
String pass = onigiri;
void actionPerformed(GUIEvent e) {
  if (e.getMessage().equals("Completed") ) {
//EnterKeyが押されたとき
    if (t.getValue().equals(pass) ) {
//且つボックスの入力とpass変数の中身が一致するとき
      l.setLabel("gohan");
//ラベルをgohanに書き換える
    } else {
      l.setLabel("noooooo");
//一致しないときは拒絶のメッセージを出す
    }
  }
}
```
`.equals(Str)`はStringを比較するときに使い、前後のStringが一致して居るかどうか判定します

参考、interfasciaの公式サイト



###特定の場面だけでテキストボックスを出したい
まともな手段では出し入れが難しかったので、少々強引に。
隠したいときはボックスとラベル共々`setPosition()`などを用いて座標を画面外`(width*2,height*2)`などに追いやってしまい、必要なときだけ座標を画面内に収める。
これで見かけ上はテキストボックスを隠せる

```
...

int intNo = 0;

if (intNo != 0){
   setPosition(width*2,height*2);
}else{
   setPosition(150,200);
}
```

#ランダムセリフ
STR型の配列を使って解決を試みます

```
Str[] serifu = new Str[7];
//Str型の配列　serifuを用意
serifu[0] = "hello";
…

int r = round(random(0,6.99));
//ランダム関数の数字を整数に丸めてint型に格納します
text(serif[r],0,0);
//配列の中のランダムなセリフを表示する
```

日本語を使う場合はエディタのフォントを日本語対応にするひつようがあります

#動画再生
Processing のvideoライブラリを使います
…

参考http://mslabo.sakura.ne.jp/WordPress/make/processing%E3%80%80%E9%80%86%E5%BC%95%E3%81%8D%E3%83%AA%E3%83%95%E3%82%A1%E3%83%AC%E3%83%B3%E3%82%B9/%E5%8B%95%E7%94%BB%E3%82%92%E5%86%8D%E7%94%9F%E3%81%99%E3%82%8B%E3%81%AB%E3%81%AF/


#BGMを流す
Minimライブラリを使います

```
Minim musik =new Minim(this);
//初期化
AudioPlayer player;

void setup() {
 player = musik.loadFile("音声ファイルの名前");
//音声を読み込む
}

void draw() {
 player.play( ) ;
//再生。最後まで再生し終わるとストップする
}
```

…
参考
http://r-dimension.xsrv.jp/classes_j/minim/