キャラクターの移動について

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

キャラクターの移動について

#1

投稿記事 by Iseuma14 » 9年前

質問させていただきます
現在、龍神録プログラミングの館のコードを可能な限りグローバル変数を使わずに、ポインタを使って自分なりに書いております
さて、キャラクターの移動に関する部分を自分なりに書いてみましたが、低速移動時に、キャラクターが右上に動いてくれません
以下、関係ありそうな部分です

コード:

//main.cpp
#include "DxLib.h"
#include "struct.h"
#include "graph.h"
#include "player.h"
#include "define.h"

int key_update(int*);
int every_process();
int check_shift(int,int);


int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int)
{
	ChangeWindowMode(TRUE),DxLib_Init(),SetDrawScreen(DX_SCREEN_BACK);
	int key[256],board;
	board = LoadGraph("画像/board.png");
	ch_t player;
	player.x = 160,0;
	player.y = 300.0;
	player.img = LoadGraph("画像/キャラクタ01.png");
	while(every_process()==0)
	{
		graph_board(&board);
		graph_ch(&player);
		key_update(key);
		if(key[KEY_INPUT_RSHIFT] > 0||key[KEY_INPUT_LSHIFT] > 0)
			slow_move(&player,key);		
		else
			quick_move(&player,key);


	}

	DxLib_End();
	return 0;
}

int every_process()
{
	ScreenFlip();
	ProcessMessage();
	ClearDrawScreen();
	return 0;
}

int key_update(int key[])
{
	char all_key[256];
	GetHitKeyStateAll(all_key);
	int i;
	for(i=0;i<256;i++)
	{
		if(all_key[i] != 0)
			key[i]++;
		else
			key[i] = 0;
	}
	return 0;
}

//ここからplayer.cpp
#include "DxLib.h"
#include "player.h"
#include "struct.h"
#include <math.h>

int slow_move(ch_t *player,int *key)
{
	if(key[KEY_INPUT_UP]>0 && key[KEY_INPUT_RIGHT]>0)
	{	
		player->y = player->y-sqrt(2.0);
		player->x = player->x+sqrt(2.0);
	}
	else if(key[KEY_INPUT_UP]>0 && key[KEY_INPUT_LEFT]>0)
	{
		player->y = player->y-sqrt(2.0);
		player->x = player->x-sqrt(2.0);
	}
	else if(key[KEY_INPUT_DOWN]>0 && key[KEY_INPUT_RIGHT]>0)
	{
		player->y = player->y+sqrt(2.0);
		player->x = player->x+sqrt(2.0);
	}
	else if(key[KEY_INPUT_DOWN]>0 && key[KEY_INPUT_LEFT]>0)
	{
		player->y = player->y+sqrt(2.0);
		player->x = player->x-sqrt(2.0);
	}
	else if(key[KEY_INPUT_UP]>0)
		player->y = player->y-1;

	else if (key[KEY_INPUT_DOWN]>0)
		player->y = player->y+1;

	else if(key[KEY_INPUT_RIGHT]>0)
		player->x = player->x+1;

	else if(key[KEY_INPUT_LEFT]>0)
		player->x = player->x-1;

	return 0;

}


int quick_move(ch_t *player,int *key)
{
	
	if(key[KEY_INPUT_UP]>0 && key[KEY_INPUT_RIGHT]>0)
	{	
		player->y = player->y-3 * sqrt(2.0);
		player->x = player->x+3 * sqrt(2.0);
	}
	else if(key[KEY_INPUT_UP]>0 && key[KEY_INPUT_LEFT]>0)
	{
		player->y = player->y-3 * sqrt(2.0);
		player->x = player->x-3 * sqrt(2.0);
	}
	else if(key[KEY_INPUT_DOWN]>0 && key[KEY_INPUT_RIGHT]>0)
	{
		player->y = player->y+3 * sqrt(2.0);
		player->x = player->x+3 * sqrt(2.0);
	}
	else if(key[KEY_INPUT_DOWN]>0 && key[KEY_INPUT_LEFT]>0)
	{
		player->y = player->y+3 * sqrt(2.0);
		player->x = player->x-3 * sqrt(2.0);
	}
	else if(key[KEY_INPUT_UP]>0)
		player->y = player->y-3;

	else if (key[KEY_INPUT_DOWN]>0)
		player->y = player->y+3;

	else if(key[KEY_INPUT_RIGHT]>0)
		player->x = player->x+3;

	else if(key[KEY_INPUT_LEFT]>0)
		player->x = player->x-3;

	return 0;

}
自分でいろいろ試してみたのですが、低速移動の時のみ、↑キーと→キーを同時に押しても先に押したほう片方からの入力、同時押しだった場合はどちらの入力も受け付けてくれていないようです

