質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.39%
C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

DXライブラリ

DXライブラリとは、DirectXを使ったWindowsソフトの開発に必ず付いて回るDirectXやWindows関連のプログラムを使い易くまとめた形で利用できるようにしたC++言語用のゲームライブラリです。

Q&A

1回答

408閲覧

シューティングゲームで敵が奥からたくさん出てくるようにしたいです。※プログラミング初心者です

zyuuiti

総合スコア0

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

DXライブラリ

DXライブラリとは、DirectXを使ったWindowsソフトの開発に必ず付いて回るDirectXやWindows関連のプログラムを使い易くまとめた形で利用できるようにしたC++言語用のゲームライブラリです。

0グッド

0クリップ

投稿2024/08/29 03:37

実現したいこと

シューティングゲームで敵が奥からたくさん出てくるようにしたいです

発生している問題・分からないこと

敵を奥のほうからたくさん出てくるようにプログラミングしてみたのですが、現状敵が描画されていません。

該当のソースコード

#include"DxLib.h" //定数 const int WIDTH = 1900; //画面の幅 const int HEIGHT = 1120; //画面の高さ const int cannonstartx1 = 750; //大砲の初期のx1座標 const int cannonstarty1 = 920; //大砲の初期のy1座標 const int cannonstartx2 = 950; //大砲の初期のx2座標 const int cannonstarty2 = 1120; //大砲の初期のy2座標 const int speed = 10; //大砲の移動スピード const int cannonwidth = 200; //大砲の幅 const int ufospeed = 2; //敵のスピード const int ballspeed = 16; //弾速 const int ufowidth = 150; //ufoの幅 const int ufoheight = 100; //ufoの高さ double frameCount = 0; int lastTime = 0, currentTime = 0; double deltaTime = 0; //敵用構造体 typedef struct enemyary { int ufox1; int ufox2; int ufoy2; int ufoy1; bool exsist; }enemyary; int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { //----------------------------------// //基本設定 //----------------------------------// ChangeWindowMode(TRUE); //ウィンドウモードにする DxLib_Init(); //ライブラリを初期化 Initialise SetMainWindowText("花火シューティング"); SetDrawScreen(DX_SCREEN_BACK); //背景をセットする SetGraphMode(WIDTH, HEIGHT, 32); //ウィンドウのサイズとカラーモードを決める //ライブラリ初期化でエラー起きたら終了 if (DxLib_Init() == -1) { return -1; } //ゲームの進行に関する変数 enum { TITLE, PLAY, OVER }; //シーンのセレクトナンバー int selectScene = TITLE; //タイマー int timer = 0; //乱数の初期化 SRand(0); //変数 int cannonx2 = cannonstartx2; int cannony2 = cannonstarty2; int cannonx1 = cannonstartx1; int cannony1 = cannonstarty1; int cannon; int night; bool flag1 = false; int ballx1 = 0, bally1 = 0; int ballx2 = 0, bally2 = 0; int shot; int ufo; int fireflower; int startScreenImage; enemyary enemy[100]; //構造体配列 int i; for (i = 0; i < 100; i++) { enemy[i].exsist = true; //出現フラグを立てる enemy[i].ufox1 = GetRand(1750); //x1の初期座標 enemy[i].ufox2 = enemy[i].ufox1 + ufowidth; //x2の初期座標 enemy[i].ufoy1 = 0; //y1の初期座標 enemy[i].ufoy2 = enemy[i].ufoy1 + ufoheight; //y2の初期座標 } while (ScreenFlip() == 0 && ProcessMessage() == 0 && ClearDrawScreen() == 0) { currentTime = GetNowCount(); //ゲームフレームカウント double deltaTime = (currentTime - lastTime) / 1000.0; //ゲームフレームカウント currentTime = lastTime - GetNowCount(); frameCount += deltaTime; ClearDrawScreen(); timer++; switch (selectScene) { case TITLE: //背景画像を描画 startScreenImage = LoadGraph("img/hanabi_sky.png"); DrawExtendGraph(0, 0, WIDTH, HEIGHT, startScreenImage, TRUE); //タイトル画面を表示 SetFontSize(100); DrawString(WIDTH / 2 - 150 / 2 * 12 / 2, HEIGHT / 3, "花火シューティング", GetColor(255, 69, 0)); //スタートボタンを点滅させる if (timer % 60 < 30) { SetFontSize(50); DrawString(WIDTH / 2 - 50 / 2 * 21 / 2, HEIGHT * 2 / 3, "Press ENTER to start.", GetColor(238, 130, 238)); } //スペースキーを押してゲームスタート if (CheckHitKey(KEY_INPUT_RETURN) == 1) { selectScene = PLAY; } break; case PLAY: //背景画像を描画 night = LoadGraph("img/yozora.png"); DrawExtendGraph(0, 0, WIDTH, HEIGHT, night, TRUE); //大砲を描画 cannon = LoadGraph("img/taihou.png"); DrawExtendGraph(cannonx1, cannony1, cannonx2, cannony2, cannon, TRUE); //大砲を移動 if (CheckHitKey(KEY_INPUT_RIGHT) == 1) { cannonx1 = cannonx1 + speed; cannonx2 = cannonx2 + speed; if (cannonx2 > WIDTH) { cannonx2 = WIDTH; cannonx1 = WIDTH - cannonwidth; } } if (CheckHitKey(KEY_INPUT_LEFT) == 1) { cannonx1 = cannonx1 - speed; cannonx2 = cannonx2 - speed; if (cannonx1 < 0) { cannonx1 = 0; cannonx2 = cannonwidth; } } //花火玉を発射 if (CheckHitKey(KEY_INPUT_SPACE)) { if (!flag1) { flag1 = true; ballx1 = cannonx1 + 75; bally1 = cannony1; ballx2 = cannonx2 - 75; bally2 = cannony1 + 50; } } //花火玉の移動 if (flag1) { bally1 -= ballspeed; bally2 -= ballspeed; if (bally1 < 0) flag1 = false; } //花火玉を描画 shot = LoadGraph("img/hanabidama.png"); if (flag1) { DrawExtendGraph(ballx1, bally1, ballx2, bally2, shot, TRUE); } //敵の移動 enemy[i].ufoy1 += ufospeed; enemy[i].ufoy2 += ufospeed; //ゲームオーバー条件 if (enemy[i].ufoy1 > cannony1) { selectScene = OVER; break; } //敵の描画 if ((int)deltaTime % 5 == 0) //5フレーム毎に敵が出現 { ufo = LoadGraph("img/ufo.png"); DrawExtendGraph(enemy[i].ufox1, enemy[i].ufoy1, enemy[i].ufox2, enemy[i].ufoy2, ufo, TRUE); } //防衛線を描画 DrawLine(0, cannony1, WIDTH, cannony1, GetColor(255, 0, 0), TRUE); //敵と玉の当たり判定 break; case OVER: SetFontSize(90); DrawString(WIDTH / 3 + 100, HEIGHT / 3, "GAME OVER", GetColor(255, 0, 0)); break; } ScreenFlip(); lastTime = currentTime; } //DXライブラリ使用の終了 DxLib_End(); return 0; }

