1フレーム押したときにだけ反応するようにしたのですが。。。

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
cupa
記事: 117
登録日時: 2年前

1フレーム押したときにだけ反応するようにしたのですが。。。

#1

投稿記事 by cupa » 7ヶ月前

お久しぶりです。

キー入力に関して問題自体は解決したのですが、それがなぜ解決したのが不明でしたので質問させていただきます。キーを入力すると連続ではなく一回だけ反応するようにしました。

◯修正前(L51~L81あたり)

コード:

#include "../DxLib/DxLib.h"

#define TILE_X_NUM		8
#define TILE_Y_NUM		98
#define TILE_NUM		TILE_X_NUM * TILE_Y_NUM
#define TILE_SIZE		32

#define SCREEN_W		640
#define SCREEN_H		480

#define MAP_W			SCREEN_W / TILE_SIZE
#define MAP_H			SCREEN_H / TILE_SIZE


int		tile[ TILE_NUM ];
int		map[ MAP_H ][ MAP_W ];

int		pX = 5, pY = 5, pImg;

int		pressingCount[ 256 ], releasingCount[ 256 ];

void load()
{
	LoadDivGraph( "tile.png", TILE_NUM, TILE_X_NUM, TILE_Y_NUM, TILE_SIZE, TILE_SIZE, tile );
	pImg = LoadGraph( "player.png" );
}

void put()
{
	int		t;
	for( int y = 0; y < MAP_H; y++ ){
		for( int x = 0; x < MAP_W; x++ ){
			t = GetRand( 1 );
			map[ y ][ x ] = t * 40;
		}
	}
	
	map[ GetRand( MAP_H - 1 ) ][ GetRand( MAP_W - 1 ) ] = 3;
}

void draw(){
	for( int y = 0; y < MAP_H; y++ ){
		for( int x = 0; x < MAP_W; x++ ){
			DrawGraph( x * TILE_SIZE, y * TILE_SIZE, tile[ map[ y ][ x ] ], TRUE );
		}
	}
	
	DrawExtendGraph( pX * TILE_SIZE, pY * TILE_SIZE, pX * TILE_SIZE + TILE_SIZE, pY * TILE_SIZE + TILE_SIZE, pImg, TRUE );
}

//	ここから
int getPressingCount( int k )
{
	char	key[ 256 ];
	GetHitKeyStateAll( key );
	for( int i = 0; i < 256; i++ ){
		if( key[ i ] > 0 ){
			if( releasingCount[ i ] > 0 ) {
				releasingCount[ i ] = 0;
			}
			pressingCount[ i ]++;
		}
		else{
			if( pressingCount[ i ] > 0 ){
				pressingCount[ i ] = 0;
			}
			releasingCount[ i ]++;
		}
	}
	
	return( pressingCount[ k ] );
}

void update()
{
	if( getPressingCount( KEY_INPUT_UP ) == 1 )			pY--;
	if( getPressingCount( KEY_INPUT_DOWN ) == 1 )		pY++;
	if( getPressingCount( KEY_INPUT_LEFT ) == 1 )		pX--;
	if( getPressingCount( KEY_INPUT_RIGHT ) == 1 )		pX++;
}
//	ここまでが問題の部分です

int WINAPI WinMain( HINSTANCE, HINSTANCE, LPSTR, int )
{
	ChangeWindowMode( TRUE );
	DxLib_Init();
	
	load();
	
	put();
	
	while( !ProcessMessage() && !CheckHitKey( KEY_INPUT_ESCAPE ) ){
		ClearDrawScreen();
		
		update();
		draw();
		
		ScreenFlip();
	}
	
	DxLib_End();
	return 0;
}
◯修正後(L41~L76あたり)

コード:

#include "../DxLib/DxLib.h"

#define TILE_X_NUM		8
#define TILE_Y_NUM		98
#define TILE_NUM		TILE_X_NUM * TILE_Y_NUM
#define TILE_SIZE		32

#define SCREEN_W		640
#define SCREEN_H		480

#define MAP_W			SCREEN_W / TILE_SIZE
#define MAP_H			SCREEN_H / TILE_SIZE


int		tile[ TILE_NUM ];
int		map[ MAP_H ][ MAP_W ];

