DxLibでインベーダーを作っています 質問です
Posted: 2013年7月01日(月) 20:57
今、私は敵の最前列を求めその最前列に弾を打たせようとしています
ですが2次元配列を使った時の敵の弾の発射がよくわからず最前列の求め方がこれで合っているのかわかりません。
最前列の求め方はこのような感じのほうがいいのではないか、弾はこのようなことをすればできるなど、解説といいますか、助言がほしいです。
プログラム歴はまだ2ヶ月半ととぼしく、ソースコードも大変見にくいとは思いますが、なにかこのような方法があるんじゃないか?と言う方はお願いします。
code
#include "DxLib.h"
void Player( );
void Enemy( );
//プレイヤーの表示座標
///////////////////////
int px = 100;
int py = 420;
///////////////////////
//int j;
//int i;//2次元配列に使う変数
//プレイヤーとプレイヤーの弾関係の変数
//////////////////////////////
int ShotX = 0;//プレイヤーの弾の位置 X
int ShotY = 0;// Y
int PlayerFlag = 0;//プレイヤーが生存しているかどうかを
int ShotFlag = 0;//プレイヤーの弾が発射されたかどうかのフラグ
int PlayerGraph;//プレイヤーの画像の読み込みに使う
int PlayerShotGraph;//プレイヤーの弾の画像の読み込みに使う
int Playerw, Playerh, PlayerShotw, PlayerShoth;//プレイヤーとプレイヤーの弾のサイズを得るときに使う変数
//////////////////////////////
//敵を表示するための2次元配列
///////////////////////////
int inv_x[ 10 ][ 8 ] = {};
int inv_ya[ 10 ][ 8 ] = {};
//////////////////////////
//敵と敵の弾関係の変数
///////////////////////////////
int EnemyShot = 0;
int EnemyShotX = 0;//敵の弾の位置 X
int EnemyShotY = 0;// Y
int EnemyFlag[ 10 ][ 8 ] = {};//敵の生存フラグ
int EnemyShotFlag[ 10 ][ 8 ];//敵の弾が発射されたかどうかのフラグ
int EnemyShotGraph[ 3 ];//敵の弾の画像読み込みに使う(分割画像なので配列)
int EnemyaGraph[ 2 ];//敵のアニメーションに使う A
int EnemybGraph[ 2 ];// B
int EnemycGraph[ 2 ];// C
int EnemyCount = 0;
int EnemySpaceFlag = 0;
int EnemySpace = 30;
int Enemyw, Enemyh, EnemyShotw, EnemyShoth;//敵の弾のサイズを得るときに使う変数
int direct = 1;//敵の移動方向
int REnd = 0;//敵の最端の変数
int FirstRow[ 10 ];//敵の最前列の変数
/////////////////////////////
unsigned int time = 0;
enum muki{ LEFT,RIGHT,DOWN };
int UnderLine = LoadGraph("image/UnderLine");//アンダーラインの画像の読み込み
int WINAPI WinMain( HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR IpCmdLine,int nCmdShow)
{
ChangeWindowMode( TRUE ); //windowモードに変更
if ( DxLib_Init() == 1 ) //DXライブラリ初期化処理
return -1;
SetDrawScreen(DX_SCREEN_BACK); //描画先を裏画面に
PlayerGraph = LoadGraph("image/player.png");
PlayerShotGraph = LoadGraph("image/PlayerShot.png");
//分割画像の読み込み
LoadDivGraph( "image/Type1Enemy.png" , 2 , 2 , 1 , 24 , 16 , EnemyaGraph );
LoadDivGraph( "image/Type2Enemy.png" , 2 , 2 , 1 , 22 , 16 , EnemybGraph );
LoadDivGraph( "image/Type3Enemy.png" , 2 , 2 , 1 , 19 , 16 , EnemycGraph );
LoadDivGraph( "image/EnemyShot2.png" , 3 , 3 , 1 , 7 , 1 , EnemyShotGraph );
//敵Cの間隔
for ( int i = 2; i < 4; i++ ) {
for ( int j = 0; j < 10; j ++ ) {
inv_x[ j ][ i ] = 30 * j;
inv_ya[ j ][ i ] = 25 * i;
}
}
//敵Bの間隔
for ( int i = 4; i < 6; i++ ) {
for ( int j = 0; j < 10; j ++ ) {
inv_x[ j ][ i ] = 30 * j;
inv_ya[ j ][ i ] = 25 * i;
}
}
//敵Aの間隔
for ( int i = 6; i < 8; i++ ) {
for ( int j = 0; j < 10; j ++ ) {
inv_x[ j ][ i ] = 30 * j;
inv_ya[ j ][ i ] = 25 * i;
}
}
while( ScreenFlip()==0 && ProcessMessage()==0 && ClearDrawScreen()==0 && CheckHitKey( KEY_INPUT_ESCAPE ) == 0 ) {
Player( );
Enemy( );
time++;
}
DxLib_End( );
return 0;
}
// プレイヤーの移動、表示
void Player( ) {
//プレイヤーの移動
if ( CheckHitKey(KEY_INPUT_RIGHT) == 1) px += 2;
if ( CheckHitKey(KEY_INPUT_LEFT) == 1) px -= 2;
// スペースキーを押していて、且弾が撃ち出されていなかったら弾を発射する
if( CheckHitKey( KEY_INPUT_SPACE ) == 1 && ShotFlag == 0 ) {
//プレイヤーと弾の画像のサイズを得る
GetGraphSize( PlayerGraph , &Playerw , &Playerh ) ;
GetGraphSize( PlayerShotGraph , &PlayerShotw , &PlayerShoth ) ;
// 弾の位置をセット、位置はプレイヤーの中心にする
ShotX = ( Playerw - PlayerShotw ) / 2 + px ;
ShotY = ( Playerh - PlayerShoth ) / 2 + py ;
// 弾は現時点を持って存在するので、存在状態を保持する変数に1を代入する
ShotFlag = 1 ;
}
//プレイヤーの描画
DrawGraph(px,py,PlayerGraph,TRUE);
// 自機の弾の移動ルーチン( 存在状態を保持している変数の内容が1(存在する)の場合のみ行う )
if( ShotFlag == 1 ) {
// 弾を7ドット上に移動させる
ShotY -= 7;
// 画面外に出てしまった場合は存在状態を保持している変数に0(存在しない)を代入する
if( ShotY < -80 ) {
ShotFlag = 0 ;
}
// 画面に弾を描画する
DrawGraph( ShotX, ShotY, PlayerShotGraph, FALSE ) ;
}
//プレイヤーの壁あたり判定
if ( px < 20 ) {
px = 20;
}
if ( px > 600 ) {
px = 600;
}
}
//敵の表示
void Enemy( ) {
//敵の当たり判定
for ( int i = 3; i < 8; i++ ) {
for ( int j = 0; j < 10; j ++ ) {
if ( ( ( ShotX + 3 > inv_x[ j ][ i ] ) && ( ShotX < inv_x[ j ][ i ] + 22 ) )
&& ( ( ShotY + 5 > inv_ya[ j ][ i ] ) && ( ShotY < inv_ya[ j ][ i ] + 16 ) ) ) {
if ( EnemyFlag[ j ][ i ] == 0 ) {
EnemyFlag[ j ][ i ] = 1;
ShotX = 0;
ShotY = 0;
ShotFlag = 0;
EnemyCount++;
}
}
}
}
//4体倒したらスピード上昇
if ( EnemyCount % 5 == 4 ) {
if ( EnemySpaceFlag == 0 ) {
EnemySpace--;
EnemySpaceFlag = 1;
}
}else{
EnemySpaceFlag = 0;
}
//最端の敵の座標を求める(右)
if ( direct == RIGHT ) {
for ( int i = 0; i < 10; i++ ) {
for ( int j = 3; j < 8; j++ ) {
if ( EnemyFlag[ i ][ j ] == 0 ) {
REnd = i;
}
}
}
}else{//(左)
for ( int i = 9; i >= 0; i-- ) {
for ( int j = 3; j < 8; j++ ) {
if ( EnemyFlag[ i ][ j ] == 0 ) {
REnd = i;
}
}
}
}
DrawFormatString( 0, 0, 0xffffff, "REnd = %d", REnd );
//敵の最前列を求める
for ( int i = 0; i < 10; i++ ) {
for ( int j = 0; j < 8; j++ ) {
if ( EnemyFlag[ i ][ j ] == 0 ) {
FirstRow[ i ] = j;
}
}
}
//敵の移動(右)
if ( time % EnemySpace == 0 ) {
if ( direct == RIGHT ) {
for ( int i = 7; i >= 2 ; i-- ) {
for ( int j = 0; j < 10; j++ ) {
if ( inv_x[ REnd ][ 2 ] < 600 && direct == RIGHT ) {
inv_x[ j ][ i ] += 15;
}else{
inv_ya[ j ][ i ] += 15;
if ( i == 7 && j == 0) {
direct = LEFT;
}
}
}
}
}else{//左の移動
for ( int i = 7; i >= 2; i-- ) {
for ( int j = 9; j >= 0; j-- ) {
if( inv_x[ REnd ][ 2 ] > 40 && direct == LEFT ) {
inv_x[ j ][ i ] -= 15;
}else{
inv_ya[ j ][ i ] += 15;
if ( i == 3 && j == 0 ){
direct = RIGHT;
}
}
}
}
}
}
DrawFormatString( 0, 20, 0xffffff, " inv_x[ REnd ][ 2 ] = %d", inv_x[ REnd ][ 2 ] );
//敵を指定の2次元配列の位置に表示(敵C)
for ( int i = 3; i < 4; i++ ) {
for ( int j = 0; j < 10; j ++ ) {
if ( EnemyFlag[ j ][ i ] == 0 ) {
DrawGraph(inv_x[ j ][ i ],inv_ya[ j ][ i ],EnemycGraph[ ( time / EnemySpace ) % 2 ],TRUE);
}
}
}
//(敵B)
for ( int i = 4; i < 6; i++ ) {
for ( int j = 0; j < 10; j ++ ) {
if ( EnemyFlag[ j ][ i ] == 0 ) {
DrawGraph(inv_x[ j ][ i ],inv_ya[ j ][ i ],EnemybGraph[ ( time / EnemySpace ) % 2 ],TRUE);
}
}
}
//(敵A)
for ( int i = 6; i < 8; i++ ) {
for ( int j = 0; j < 10; j ++ ) {
if ( EnemyFlag[ j ][ i ] == 0 ) {
DrawGraph(inv_x[ j ][ i ],inv_ya[ j ][ i ],EnemyaGraph[ ( time / EnemySpace ) % 2 ],TRUE);
}
}
}
}
/code
ですが2次元配列を使った時の敵の弾の発射がよくわからず最前列の求め方がこれで合っているのかわかりません。
最前列の求め方はこのような感じのほうがいいのではないか、弾はこのようなことをすればできるなど、解説といいますか、助言がほしいです。
プログラム歴はまだ2ヶ月半ととぼしく、ソースコードも大変見にくいとは思いますが、なにかこのような方法があるんじゃないか?と言う方はお願いします。
code
#include "DxLib.h"
void Player( );
void Enemy( );
//プレイヤーの表示座標
///////////////////////
int px = 100;
int py = 420;
///////////////////////
//int j;
//int i;//2次元配列に使う変数
//プレイヤーとプレイヤーの弾関係の変数
//////////////////////////////
int ShotX = 0;//プレイヤーの弾の位置 X
int ShotY = 0;// Y
int PlayerFlag = 0;//プレイヤーが生存しているかどうかを
int ShotFlag = 0;//プレイヤーの弾が発射されたかどうかのフラグ
int PlayerGraph;//プレイヤーの画像の読み込みに使う
int PlayerShotGraph;//プレイヤーの弾の画像の読み込みに使う
int Playerw, Playerh, PlayerShotw, PlayerShoth;//プレイヤーとプレイヤーの弾のサイズを得るときに使う変数
//////////////////////////////
//敵を表示するための2次元配列
///////////////////////////
int inv_x[ 10 ][ 8 ] = {};
int inv_ya[ 10 ][ 8 ] = {};
//////////////////////////
//敵と敵の弾関係の変数
///////////////////////////////
int EnemyShot = 0;
int EnemyShotX = 0;//敵の弾の位置 X
int EnemyShotY = 0;// Y
int EnemyFlag[ 10 ][ 8 ] = {};//敵の生存フラグ
int EnemyShotFlag[ 10 ][ 8 ];//敵の弾が発射されたかどうかのフラグ
int EnemyShotGraph[ 3 ];//敵の弾の画像読み込みに使う(分割画像なので配列)
int EnemyaGraph[ 2 ];//敵のアニメーションに使う A
int EnemybGraph[ 2 ];// B
int EnemycGraph[ 2 ];// C
int EnemyCount = 0;
int EnemySpaceFlag = 0;
int EnemySpace = 30;
int Enemyw, Enemyh, EnemyShotw, EnemyShoth;//敵の弾のサイズを得るときに使う変数
int direct = 1;//敵の移動方向
int REnd = 0;//敵の最端の変数
int FirstRow[ 10 ];//敵の最前列の変数
/////////////////////////////
unsigned int time = 0;
enum muki{ LEFT,RIGHT,DOWN };
int UnderLine = LoadGraph("image/UnderLine");//アンダーラインの画像の読み込み
int WINAPI WinMain( HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR IpCmdLine,int nCmdShow)
{
ChangeWindowMode( TRUE ); //windowモードに変更
if ( DxLib_Init() == 1 ) //DXライブラリ初期化処理
return -1;
SetDrawScreen(DX_SCREEN_BACK); //描画先を裏画面に
PlayerGraph = LoadGraph("image/player.png");
PlayerShotGraph = LoadGraph("image/PlayerShot.png");
//分割画像の読み込み
LoadDivGraph( "image/Type1Enemy.png" , 2 , 2 , 1 , 24 , 16 , EnemyaGraph );
LoadDivGraph( "image/Type2Enemy.png" , 2 , 2 , 1 , 22 , 16 , EnemybGraph );
LoadDivGraph( "image/Type3Enemy.png" , 2 , 2 , 1 , 19 , 16 , EnemycGraph );
LoadDivGraph( "image/EnemyShot2.png" , 3 , 3 , 1 , 7 , 1 , EnemyShotGraph );
//敵Cの間隔
for ( int i = 2; i < 4; i++ ) {
for ( int j = 0; j < 10; j ++ ) {
inv_x[ j ][ i ] = 30 * j;
inv_ya[ j ][ i ] = 25 * i;
}
}
//敵Bの間隔
for ( int i = 4; i < 6; i++ ) {
for ( int j = 0; j < 10; j ++ ) {
inv_x[ j ][ i ] = 30 * j;
inv_ya[ j ][ i ] = 25 * i;
}
}
//敵Aの間隔
for ( int i = 6; i < 8; i++ ) {
for ( int j = 0; j < 10; j ++ ) {
inv_x[ j ][ i ] = 30 * j;
inv_ya[ j ][ i ] = 25 * i;
}
}
while( ScreenFlip()==0 && ProcessMessage()==0 && ClearDrawScreen()==0 && CheckHitKey( KEY_INPUT_ESCAPE ) == 0 ) {
Player( );
Enemy( );
time++;
}
DxLib_End( );
return 0;
}
// プレイヤーの移動、表示
void Player( ) {
//プレイヤーの移動
if ( CheckHitKey(KEY_INPUT_RIGHT) == 1) px += 2;
if ( CheckHitKey(KEY_INPUT_LEFT) == 1) px -= 2;
// スペースキーを押していて、且弾が撃ち出されていなかったら弾を発射する
if( CheckHitKey( KEY_INPUT_SPACE ) == 1 && ShotFlag == 0 ) {
//プレイヤーと弾の画像のサイズを得る
GetGraphSize( PlayerGraph , &Playerw , &Playerh ) ;
GetGraphSize( PlayerShotGraph , &PlayerShotw , &PlayerShoth ) ;
// 弾の位置をセット、位置はプレイヤーの中心にする
ShotX = ( Playerw - PlayerShotw ) / 2 + px ;
ShotY = ( Playerh - PlayerShoth ) / 2 + py ;
// 弾は現時点を持って存在するので、存在状態を保持する変数に1を代入する
ShotFlag = 1 ;
}
//プレイヤーの描画
DrawGraph(px,py,PlayerGraph,TRUE);
// 自機の弾の移動ルーチン( 存在状態を保持している変数の内容が1(存在する)の場合のみ行う )
if( ShotFlag == 1 ) {
// 弾を7ドット上に移動させる
ShotY -= 7;
// 画面外に出てしまった場合は存在状態を保持している変数に0(存在しない)を代入する
if( ShotY < -80 ) {
ShotFlag = 0 ;
}
// 画面に弾を描画する
DrawGraph( ShotX, ShotY, PlayerShotGraph, FALSE ) ;
}
//プレイヤーの壁あたり判定
if ( px < 20 ) {
px = 20;
}
if ( px > 600 ) {
px = 600;
}
}
//敵の表示
void Enemy( ) {
//敵の当たり判定
for ( int i = 3; i < 8; i++ ) {
for ( int j = 0; j < 10; j ++ ) {
if ( ( ( ShotX + 3 > inv_x[ j ][ i ] ) && ( ShotX < inv_x[ j ][ i ] + 22 ) )
&& ( ( ShotY + 5 > inv_ya[ j ][ i ] ) && ( ShotY < inv_ya[ j ][ i ] + 16 ) ) ) {
if ( EnemyFlag[ j ][ i ] == 0 ) {
EnemyFlag[ j ][ i ] = 1;
ShotX = 0;
ShotY = 0;
ShotFlag = 0;
EnemyCount++;
}
}
}
}
//4体倒したらスピード上昇
if ( EnemyCount % 5 == 4 ) {
if ( EnemySpaceFlag == 0 ) {
EnemySpace--;
EnemySpaceFlag = 1;
}
}else{
EnemySpaceFlag = 0;
}
//最端の敵の座標を求める(右)
if ( direct == RIGHT ) {
for ( int i = 0; i < 10; i++ ) {
for ( int j = 3; j < 8; j++ ) {
if ( EnemyFlag[ i ][ j ] == 0 ) {
REnd = i;
}
}
}
}else{//(左)
for ( int i = 9; i >= 0; i-- ) {
for ( int j = 3; j < 8; j++ ) {
if ( EnemyFlag[ i ][ j ] == 0 ) {
REnd = i;
}
}
}
}
DrawFormatString( 0, 0, 0xffffff, "REnd = %d", REnd );
//敵の最前列を求める
for ( int i = 0; i < 10; i++ ) {
for ( int j = 0; j < 8; j++ ) {
if ( EnemyFlag[ i ][ j ] == 0 ) {
FirstRow[ i ] = j;
}
}
}
//敵の移動(右)
if ( time % EnemySpace == 0 ) {
if ( direct == RIGHT ) {
for ( int i = 7; i >= 2 ; i-- ) {
for ( int j = 0; j < 10; j++ ) {
if ( inv_x[ REnd ][ 2 ] < 600 && direct == RIGHT ) {
inv_x[ j ][ i ] += 15;
}else{
inv_ya[ j ][ i ] += 15;
if ( i == 7 && j == 0) {
direct = LEFT;
}
}
}
}
}else{//左の移動
for ( int i = 7; i >= 2; i-- ) {
for ( int j = 9; j >= 0; j-- ) {
if( inv_x[ REnd ][ 2 ] > 40 && direct == LEFT ) {
inv_x[ j ][ i ] -= 15;
}else{
inv_ya[ j ][ i ] += 15;
if ( i == 3 && j == 0 ){
direct = RIGHT;
}
}
}
}
}
}
DrawFormatString( 0, 20, 0xffffff, " inv_x[ REnd ][ 2 ] = %d", inv_x[ REnd ][ 2 ] );
//敵を指定の2次元配列の位置に表示(敵C)
for ( int i = 3; i < 4; i++ ) {
for ( int j = 0; j < 10; j ++ ) {
if ( EnemyFlag[ j ][ i ] == 0 ) {
DrawGraph(inv_x[ j ][ i ],inv_ya[ j ][ i ],EnemycGraph[ ( time / EnemySpace ) % 2 ],TRUE);
}
}
}
//(敵B)
for ( int i = 4; i < 6; i++ ) {
for ( int j = 0; j < 10; j ++ ) {
if ( EnemyFlag[ j ][ i ] == 0 ) {
DrawGraph(inv_x[ j ][ i ],inv_ya[ j ][ i ],EnemybGraph[ ( time / EnemySpace ) % 2 ],TRUE);
}
}
}
//(敵A)
for ( int i = 6; i < 8; i++ ) {
for ( int j = 0; j < 10; j ++ ) {
if ( EnemyFlag[ j ][ i ] == 0 ) {
DrawGraph(inv_x[ j ][ i ],inv_ya[ j ][ i ],EnemyaGraph[ ( time / EnemySpace ) % 2 ],TRUE);
}
}
}
}
/code