ご無沙汰しております、アメヒルネです。
無事春休みを迎えられそうなので、こうしてまたこちらに顔を出すことができそうです。
さて、今回はDXライブラリを用いたゲーム開発の最中に発生したバグに関する質問です。
以下に簡潔に内容を示します。
[hr]
概要
・これは、クォータービューを表示・カメラの視点を移動させるプログラムである
・外部ファイル(CSV形式)から、MAP_W×MAP_Hサイズのマップデータを読み込む
内容は、「0:移動不可能領域」「1:移動可能領域」で表す
・十字キーで縦横に視点を移動させる。Xキーを押している間は、視点を二倍速移動させる。
バグの内容
・計算上では通るべきif文が通らない(縦、横への移動が不可能。斜め移動のみ可能)
・printfDX関数をif文の中に挿入するとバグが改善される(何故?)
・時々、カメラの視点が急にワープする(頻発するが条件が不明。再現性なし?)
開発環境
・VC++2008EE
・DXライブラリ
ご教授いただきたいこと
・[メイン]バグの原因は何か?なぜprintfDXがif文に作用しているのか?
・[サブ]コーディング、変数の命名規則など、開発上のアドバイス
ソースコード
map.h
► スポイラーを表示
コード:
#pragma once
#include "GV.h"
class Map{
static const int MAP_H = 30;
static const int MAP_W = 30;
static const int TILE_H = 50;
static const int TILE_W = 100;
int _x, _y;
int _backCnt;
int _imgTile;
int _imgBack[8];
int _tiles[MAP_W][MAP_H];
public:
Map();
~Map();
void calc();
void draw();
int main();
private:
int screenToWorldX(int x,int y);
int screenToWorldY(int x,int y);
void loadTiles(const char *filename);
bool checkTiles(int x,int y);
};
map.cpp
► スポイラーを表示
コード:
#include "map.h"
#include "pad.h"
#include "toast.h"
#include <math.h>
Map::Map(){
_imgTile = LoadGraph( "dat/img/tile.png" );
_x = 0;
_y = 0;
_backCnt = 0;
loadTiles( "dat/maps/0.csv" );
}
Map::~Map(){
DeleteGraph( _imgTile );
}
int Map::screenToWorldX(int x,int y){
return (int)floor((float)x/TILE_W+(float)_y/TILE_H);
}
int Map::screenToWorldY(int x,int y){
return (int)floor((float)-x/TILE_W+(float)_y/TILE_H);
}
// マップデータをダウンロードする関数
void Map::loadTiles(const char *filename){
int x, y, input[64];
char inputc[64];
int fp = FileRead_open( filename );
if( fp==NULL ){
Toast::getIns()->regist(4);
return;
}
x = y = 0;
while(true){
for(int i=0;i<128;i++){
inputc[i]=input[i]=FileRead_getc(fp); // 1文字取得する
if(inputc[i]=='/'){ // スラッシュがあれば
while(FileRead_getc(fp)!='\n'); // 改行までループ
i=-1; // カウンタを最初に戻して
continue;
}
if(input[i]==',' || input[i]=='\n'){ // カンマか改行なら
inputc[i]='\0'; // そこまでを文字列とし
break;
}
if(input[i]==EOF){ // ファイルの終わりなら
FileRead_close( fp ); // ファイルポインタを閉じて
return; // 終了
}
}
_tiles[x][y] = atoi(inputc);
x++;
if( x>=MAP_W ){
x = 0;
y++;
}
if( y>=MAP_H ){
break;
}
}
FileRead_close( fp );
}
// 指定した地点が移動可能範囲か調べる
bool Map::checkTiles(int x, int y){
int cx, cy;
cx = screenToWorldX( x, y );
cy = screenToWorldY( x, y );
if( cx<0 || cx>=MAP_W ) return false;
if( cy<0 || cy>=MAP_H ) return false;
if( _tiles[cx][cy]==0 ) return false;
return true;
}
void Map::calc(){
int vx, vy;
for(int i=0;i<(Pad::getIns()->get(ePad::cancel)>0?2:1);i++){
if( Pad::getIns()->get(ePad::up)>0 ) vy = -2;
if( Pad::getIns()->get(ePad::down)>0 ) vy = 2;
if( Pad::getIns()->get(ePad::left)>0 ){
vx = -2;
if( Pad::getIns()->get(ePad::up)>0 ) vy = -1;
if( Pad::getIns()->get(ePad::down)>0 ) vy = 1;
}
if( Pad::getIns()->get(ePad::right)>0 ){
vx = 2;
if( Pad::getIns()->get(ePad::up)>0 ) vy = -1;
if( Pad::getIns()->get(ePad::down)>0 ) vy = 1;
}
_x += vx;
_y += vy;
//以下、問題だと思われる部分-------------------------------------------------------------------------------
// 進めなかったら
if( !checkTiles( _x, _y ) ){
printfDx("Error\n"); //これがなぜかバグに影響する
_x -= vx;
_y -= vy;
}
}
//ここまで--------------------------------------------------------------------------------------------------------
}
void Map::draw(){
int bx, by;
for(int i=0;i<MAP_H;i++){
for(int j=0;j<MAP_W;j++){
if( _tiles[i][j]==0 ) continue; // そこにタイルが存在しなければ描写しない
// 描写位置計算
bx = Define::Win_W/2-_x-(TILE_W/2)*(1+j-i);
by = Define::Win_H/2-_y+TILE_H/2*(i+j);
// 余分な描写を避ける
if( bx<-TILE_W || bx>Define::Win_W || by<-TILE_H || by>Define::Win_H ) continue;
DrawGraph( bx, by, _imgTile, TRUE );
}
}
DrawCircle( Define::Win_W/2, Define::Win_H/2, 3, GetColor(255,0,0) );
}
int Map::main(){
calc();
draw();
return 0;
}
オフトピック
C言語歴は4年ほど。C++は勉強中で、その一環として本プログラムを開発しています