また、main.cppの低速、高速の分岐を消し、低速移動のみにしてみると右上への入力も入りました
原因を教えていただけるとうれしいです。

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

Re: キャラクターの移動について

#2

投稿記事 by みけCAT » 9年前

キーボードの仕様が原因である可能性が高い気がします。
オフトピック
ななめの移動とななめでない移動で速さを同じにするには速度成分を√2で割らないといけず、龍神録プログラミングの館でもそのようになっているのに、
このプログラムではななめの時逆に√2を掛けている…?
面白そうな仕様ですね。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

Iseuma14
記事: 54
登録日時: 10年前

Re: キャラクターの移動について

#3

投稿記事 by Iseuma14 » 9年前

>>みけCAT様いつもご回答ありがとうございます
みけCAT さんが書きました:キーボードの仕様が原因である可能性が高い気がします。
オフトピック
ななめの移動とななめでない移動で速さを同じにするには速度成分を√2で割らないといけず、龍神録プログラミングの館でもそのようになっているのに、
このプログラムではななめの時逆に√2を掛けている…?
面白そうな仕様ですね。
√2かけてるのは私のミスです お恥ずかしい限りです、、、

肝心の質問本文のほうですが、もう一度コードを見直してみましたが、やはりわかりません、、、
右上への移動の分岐条件は高速移動も低速移動も変わらないですし...
もう少し教えていただけませんか?
何度も申し訳ございません

アバター
Hiragi(GKUTH)
記事: 167
登録日時: 14年前
住所: 大阪府
連絡を取る:

Re: キャラクターの移動について

#4

投稿記事 by Hiragi(GKUTH) » 9年前

とりあえず動かしてみたかったので最小限で動くようにしてみました。

コード:

#include "DxLib.h"
#include <math.h>

int key[256];

int key_update(int key[])
{
	char all_key[256];
	GetHitKeyStateAll(all_key);
	int i;
	for (i = 0;i<256;i++)
	{
		if (all_key[i] != 0)
			key[i]++;
		else
			key[i] = 0;
	}
	return 0;
}

int slow_move(int *x, int *y, int *key)
{
	if (key[KEY_INPUT_UP]>0 && key[KEY_INPUT_RIGHT]>0)
	{
		*y = *y - 1/sqrt(2.0);
		*x = *x + 1/sqrt(2.0);
	}
	else if (key[KEY_INPUT_UP]>0 && key[KEY_INPUT_LEFT]>0)
	{
		*y = *y - 1/sqrt(2.0);
		*x = *x - 1/sqrt(2.0);
	}
	else if (key[KEY_INPUT_DOWN]>0 && key[KEY_INPUT_RIGHT]>0)
	{
		*y = *y + 1/sqrt(2.0);
		*x = *x + 1/sqrt(2.0);
	}
	else if (key[KEY_INPUT_DOWN]>0 && key[KEY_INPUT_LEFT]>0)
	{
		*y = *y + 1/sqrt(2.0);
		*x = *x - 1/sqrt(2.0);
	}
	else if (key[KEY_INPUT_UP]>0)
		*y = *y - 1;

	else if (key[KEY_INPUT_DOWN]>0)
		*y = *y + 1;

	else if (key[KEY_INPUT_RIGHT]>0)
		*x = *x + 1;

	else if (key[KEY_INPUT_LEFT]>0)
		*x = *x - 1;

	return 0;

}


