微妙な位置にいるとき

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
nya

微妙な位置にいるとき

#1

投稿記事 by nya » 17年前

はじめまして。(と言っても私の方は友人の紹介で数年間見てました。)

ここの掲示板とかゲームの作り方のページとか見て、私もゲーム作りたいって事で、
初心者ですけどDXライブラリで作っているところです。

で、ボ○バーマンのパロディ(笑)を作ってるのですが、
キャラクタが通れる所とブロックの微妙な位置に立ってる時、
自 <こんな具合
 ■
ずれて動いてくれるようにするには、どんなプログラムを書くべきでしょうか…
(上の場合、↓を入力するとちょっと左にずれてくれる、みたいな。)
キャラの座標を小数で設定すると、色々と変なことになってしまうのです…

管理人

Re:微妙な位置にいるとき

#2

投稿記事 by 管理人 » 17年前

初めまして。

お~まさに私と同じ所でつまずいていらっしゃいますね(笑
私もボンバーマンは作ったのですが、そこで苦労しました。

座標がちょうど32で割れる時だけしか十字方向に進めないシステムではものすごく操作性が悪いので、
中間でもスムーズに動かないといけないんですよね。

まぁ単純に考えられるのが、画像のような中途半端な位置で上ボタンを押した時、上には行かず、
現在の位置から近い左右どちらかの方に進ませる方法ですよね。

フィーリングとしてこんな感じですかね?
(1区間が32ピクセルだと仮定します)
if(上方向が押されている){
	if(xが32で割り切れない位置){
		if(座標%32>=16)
			右に進ませる;
		else
			左に進ませる;
	}
	else{
		上に進ませる;
	}
}
 
ただこれではカクカク動いて美しくないので、カドッコに来たら曲線を描くようにしました。
ややこしいんで、最初はやらない方がいいと思います^^;

管理人

Re:微妙な位置にいるとき

#3

投稿記事 by 管理人 » 17年前

なお、曲線にしなくても、こんな風に軌跡を描かせても見た目随分滑らかに動いているように見えました。
というか、むしろ見た目これと全く違いがわかりません。
もし上の方法ではあまりにカクカクしすぎると思ったときはこちらで実装してみてはいかがでしょうか。

もうご覧になったかもしれませんが、実装したらこんな感じになりました。
[youtube][/youtube]

nya

Re:微妙な位置にいるとき

#4

投稿記事 by nya » 17年前

おぉ、早速ありがとうございます。

実は、管理人さんの作られたボンバーマンもちゃっかり持ってます。全クリしましたw

それで、実はそんな感じのプログラムを組んでるんですが、
キャラクタのスピードを設定するのに、
if(下が押された){
	…
	if(左下が壁){
		(キャラのx座標)+=0.5+(0.5*スピード);
	}
	(キャラのy座標)+=0.5+(0.5*スピード);
	…
}
として、表示する時に (int)(キャラの座標) みたいにして動かしてるんです。
そうすると、スピードが速い時に絵のように壁にめり込んで…

微妙なスピードでキャラを動かすにはどうすべきなんでしょうか?
画面の更新(垂直同期がどーとか)とは別個にこういう数値を変える方法があるんでしょうか?

管理人

Re:微妙な位置にいるとき

#5

投稿記事 by 管理人 » 17年前

え、マジですか!配布していないゲームを持っていらっしゃるとは結構こちらも存じている可能性が・・。
あのゲームは爆弾を蹴るとたまに変な残像が表示されます(笑


え~とプログラムがはっきり想像出来ませんが、例えば32で割り切れる座標を区間の境目として計算していますか?

32の倍数の座標はスピードが+1、+2なら通りますが、+3なら通りません。+4なら通ります。
そういった加算がうまくいってないとかそういう意味でしょうか?
でも、小数点を使っていると言う事は座標はdouble型で管理しているんでしょうか?

マップがどういった管理になっているのか、配列を使っているのかもわかりませんし、
これだけじゃなんともいえないのですが、

例えば添付ファイルのような3x3の二次元配列で管理した時、属する要素は[y/32][x/32]=[1][0]ですからねぇ。
見た目属している区間は[2][1]のようですが、そういうのに気をつけないといけませんね。

もうちょっと移動制御の部分を詳しく書いてもらえるとわかるかもしれません。

nya

Re:微妙な位置にいるとき

#6

投稿記事 by nya » 17年前

本文長いです、スミマセン…
ソースまるごとはチト恥ずかしいので、勘弁してください…
あと、無駄に絵とか貼っちゃってモウシワケナイ…


>え、マジですか!配布していないゲームを持っていらっしゃるとは結構こちらも存じている可能性が・・。
友人が以前ここでC言語のお勉強をしてました。私自身は確かにはじめましてです。
ちなみに来月から大学生の予定です。(まだ受かってませんが)


管理人さんが言わんとしている事が分かるような分からないような…

すみませんが、こっちが解像度320x240、1ブロック16x16でやってるので、
それで話を進めさせてください。

まず、マップのデータは
unsigned char STAGE_MAP_DATA[20*15]={
	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,
	0,1,1,1,1,1,1,1,1,1,1,1,1,1,0, 0,0,0,0,0,
	0,1,0,1,0,1,0,1,0,1,0,1,0,1,0, 0,0,0,0,0,
	0,1,1,1,1,1,1,1,1,1,1,1,1,1,0, 0,0,0,0,0,
	0,1,0,1,0,1,0,1,0,1,0,1,0,1,0, 0,0,0,0,0,
	0,1,1,1,1,1,1,1,1,1,1,1,1,1,0, 0,0,0,0,0,
	0,1,0,1,0,1,0,1,0,1,0,1,0,1,0, 0,0,0,0,0,
	0,1,1,1,1,1,1,1,1,1,1,1,1,1,0, 0,0,0,0,0,
	0,1,0,1,0,1,0,1,0,1,0,1,0,1,0, 0,0,0,0,0,
	0,1,1,1,1,1,1,1,1,1,1,1,1,1,0, 0,0,0,0,0,
	0,1,0,1,0,1,0,1,0,1,0,1,0,1,0, 0,0,0,0,0,
	0,1,1,1,1,1,1,1,1,1,1,1,1,1,0, 0,0,0,0,0,
	0,1,0,1,0,1,0,1,0,1,0,1,0,1,0, 0,0,0,0,0,
	0,1,1,1,1,1,1,1,1,1,1,1,1,1,0, 0,0,0,0,0,
	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0
};
という感じで作ってます。0が通れないブロック、1が通れるブロックです。

で、どんなマップでも同じ動きをするよう汎用性を持たせたかったので、
キャラクタの上下左右を調べて、そこに該当するブロックが何か調べたりしてます。
画像の淡灰色の■がキャラで、赤い点が調べる位置です。
//キャラの上側のブロック当たり判定。0:動けない  1:動ける
unsigned char BlockJudge_U(int x,int y,unsigned char *map){
	if( map[ ((y+16)/16)*20 + (x+8)/16 ] == 0 ) return 0;
	else return 1;
};
こんな感じで上下左右作ってます。それで、
if( Key[ KEY_INPUT_UP ] ){		//上ボタンが押されたら
	if(BlockJudge_U((int)ch.x,(int)ch.y,STAGE_MAP_DATA)==1){	//上が動けるブロックで
		if( (int)ch.x%16!=0 ){					//微妙な位置のとき、
			if( BlockJudge_L((int)ch.x,(int)ch.y-16,STAGE_MAP_DATA)==1 )	//左上が動けるなら(-16は1ブロック上の意)
				ch.x-=(0.5+ch.speed*0.5);				//xの値を1減らす
			if( BlockJudge_R((int)ch.x,(int)ch.y-16,STAGE_MAP_DATA)==1 )	//右上が動けるなら
				ch.x+=(0.5+ch.speed*0.5);				//xの値を1増やす
		}
		ch.y-=(0.5+ch.speed*0.5);				//yの値を1減らす
	}
}
そうそう、 ch.x と ch.y はdouble型、ch.speed はint型です。けど、こうやって書いちゃえばいいかなぁなんて…
元々整数値にしてたんですが、それだけだと急激に速くなるので、小数を使ってみました。
そうすると、「ch.x+=1」とかと等しい値になるとちゃんと画像のように行ってくれますが、
やっぱり3とか5とかX.5になると移動しすぎで右側のブロックにズボッとなります。(ならない場合もあったりしちゃう)


…なんか16の約数の問題っぽい気もしてきましたが。うまく思いつかない…

管理人

Re:微妙な位置にいるとき

#7

投稿記事 by 管理人 » 17年前

こういうのは1次元配列で扱うとバグの元になると思います。
2次元の問題は2次元配列で扱うとわかりやすいです。

まずマップを
STAGE_MAP_DATA[15][20]で書いたほうがよさそうです。
unsigned char STAGE_MAP_DATA[15][20]=
{
	{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0},
	{0,1,1,1,1,1,1,1,1,1,1,1,1,1,0, 0,0,0,0,0},

(略)

	{0,1,1,1,1,1,1,1,1,1,1,1,1,1,0, 0,0,0,0,0},
	{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0}
};

こういう形で初期化したとき、[y][x]になるので気をつけて下さい。
現在属している配列要素が

map[y][x]だとしたら、
上にいけるかどうかは単純に言えば

if(map[y-1][x]==1)
    return 通れる;

で判定できます。まぁここの判定は仰るようにちょっと面倒なわけですが。


そして

ch.x-=(0.5+ch.speed*0.5);

このspeedが大きいと、16の倍数の座標を通り越してしまうということが
問題だと仰っているのでしょうか?
足し算をするとき、私はループ分で行いました。

ch.x += 3;

じゃなく、

for(i=0;i<3;i++){
    ch.x += 1;
    if(ch.xが境界線なら)
        break;
}

こうすれば、境界線を踏み越える事がありません。
 
 

nya

Re:微妙な位置にいるとき

#8

投稿記事 by nya » 17年前

ありがとうございます!

そんな単純なことだったんですか。
配列も二次元で書くよう気をつけます…

なんか複雑に考えようとしてた自分がバカみたいです。

自分の中ではスッキリしたので、解決とさせてください。

今後も何かあったら宜しくお願いします…

管理人

Re:微妙な位置にいるとき

#9

投稿記事 by 管理人 » 17年前

多分そんなに簡単には解決せず、色々と苦労するとは思いますが、頑張って下さい^^;
作ってみると「あ~ハドソンもここで苦労したんだろうな~」とか分ってくるのでおもしろいですよねw

閉鎖

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