床や壁の当たり判定



床や壁の当たり判定は厄介です。人それぞれ判定の方法は違うんだと思いますが、私の方法は、 画面をRPGと同じようなマップチップで区切り、キャラクターの4点それぞれのマップ上の座標から判定します。
左方向への移動の場合はキャラクターの左端座標、右方向なら右端、上方向なら上端、下方向なら下端をチェックし、 そのマップ上の座標が前回のループと違っていたらそこを壁と判断し、位置を訂正する、という方法です。

#const scx 300		;ウィンドウサイズx
#const scy 300		;ウィンドウサイズy
#const osize 16		;自分の大きさ

	buffer 2,scx,scx	;背景画像用
	tipsize=20		;1マスの大きさ
	tipx=scx/tipsize	;マスの数x
	tipy=scy/tipsize	;マスの数y
	dim map,tipx,tipy	;マップデータ
	color : boxf
	repeat tipx	;ランダムでマップ作成
		c=cnt
		rnd high,5 : high++
		repeat high,1
			c2=tipy-cnt
			map.c.c2=1		;1で移動不可能場所
			color 255,255,255	;移動不可能場所は白
			boxf c*tipsize,c2*tipsize,c+1*tipsize-1,c2+1*tipsize-1
		loop
	loop

	screen 0,scx,scx

	jump=10		;ジャンプ力
	grab=2		;重力(高いほど重力低い)
	gcount=grab	;重力カウンター
	fallmax=15	;最高落下速度
	speed=2		;横移動スピード
	ox=winx-osize/2	;自分位置x
	oy=0		;自分位置y
	omx=0		;左右移動量
	omy=0		;上下移動量
	gos=0		;地上にいるか空中にいるか

	font "MS ゴシック",osize

*mainloop	;メインループ
	redraw 0
	gosub *drawback
	gosub *setown
	gosub *drawown
	redraw
	await 1
	goto *mainloop

*drawback	;背景描画
	pos 0,0 : gcopy 2,0,0,winx,winy
	return

*drawown	;自分描画
	color 255 : pos ox,oy : mes "●"
	return

*setown		;自分の処理
	olp=ox/tipsize		;移動前のマップ上の位置を保存(左)
	orp=ox+osize-1/tipsize	;右
	otp=oy/tipsize		;上
	obp=oy+osize-1/tipsize	;下

	obp2=oy+1+osize/tipsize
	if map.olp.obp2|map.orp.obp2 : gos=1 : else : gos=0	;地上にいるか空中にいるか

	stick key,5
	if key&1 : omx=-speed
	if key&4 : omx=speed
	if key&16 : if gos : omy=-jump

	gcount--
	if gos : gcount=0
	if gcount=0 {
		omy++		;下方向移動量+1
		gcount=grab	;カウンターを元に戻す
	}
	if omy>fallmax : omy=fallmax	;最高落下速度に達したらそこまで
	ox+omx : oy+omy	;移動

	if ox<0 : ox=0	;画面左端
	if ox>(scx-osize-1) : ox=scx-osize-1	;画面右端
	if oy<0 : oy=0	;画面上端

	if omx<0{
		olp2=ox/tipsize
		if olp2!=olp {
			otp2=oy/tipsize
			obp2=oy+osize-omy/tipsize
			if map.olp2.otp2|map.olp2.obp2 : ox=olp*tipsize
		}
	}
	if omx>0 {
		orp2=ox+osize/tipsize
		if orp2!=orp {
			otp2=oy/tipsize
			obp2=oy+osize-omy/tipsize
			if map.orp2.otp2|map.orp2.obp2 : ox=orp2*tipsize-osize-1
		}
	}
	omx=0	;横移動量を0に戻す

	if omy<0{
		otp2=oy/tipsize
		if otp2!=otp {
			olp2=ox/tipsize
			orp2=ox+osize/tipsize
			if map.olp2.otp2|map.orp2.otp2 : oy=otp*tipsize : omy=0
		}
	}
	if omy>0 {
		obp2=oy+osize/tipsize
		if obp2!=obp {
			olp2=ox/tipsize
			orp2=ox+osize/tipsize
			if map.olp2.obp2|map.orp2.obp2 : oy=obp2*tipsize-osize-1 : omy=0
		}
	}
	return

黄色い文字のところが変更点です。たくさん変数使っててわかりにくいですが…。
*setownルーチンのif omx<0から最後までが、壁判定を行っています。
その判定の前に実際に移動してあり、移動した場所が壁と重なっていると元の位置へ戻るようになっています。
この方法は…どうなんでしょう?効率悪い気もするんですが…。
みんなはどうやってジャンプアクション系作っているのかが未だにわからないのですが…。


前へ 戻る 次へ