int quick_move(int *x, int *y, int *key)
{

	if (key[KEY_INPUT_UP]>0 && key[KEY_INPUT_RIGHT]>0)
	{
		*y = *y - 3 / sqrt(2.0);
		*x = *x + 3 / sqrt(2.0);
	}
	else if (key[KEY_INPUT_UP]>0 && key[KEY_INPUT_LEFT]>0)
	{
		*y = *y - 3 / sqrt(2.0);
		*x = *x - 3 / sqrt(2.0);
	}
	else if (key[KEY_INPUT_DOWN]>0 && key[KEY_INPUT_RIGHT]>0)
	{
		*y = *y + 3 / sqrt(2.0);
		*x = *x + 3 / sqrt(2.0);
	}
	else if (key[KEY_INPUT_DOWN]>0 && key[KEY_INPUT_LEFT]>0)
	{
		*y = *y + 3 / sqrt(2.0);
		*x = *x - 3 / sqrt(2.0);
	}
	else if (key[KEY_INPUT_UP]>0)
		*y = *y - 3;

	else if (key[KEY_INPUT_DOWN]>0)
		*y = *y + 3;

	else if (key[KEY_INPUT_RIGHT]>0)
		*x = *x + 3;

	else if (key[KEY_INPUT_LEFT]>0)
		*x = *x - 3;

	return 0;

}

int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
	ChangeWindowMode(TRUE), DxLib_Init(), SetDrawScreen(DX_SCREEN_BACK);
	SetWindowSizeChangeEnableFlag(TRUE);

	int x = 320,y=240;

	while (ProcessMessage() == 0 && ClearDrawScreen() == 0)
	{
		key_update(key);

		if (key[KEY_INPUT_RSHIFT] > 0 || key[KEY_INPUT_LSHIFT] > 0)
			slow_move(&x,&y, key);
		else
			quick_move(&x, &y, key);

		DrawBox(x,y,x+32,y+32,GetColor(255,255,255),true);

		ScreenFlip();
	}
	
	DxLib_End();
	return 0;
}

仰るとおり右上、の他にも色々と謎の挙動が起きてます。 とりあえずキーボードの仕様ではなさ気です。

通常の移動でも左下移動時とかに角度がどう考えてもおかしい...
斜め移動の計算式が間違えている可能性があるんじゃないでしょうか。
だいがくせい!

アバター
Hiragi(GKUTH)
記事: 167
登録日時: 14年前
住所: 大阪府
連絡を取る:

Re: キャラクターの移動について

#5

投稿記事 by Hiragi(GKUTH) » 9年前

さっきのやつは色々とおかしかったので少し修正しました。

・まず提示されたコードの19行目がピリオドでなくコンマが使われています。
else if~が大量に出現するのはマズい、というか自身でも何がどうなっているのか理解できなくなってしまいそうなので、 そんなことなかったです。斜め移動時に
 フラグを立て、斜め移動した後は純粋な横、縦移動をしないように作ってみるとそれなりの動きをしてくれました。
実数型を使われているのでしょうか? 切り落とされて移動できない可能性もあります。 こちらではfloatにしました 初期化部より実数型なのでしょう。
ご確認ください。

というか殆どコンマのせいに思えてきました。

コード:

#include "DxLib.h"
#include <math.h>

int key[256];

int key_update(int key[])
{
	char all_key[256];
	GetHitKeyStateAll(all_key);
	int i;
	for (i = 0;i<256;i++)
	{
		if (all_key[i] != 0)
			key[i]++;
		else
			key[i] = 0;
	}
	return 0;
}

