実際は
以下「14歳からはじめるC言語わくわくゲームプログラミング教室 VS2013編」から引用したコードを載せます。(本を見ながらプログラムしました)gamemain.cppでマップ描画、主人公、モンスターの処理を行っています。上記のようなバグが出たのはドラゴンに炎を吐かせるようにプログラムしてから発生したのでおそらくgamemain.cppのInitStage関数、DrawDragonFire関数、DrawEnemy関数のいずれかにおかしいところがあるのかなーっと思い考えてみたのですが解決しません。すいませんが間違いを見つけていただけると嬉しいです。
main.cpp
#include"main.h"
//グローバル変数
//時間計測用変数
int g_lasttime = 0; //直前の計測時間
float g_frametime = 0; //1ループにかかった時間
int g_timerstart;
GameState g_gamestate;
int g_gametitling; //タイトルイメージ
int g_heroimg; //画像
float g_hx=0, g_hy=0; //座標
//ボタン
BOOL g_akey_prev; //直前のAボタンの状態
//フォント
int g_middlefont; //中サイズフォントハンドル
int g_largefont; //大サイズフォントハンドル
int WINAPI WinMain(HINSTANCE h1, HINSTANCE hP, LPSTR lpC, int nC){
//ウィンドウモードにする
ChangeWindowMode(TRUE);
//ウィンドウサイズを変更する
SetGraphMode(800, 600, 32);
//DXライブラリ初期化
if(DxLib_Init() == -1) return -1;
//画像を読み込み
if(LoadGameImage() == FALSE) return -1;
g_gametitling = LoadGraph("media\\smp1_title.png");
g_heroimg = LoadGraph("media\\smp1_chara01.png");
g_middlefont = CreateFontToHandle("メイリオ", 42, -1, DX_FONTTYPE_ANTIALIASING);
g_largefont = CreateFontToHandle("メイリオ", 90, -1, DX_FONTTYPE_ANTIALIASING);
SetDrawScreen(DX_SCREEN_BACK);
g_lasttime = GetNowCount()&INT_MAX; //現在時刻の記録
while(ProcessMessage() == 0 && CheckHitKey(KEY_INPUT_ESCAPE) == 0){
//1ループにかかった時刻を計測
int curtime = GetNowCount();
g_frametime = (float)(curtime - g_lasttime)/1000.0f;
g_lasttime = curtime;
ClearDrawScreen();
//画面描画関数に切り替え
switch(g_gamestate)
{
case GAME_TITLE:
DrawGameTitle();
break;
case GAME_MAIN:
DrawGameMain();
break;
case GAME_CLEAR:
DrawGameClear();
break;
case GAME_OVER:
DrawGameOver();
break;
default:
break;
}
ScreenFlip();
}
WaitKey();
DxLib_End();
return 0;
}
//タイトル画面描画
void DrawGameTitle(){
DrawBox(0, 0, 800, 600, GetColor(255, 255, 255), TRUE);
DrawGraph(0, 0, g_gametitling, TRUE);
//テキストを表示
DrawStringToHandle(100, 400, "Zキーでゲームスタート", GetColor(255, 0, 255), g_middlefont);
DrawStringToHandle(100, 460, "カーソルキーで上下左右に移動", GetColor(0, 0, 0), g_middlefont);
//キーチェックをして画面を切り替え
int key = GetJoypadInputState(DX_INPUT_KEY_PAD1);
if(IsAKeyTrigger(key) == TRUE) g_gamestate = GAME_MAIN;
InitStage();
}
//ゲーム本編描画
void DrawGameMain(){
GameMain();
}
void DrawGameClear(){
}
//ゲームオーバー画面描画
void DrawGameOver(){
//テキスト表示
DrawStringToHandle(100, 400, "ゲームオーバー", GetColor(255, 0, 0), g_largefont);
//5秒たったらタイトル画面へ
if(g_lasttime - g_timerstart >5000) g_gamestate = GAME_TITLE;
}
//キートリガー処理
BOOL IsAKeyTrigger(int key){
if(key & PAD_INPUT_A){
if(g_akey_prev == FALSE){
g_akey_prev = TRUE;
return TRUE;
}
}
else{
g_akey_prev = FALSE;
}
return FALSE;
}
#ifndef _MAIN_H_
#define _MAIN_H_
#include<DxLib.h>
#include"gamemain.h"
#include"loading.h"
//グローバル変数
//時間計測用変数
extern int g_lasttime; //直前の計測時間
extern float g_frametime; //1ループにかかった時間
extern int g_timerstart; //タイマー用変数
enum GameState{ //ゲーム状態
GAME_TITLE, GAME_MAIN,
GAME_CLEAR, GAME_OVER
};
extern GameState g_gamestate;
extern int g_gametitling; //タイトルイメージ
extern int g_heroimg; //画像
extern float g_hx, g_hy; //座標
//ボタン
extern BOOL g_akey_prev; //直前のAボタンの状態
//フォント
extern int g_middlefont; //中サイズフォントハンドル
extern int g_largefont; //大サイズフォントハンドル
//関数プロトタイプ宣言
void DrawGameTitle();
void DrawGameMain();
void DrawGameClear();
void DrawGameOver();
BOOL IsAKeyTrigger(int key);
#endif
#include "gamemain.h"
int g_mapdata[MAP_HEIGHT][MAP_WIDTH]={
//0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, //0
{ 1, 7, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0 ,4}, //1
{ 1, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 9}, //2
{ 1, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1}, //3
{ 1, 0, 1, 1, 1, 1, 0, 0, 1, 0, 3, 1, 0, 0, 0, 1}, //4
{ 1, 0, 1, 0, 0, 1, 0, 8, 1, 0, 0, 1, 0, 1, 0, 1}, //5
{ 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1}, //6
{ 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1}, //7
{ 1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1}, //8
{ 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1}, //9
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1}, //10
{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, //11
};
StageData g_stagedata;
//ステージ初期化
void InitStage(){
int enemy=0;
for(int y=0; y<MAP_HEIGHT; y++){
for(int x=0; x<MAP_WIDTH; x++){
int c = g_mapdata[y][x];
switch(c)
{
case MPITEM_HEROPOS:
g_stagedata.herox = x;
g_stagedata.heroy = y;
g_mapdata[y][x] = 0;
break;
case MPITEM_HMONSTER:
case MPITEM_VMONSTER:
case MPITEM_DRAGON:
g_stagedata.enemies[enemy].x=x;
g_stagedata.enemies[enemy].y=y;
g_stagedata.enemies[enemy].type=(MonsterType)c;
g_stagedata.enemies[enemy].living=TRUE;
g_stagedata.enemies[enemy].direction=-1;
g_mapdata[y][x]=0;
enemy++;
break;
default:
break;
}
}
}
//ドラゴンの炎のために予約
for(int i=0; i<=MAXENEMY; i++){
//ドラゴンを探す
if(g_stagedata.enemies[i].type == MT_DRAGON){
g_stagedata.enemies[i].fireidx = enemy;
g_stagedata.enemies[i].firetimer = 0;
enemy += FIREEXPAND;
}
}
}
void GameMain(){
//移動制限
g_stagedata.movecounter++;
g_stagedata.movecounter %= MOVERATE;
DrawMap();
DrawEnemy();
//自キャラ移動
int key =GetJoypadInputState(DX_INPUT_KEY_PAD1);
if(g_stagedata.movecounter==0){
int hx = g_stagedata.herox;
int hy = g_stagedata.heroy;
if(key&PAD_INPUT_UP) hy -= 1;
if(key&PAD_INPUT_DOWN) hy += 1;
if(key&PAD_INPUT_LEFT) hx -= 1;
if(key&PAD_INPUT_RIGHT) hx += 1;
//障害物チェック
if(g_mapdata[hy][hx]==MPITEM_NO){
g_stagedata.herox = hx;
g_stagedata.heroy = hy;
}
}
DrawGraph(g_stagedata.herox*IMG_CHIPSIZE,
g_stagedata.heroy*IMG_CHIPSIZE,
g_imghandles.mapitems[MPITEM_HEROPOS], TRUE);
//Zキーをチェックして画面を切り替え
if(IsAKeyTrigger(key) ==TRUE){
g_gamestate = GAME_OVER;
g_timerstart = g_lasttime; //タイマーセット
}
}
void DrawMap(){
for(int y=0;y<MAP_HEIGHT;y++){
for(int x=0;x<MAP_WIDTH;x++){
DrawGraph(x*IMG_CHIPSIZE, y*IMG_CHIPSIZE, g_imghandles.field, FALSE);
//マップアイテム描画
int c = g_mapdata[y][x];
if(c>0){
DrawGraph(x*IMG_CHIPSIZE, y*IMG_CHIPSIZE,
g_imghandles.mapitems[c], TRUE);
}
}
}
}
void DrawEnemy(){
for(int i=0; i<MAXENEMY; i++){
if(g_stagedata.enemies[i].living == FALSE)continue;
MonsterType c = g_stagedata.enemies[i].type;
if(g_stagedata.movecounter == 0){
int ex = g_stagedata.enemies[i].x;
int ey = g_stagedata.enemies[i].y;
//移動処理
if(c == MT_HOLI)ex += g_stagedata.enemies[i].direction;
if(c == MT_VERT)ey += g_stagedata.enemies[i].direction;
if(c == MT_DRAGON)DrawDragonFire(i);
if(g_mapdata[ey][ex] == MPITEM_NO){
g_stagedata.enemies[i].x = ex;
g_stagedata.enemies[i].y = ey;
}
else{
//方向反転
g_stagedata.enemies[i].direction *= -1;
}
//当たり判定
if((g_stagedata.enemies[i].x == g_stagedata.herox)&&
(g_stagedata.enemies[i].y == g_stagedata.heroy)){
g_gamestate = GAME_OVER;
g_timerstart = g_lasttime; //タイマーセット
}
}
DrawGraph(g_stagedata.enemies[i].x*IMG_CHIPSIZE,
g_stagedata.enemies[i].y*IMG_CHIPSIZE,
g_imghandles.mapitems[(int)c], TRUE);
}
}
void DrawDragonFire(int idx){
int t = g_stagedata.enemies[idx].firetimer;
int f = g_stagedata.enemies[idx].fireidx;
if(t < FIREEXPAND){
//炎を伸ばす
for(int i=0; i<FIREEXPAND; i++){
if(i <= t){
g_stagedata.enemies[f+i].living=TRUE;
g_stagedata.enemies[f+i].type=MT_FIRE;
g_stagedata.enemies[f+i].x=g_stagedata.enemies[idx].x-i-1;
g_stagedata.enemies[f+i].y=g_stagedata.enemies[idx].y;
}
else{
g_stagedata.enemies[f+i].living=FALSE;
}
}
}
else if(t < FIRESHRINK){
//炎を縮める
for(int i=0; i<FIREEXPAND; i++){
if(i <= (FIRESHRINK-t-1)){
g_stagedata.enemies[f+i].living=TRUE;
g_stagedata.enemies[f+i].type=MT_FIRE;
g_stagedata.enemies[f+i].x=g_stagedata.enemies[idx].x-i-1;
g_stagedata.enemies[f+i].y=g_stagedata.enemies[idx].y;
}
else{
g_stagedata.enemies[f+i].living=FALSE;
}
}
}
else{
for(int i=0; i<FIREEXPAND; i++){
g_stagedata.enemies[f+i].living=FALSE;
}
}
g_stagedata.enemies[idx].firetimer++;
g_stagedata.enemies[idx].firetimer %= FIRESTOP;
}
#ifndef _GAMEMAIN_H_
#define _GAMEMAIN_H_
#include <DxLib.h>
#include"main.h"
#define IMG_CHIPSIZE 50
#define MAP_WIDTH 16
#define MAP_HEIGHT 12
#define MOVERATE 15
#define MAXENEMY 20
#define FIREEXPAND 3
#define FIRESHRINK 6
#define FIRESTOP 12
extern int g_mapdata[MAP_HEIGHT][MAP_WIDTH];
enum MapItem{
MPITEM_NO, MPITEM_ROCK, MPITEM_HMONSTER, MPITEM_VMONSTER, MPITEM_DRAGON,
MPITEM_HEROPOS = 7, MPITEM_KEY, MPITEM_GOAL
};
enum MonsterType{
MT_HOLI=2, MT_VERT, MT_DRAGON, MT_FIRE
};
struct CharaData{
int x, y;
BOOL living;
MonsterType type;
int direction;
int fireidx;
int firetimer;
};
struct StageData{
int herox, heroy;
int movecounter;
CharaData enemies[MAXENEMY];
};
extern StageData g_stagedata;
void GameMain();
void DrawMap();
void InitStage();
void DrawEnemy();
void DrawDragonFire(int idx);
#endif
#include "loading.h"
ImageHandles g_imghandles;
BOOL LoadGameImage(){
g_imghandles.field = LoadGraph("media\\smp1_back.png");
if(g_imghandles.field == -1)return FALSE;
g_imghandles.mapitems[1] = LoadGraph("media\\smp1_rock.png");
if(g_imghandles.mapitems[1] == -1) return FALSE;
g_imghandles.mapitems[2] = LoadGraph("media\\smp1_chara02.png");
if(g_imghandles.mapitems[2] == -1) return FALSE;
g_imghandles.mapitems[3] = g_imghandles.mapitems[2];
g_imghandles.mapitems[4] = LoadGraph("media\\smp1_chara03.png");
if(g_imghandles.mapitems[4] == -1) return FALSE;
g_imghandles.mapitems[5] = LoadGraph("media\\smp1_chara04.png");
if(g_imghandles.mapitems[5] == -1) return FALSE;
g_imghandles.mapitems[7] = LoadGraph("media\\smp1_chara01.png");
if(g_imghandles.mapitems[7] == -1) return FALSE;
g_imghandles.mapitems[8] = LoadGraph("media\\smp1_key.png");
if(g_imghandles.mapitems[8] == -1) return FALSE;
g_imghandles.mapitems[9] = LoadGraph("media\\smp1_goal.png");
if(g_imghandles.mapitems[9] == -1) return FALSE;
return TRUE;
}