【超初心者向け】Java派生のProcessingで超簡単なゲームを作ってみよう

# Processingでなんかつくろう

## はじめに
ProcessingとかJavaとかオブジェクト指向はよくわからんけど、とりあえずなんか動くゲーム作ってプログラミングに触れたいってコース。

まずはクラスなんか作らずに、動くものを目指す

簡単なSTG（シューティングゲーム）を作る。

完成例はこれ↓
![fig0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/340870/d5896c59-1e2f-e8e2-4d21-38759339a8fa.png)


## 画面～自機

とりあえず自機をポン置きしてみよう
使う関数はsizeとtriangle

それぞれ setup()とdraw()に書こう。
trigangleは３頂点の座標をうつだけなので、適当に。

```java
void settings() {
        size(600 , 600);
    }
    
void draw(){
    triangle(300,300,250,400,350,400);
}
```

![fig1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/340870/89ba955b-de5c-c31e-14b6-cd7105cb38e7.png)


おけた。
今度はこれを動かす。
動かすには、trigangleの座標を動かす必要がある。
実行中に数字打ち直すわけにいかんので、これらを変数で置き直す

プレイヤーのx、y座標なので安直にpx,pyとした

**draw関数内に書くと毎回宣言し直されて位置変わらないので注意！**


```java
int px = 300;
int py = 300;
void draw(){
    triangle(px,py,px-50,py+100,px+50,py+100);
    px += 2;
    py += 2;
    }
```

これで、座標がx,yともに2ずつ増えていく！
![fig2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/340870/600f057d-0f78-695e-81f8-561895153a6d.png)


しかし、このように画面が更新されず軌跡が残り続けるので、毎回画面を真っ更にする必要がある。
background関数で画面を一気に色つけれるので、200とか入れて灰色にしよう。

この関数はこれからtriangleとか描写系関数よりも先に実行される必要がある（じゃないと塗りつぶされちゃう）

```java
void draw(){
    background(200);
    triangle(　略
```

##操作可能にしよう
次にキーボードによる操作を可能にしてゲームっぽくする

キーボードが押されたら、keyPressed()て関数が実行されるので、これを記述する。

```java
    void keyPressed() {

        if(keyCode==LEFT){
            px-=10;
        }else if(keyCode==RIGHT){
            px+=10;
        }else if(keyCode==UP){
            py-=10; 
        }else if(keyCode==DOWN){
            py+=10;
        }
    }
    
    void draw(){
        background(200);
        triangle(px,py,px-50,py+100,px+50,py+100);
    }
```

ここで、どのキーが押されたか判定は、変数keyCodeを見る。LEFT,RIGHT等は既に変数として用意されているので利用。

押されたキーに対応するよう座標を+-で調整しよう。

**ここで座標軸の向きに注意！x→、y↓の向きで正**

px+=2を消すのをお忘れなく

これで自由にキーで操作できるようになった。
![fig3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/340870/1cc7869d-0160-7b19-c3c9-066fe68f1bb1.png)

## 弾を撃とう

シューティングゲームなので、発砲したい。

まずは弾丸を用意しよう。これも同じように変数で用意する。Tamaなのでtx,tyとした。
とりあえず四角形（rect)でおく

```java
   int px = 300; // Player
   int py = 300;
   
   int tx = 300; // Tama
   int ty = 300;
   
    void keyPressed() {省略}
    
void draw(){
    background(200);
    triangle(px,py,px-50,py+100,px+50,py+100); //Player
    rect(tx,ty,10,10); // Tama
    ty -= 2 ;
}
```
![fig4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/340870/eadfd239-a3dc-cbc1-22b4-99996d903aee.png)


弾のy座標が２づつ減ってくので、上にうちあがっていく

このままでは上に一生上がり続けるだけなので、発射ボタンを押したら自機から発射されるようにしたい。

→ボタンおしたら自機の座標に弾を移動。弾は上に上がり続ける。また押されたらまた移動・・・

これでいけそう。

