2Dゲーム制作Ⅰ⑫(2025/07/03)

ファイル分割(ヘッダーファイル)

定数定義~プロトタイプ宣言(変数宣言を除く)までを main.h に移動。
※C言語では変数をヘッダーファイルに「宣言(extern)」として分離することは可能だが、実体(定義)は1つだけソースファイルに置く必要がある。
C++ではクラスなどの構造にまとめることで、より柔軟に外部ファイル化できる。

//main.h
#pragma once
//-----------------
// 定数定義
//-----------------
const int WINDOW_WID = 800;		// ウィンドウの横サイズ
const int WINDOW_HIG = 600;		// ウィンドウの縦サイズ

// プレイヤー
const int PLAYER_WID = 32;		// プレイヤー画像の横サイズ
const int PLAYER_HIG = 19;		// プレイヤー画像の縦サイズ
const int PLAYER_MOVE_SPEED = 6;	// プレイヤーの左右の移動速度

// プレイヤー弾
const int PLAYER_BULLET_WID = 6;	// プレイヤー弾の画像の横サイズ
const int PLAYER_BULLET_HIG = 30;	// プレイヤー弾の画像の縦サイズ
const int PLAYER_BULLET_MOVE = 12;	// プレイヤー弾の移動速度

// 敵キャラ
const int ENEMY_WID = 32;		// 敵の画像の横サイズ
const int ENEMY_HIG = 23;		// 敵の画像の縦サイズ

// 敵キャラの画面表示関連
const int ENEMY_DISP_XNUM = 8;		// 敵キャラの横の表示個数
const int ENEMY_DISP_YNUM = 7;		// 敵キャラの縦の表示個数
const int ENEMY_DISP_ALL_NUM = ENEMY_DISP_XNUM * ENEMY_DISP_YNUM;

//プロトタイプ宣言
bool Init(void);
void Update(void);
void Draw(void);

main.cppの先頭に下記をinclude。

#include"main.h"

※変数のスコープ
**C言語における変数のスコープ(有効範囲)**について、簡潔に整理します。


✅ 変数のスコープとは?

**「その変数が使える範囲(見える範囲)」**のこと。


🔹 スコープの種類(主に3つ)

スコープ説明
ブロック内スコープ(ローカル変数){}で囲まれた範囲内だけで有効関数内の int x = 10; など
関数スコープ関数名 によって識別される範囲。主に goto のラベルに適用start: ラベルなど
ファイルスコープ(グローバル変数)ファイル全体で有効(関数の外で定義された変数)int count = 0;(関数の外)

🔹 補足:リンク可能性による違い(外部から見えるか)

修飾子意味使える範囲
staticファイル内限定他のファイルから見えない
extern他のファイルにも見せる宣言他の .c から参照可能

✅ まとめ一言

スコープ=「どこから見えるか」
{}の中=ローカル変数関数の外=グローバル変数
static → ファイル限定、extern → 他ファイルへ開示
(by ChatGPT)
また、基本的に変数は「宣言後」にしか使えないので、使う行以前に必ず宣言しておく。

※pragma once
ヘッダーファイルの多重定義を防ぐための一行。

Player.cpp と Player.h を作成。
プレイヤー関係の変数宣言を main.cpp ⇒ Player.cpp に移動。
初期化用関数の作成とプロトタイプ宣言

//Player.h
#pragma once

//------------------------------------------
//他のファイルでも参照が必要な変数の extern宣言
//------------------------------------------
extern int playerPosX;		// 自機のX座標
extern int playerPosY;		// 自機のY座標
extern bool playerFlg;		// 自機の表示状態管理用フラグ(true:表示、false:非表示)

//-------------------------------------------
//プロトタイプ宣言
//-------------------------------------------
bool PlayerInit(void);
//Player.cpp

//-----------------------------------------------------------------------------
// インベーダーゲーム
// 氏 名:
//-----------------------------------------------------------------------------
#include <DxLib.h>
#include"main.h"
#include"Player.h"

//-----------------
// 変数の宣言
//-----------------
// プレイヤー
int playerImage;		// 自機の画像ハンドル番号
int playerPosX;			// 自機のX座標
int playerPosY;			// 自機のY座標
bool playerFlg;			// 自機の表示状態管理用フラグ(true:表示、false:非表示)


bool PlayerInit(void)
{
	return true;
}

※extern

✅ 正確な定義(C言語の文法的視点)

  • extern int count;
    → これは **「変数の宣言(宣言だけ、定義ではない)」**です。
  • int count = 0;
    → これが **定義(実体を与える)**です。

✅ 先生の説明の意図(実務・設計視点)

「他のファイルに変数を公開するもの」

これは要するに:

  • extern は **「ここには実体がないけど、どこかにある前提で使いますよ」**という宣言
  • 他の .c ファイルにある変数を 他のソースから見えるように“見せる”ためのラベル
  • 外部リンク可能にする記号という意味では、「公開する」もOK

✅ つまり両方を整理すると…

観点内容
文法的に正しい定義extern は「宣言」であって「定義」ではない
実務的にわかりやすい説明他ファイルに「公開する」「参照可能にする」ための仕組み
最も正確な表現「他ファイルにある実体の宣言を、他の場所でも使うための公開宣言

