Skip to content

第04回 構造体と矩形

前回: 第03回 入力と移動 / 次回: 第05回 弾を撃つ

今回の授業内容

  • 座標をVec2構造体でまとめる
  • 当たり判定用の範囲をRect構造体で表す
  • プレイヤーの座標をintからVec2へ変更する
  • 矩形同士の重なりを判定する関数を作る
  • 見た目と当たり判定の位置を確認する

今回の開始状態

第03回終了時点では、playerXplayerYを使ってプレイヤーを動かしています。
今回の終了時点では、位置をVec2で持ち、当たり判定用のRectを作れるようにします。

変更するファイル

ファイル変更内容
Common.hVec2Rectを追加する
Collision.h矩形同士の重なり判定を追加する
Game.hプレイヤー座標をVec2へ変更する
Game.cpp移動、描画、デバッグ表示をVec2基準に変更する

Vec2を追加する

Common.hに、2D座標を表す構造体を追加します。

cpp
struct Vec2
{
    float x;
    float y;
};

Game.hのプレイヤー座標を、2つのintから1つのVec2へ変更します。

cpp
Vec2 playerPosition = {};
float playerSpeed = 4.0f;

初期化もVec2へ合わせます。

cpp
playerPosition = { screenWidth * 0.5f, screenHeight - 60.0f };

Rectを追加する

当たり判定では、位置だけでなく幅と高さが必要です。
Common.hへ矩形を表す構造体を追加します。

cpp
struct Rect
{
    float x;
    float y;
    float width;
    float height;
};

プレイヤーの当たり判定を作るときは、中心座標から左上座標を計算します。

cpp
Rect playerRect =
{
    playerPosition.x - 14.0f,
    playerPosition.y - 14.0f,
    28.0f,
    28.0f
};

Collision.hを追加する

SourceCollision.hを追加し、矩形同士の重なりを判定する関数を作ります。

cpp
#pragma once

#include "Common.h"

inline bool IsOverlapping(const Rect& a, const Rect& b)
{
    return a.x < b.x + b.width &&
        a.x + a.width > b.x &&
        a.y < b.y + b.height &&
        a.y + a.height > b.y;
}

まだ敵や弾はないため、今回はプレイヤーの矩形を線で表示して確認します。

cpp
DrawBox(
    static_cast<int>(playerRect.x),
    static_cast<int>(playerRect.y),
    static_cast<int>(playerRect.x + playerRect.width),
    static_cast<int>(playerRect.y + playerRect.height),
    yellow,
    FALSE
);

動作確認

  1. 第03回と同じようにプレイヤーを移動できることを確認する
  2. 当たり判定の黄色い矩形がプレイヤーに追従することを確認する
  3. 矩形のサイズを変えて、見た目との違いを確認する
  4. Collision.hをインクルードし忘れたときのエラーを確認し、戻す

よくある問題

  • Vec2を追加した後は、playerXplayerYの古い参照が残っていないか確認する
  • floatを描画関数へ渡すときは、static_cast<int>で整数へ変換する
  • Collision.hは関数定義をヘッダーに置くため、inlineを付ける

今回の完成条件

  • Vec2で位置を表せる
  • Rectで当たり判定の範囲を表せる
  • プレイヤーの移動と描画をVec2基準に変更できる
  • 矩形同士の重なり判定の考え方を説明できる

まとめ

今回は、座標と範囲を構造体として整理しました。
次回は、固定配列と有効フラグを使って複数の弾を扱います。