```java
   int tx = 0; // Tama
   int ty = 0;
   
    void keyPressed() {

        if(keyCode==LEFT){
            px-=10;
        }else if(keyCode==RIGHT){
            px+=10;
        }else if(keyCode==UP){
            py-=10; 
        }else if(keyCode==DOWN){
            py+=10;
        }
        
        if(key==' '){ // space!!!!!!
            tx=px;
            ty=py;
        }
    }   
    
void draw(){略}
```
弾の宣言を0,0スタートにして、撃つまで出現しないように。

射撃をSpaceキーにしたが、矢印キーと違う条件式なのでこれも注意。

これでどこへ自機が移動しても射撃できるように。
![fig5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/340870/11adf24f-9f45-c5f0-ffb8-ca50a306a033.png)

## 的を表示し、当たり判定をつける

的（敵）を表示する。なんとなく円で表示することとし、とりあえず適当においてみよう

座標は(100,100)、直径は90とする。

```java
void draw(){
    background(200);
    triangle(px,py,px-50,py+100,px+50,py+100); //Player
    rect(tx,ty,10,10); // Tama
    ty -= 2 ;  //ここまで同じ
    ellipse(100,100,90,90);
}
```

![fig6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/340870/b9016a2e-f355-a703-2437-19d7cd46c2a4.png)



もちろん弾は通過する。以下で的の座標を利用するので、これも変数でおいてしまおう。

変数名は、ボール１つめってことでb1x,b1yとした。

```java
略
    int b1x=100;
    int b1y=100;
略
void draw(){
    略
    ty -= 2 ;  //ここまで同じ
    ellipse(b1x,b1y,90,90);
}

```

今度は当たり判定を考えるが、"当たった"と判定する関数は用意されていないので、条件式を考える必要がある。

このゲーム、やっているのは指定した座標に図形を設置しているだけなので、すべて座標で計算すればよさそう。

→当たる＝座標が重なる、ということなので、これをif文で書く。

当たったら的の座標を(1000,1000)とかに飛ばしておけば見えなくなるのでとりあえずOK!

```java
void draw(){
  略
        ellipse(b1x,b1y,90,90);
        if(tx > b1x-45 && tx < b1x+45 && ty > b1y-45 && ty < b1y+45) {
            b1x = 1000;
            b1y = 1000;
        }
```
当たり判定を図解↓

![fig7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/340870/43485576-8212-8fe6-2301-e75611a3dc9b.png)


とりあえずこれでクソゲー完成。
コードをまとめておく

```java

void setup() {
  size(600, 600);
}

int px = 300; //Player
int py = 300;

int tx = 0; // Tama
int ty = 0;

int b1x=100; // Ball 1
int b1y=100;

void keyPressed() {
  if (keyCode==LEFT) { //Move
    px-=10;
  } else if (keyCode==RIGHT) {
    px+=10;
  } else if (keyCode==UP) {
    py-=10;
  } else if (keyCode==DOWN) {
    py+=10;
  }

  if (key==' ') { // Space key
    tx=px;
    ty=py;
  }
}   

void draw() {
  background(200);
  triangle(px, py, px-50, py+100, px+50, py+100); //Player
  rect(tx, ty, 10, 10); // Tama
  ty -= 2 ; 
  
  ellipse(b1x, b1y, 90, 90);
  if (tx>(b1x-45) && tx<b1x+45 && ty>b1y-45 && ty<b1y+45) { // Hit judge
    b1x = 1000; // Out of Range
    b1y = 1000;
  }
}


```

## 色をつけよう

モノクロは味気ないので、色を付ける。
インベーダーっぽく背景は適当に紺色、自機好きな色（ピンク）にしよう

的は赤、弾は黄色とかにしてみる。


背景は`bacground(R,G,B);`で色付け。

他の図形は`fill(R,G,B)`で色付けできる。

ちなみに、標準IDEを使ってる場合、適当に`fill(0,0,0)`とか打って、上のメニューから`スケッチ→Tweak`で実行すると色がビジュアル的に変更できる。

![fig7_5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/340870/03b27a89-b045-ba67-f60d-671aa2ad8bc2.png)