int slow_move(float *x, float *y, int *key)
{
	bool nanameflag = false;
	if (key[KEY_INPUT_UP]>0 && key[KEY_INPUT_RIGHT]>0)
	{
		*y = *y - 1/sqrt(2.0);
		*x = *x + 1/sqrt(2.0);
		nanameflag = true;
	}
	else if (key[KEY_INPUT_UP]>0 && key[KEY_INPUT_LEFT]>0)
	{
		*y = *y - 1/sqrt(2.0);
		*x = *x - 1/sqrt(2.0);
		nanameflag = true;
	}
	else if (key[KEY_INPUT_DOWN]>0 && key[KEY_INPUT_RIGHT]>0)
	{
		*y = *y + 1/sqrt(2.0);
		*x = *x + 1/sqrt(2.0);
		nanameflag = true;
	}
	else if (key[KEY_INPUT_DOWN]>0 && key[KEY_INPUT_LEFT]>0)
	{
		*y = *y + 1/sqrt(2.0);
		*x = *x - 1/sqrt(2.0);
		nanameflag = true;
	}
	if(nanameflag == false)
	{ 
		if (key[KEY_INPUT_UP]>0)
			*y = *y - 1;

		else if (key[KEY_INPUT_DOWN]>0)
			*y = *y + 1;

		else if (key[KEY_INPUT_RIGHT]>0)
			*x = *x + 1;

		else if (key[KEY_INPUT_LEFT]>0)
			*x = *x - 1;
	}
	return 0;

}


int quick_move(float *x, float *y, int *key)
{
	bool nanameflag = false;
	if (key[KEY_INPUT_UP]>0 && key[KEY_INPUT_RIGHT]>0)
	{
		*y = *y - 3 / sqrt(2.0);
		*x = *x + 3 / sqrt(2.0);
		nanameflag = true;
	}
	else if (key[KEY_INPUT_UP]>0 && key[KEY_INPUT_LEFT]>0)
	{
		*y = *y - 3 / sqrt(2.0);
		*x = *x - 3 / sqrt(2.0);
		nanameflag = true;
	}
	else if (key[KEY_INPUT_DOWN]>0 && key[KEY_INPUT_RIGHT]>0)
	{
		*y = *y + 3 / sqrt(2.0);
		*x = *x + 3 / sqrt(2.0);
		nanameflag = true;
	}
	else if (key[KEY_INPUT_DOWN]>0 && key[KEY_INPUT_LEFT]>0)
	{
		*y = *y + 3 / sqrt(2.0);
		*x = *x - 3 / sqrt(2.0);
		nanameflag = true;
	}
	else if(nanameflag == false)
	{ 
		if (key[KEY_INPUT_UP]>0)	
			*y = *y - 3;
		else if (key[KEY_INPUT_DOWN]>0)
			*y = *y + 3;
		else if (key[KEY_INPUT_RIGHT]>0)
			*x = *x + 3;
		else if (key[KEY_INPUT_LEFT]>0)
			*x = *x - 3;
	}
	return 0;

}

int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
	ChangeWindowMode(TRUE), DxLib_Init(), SetDrawScreen(DX_SCREEN_BACK);
	SetWindowSizeChangeEnableFlag(TRUE);

	float x = 320,y=240;

	while (ProcessMessage() == 0 && ClearDrawScreen() == 0)
	{
		key_update(key);

		if (key[KEY_INPUT_RSHIFT] > 0 || key[KEY_INPUT_LSHIFT] > 0)
			slow_move(&x,&y, key);
		else
			quick_move(&x, &y, key);

		DrawBox(x,y,x+32,y+32,GetColor(255,255,255),true);

		ScreenFlip();
	}
	
	DxLib_End();
	return 0;
}

少し他の所についても言っておくと、速度等は定数にしてPlayerに持たせるか、どこか別の場所に定義しておくべきでは?
それとsqrt関数を使用するにはmath.hが必要です(開発環境によっては動いてしまうけど)書いておいたほうが親切かとおもいます。
オフトピック
どうでもいいけど、右Shiftで低速移動する人なんているのかなぁ...
だいがくせい!

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

Re: キャラクターの移動について

#6

投稿記事 by みけCAT » 9年前

