glutとC言語でシューティングゲーム6日目

#これまでのあらすじ

+ 自機キャラの描画
+ 自機キャラの移動

5日目は[ここ](https://qiita.com/remi_0753_yu/items/a6a98998636e997bb6ad)です。

#6日目
弾幕シューティング開発6日目です。今回はゲームシーンの見た目をそれっぽくしていきます。

今回作る弾幕シューティングの自機キャラが移動できる範囲は画面全体ではなく、ゲームシーンの中に自機が入って動ける範囲と自機が入ることができずいろいろな情報を描画する部分があるものとします。東方projectの弾幕シューティングのゲーム画面のような見た目です。といっても、普通なら外枠みたいな画像を用意して常に描画し続ける、みたいな実装になると思いますが、今回は画像を一切使わずglutが提供する機能だけで弾幕シューティングを作ります。なので、これまでに実装してきた機能をうまく使って、ゲームシーン全体の見た目をよくしていきます。

その後で、実際に自機が動ける範囲を限定します。今のままでは画面外にまで動けてしましますからね笑。

それでは今回も頑張っていきます。

#今日の目標

+ ゲームシーンの見た目をよくする
+ 　自機の移動範囲を制限する

#ゲームシーンの見た目
##ゲームシーンのデザイン
まずはゲームシーンのデザインを決めます。といっても、正直私はデザインのセンスがないので、ほとんど東方projectの弾幕シューティングの見た目をパクります。それでもクオリティは遠く及ばないと思います笑。

```
画面
+---------------------------------------+
| +-----------------------+             |
| |  自機移動可能領域      |             |
| |                       |             |
| |                       |             |
| |                       |             |
| |                       |             |
| |                       | DANMAKU     |
| |                       |   SHOOTING  |
| |        ●◇●           |             |
| |                       |             |
| +-----------------------+    fps:60.0 |
+---------------------------------------+
```

このようなデザインにします。右上の範囲には、自機の状態や残機数などのゲームで表示するべきパラメータを描画する予定です。色は実装する中で、いろいろ試しながら決めたいと思います。

##描画処理の実装
それでは画面の様々なものを描画する処理を作ります。新たに定めなければいけないパラメータは、自機移動可能範囲の左上の座標と自機移動可能範囲の幅と高さです。これらの値は様々なところから参照する必要があります。なので、まずはその情報が書かれたヘッダーファイルを作成します。

```
src/
 +- ...
 +- scene/
     +- menu/
     +- game/
         +- ...
         +- gameField.h : 自機移動範囲
```

```c:gameField.h
#ifndef ___HEADER_GAMEFIELD

#define ___HEADER_GAMEFIELD


#define FIELD_SIZE_X 384.0f
#define FIELD_SIZE_Y 448.0f

#define FIELD_START_X 32.0f
#define FIELD_START_Y 16.0f


#endif
```

自機移動可能範囲の左上の座標を(32, 16)とし、自機移動可能範囲の横幅を384px、高さを448pxとしました。

次に、実際に描画を行う処理を実装します。

```
src/
 +- scene/
     +- game/
         +- ...
         +- sceneGameBoard.h
         +- sceneGameBoard.c
```

```c:sceneGameBoard.h
#ifndef ___HEADER_SCENEGAMEBOARD

#define ___HEADER_SCENEGAMEBOARD


void drawBoard();


#endif
```

```c:sceneGameBoard.c
#include "sceneGameBoard.h"

#include "../gameUtils.h"
#include "../../shape/rect.h"
#include "gameField.h"

void drawBoard(){
  fontBegin();
  //rogo
  fontSetPosition(425.0, 305.0);
  fontSetSize(FONT_DEFAULT_SIZE * 0.3);
  fontSetWeight(4.0);
  fontSetColor(255, 150, 150);
  fontDraw("DANMAKU");
  fontSetPosition(440.0, 340.0);
  fontSetSize(FONT_DEFAULT_SIZE * 0.3);
  fontSetWeight(4.0);
  fontSetColor(255, 255, 100);
  fontDraw("SHOOTING");
  fontSetPosition(430.0, 380.0);
  fontSetSize(FONT_DEFAULT_SIZE * 0.12);
  fontSetWeight(1.0);
  fontSetColor(200, 200, 200);
  fontDraw("- respect for touhou -");

  //fps
  fontSetPosition(550.0, 440.0);
  fontSetSize(FONT_DEFAULT_SIZE * 0.15);
  fontSetWeight(2.0);
  fontSetColor(5, 5, 5);
  fontDraw("fps:%.1f", fpsGet());
  fontEnd();

  //field
  rectDraw(
      FIELD_START_X + FIELD_SIZE_X / 2.0f,
      FIELD_START_Y + FIELD_SIZE_Y / 2.0f,
      FIELD_SIZE_X,
      FIELD_SIZE_Y,
      0.0,
      10,
      10,
      10);
}
```

drawBoard関数の中では、右下のほうに描画する"DANMAKU SHOOTING -respect for touhou -"という文字列とfpsを描画し、矩形で自機移動可能範囲を描画します。

最後にこの関数を呼ぶsceneGame.cに追記します。

```c:sceneGame.c
//以下を追記
#include "sceneGameBoard.h"

void sceneGameInit(unsigned char *p){
  //sceneGameInit()の中に追記
  glClearColor(0.15f, 0.15f, 0.4f, 1.0f);
}

//sceneGameDisplay関数を修正
void sceneGameDispaly(){
  glClear(GL_COLOR_BUFFER_BIT);
  
  drawBoard();
  playerDraw(&player);

  glutSwapBuffers();

}
```

ゲームシーンの初期化部分で背景色を設定します。そのあと、ゲームシーン描画関数で、drawBoard関数を使います。

それではMakefileを書き換えてmake、実行してみましょう。
![day6.JPG](https://qiita-image-store.s3.amazonaws.com/0/372314/ae2cd014-c908-408a-5bf1-93e359087d0d.jpeg)
それっぽい見た目になりました。

色に関しては本当にセンスがないので背景色はもしかしたら変えるかもしれません。右下の文字の色はこだわりがあるのでこれで決定です。

#自機の移動範囲の制限
それでは、見た目に従って自機の移動範囲を制限ます。

```c:player.c
//以下を追記
#include "./scene/game/gameField.h"

#define PLAYER_MOVE_MIN_X (FIELD_START_X + PLAYER_SIDE_BALL_R + PLAYER_SIDE_BALL_POSITION)
#define PLAYER_MOVE_MIN_Y (FIELD_START_Y + PLAYER_RECT_SIZE * sqrt(2.0) * 0.5f)
#define PLAYER_MOVE_MAX_X (FIELD_START_X + FIELD_SIZE_X - (PLAYER_SIDE_BALL_R + PLAYER_SIDE_BALL_POSITION))
#define PLAYER_MOVE_MAX_Y (FIELD_START_Y + FIELD_SIZE_Y - PLAYER_RECT_SIZE * sqrt(2.0) * 0.5f)

//move関数を修正
void move(player_t player){
  //player->m_x += x;
  //player->m_y += y;
  //上の2行を以下に変更
  float px = player->m_x + x;
  float py = player->m_y + y;
  if (PLAYER_MOVE_MIN_X <= px && px <= PLAYER_MOVE_MAX_X)
    player->m_x = px;
  if (PLAYER_MOVE_MIN_Y <= py && py <= PLAYER_MOVE_MAX_Y)
    player->m_y = py;
}
```

マクロで自機の中心が移動できる最小値と最大値を縦横それぞれで定義しています。また、move関数の中で実際に自機を移動させる処理の部分に、移動可能範囲内におさまっているかどうかを判定するを追加しました。

これでmakeして実行すると、自機移動可能範囲から出られなくなっています。

#6日目まとめ

+ ゲームシーンの見た目がゲームっぽくなった
+ 自機の移動が制限された

ようやくゲームっぽい見た目になりました。目に見える部分ができてくるとやっぱり楽しいです。これから敵の実装やこのゲームのメインでもある弾幕の実装に入っていくので、さらに楽しみです。それでは今回はここまで。