```java
関係部以外省略
void draw() {
  background(0, 0, 50);
  
  fill(246,118,255);
  triangle(px, py, px-50, py+100, px+50, py+100); //Player
  
  fill(255,255,0);
  rect(tx, ty, 10, 10); // Tama
  
  fill(229,10,98);
  ellipse(b1x, b1y, 90, 90);
}
```
色をセットするとこうなる。

![fig8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/340870/1309b02f-6dde-352c-c487-af6fcf30c563.png)

そこそこですね。


## 量産

的が１つなのは味気ないので、３つくらい設置しよう。

同じように、b2x,b2y b3x,b3yとする。

**本当はオブジェクト指向に則ってクラスを使うべきだが、簡単に済ませるため割愛。2部でやる**

```java
int b1x=100; // Ball 1
int b1y=100;

int b2x=200; // Ball 2
int b2y=150;

int b3x=300; // Ball 3
int b3y=100;

略

void draw(){
        略
        
        fill(229,10,98);
        ellipse(b1x, b1y, 90, 90);
        
        fill(200,10,0);
        ellipse(b2x, b2y, 90, 90);
        
        fill(100,10,200);
        ellipse(b3x, b3y, 90, 90);
        
      if (tx>(b1x-45) && tx<b1x+45 && ty>b1y-45 && ty<b1y+45) { // Hit judge
         b1x = 1000; // Out of Range　Tama 1
         b1y = 1000;
      }
      if (tx>(b2x-45) && tx<b2x+45 && ty>b2y-45 && ty<b2y+45) { // Hit judge
        b2x = 1000; //Tama2 
        b2y = 1000;
      }
      if (tx>(b3x-45) && tx<b3x+45 && ty>b3y-45 && ty<b3y+45) { // Hit judge
         b1x = 1000; //Tama3
         b1y = 1000;
      }
}
```

## END表示したい

END表示したい

的を3つ消したらENDて表示させたいですね。

これには、残りの的の数を記憶する変数を用意して、0になったらEND表示させましょう。

各当たり判定の処理に残り数を減らすコードも必要

```java
int Nokori = 3

略
void draw(){
略

if(当たり判定
 b1x =1000;
 b1y =1000;
Nokori-- ; //残り数減らす
}
下２つも同じように

if(Nokori == 0){
 fill(255,255,255); //好きな色で
textSize(100); //お好み
text("END",300,300); //座標300,300にEND表示
}

```

![fig9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/340870/bc0efb16-8c23-892e-494b-449a9df65c35.png)


これで一応ENDが出るが、真ん中から左づめで文字表示されててダサい。座標をずらしてもいいけど、ここは中央揃いで表示させる


```java
一回の実行でいいのでセットアップに書く
void setup(){
 size(600,600);
 textAlign(CENTER);
}
```

![fig10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/340870/949d7cd0-9ad5-fbce-50f5-2d07f67f31e6.png)

きれい？

## 秒数表示

せっかくなので、タイムアタック出来るようにする。

時間を測る関数に、`millis()`というのがあるのでこれを使う。これはプログラム開始時からこの処理が実行されたタイミングまでの時間を返す。

例えば、`int m = millis(); `と書いて、これが1.5秒後に実行されたとすると、mには
1500が入る、というわけである。

次に、時間を表示したいなら、
```java
int time = millis() / 1000 ;
text(time,50,500);
```


をdraw()の中に書けば毎回timeが更新されるので、現在の秒数が表示される。0.x秒数で表示したいなら１００で割ればいい。少数で表示するならintをfloatにすればOK

今回は`int time = millis() / 100 ;`としよう

というわけでdraw関数中に書けば

```java
略
  void draw(){
    略
    int time = millis() / 100 ;
    fill(253, 8, 146);
    textSize(30);  
    text(time, 50, 550);
  }
  
```

![fig11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/340870/6d0ea3da-fd48-8652-fc76-79742ad131fb.png)


このように時間表示が可能となる。

なお、カウントアップは止まらない。

### END時にタイムも表示

単に、`if(Nokori == 0)`の中に、`text(m,300,400)`と書けばよさそうに見えるが、それだと「終了した時のタイム」ではなく「現在のタイム」が表示される。（つまりカウントアップしたまま）