こちらで試した所高速移動、低速移動ともに8方向に普通に動けたので、やはりキーボードの仕様でしょう。
Iseuma14 さんが書きました:もう少し教えていただけませんか?
  • 安いキーボードでは、回路の都合上全てのキーの押し方の組み合わせを検出できないことがある
  • USB接続のキーボードでは、プロトコルの都合上6キー+修飾キーまでしか送れない
だそうです。
詳しくはこの辺の記事を見るといいでしょう。
なぜPCのキーボードは「3キー以上の同時押し」ができないのか - DNA
4Gamer.net ― 「4Gamer Keyboard Checker」公開。キーボードのロールオーバーや同時押し対応をチェックしてみよう
Hiragi(GKUTH) さんが書きました:というか殆どコンマのせいに思えてきました。
それは気のせいでしょう。
player.x = 160,0; は「player.xに整数の160を代入し、その後0(無意味な式)を評価する」
player.x = 160.0; は「player.xに実数の160.0を代入する」
であり、今回の場合は結果に影響を与えないはずです。
厳密に規格をチェックしてはいませんが、おそらくundefined behaviorでもないでしょう。
もしもこの程度のコードの違いで計算結果に影響が出るようなら、明らかにコンパイラ(アセンブラやリンカなどのツールチェインを含む)が悪いでしょう。
添付ファイル
kyarakutaanoidounituite.zip
コンパイルしたソースコードとバイナリ
(3.17 MiB) ダウンロード数: 120 回
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

Iseuma14
記事: 54
登録日時: 10年前

Re: キャラクターの移動について

#7

投稿記事 by Iseuma14 » 9年前

>>Hiragi(GKUTH)様ご回答ありがとうございます
Hiragi(GKUTH) さんが書きました: ・まず提示されたコードの19行目がピリオドでなくコンマが使われています。
else if~が大量に出現するのはマズい、というか自身でも何がどうなっているのか理解できなくなってしまいそうなので、 そんなことなかったです。斜め移動時に
 フラグを立て、斜め移動した後は純粋な横、縦移動をしないように作ってみるとそれなりの動きをしてくれました。
実数型を使われているのでしょうか? 切り落とされて移動できない可能性もあります。 こちらではfloatにしました 初期化部より実数型なのでしょう。
ご確認ください。

少し他の所についても言っておくと、速度等は定数にしてPlayerに持たせるか、どこか別の場所に定義しておくべきでは?
それとsqrt関数を使用するにはmath.hが必要です(開発環境によっては動いてしまうけど)書いておいたほうが親切かとおもいます。
オフトピック
どうでもいいけど、右Shiftで低速移動する人なんているのかなぁ...
19行目のコンマ、お恥ずかしい限りにございます、、、
今回、このプログラムでfloatでなく、doubleを採用しているのは、龍神録プログラミングの館のDixq様のch_t構造体に則らせていただいているゆえです

さて、ご教授いただきましたプログラムを私のほうでも実行させていただきましたが、やはり右上に動けないのでみけCAT様が先にお答えしたようにこちらのノートパソコンのキーボードの仕様のようです

それと速度のほうですが、確かに定数のほうが良いかもですね 作り変えさせていただきます
また、math.hはmain.cppではsqrtを使っていないのでincludeしておりませんでした

右shiftでも低速移動できるのは東方紅魔郷で右shiftでも低速移動できたのでつけてみました^^;

Iseuma14
記事: 54
登録日時: 10年前

Re: キャラクターの移動について

#8

投稿記事 by Iseuma14 » 9年前

>>みけCAT様、再び回答ありがとうございます
みけCAT さんが書きました:こちらで試した所高速移動、低速移動ともに8方向に普通に動けたので、やはりキーボードの仕様でしょう。
そのようですね
私もほかの弾幕シューティング(東方)で試したところ、そちらでも低速で右上へは動けませんでした

今まで気がつかなかった = ある程度プレイには支障がないということなので、公にリリースすることレベルになったとき
またこの問題については考えてみようと思います

改めましてありがとうございました

閉鎖

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