✅ まとめ一言

extern は「宣言」であり、
「他ファイルにある変数を見えるようにする(公開する)手段」でもある。
(by ChatGPT)

プレイヤー関係の処理をmain.cpp内のInit()関数からPlayer.cpp内に関数を作成して移動。
代わりに各関数をInit()内に配置。併せてPlayer.hもincludeする。

//Player.cpp
//-----------------------------------------------------------------------------
// インベーダーゲーム
// 氏 名:
//-----------------------------------------------------------------------------
#include <DxLib.h>
#include"main.h"
#include"Player.h"

//-----------------
// 変数の宣言
//-----------------
// プレイヤー
int playerImage;							// 自機の画像ハンドル番号
int playerPosX;								// 自機のX座標
int playerPosY;								// 自機のY座標
bool playerFlg;								// 自機の表示状態管理用フラグ(true:表示、false:非表示)


bool PlayerInit(void)
{
	// プレイヤー画像の読込み
	playerImage = LoadGraph("image/player.png");
	if (playerImage == -1)return false;

	//-----------------
	// 変数の初期化
	//-----------------
	// プレイヤー
	playerPosX = WINDOW_WID / 2 - PLAYER_WID / 2;		// ウィンドウの中央X座標
	playerPosY = WINDOW_HIG - PLAYER_HIG;
	playerFlg = true;

	return true;
}

void PlayerMove(void)
{
	// プレイヤーの移動
	if (playerFlg) {
		//右キーが押されたか
		if (CheckHitKey(KEY_INPUT_RIGHT) == 1) {
			playerPosX += PLAYER_MOVE_SPEED; //右に移動
		}
		//左キーが押されたか
		if (CheckHitKey(KEY_INPUT_LEFT) == 1) {
			playerPosX -= PLAYER_MOVE_SPEED; //左に移動
		}
		//左端のチェック
		if (playerPosX < 0)playerPosX = 0;
		//右端のチェック
		if (playerPosX > (WINDOW_WID - PLAYER_WID - 1))playerPosX = (WINDOW_WID - PLAYER_WID - 1);
	}
}

void PlayerDraw(void)
{
	// プレイヤーの描画
	if (playerFlg) {
		DrawGraph(playerPosX, playerPosY, playerImage, true);
	}

}
//Player.h
#pragma once

//------------------------------------------
//他のファイルでも参照が必要な変数の extern宣言
//------------------------------------------
extern int playerPosX;								// 自機のX座標
extern int playerPosY;								// 自機のY座標
extern bool playerFlg;								// 自機の表示状態管理用フラグ(true:表示、false:非表示)

//-------------------------------------------
//プロトタイプ宣言
//-------------------------------------------
bool PlayerInit(void);
void PlayerMove(void);
void PlayerDraw(void);

PlayerBullet.cpp、PlayerBullet.hを作成。自機の弾関連の処理を移行。

//PlayerBullet.cpp
//-----------------------------------------------------------------------------
// インベーダーゲーム
// 氏 名:
//-----------------------------------------------------------------------------
#include <DxLib.h>
#include"main.h"
#include"PlayerBullet.h"
#include"Player.h"

//-----------------
// 変数の宣言
//-----------------

// プレイヤー弾
int playerBulletImage;						// プレイヤー弾の画像ハンドル番号
int playerBulletPosX;						// プレイヤー弾のX座標
int playerBulletPosY;						// プレイヤー弾のY座標
bool playerBulletFlg;						// プレイヤー弾の発射状態管理用フラグ(true:表示、false:非表示)

bool PlayerBulletInit(void) {
	// プレイヤー弾の画像の読込み
	playerBulletImage = LoadGraph("image/playerBullet.png");
	if (playerBulletImage == -1)return false;

	// プレイヤー弾
	playerBulletPosX = playerBulletPosY = 0;
	playerBulletFlg = false;

}

void PlayerBulletShot(void) {
	if (playerBulletFlg == false) {
		//弾が未発射状態なので射撃可能
		if (CheckHitKey(KEY_INPUT_SPACE) == 1) {
			playerBulletPosX = (playerPosX + PLAYER_WID / 2) - (PLAYER_BULLET_WID / 2);
			playerBulletPosY = playerPosY - PLAYER_BULLET_HIG;
			playerBulletFlg = true;
		}
	}

}

void PlayerBulletMove(void) {
		if(playerBulletFlg) {
			//弾の移動処理
			playerBulletPosY -= PLAYER_BULLET_MOVE;
			if (playerBulletPosY < 0)playerBulletFlg = false;
	}
}
//PlayerBullet.h
#pragma once

//----------------------------------------------
//他のファイルでも参照が必要な変数の extern宣言
//----------------------------------------------
extern int playerBulletPosX;		// プレイヤー弾のX座標
extern int playerBulletPosY;		// プレイヤー弾のY座標
extern bool playerBulletFlg;		// プレイヤー弾の発射状態管理用フラグ(true:表示、false:非表示)


bool PlayerBulletInit(void);
void PlayerBulletShot(void);
void PlayerBulletMove(void);

とりあえず続きはまた次回。(現時点では動作しない)

コメント

タイトルとURLをコピーしました