====== 第3回:クラス・コンストラクタ入門(キャラクターの動きを例に) ====== **テーマ:構造体ベースのキャラ操作 → クラス化で整理しよう!** ---- ===== 🎯 学習目標 ===== * 構造体とクラスの違いを、キャラクター制御の例から理解する * public / private / this の意味を説明できる * コンストラクタでキャラ初期化を自動化できる * 自分で「キャラクタークラス」を設計できる ---- ===== 🧩 Step 1:構造体でキャラを動かしてみよう(C++構文版) ===== #include using namespace std; struct Character { float x, y; // 位置 float speed; // 速度 bool isJumping; // ジャンプ中かどうか }; // 関数(キャラを操作) void Walk(Character& c) { c.x += c.speed; } void Run(Character& c) { c.x += c.speed * 2; } void Jump(Character& c) { if (!c.isJumping) { c.y += 5; c.isJumping = true; } } int main() { Character player = {0, 0, 1.0f, false}; Walk(player); Run(player); Jump(player); cout << "pos=(" << player.x << ", " << player.y << ")\n"; } **▶ 特徴** * データ(構造体)と動作(関数)が別々 * 引数で常に `player` を渡す必要がある * 「自分の関数」という感じがしない ---- ===== 🧭 Step 2:クラスにしてみよう ===== #include using namespace std; class Character { public: float x, y; float speed; bool isJumping; // コンストラクタ(初期化) Character(float _x, float _y, float _speed) : x(_x), y(_y), speed(_speed), isJumping(false) { } // メンバ関数(自分自身を操作) void Walk() { x += speed; } void Run() { x += speed * 2; } void Jump() { if (!isJumping) { y += 5; isJumping = true; } } void Print() { cout << "pos=(" << x << ", " << y << ")\n"; } }; int main() { Character player(0, 0, 1.0f); player.Walk(); player.Run(); player.Jump(); player.Print(); } **💡 ポイント** * `player.Walk()` のようにドットで呼び出せる * データと動作が一つのかたまりになった * コンストラクタで初期化が自動化される ---- ===== 🧠 Step 3:アクセス制御(public / private) ===== class Character { private: float x, y; float speed; bool isJumping; public: Character(float _x, float _y, float _speed) : x(_x), y(_y), speed(_speed), isJumping(false) {} void Walk() { x += speed; } void Run() { x += speed * 2; } void Jump() { if (!isJumping) { y += 5; isJumping = true; } } void Print() { cout << "pos=(" << x << ", " << y << ")\n"; } }; **▶ 解説** * `private` は外部から見えない * `public` は外部から呼び出せる * クラスの内部構造を守る「カプセル化」 ---- ===== 🧩 Step 4:thisポインタと初期化の話 ===== class Character { public: float x, y; float speed; Character(float x, float y, float speed) { this->x = x; this->y = y; this->speed = speed; } }; **💬 thisとは?** * 「自分自身」を指す特別なポインタ * 同じ名前の変数を区別するために使う 例: > 「私のx」「私のy」と言いたいときに this->x, this->y を使う ---- ===== 🧱 Step 5:ファイル分割(.h / .cpp) ===== **Character.h** #pragma once #include class Character { private: float x, y; float speed; bool isJumping; public: Character(float _x, float _y, float _speed); void Walk(); void Run(); void Jump(); void Print(); }; **Character.cpp** #include "Character.h" using namespace std; Character::Character(float _x, float _y, float _speed) : x(_x), y(_y), speed(_speed), isJumping(false) {} void Character::Walk() { x += speed; } void Character::Run() { x += speed * 2; } void Character::Jump() { if (!isJumping) { y += 5; isJumping = true; } } void Character::Print() { cout << "pos=(" << x << ", " << y << ")\n"; } **main.cpp** #include "Character.h" int main() { Character hero(0, 0, 1.5f); hero.Walk(); hero.Run(); hero.Jump(); hero.Print(); } ---- ===== 🧩 Step 6:演習 ===== **課題1** キャラクターに **Dash()** を追加して、スピード3倍で移動するようにせよ。 **課題2** ジャンプ中にもう一度ジャンプできないようにしてみよう。 **課題3** `Reset()` 関数を追加し、座標を(0,0)に戻すようにせよ。 **課題4** `Character` クラスに「名前(std::string name)」を追加し、 `Print()` で `"name : pos=(x,y)"` と表示するようにしてみよう。 ---- ===== 🧠 Step 7:まとめ ===== | 用語 | 意味 | |--------|--------| | class | データ+関数をまとめた型 | | public/private | アクセス制御(情報隠蔽) | | this | 自分自身を指すポインタ | | コンストラクタ | 自動初期化関数 | | カプセル化 | 内部データを守る仕組み | ---- ===== 🎮 応用アイデア ===== * **Playerクラス**にHPや名前を追加して、`TakeDamage(int amount)` を実装 * **Enemyクラス**を派生させ、プレイヤーとの距離を求めて「追いかける」動作へ発展 ----