🎯 第6章 距離で判断するオブジェクト:Enemyクラス

🏁 学習目標


💬 あたり判定とは?

ゲームでは、キャラクター同士や攻撃との「距離」で当たりを判定します。

たとえば、 「敵とプレイヤーの距離が 2 以下なら攻撃が届いた」 というように、数値的な距離比較 で処理を行います。

数式で表すと、次のようになります:

$$ 距離 = \sqrt{(x_1 - x_2)^2 + (y_1 - y_2)^2} $$

この考え方は、どんなジャンルのゲームにも共通する基本です。


💡 const参照で安全に距離を測る

距離を計算する関数では、プレイヤーやベクトルのデータをコピーせずに 「読み取り専用」で使いたい場面が多くあります。

double calcDistance(const Vector2D& a, const Vector2D& b);
記号 意味
&(参照渡し) コピーせずに「元データ」を参照する
const 関数内で変更できない「読み取り専用」にする

高速で安全 に距離を計算できる!


🧮 例題:Enemyクラス

目的: Playerとの距離を計算し、一定距離以内なら「攻撃できる」と表示する。

#include <iostream>
#include <cmath>
using namespace std;
 
// ======================
// Vector2D クラス
// ======================
class Vector2D {
public:
    double x;
    double y;
    Vector2D(double a, double b);
    static double distance(const Vector2D& a, const Vector2D& b);
};
 
// ---- Vector2D メンバ関数の外部定義 ----
Vector2D::Vector2D(double a, double b) {
    x = a;
    y = b;
}
 
double Vector2D::distance(const Vector2D& a, const Vector2D& b) {
    double dx = a.x - b.x;
    double dy = a.y - b.y;
    return sqrt(dx * dx + dy * dy);
}
 
// ======================
// Player クラス
// ======================
class Player {
public:
    string name;
    Vector2D pos;
    Player(string n, Vector2D p);
    void show();
};
 
Player::Player(string n, Vector2D p) {
    name = n;
    pos = p;
}
 
void Player::show() {
    cout << name << " の位置: (" << pos.x << ", " << pos.y << ")" << endl;
}
 
// ======================
// Enemy クラス
// ======================
class Enemy {
public:
    string name;
    Vector2D pos;
    double range;   // 攻撃可能距離
 
    Enemy(string n, Vector2D p, double r);
    bool canAttack(const Player& target);
    void show();
};
 
// ---- Enemy メンバ関数の外部定義 ----
Enemy::Enemy(string n, Vector2D p, double r) {
    name = n;
    pos = p;
    range = r;
}
 
bool Enemy::canAttack(const Player& target) {
    double d = Vector2D::distance(pos, target.pos);
    return d <= range;
}
 
void Enemy::show() {
    cout << name << " の位置: (" << pos.x << ", " << pos.y << ")" << endl;
}
 
// ======================
// main 関数
// ======================
int main() {
    Player p("Hero", Vector2D(0, 0));
    Enemy  e("Slime", Vector2D(1, 1), 2.0);
 
    p.show();
    e.show();
 
    double dist = Vector2D::distance(p.pos, e.pos);
    cout << "距離: " << dist << endl;
 
    if (e.canAttack(p)) {
        cout << e.name << " は " << p.name << " を攻撃できる!" << endl;
    } else {
        cout << e.name << " はまだ届かない…" << endl;
    }
}

実行結果

Hero の位置: (0, 0)
Slime の位置: (1, 1)
距離: 1.41421
Slime は Hero を攻撃できる!

ポイント


🎮 イメージ図

(0,0)  プレイヤー(Hero)
  ↓ 距離 1.41
(1,1)  敵(Slime)

「距離 ≤ 攻撃範囲(range)」なら「攻撃可能!」という考え方。


🧩 練習問題(第6問)

複数の敵とプレイヤーのあたり判定を作ってみよう。

// クラス: Enemy, Player, Vector2D(同様の定義)
//
// main()の仕様:
//   ・プレイヤーを (0,0) に配置
//   ・敵を3体作る:
//       Enemy("Slime",  Vector2D(1,1), 2.0)
//       Enemy("Bat",    Vector2D(3,4), 2.0)
//       Enemy("Orc",    Vector2D(5,1), 3.0)
//   ・それぞれについて canAttack() を使い、攻撃可能か判定して表示
//
// 出力例:
// Slime は Hero を攻撃できる!
// Bat はまだ届かない…
// Orc はまだ届かない…

ヒント


🎯 まとめ

覚えるポイント 内容
const参照 (const &) データをコピーせず、安全に読み取る(読み取り専用)
static関数 クラスに属するが、特定のインスタンスに依存しない関数
スコープ解決演算子(::) 所属を明示する。「Vector2D::distance」のように使う
あたり判定の考え方 「距離 ≤ 範囲」で攻撃や接触を判定する