第3回:クラス・コンストラクタ入門(キャラクターの動きを例に)
テーマ:構造体ベースのキャラ操作 → クラス化で整理しよう!
🎯 学習目標
- 構造体とクラスの違いを、キャラクター制御の例から理解する
- public / private / this の意味を説明できる
- コンストラクタでキャラ初期化を自動化できる
- 自分で「キャラクタークラス」を設計できる
🧩 Step 1:構造体でキャラを動かしてみよう(C++構文版)
#include <iostream> 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 <iostream> 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 <iostream> 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クラスを派生させ、プレイヤーとの距離を求めて「追いかける」動作へ発展