試したこと・調べたこと

  • teratailやGoogle等で検索した
  • ソースコードを自分なりに変更した
  • 知人に聞いた
  • その他
上記の詳細・結果

少し前までは敵が1体だけ描画されていたのですが敵をたくさん出そうとコードを修正したら敵が描画されなくなってしまいました

補足

特になし

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

コードのここの部分にて…

C++

1//敵の描画 2if ((int)deltaTime % 5 == 0) //5フレーム毎に敵が出現 3{ 4 ufo = LoadGraph("img/ufo.png"); 5 DrawExtendGraph(enemy[i].ufox1, enemy[i].ufoy1, enemy[i].ufox2, enemy[i].ufoy2, ufo, TRUE); 6}

enemy[i] というデータを用いているわけだが,そしたらこの i の値っていうのは何なのか?(:本来どうあるべきなのか?)

ざっくりとこの質問ページ内を i で検索してみた感じ,
この変数 i はループ内では全く更新されてもいないように見えるので, i の値は常に 100 になっているのではないでしょうか.
(それだと enemu[100] は範囲外参照になりますね)

…っていうあたりを確認されると良いのではないかと見えます.

LoadGraph() なんてのをループ内で毎回やっている点もまずそうに思うが,それはまた別の話.


追記:

このコードだと「出現」と「描画」がなんかごっちゃになってるよね.
これだと 「(int)deltaTime % 5 == 0 であるときしか描画しない」みたいなことになってる.

