STG 講座その 3 まずは実行してみよう! ・タイトル画面が出るようになりました。 ・ボスの HP を 0 にすると画面が切り替わりました。 ・今回はこのようなシーン管理についてを説明していきます。 シーンの代わる仕組み ・シーンの切り替えでは主に switch 文を使います。 現在のシーンがどこであるかを保存する scene 変数を毎回参照し、そのシーンに 合った計算処理と描画処理を実行させます。 ソースコード <main.cpp> #include #include #include #include #include "DxLib.h" "game.h" "scenemanager.h" "title.h" "clear.h" //game.hを読み込む //scenemanager.hを読み込む int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) { ChangeWindowMode(TRUE), SetGraphMode(800, 600, 32), DxLib_Init(), SetDrawScreen(DX_SCREEN_BACK); //今回はウィンドウモード、800x600のお大きさで Title_Initialize(); Game_Initialize(); Clear_Initialize(); //タイトルの初期化処理 //ゲームの初期化処理 //クリア画面の初期化処理 while (ScreenFlip() == 0 && ProcessMessage() == 0 && ClearDrawScreen() == 0 && CheckHitKey(KEY_INPUT_ESCAPE) != 1) { switch (NowScene()){ //現在のシーンによって動作を変える case title: Title_Update(); Title_Draw(); break; case game: //背景だけ先に描画 DrawBackGround(); Game_Update(); Game_Draw(); break; //新しく作った自作関数 //計算処理 //描画処理 case clear: Clear_Update(); Clear_Draw(); break; } } Title_Finalize(); //タイトルの終了処理 Game_Finalize(); //ゲームの終了処理 Clear_Finalize(); //クリア画面の終了処理 /////////////////////////////////////////////////////// DxLib_End(); return 0; } <scenemanager.h> #pragma once enum scene{ title, game, clear }; //シーン管理のための列挙型作成 scene NowScene(); void ChangeScene(scene NextScene); <scenemanager.cpp> #include "DxLib.h" #include "scenemanager.h" enum scene eScene = title; //列挙型の宣言 scene NowScene() { return eScene; } //現在のシーンを教えてくれる関数 void ChangeScene(scene NextScene) { eScene = NextScene; } //次のシーンに移る関数 <title.h> #pragma once void Title_Initialize(); void Title_Update(); void Title_Draw(); void Title_Finalize(); <title.cpp> #include "DxLib.h" #include "scenemanager.h" #include "game.h" static int title_image; void Title_Initialize() { title_image = LoadGraph("title.png"); } void Title_Update() { if (CheckHitKey(KEY_INPUT_Z)) //Zキーが押されたらゲームシーンに移る { Game_Initialize(); //ゲームの初期化処理もする(重要) ChangeScene(game); } } void Title_Draw() { DrawGraph(0, 0, title_image, 0); } void Title_Finalize() { DeleteGraph(title_image); } <game.h> #pragma once //二重インクルード防止 void Game_Initialize(); void Game_Update(); void Game_Draw(); void Game_Finalize(); void DrawBackGround(); <game.cpp> #include "DxLib.h" #include "game.h" #include "scenemanager.h" #define PI 3.1415926535897932384626433832795f #define PLAYER_SHOT_MAX 200 static struct{ double x, y; int r; float angle; //int image; int shot_cnt; int score; //プレイヤー情報の構造体 //プレイヤーの座標 //プレイヤーの半径(今回の自機は円だから) //プレイヤーの向いている方向 //プレイヤーの画像(今回は使用しません) //shotボタンが押されてから何カウント経ったか //プレイヤーの入手した得点 }Player; static struct{ int hp; double x, y; int r; float angle; //int image; //敵情報の構造体 //敵の体力 //敵の座標 //敵の半径 //敵の向いている方向 //敵の画像 }Enemy; static struct{ int image; int one_y, two_y; //背景情報の構造体 //背景の画像 //2つの背景の座標(詳しくは計算部で) }Back; int int int int int black = GetColor(0, 0, 0); blue = GetColor(0, 0, 255); red = GetColor(255, 0, 0); green = GetColor(0, 255, 0); yellow = GetColor(255, 255, 0); typedef struct { int flag, cnt, knd; //int Image; //色の定数化 //自機の弾情報の構造体 //弾が生きているか、弾が出て何秒か、弾の種類、の変数 //弾の画像 double x, y, angle, spd, angle_pls; //弾の座標、方向、速度、角速度 int r; //弾の半径 }Player_sDATA; Player_sDATA Player_Shot[PLAYER_SHOT_MAX]; //自機弾の生成(宣言) //プロトタイプ宣言 void Player_Shotupdate(); void Enter_Shot(); void Player_Shotdraw(); void Game_Initialize() { Back.image = LoadGraph("bg.png"); Back.one_y = 0; Back.two_y = Back.one_y - 600; Player.x = 400, Player.y = 500, Player.r = 10; Enemy.x = 400, Enemy.y = 100, Enemy.r = 50; //背景画像の読み込み //背景の初期位置 //自分の座標と半径 //障害物の座標と半径 Player.score = 0; Enemy.hp = 100; for (int i = 0; i < PLAYER_SHOT_MAX; i++) Player_Shot[i].flag = 0; } void Game_Update() { //<キー入力> if (CheckHitKey(KEY_INPUT_RIGHT) == 1) Player.x += 5; if (CheckHitKey(KEY_INPUT_LEFT) == 1) Player.x -= 5; if (CheckHitKey(KEY_INPUT_DOWN) == 1) Player.y += 5; if (CheckHitKey(KEY_INPUT_UP) == 1) Player.y -= 5; //<画面外へ行くのを防止> if (Player.x < 0) Player.x = 0; if (Player.x > 800) Player.x = 800; if (Player.y < 0) Player.y = 0; if (Player.y > 600) Player.y = 600; //<背景のスクロール> Back.one_y = (Back.one_y + 5) % 600; Back.two_y = Back.one_y - 600; //<弾発射> Enter_Shot(); Player_Shotupdate(); //弾の初期化処理(前回忘れてました) if (Enemy.hp <= 0) ChangeScene(clear); } void Game_Draw() { //<描画> DrawCircle((int)Enemy.x, (int)Enemy.y, Enemy.r, red, 1); DrawCircle((int)Player.x, (int)Player.y, Player.r, blue, 1); Player_Shotdraw(); DrawFormatString(10, 10, black, "HP = %d", Enemy.hp); DrawFormatString(10, 30, black, "SCORE %d", Player.score); } void Game_Finalize() { DeleteGraph(Back.image); } //背景画像情報の開放 void DrawBackGround() { DrawGraph(0, Back.one_y, Back.image, 0); DrawGraph(0, Back.two_y, Back.image, 0); } ////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////// int atarihantei(int A_x, int A_y, int A_r, int B_x, int B_y, int B_r)//円と円の当たり判定 { if (((A_x - B_x)*(A_x - B_x)) + ((A_y - B_y)*(A_y - B_y)) < (A_r + B_r)*(A_r + B_r)) return 1; //当たってたら1を返し else return 0; //当たってなかったら0を返す } int search_cshot() //弾の配列のうち使われてないのを検索 { for (int i = 0; i < PLAYER_SHOT_MAX; i++) { if (Player_Shot[i].flag == 0) return i; //flagが0(使われていない)のを見つけたら教える } return -1; //全ての弾が生きている(使われている) } void Player_Shotpattern() { int k; if ((k = search_cshot()) != -1) { Player_Shot[k].flag = 1; Player_Shot[k].cnt = 0; Player_Shot[k].spd = 5; Player_Shot[k].angle = -(PI / 2); //弾の前処理 //これから使う弾の初期化 //-90度→鉛直上向き Player_Shot[k].x = Player.x; Player_Shot[k].y = Player.y - 5; Player_Shot[k].r = 5; } } void Enter_Shot() { if (CheckHitKey(KEY_INPUT_Z) == 1) { Player.shot_cnt++; if (Player.shot_cnt % 15 == 1) Player_Shotpattern(); } else Player.shot_cnt = 0; } //弾の発射条件等 void Player_Shotupdate() { for (int i = 0; i < PLAYER_SHOT_MAX; i++) { //弾の軌道等 //Zを押してる間これが増加 //15フレームごとに //弾を生成 //Zが離されたらカウントが0になる if (Player_Shot[i].flag == 1) { Player_Shot[i].cnt++; Player_Shot[i].x += Player_Shot[i].spd * cos(Player_Shot[i].angle); Player_Shot[i].y += Player_Shot[i].spd * sin(Player_Shot[i].angle); //決められた値ずつXとYに加算していく //当たり判定 if (Player_Shot[i].y < 0) //画面外に出たら弾を消す Player_Shot[i].flag = 0; if (atarihantei((int)Player_Shot[i].x, (int)Player_Shot[i].y, Player_Shot[i].r, (int)Enemy.x, (int)Enemy.y, Enemy.r) == 1) //弾が敵に当たっていたら { Player_Shot[i].flag = 0; //弾を消して、 Enemy.hp--; //敵のHPを減らして、 Player.score += 50; //プレイヤーのスコアを増やして、 DrawFormatString((int)Enemy.x - 100, (int)Enemy.y - 10, black, "いたい "); //敵に「いたい」と喋らせる } } } } void Player_Shotdraw() //弾の描画 { for (int i = 0; i < PLAYER_SHOT_MAX; i++) { if (Player_Shot[i].flag > 0) //弾が生きている時だけ描画 { DrawCircle((int)Player_Shot[i].x, (int)Player_Shot[i].y, Player_Shot[i].r, green, 1); DrawFormatString((int)Player_Shot[i].x + 50, (int)Player_Shot[i].y, GetColor(0, 0, 0), "No.%d", i);//デバッグ用 } } } <clear.h> #pragma once void Clear_Initialize(); void Clear_Update(); void Clear_Draw(); void Clear_Finalize(); <clear.cpp> #include "DxLib.h" #include "clear.h" #include "scenemanager.h" static int clear_image; void Clear_Initialize() { clear_image = LoadGraph("clear.png"); } void Clear_Update() { if (CheckHitKey(KEY_INPUT_X)) ChangeScene(title); } void Clear_Draw() { DrawGraph(0, 0, clear_image, 0); } void Clear_Finalize() { DeleteGraph(clear_image); }
© Copyright 2024 ExpyDoc