STG 講座その 3

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);
}