ゲーム制作において、自機から弾を発射する処理は基本中の基本です。
しかし、ただ弾を出すだけではなく「一定の間隔で連射する」「大量の弾を効率よく管理する」となると、初心者の方は壁にぶつかりがちです。
実は、C++での連射処理は、単純なループではなく「タイマー制御」と「構造体配列のフラグ管理」をマスターすることで、プロのような滑らかな動作が実現できます。
DirectXやDxLib環境でも共通して使える、汎用的なロジックを身につけましょう。
この記事では、単なるコードの紹介にとどまらず、なぜその計算が必要なのかという仕組みの部分から、コピペで即導入できるサンプルコードまで詳しく解説します。
- PCの性能に依存しない正確な連射タイマーの実装法
- 100発以上の弾をスムーズに処理する「フラグ管理」の秘訣
- DirectX/DxLib両対応の弾移動・描画ロジック
- ゲームが重くならないためのメモリ最適化の基礎知識

Unity入門の森を見る 初心者歓迎!動画×プロジェクト一式で本格ゲーム制作を学べる
あなたのオリジナルゲーム、今年こそ完成させませんか?
RPG・アクション・ホラー…Unityで本格ゲームを作りたい人のための学習サイトです。
実際に完成するゲームを題材に、
ソースコード・素材・プロジェクト一式をすべて公開。
仕事や学校の合間の1〜2時間でも、
「写経→改造」で自分のゲームまで作りきれる環境です。
なぜ「タイマー」と「配列管理」が必要なのか?

初心者が陥りやすいミスは、キー入力を検知したフレームでそのまま弾を生成してしまうことです。
これでは1秒間に60発(60FPSの場合)もの弾が出てしまい、ゲームバランスが崩れるだけでなく、処理負荷も急増します。
自然な連射を実現するには、以下の2つの概念を組み合わせるのが正解です。
1. 発射インターバルの制御(タイマー)
「前回の発射から何フレーム経過したか」をカウントする変数を用意します。
設定したインターバル(例:10フレーム)に達するまでは次の弾を出さないように制御することで、リズミカルな連射が可能になります。
これにより、マシンスペックに関わらず一定の連射速度を保てます。
2. オブジェクトプーリング(配列の再利用)
弾が出るたびに新しくメモリを確保(new)して、消えるたびに解放(delete)するのは非常に効率が悪いです。
あらかじめ「弾の最大数(例:100個)」を配列として確保しておき、「有効フラグ(active)」を切り替えることで使い回す手法が、ゲーム開発のスタンダードです。
Unity入門の森を見る 初心者歓迎!動画×プロジェクト一式で本格ゲーム制作を学べる
DirectX/標準C++による実践的な連射実装