これでは困るので、的が3つ消えた時点でタイムを取得して、ENDと共に表示すればOKというわけだ。

この「的が3つ消えた時点でタイムを取得」の処理が難しいが、今回は残り的数を少し工夫して対応する。

具体的には、

`的が1〜3こ→何もしない`

`的が0こ→END表示`

だったのを、

`的が1〜3こ→何もしない`

`的が0こ→タイム取得 & 的の数を-1に`

`的が-1こ→END表示`

とする。的が-1個というのが意味不明だが、0になったら自動的に-1になるので0みたいなものである。

これをif文で書くと、

```java
int endTime = 0 ;

略

void draw()
略

if(Nokori == 0){
    endTime = millis() /100 ;
    Nokori = -1 ;
}else if(Nokori == -1){ //ここの処理は前のと同じ
    fill(0,0,0) 
    textSize(30) 
    text("END",300,300);
    text(endTime,300,400);
}

```
とすれば良い。

![fig12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/340870/ad0b603a-8982-0e13-9786-3f7aa679ca81.png)


右下のタイマーはもう必要ないので消したい。

つまり、残り的数が１～３のときに表示してればいいので、elseにすれば解決。

```java
  if (Nokori == 0) {
    endTime = millis() /100 ;
    Nokori = -1 ;
  } else if (Nokori == -1) {
    fill(50, 50, 250); 
    textSize(100); 
    text("END", 300, 300);
    text(endTime, 300, 400);
  }else{
      int time = millis() / 100 ;
      fill(253, 8, 146);
      textSize(30);  
      text(time, 50, 550);
  }

```

## ランダム

的の位置をランダムにする。
ランダムの関数は`random(LOW,HIGH)`または`random(HIGH)`。これは中に１つ数字書くと０～その数字までの乱数、２つ書くとLOW～HIGHまでの乱数が帰ってくる。

返り値はfloatなのだが、座標は整数のため(int)(random～)で囲って整数に変える（ダウンキャスト）

```java
    int b1x = (int)( random(600) );
    int b1y = (int)( random(400) );

    int b2x=(int)( random(600) );
    int b2y=(int)( random(400) );

    int b3x=(int)( random(600) );
    int b3y=(int)( random(400) );
```

## おじゃまバー

弾を消し去るおじゃまバーを実装したい。

細い長方形を移動させて、当たったら、弾を画面外に飛ばせばOKかな

```java
    int lx=(int)( random(500) );
    
    void draw(){
        略(ellipseの次とか)
        
        fill(206,255,34);
        rect(lx,250,100,10);
        lx += 3 ;
        
        略
    }

```

![fig13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/340870/b6d4f559-23c4-95b5-a2be-0e95d14c6bef.png)

ああどこへ行ってしまう

困るので、壁で反射してもらう。反射については、移動スピードを逆向きにすればよい。

移動スピードをlspeedと置き、反射するタイミングで-1を掛ける。

```java
    int lx=(int)( random(500) );
    int ly = 250 ;
    int lspeed = 3 ;
    
    void draw(){
        略(ellipseの次とか)
        
        fill(206,255,34);
        rect(lx,ly,100,10);
        lx += lspeed ;
        if(lx <0 || lx >500){ // 反射
          lspeed *= -1 ;
        }
        略
    }

```

![fig14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/340870/a4c770f3-ec37-d69b-892e-08ace42e1dbe.png)


当たったときに、弾を消失させたいのでこれもifで

```java
    if(tx > lx && tx < lx + 100 && ty > ly &&  ty < ly+10){
        tx = 1400; // かぶらなければどこでも
        ty = 1000;
    }
```

## 移動範囲制限をつける

このままでは敵にアタックして弾が打ててしまうので、画面下の方だけ移動できるようにしたい。

これもif文で処理する。

```java
void draw()中に

        if (px <= 0) {
            px = 0;
        } else if (px >= 600) {
            px = 600;
        }
        if (py <= 400) {
            py = 400;
        } else if (py >= 540) {
            py = 540;
        }

```

##とりあえずここまで。