5フレーム毎に行う事とは「(プログラムが管理しているデータの上で)敵を増やすこと」であり,
各時刻における敵の「描画」は何フレーム目だろうがとにかく必ず行うんだよね?

極端な話,一切「描画」しなくてもゲームの処理自体は動く(言わば 目をつぶってゲームプレイしているような状態)のだから,
もうちょっと切り分けて考えると良いのではないかな.

投稿2024/08/29 04:06

編集2024/08/29 07:42
fana

総合スコア11931

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

fana

2024/08/29 04:17 編集

enemyary 構造体の exsist なるメンバも実際には何も使われてない(その値をチェックするような処理が無い)様子だし, なんというか全体的に 単に「コード書きかけだから → 当然,最終的な動作が実現されていない」っていうだけの話にしか見えない. 少なくとも「複数の敵がゲームに登場する」の実現に関する実装を最後まで一通り行い,その後で 「この実装だと,ここがこういう形に動いていくから,結果として複数の敵が表示されるハズなのだが,表示されない.何故なのか?」 とかなんとか問うのがあるべき順序なのでは. 「この実装だと,ここがこういう形に動いていくから,結果として複数の敵が表示されるハズなのだが…」っていう部分がまともに存在しないならば,所望の動作が観測できるわけないのだし,その段階で「何故?」って問うことにも意味は無いと思うよ.
fana

2024/08/29 04:34 編集

> enemyary enemy[100]; これはとりあえず 敵のデータを最大で100体分だけ保持できる ようにしているんだよね? で,それはそれとして > //5フレーム毎に敵が出現 とかいう話なので,いきなり100体の敵がいる状態からゲームが始まるのではなくて ゲームプレイ中に敵が増えたり(減ったりも)するわけだよね. ということは少なくとも 「今現在出現している(=描画すべき)敵とは どれどれなのか?」という事柄の判断ができないと,まともな描画ができるわけないよね. (今現在,何体描画すればよいのか? それぞれどこに描画すれば良いのか?) 例えばある瞬間に敵が5体いる状態になっているとして,その5体分の情報ってのは 100個のデータ enemy[100] の中のどれどれなのかな? 常に enemu[0]~enemy[4] の5つだとかいう話なのかな? それともその時々で enemy[3], [7], [21], [66], [99] の5つであるみたいな状況になるのかな? その他? どんなやり方が正解だとか言う話は無いので, とにかく何らかの理路整然とした「俺はこういう形に情報を管理するぜ!」っていう話をきっちりと用意する(定める)ところが必要なんじゃないかな? そういうのが定まっているならば,質問に際してはそこを説明する必要があるんじゃないかな?(他者はその辺のことを全く知らないのだから)
zyuuiti

2024/08/29 04:39

なるほど。参考になります。もうちょっと自分で頑張ってみます
fana

2024/08/29 04:52

> 敵のデータを最大で100体分だけ保持できる 最初はもっと少なく 3 とか 5 とかでやってみるのが良いかも. プログラムの動作として 【「データ保持可能最大数を超えてしまって大変なことに!」みたいな動きにならないこと】 みたいなのも見ておく必要があるならば,だけど.
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.39%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問