まずは、どの環境でも利用できる標準的なC++の構造体とロジックを見ていきましょう。
ここでは「弾のデータ管理」に焦点を当てます。
ステップ1:弾を管理する構造体を定義する
弾一つひとつが持つべき情報(座標、速度、生存状態)をまとめます。
bool activeを持つのがポイントです。
|
1 2 3 4 5 6 7 8 9 10 11 |
struct Bullet { float x, y; // 座標 float vx, vy; // 速度(ベクトル) bool active; // 画面上に存在しているか }; const int MAX_BULLETS = 100; // 同時に出せる最大数 Bullet bullets[MAX_BULLETS]; // 配列で一括管理 int fireTimer = 0; // 発射間隔を測るカウンター const int FIRE_INTERVAL = 12; // 何フレームごとに発射するか |
ステップ2:弾の「有効化」と「移動」の分離
弾を発射する処理(Fire)と、出ている弾を動かす処理(Update)を分けます。
これにより、メインループがスッキリし、拡張性が高まります。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
// 弾を発射する関数 void FireBullet(float startX, float startY) { fireTimer++; if (fireTimer < FIRE_INTERVAL) return; // インターバル中なら何もしない for (int i = 0; i < MAX_BULLETS; i++) { if (!bullets[i].active) { // 空いている(active=false)の弾を探す bullets[i].x = startX; bullets[i].y = startY; bullets[i].vy = -7.0f; // 上方向に進む bullets[i].active = true; // ここで「有効」にする fireTimer = 0; // タイマーリセット break; } } } // 弾を更新する関数 void UpdateBullets() { for (int i = 0; i < MAX_BULLETS; i++) { if (bullets[i].active) { bullets[i].y += bullets[i].vy; // 移動 // 画面外(上端)に出たら無効化して再利用可能にする if (bullets[i].y < -20) bullets[i].active = false; } } } |
Unity入門の森を見る 初心者歓迎!動画×プロジェクト一式で本格ゲーム制作を学べる
DxLib環境でのビジュアル実装例

ライブラリとしてDxLibを使用する場合、入力検知と描画処理をメインループに組み込みます。
マウスや特定のキーを押し続けている間の挙動を確認しましょう。
実装手順:描画ループへの組み込み
DxLibのDrawCircleなどを使って、activeがtrueの弾だけを画面に表示させます。
ループ内で常に「弾の状態を確認して描画する」という流れを作ります。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
#include "DxLib.h" // (ここに前述のBullet構造体とInit関数を記述) int WINAPI WinMain(...) { if (DxLib_Init() == -1) return -1; SetDrawScreen(DX_SCREEN_BACK); while (ProcessMessage() == 0 && ClearDrawScreen() == 0) { // Zキーが押されている間、FireBulletを呼び出し続ける if (CheckHitKey(KEY_INPUT_Z)) { FireBullet(playerX, playerY); } UpdateBullets(); // 移動と画面外判定 // 描画処理 for (int i = 0; i < MAX_BULLETS; i++) { if (bullets[i].active) { DrawCircle(bullets[i].x, bullets[i].y, 5, GetColor(255, 255, 0), TRUE); } } ScreenFlip(); } DxLib_End(); return 0; } |
Unity入門の森を見る 初心者歓迎!動画×プロジェクト一式で本格ゲーム制作を学べる
連射システムでよくある「バグ」と解決策5選

コードを書いても思い通りに動かない場合、大抵は以下の5つのいずれかに原因があります。
特にメモリ関連のミスはゲームの強制終了を招くため注意が必要です。
1. 弾が消えずに新しい弾が出なくなる
画面外に出た時の判定が漏れているか、座標の条件が間違っているケースです。bullets[i].active = false;が確実に実行されるか、ログを出して確認しましょう。
2. 1フレームで全弾(100発など)が同時発射される
発射時のループ内でbreak;を忘れていませんか?
breakがないと、一回の発射処理で配列内の空いている弾をすべて有効化してしまいます。
3. PCによって連射速度が変わってしまう
これはFPS(フレームレート)を固定していない、あるいは時間(デルタタイム)による計算を行っていない場合に起こります。
垂直同期(ScreenFlip等)を有効にするか、時間ベースのタイマーを検討しましょう。
4. 配列の範囲外アクセスによるクラッシュ
MAX_BULLETSを超えてループを回したり、インデックス計算を間違えると致命的なエラーになります。
必ず定数を使ってループの回数を制限してください。
5. 初期化忘れによる「弾の散乱」
ゲーム開始時にactive = falseに初期化していないと、ゴミデータが入った状態で弾が存在していると判定され、画面のあちこちに消えない弾が表示されることがあります。
Unity入門の森を見る 初心者歓迎!動画×プロジェクト一式で本格ゲーム制作を学べる
実用的な連射システムへの3ステップ

- STEP1構造体と配列の準備(所要1時間)
まずは描画は後回しで、100個の弾データをメモリ上に確保し、正しく初期化する処理を作ります。
- STEP2タイマーによる発射制御(所要1時間)
キーを押しっぱなしにしても、意図した間隔(0.2秒に1回など)で発射ログが出るように調整します。
- STEP3画面外判定とリサイクル(所要2時間)
弾が移動し、画面から消えた瞬間に配列の枠が空き、再び発射可能になる「循環システム」を完成させます。
合計4時間ほど集中して取り組めば、市販のシューティングゲームと同じ基盤の連射システムが完成します。
一度作れば、弾の形を変えたり、攻撃パターンを増やすのも簡単です。
あなたのオリジナルゲーム、今年こそ完成させませんか?
RPG・アクション・ホラー…Unityで本格ゲームを作りたい人のための学習サイトです。
実際に完成するゲームを題材に、
ソースコード・素材・プロジェクト一式をすべて公開。
仕事や学校の合間の1〜2時間でも、
「写経→改造」で自分のゲームまで作りきれる環境です。
まとめ:滑らかな連射がゲームの質を変える
弾の連射処理は、単に画像を表示させることではなく、「時間管理」と「メモリ管理」の組み合わせです。
この考え方は、敵キャラクターの生成やエフェクト(パーティクル)の表示など、あらゆるゲームプログラムに応用できます。
- タイマー制御:フレーム数を数えて発射頻度を一定にする。
- アクティブフラグ:配列の各要素に「使用中か」の状態を持たせる。
- リサイクル管理:画面外でフラグをOFFにし、メモリを節約する。
- 適切なインターバル:ゲーム性に合わせてFPSベースで調整する。
弾がスムーズに出るようになれば、ゲームの爽快感は一気に高まります。
まずは今回紹介した基本コードをあなたのプロジェクトにコピーして、数値を変えながら自分好みの「撃ち心地」を探してみてください。
次は、発射した弾を「敵に向けて自動で追尾させる」AIの実装に挑戦してみるのがおすすめです!
Unity入門の森を見る 初心者歓迎!動画×プロジェクト一式で本格ゲーム制作を学べる



コメント