int		pX = 5, pY = 5, pImg;

int		pressingCount[ 256 ], releasingCount[ 256 ];

void load()
{
	LoadDivGraph( "tile.png", TILE_NUM, TILE_X_NUM, TILE_Y_NUM, TILE_SIZE, TILE_SIZE, tile );
	pImg = LoadGraph( "player.png" );
}

void put()
{
	int		t;
	for( int y = 0; y < MAP_H; y++ ){
		for( int x = 0; x < MAP_W; x++ ){
			t = GetRand( 1 );
			map[ y ][ x ] = t * 40;
		}
	}
	
	map[ GetRand( MAP_H - 1 ) ][ GetRand( MAP_W - 1 ) ] = 3;
}

void draw(){
	for( int y = 0; y < MAP_H; y++ ){
		for( int x = 0; x < MAP_W; x++ ){
			DrawGraph( x * TILE_SIZE, y * TILE_SIZE, tile[ map[ y ][ x ] ], TRUE );
		}
	}
	
	DrawExtendGraph( pX * TILE_SIZE, pY * TILE_SIZE, pX * TILE_SIZE + TILE_SIZE, pY * TILE_SIZE + TILE_SIZE, pImg, TRUE );
}

//	ここから
void GetHitKeyStateAll_2()
{
	char	key[ 256 ];
	GetHitKeyStateAll( key );
	for( int i = 0; i < 256; i++ ){
		if( key[ i ] > 0 ){
			if( releasingCount[ i ] > 0 ) {
				releasingCount[ i ] = 0;
			}
			pressingCount[ i ]++;
		}
		else{
			if( pressingCount[ i ] > 0 ){
				pressingCount[ i ] = 0;
			}
			releasingCount[ i ]++;
		}
	}
}

int getPressingCount( int k )
{
	return( pressingCount[ k ] );
}

void update()
{
	if( getPressingCount( KEY_INPUT_UP ) == 1 )			pY--;
	if( getPressingCount( KEY_INPUT_DOWN ) == 1 )		pY++;
	if( getPressingCount( KEY_INPUT_LEFT ) == 1 )		pX--;
	if( getPressingCount( KEY_INPUT_RIGHT ) == 1 )		pX++;
}
//	ここまでが問題の部分です

int WINAPI WinMain( HINSTANCE, HINSTANCE, LPSTR, int )
{
	ChangeWindowMode( TRUE );
	DxLib_Init();
	
	load();
	
	put();
	
	while( !ProcessMessage() && !CheckHitKey( KEY_INPUT_ESCAPE ) ){
		ClearDrawScreen();
		
		GetHitKeyStateAll_2();
		update();
		draw();
		
		ScreenFlip();
	}
	
	DxLib_End();
	return 0;
}
修正前のソースは、キー入力を監視するのと任意のキーの押されたフレーム数返す2つが混合している関数をキーを入力されるごとに呼び出していてよろしく無いことは解るのですが、、、。
なぜ修正後(キー入力を監視する関数と、押されたフレーム数を返す関数を分けた方)はうまく動作するのかよくわかりません。修正前と修正後の違いを教えていただきたいです。

アバター
みけCAT
記事: 6734
登録日時: 13年前
住所: 千葉県
連絡を取る:

Re: 1フレーム押したときにだけ反応するようにしたのですが。。。

#2

投稿記事 by みけCAT » 7ヶ月前

修正前は、getPressingCount 関数内で pressingCount の更新をしているため、getPressingCount 関数を呼び出すたびに時間 (実質何フレーム目か) が進んでしまい、キーが押されたタイミングを見逃す可能性が発生します。
修正後は、getPressingCount 関数を呼び出しても pressingCount は更新されず、GetHitKeyStateAll_2 関数により1フレームに1回のみ時間を進めるので、キーが押されたタイミングを見逃さずにすみます。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

cupa
記事: 117
登録日時: 2年前

Re: 1フレーム押したときにだけ反応するようにしたのですが。。。

#3

投稿記事 by cupa » 7ヶ月前

みけCATさんありがとうございます!
お陰で蟠りが解けました!

毎回呼んじゃってるとpressingCountが何回も更新されておかしくなってしまうんですね...

返信

“C言語何でも質問掲示板” へ戻る