けせらせらのブログ

数学やプログラミングを中心に感想を流していきます。

またnullptrだよ...

少し間が空いてしまいましたが取り敢えずの進捗報告をします。

今回の成果

  • 簡単なシーケンス遷移の実装
  • ジャンプの高さ、時間制限
  • ジャンプすると自動的に一度相手をロックする
  • 弾の発射、またその弾が一定時間たつ、又は相手に当たると消える
  • Imageクラスの実装

という感じです。
シーケンス遷移の階層は簡単のため1段階にし、タイトル、ゲーム開始前、ゲーム、ゲーム結果画面を実装しました。*1
ジャンプに関しては書いてある通りで、弾の当たり判定は「弾の座標がロボの直方体の中に入るかどうか」というシンプルな実装になっています。
Imageクラスに関しては画像をただ表示するクラスです。これは、以前制作したボンバーマンクラスにもありましたが*2、今回はハードウェアの力を借りて三角形に分割して表示しようという方針ですので別で作る必要がありました。前回に比べ、かなりすっきりしたコードになりハードウェアの力を実感しております...


今回の失敗

  • シーケンス遷移の作り方を完全に忘れていた(一番時間を食いました...)
  • この本では画像ファイルを2冪×2冪で取ることをすっかり忘れていた
  • ジャンプ時に相手と反対方向を向き、空中浮遊したまま地面に戻らない

またもう一つ以下のような失敗をしました。簡単に言うとnullptrです。 ロボ(プレイヤー)の位置、角度、カメラの初期位置から、現在のカメラの位置を設定する以下の部分を関数化してupdate関数の見た目をすっきりさせようと試みたところ画面が真っ黒になってしまいました…

Child* Game::update(Parent* parent) {
  //ここから
  Matrix34 w;
  w.setTranslation(mRobo[mPlayerId]->position());
  w.rotateY(mRobo[mPlayerId]->angleY());

  Vector3 cameraPos, cameraTarget;  
  w.multiply(&cameraPos, mRobo[mPlayerId]->cameraPosition());
  w.multiply(&cameraTarget, mRobo[mPlayerId]->cameraTarget());
        
  mCamera->setPosition(cameraPos);
  mCamera->setTarget(cameraTarget);
  //ここまでを関数化
}

本当に関数化以外は何もしていなかったので大パニック! 実際に悪さをしていたのはsetPositionsetTargetの2つの関数だと判明。

// Cameraクラス内
void Camera::setPosition(Vector3& pos) {
    mPosition = &pos;
}
void Camera::setTarget(Vector3& target) {
    mTarget = ⌖
}

という定義だったので、update内で定義していた変数cameraPos,cameraTargetを新しい関数内で定義すると、新しい関数の実行後にその2つの変数は消され、mPosition,mTargetは既に存在しない参照を見ることになります。(同じようなミスを前にもしたような…)

// Cameraクラス内
void Camera::setPosition(Vector3& pos) {
    *mPosition = pos;
}
void Camera::setTarget(Vector3& target) {
    *mTarget = target;
}

へ訂正すると、mPosition,mTargetの(事前に確保されている)参照先にcameraPos,cameraTargetの値を代入できるので、解決。(mPosition,mTarget == 0の時に*mPositionを見てよいのか気になりますが、これはCameraクラスのコンストラクタ内でnewによりメモリを確保しているので大丈夫です。)

関数化だけでもバグの原因になってしまうという良い教訓でした。
これからもぼちぼち頑張っていきます。

*1:ただ、今現在はHPの概念をゲーム内に入れていないのでゲーム結果は常に1Pが勝利するようにしています

*2:その時は1画素ずつ色を決定していく方式でした。