マリオ系2Dアクション。ブロックに当たったら。
マリオ系2Dアクション。ブロックに当たったら。
こんにちわ。今、マリオ系の2Dアクションゲームを適当に作ってるんですけど、
ゲームプログラミングの館の
「27. ジャンプの考え方1(物理)」を参考にしてキャラを動かしたり、
「24. 行けない所を作る。~2D~」を参考にしてブロックを描画することができたのですが、
ブロックに乗れたり、下からぶつかった時の判定(ぶつかっておちる)
をどうやってやればいいのかわかりませんorz
何かいい方法を教えてくださいm(_ _)m
ゲームプログラミングの館の
「27. ジャンプの考え方1(物理)」を参考にしてキャラを動かしたり、
「24. 行けない所を作る。~2D~」を参考にしてブロックを描画することができたのですが、
ブロックに乗れたり、下からぶつかった時の判定(ぶつかっておちる)
をどうやってやればいいのかわかりませんorz
何かいい方法を教えてくださいm(_ _)m
Re:マリオ系2Dアクション。ブロックに当たったら。
あたり判定は人によって違うので、いい方法なのかはわかりませんが、1つの方法として…
私が使っているのは
x1=x/32;
y1=y/32;
x2=(x+31)/32;
y2=(y+31)/32;
//左上判定
if(map[x1][y1]==1){//1はブロック
ぶつかったときの処理
}
//右上判定
else if(map[x2][y1]==1){
ぶつかったときの処理
}
//左下判定
else if(map[x1][y2]==1){
ぶつかったときの処理
}
右下判定
else if(map[x2][y2]==1){
ぶつかったときの処理
}
ぶつかったときの処理は、ブロックの位置に戻す、移動量を0にするとか…
私の場合、自分の周りを4つに区切ってそれぞれ判定させてます。
私が使っているのは
x1=x/32;
y1=y/32;
x2=(x+31)/32;
y2=(y+31)/32;
//左上判定
if(map[x1][y1]==1){//1はブロック
ぶつかったときの処理
}
//右上判定
else if(map[x2][y1]==1){
ぶつかったときの処理
}
//左下判定
else if(map[x1][y2]==1){
ぶつかったときの処理
}
右下判定
else if(map[x2][y2]==1){
ぶつかったときの処理
}
ぶつかったときの処理は、ブロックの位置に戻す、移動量を0にするとか…
私の場合、自分の周りを4つに区切ってそれぞれ判定させてます。
Re:マリオ系2Dアクション。ブロックに当たったら。
回答ありがとうございます。
ぶつかったときの処理ですが、右から左や左から右に当たった処理はできたんですが、
上から乗ることや下から上にぶつかるなどの処理をどうすればいいのかわかりませんでした。
ジャンプの処理は「27. ジャンプの考え方1(物理)」を参考にして↓のようにしています。
//ジャンプの動き
//ジャンプしてたら
if(xh.flag==1){
xh.time2 = GetNowCount() ; // 現在経過時間を得る
xh.t = (double)(xh.time2 - xh.time) / 1000.000; // ミリ秒を秒に変換して、エンターが押されてからの経過時間を計算
y = (int)( (sqrt ( 2.000 * g * y_max) * xh.t - 0.500 * g * xh.t * xh.t ) * 200.000 / y_max );//y座標を計算
if(y>=0){
if(xh.flag2==0){
xh.y=384-y;
xh.gazo=gazou[xh.muki];
}
if(xh.flag2==1){
xh.y=384-y;
xh.gazo=gazou[xh.muki2];
}
}
else{
xh.flag=0;
}
}
//ジャンプしてなかったら
if(xh.flag==0){
if(xh.flag2==0){
xh.y=384;
xh.gazo=gazou[xh.muki];
}
if(xh.flag2==1){
xh.y=384;
xh.gazo=gazou[xh.muki2];
}
}
と、こんな感じなんですけど・・・。
もしもぶつかったらどういうふうに数値を変更させたらいいのかわかりません。
どうすればいいのでしょうか?
ぶつかったときの処理ですが、右から左や左から右に当たった処理はできたんですが、
上から乗ることや下から上にぶつかるなどの処理をどうすればいいのかわかりませんでした。
ジャンプの処理は「27. ジャンプの考え方1(物理)」を参考にして↓のようにしています。
//ジャンプの動き
//ジャンプしてたら
if(xh.flag==1){
xh.time2 = GetNowCount() ; // 現在経過時間を得る
xh.t = (double)(xh.time2 - xh.time) / 1000.000; // ミリ秒を秒に変換して、エンターが押されてからの経過時間を計算
y = (int)( (sqrt ( 2.000 * g * y_max) * xh.t - 0.500 * g * xh.t * xh.t ) * 200.000 / y_max );//y座標を計算
if(y>=0){
if(xh.flag2==0){
xh.y=384-y;
xh.gazo=gazou[xh.muki];
}
if(xh.flag2==1){
xh.y=384-y;
xh.gazo=gazou[xh.muki2];
}
}
else{
xh.flag=0;
}
}
//ジャンプしてなかったら
if(xh.flag==0){
if(xh.flag2==0){
xh.y=384;
xh.gazo=gazou[xh.muki];
}
if(xh.flag2==1){
xh.y=384;
xh.gazo=gazou[xh.muki2];
}
}
と、こんな感じなんですけど・・・。
もしもぶつかったらどういうふうに数値を変更させたらいいのかわかりません。
どうすればいいのでしょうか?
Re:マリオ系2Dアクション。ブロックに当たったら。
ぐれーとさんのプログラムを理解してませんが、
上の壁にぶつかったら、自動落下に切り換え
地面にあたったらめり込まないように持ち上げる。
と、言う感じです。
私はジャンプを簡単に済ませてしまってるので…
同じジャンプの形を使ってる人を待つしか…
上の壁にぶつかったら、自動落下に切り換え
地面にあたったらめり込まないように持ち上げる。
と、言う感じです。
私はジャンプを簡単に済ませてしまってるので…
同じジャンプの形を使ってる人を待つしか…
Re:マリオ系2Dアクション。ブロックに当たったら。
僕もあんまり、「27. ジャンプの考え方1(物理)」
を理解していないので、どうやればいいのか・・・。
多分、「ジャンプを厳密に表現しようとすると」
って書いてあるので、なんだか難しいものになってるんだと思います。
なんだか僕には難しそうなので、
もしよければパコネコさんがどうやってプログラムしてるか見せてもらえませんか?
を理解していないので、どうやればいいのか・・・。
多分、「ジャンプを厳密に表現しようとすると」
って書いてあるので、なんだか難しいものになってるんだと思います。
なんだか僕には難しそうなので、
もしよければパコネコさんがどうやってプログラムしてるか見せてもらえませんか?
Re:マリオ系2Dアクション。ブロックに当たったら。
移動の部分だけ…
//================================横移動=================================
if(gl_getkeystate(VK_LEFT)<0){//左ボタン押したなら
sp--;
if(sp<-msp)sp=-msp;
}
else if(sp<0)sp++;
//-------------------------------------------------------------------------
if(gl_getkeystate(VK_RIGHT)<0){//右ボタン押したなら
sp++;
if(msp<sp)sp=msp;
}
else if(0<sp)sp--;
//===================================縦移動==================================
if(gl_getkeystate('X')<0 && jp==0){//ジャンプボタン押したなら
jps=-msp-msp/4;
jp=1;
}
//自動落下
jps++;
//横移動
x+=sp;
x1=x/z;
y1=y/z;
x2=(x+z-1)/z;
y2=(y+z-1)/z;
//ブロック判定
if(map[x1][y1]!=0 || map[x1][y2]!=0){//左判定
x=x2*z;
sp=0;
}
if(map[x2][y1]!=0 || map[x2][y2]!=0){//右判定
x=x1*z;
sp=0;
}
if(x-sk<z*2 || z*14<x-sk){//スライド
sk+=sp;
}
//ジャンプの処理
y+=jps;
x1=x/z;
y1=y/z;
x2=(x+z-1)/z;
y2=(y+z-1)/z;
if(map[x1][y1]!=0 || map[x2][y1]!=0){//上判定
y=y2*z;
jps=0;
}
if(map[x1][y2]!=0 || map[x2][y2]!=0){//下判定
y=y1*z;
jps=0;
jp=0;
}
全部int宣言(整数型)
sp :x軸の移動量
jps :y軸の移動量
msp :マックススピード
jp :ジャンプフラグ
x :キャラのx座標
y :キャラのy座標
z :キャラの大きさ
x1 :左ブロックの位置
x2 :右ブロックの位置
y1 :上ブロックの位置
y2 :下ブロックの位置
map[/url][/url]:0ならとおれる。1ならブロック。
それっぽいところを抜き出してみました…
あくまでも私の場合ですので…参考までに
入力はそのままでは使えませんよ。
//================================横移動=================================
if(gl_getkeystate(VK_LEFT)<0){//左ボタン押したなら
sp--;
if(sp<-msp)sp=-msp;
}
else if(sp<0)sp++;
//-------------------------------------------------------------------------
if(gl_getkeystate(VK_RIGHT)<0){//右ボタン押したなら
sp++;
if(msp<sp)sp=msp;
}
else if(0<sp)sp--;
//===================================縦移動==================================
if(gl_getkeystate('X')<0 && jp==0){//ジャンプボタン押したなら
jps=-msp-msp/4;
jp=1;
}
//自動落下
jps++;
//横移動
x+=sp;
x1=x/z;
y1=y/z;
x2=(x+z-1)/z;
y2=(y+z-1)/z;
//ブロック判定
if(map[x1][y1]!=0 || map[x1][y2]!=0){//左判定
x=x2*z;
sp=0;
}
if(map[x2][y1]!=0 || map[x2][y2]!=0){//右判定
x=x1*z;
sp=0;
}
if(x-sk<z*2 || z*14<x-sk){//スライド
sk+=sp;
}
//ジャンプの処理
y+=jps;
x1=x/z;
y1=y/z;
x2=(x+z-1)/z;
y2=(y+z-1)/z;
if(map[x1][y1]!=0 || map[x2][y1]!=0){//上判定
y=y2*z;
jps=0;
}
if(map[x1][y2]!=0 || map[x2][y2]!=0){//下判定
y=y1*z;
jps=0;
jp=0;
}
全部int宣言(整数型)
sp :x軸の移動量
jps :y軸の移動量
msp :マックススピード
jp :ジャンプフラグ
x :キャラのx座標
y :キャラのy座標
z :キャラの大きさ
x1 :左ブロックの位置
x2 :右ブロックの位置
y1 :上ブロックの位置
y2 :下ブロックの位置
map[/url][/url]:0ならとおれる。1ならブロック。
それっぽいところを抜き出してみました…
あくまでも私の場合ですので…参考までに
入力はそのままでは使えませんよ。
Re:マリオ系2Dアクション。ブロックに当たったら。
長かったので、こっちに解説を書きます。
キャラの周りのブロックなどを4つに分けました。
左上:map[x1][y1]
右上:map[x2][y1]
左下:map[x1][y2]
右下:map[x2][y2]
こんな感じで…
x1:左(x/z) || x2:右((x+z-1)/z)
y1:上(y/z) || y2:下((y+z-1)/z)
条件は…ブロックと自分の大きさが同じこと
横移動するときは、
左の判定if(map[x1][y1]!=0 || map[x1][y2]!=0)を判定して、x2*z(ブロックの右)の位置に移動
右の判定if(map[x2][y1]!=0 || map[x2][y2]!=0)を判定して、x1*z(ブロックの左)の位置に移動
次に縦移動させてから、
上判定if(map[x1][y1]!=0 || map[x2][y1]!=0)を判定する、y2*z(ブロックの下)の位置に移動
下判定if(map[x1][y2]!=0 || map[x2][y2]!=0)を判定する、y1*z(ブロックの上)の位置に移動
計4回の判定をすることになりますね。
それぞれ移動の後に移動量は0になります。
あたり判定はわりと気に入ってます。
ジャンプについてですよね。
自動落下?jps(縦移動量)は毎回下に行くように+1ずつされています。
ジャンプボタンを押したなら、jpsに-(マイナス)の値を入れてあげます。
マイナスのときは、上に行こうとするので0になるまで飛んでいきます。
自動落下のおかげで値は大きくなっていくので、マイナスのときは0に近づきます。
0になった後も大きくなり続けるので、床につくまで落下速度も大きくなります。(制限も入れましょう)
大きくというより、「はやく」ですけど…
長くなりましたが(書くのに1時間ぐらいかかっちゃった…)、解説もこんな感じです。
私の個人的なプログラムの傾向として、整数型しか扱ってませんが…
参考になったらうれしいです。
(物理的なちゃんとした式で作ってないので、妥協していい時だけにしたほうがいいです)
======ついで=========
このプログラムは、落下中のジャンプはOKという感じに作っています。
ただし、2段跳び禁止。
その他、このプログラムについてわからなければどうぞ…

キャラの周りのブロックなどを4つに分けました。
左上:map[x1][y1]
右上:map[x2][y1]
左下:map[x1][y2]
右下:map[x2][y2]
こんな感じで…
x1:左(x/z) || x2:右((x+z-1)/z)
y1:上(y/z) || y2:下((y+z-1)/z)
条件は…ブロックと自分の大きさが同じこと
横移動するときは、
左の判定if(map[x1][y1]!=0 || map[x1][y2]!=0)を判定して、x2*z(ブロックの右)の位置に移動
右の判定if(map[x2][y1]!=0 || map[x2][y2]!=0)を判定して、x1*z(ブロックの左)の位置に移動
次に縦移動させてから、
上判定if(map[x1][y1]!=0 || map[x2][y1]!=0)を判定する、y2*z(ブロックの下)の位置に移動
下判定if(map[x1][y2]!=0 || map[x2][y2]!=0)を判定する、y1*z(ブロックの上)の位置に移動
計4回の判定をすることになりますね。
それぞれ移動の後に移動量は0になります。
あたり判定はわりと気に入ってます。
ジャンプについてですよね。
自動落下?jps(縦移動量)は毎回下に行くように+1ずつされています。
ジャンプボタンを押したなら、jpsに-(マイナス)の値を入れてあげます。
マイナスのときは、上に行こうとするので0になるまで飛んでいきます。
自動落下のおかげで値は大きくなっていくので、マイナスのときは0に近づきます。
0になった後も大きくなり続けるので、床につくまで落下速度も大きくなります。(制限も入れましょう)
大きくというより、「はやく」ですけど…
長くなりましたが(書くのに1時間ぐらいかかっちゃった…)、解説もこんな感じです。
私の個人的なプログラムの傾向として、整数型しか扱ってませんが…
参考になったらうれしいです。
(物理的なちゃんとした式で作ってないので、妥協していい時だけにしたほうがいいです)
======ついで=========
このプログラムは、落下中のジャンプはOKという感じに作っています。
ただし、2段跳び禁止。
その他、このプログラムについてわからなければどうぞ…

Re:マリオ系2Dアクション。ブロックに当たったら。
親切に解説してくれて本当にありがとうございます!
この方法ならいけると思います。
これから調整していくので、もし、分からないことがあったら質問させていただきます。
この方法ならいけると思います。
これから調整していくので、もし、分からないことがあったら質問させていただきます。
Re:マリオ系2Dアクション。ブロックに当たったら。
試してみたんですけど、
ブロックの上にのるとブロックに張り付いちゃって左右に動けなくなるんですけど、
どうすればいいんでしょうか?
ブロックの上にのるとブロックに張り付いちゃって左右に動けなくなるんですけど、
どうすればいいんでしょうか?
Re:マリオ系2Dアクション。ブロックに当たったら。
もしかしたら
y2の代入を間違えていたりはしませんか?
y2=(y+z-1)/z
この「-1」を忘れていたり…違ったらすいません。
========
もうひとつ可能性が…
あたり判定や移動のプログラムの順番などを動かしたらうごかなくなります…
横移動
↓
横あたり判定
↓
縦移動
↓
縦あたり判定
みたいな順番が大切。
y2の代入を間違えていたりはしませんか?
y2=(y+z-1)/z
この「-1」を忘れていたり…違ったらすいません。
========
もうひとつ可能性が…
あたり判定や移動のプログラムの順番などを動かしたらうごかなくなります…
横移動
↓
横あたり判定
↓
縦移動
↓
縦あたり判定
みたいな順番が大切。

Re:マリオ系2Dアクション。ブロックに当たったら。
キャラの大きさは32です。
Xを押すとダッシュできるようにしています。
ダッシュの状態のマックススピードがdmspです。
どこか間違っているでしょうか><
x1 = x/32;
y1 = y/32;
x2 = (x+31)/32;
y2 = (y+31)/32;
//右方向の動き
if( Key[ KEY_INPUT_RIGHT ] == 1 ){
sp += 1;
if(msp < sp && Key[KEY_INPUT_X]==0)
sp = msp;
if( Key[ KEY_INPUT_X] ==1 ){
sp += 1;
if(dmsp < sp)
sp = dmsp;
}
}
//左方向の動き
if( Key[ KEY_INPUT_LEFT ] == 1 ){
sp -= 1;
if(sp < -msp && Key[KEY_INPUT_X]==0)
sp = -msp;
if( Key[ KEY_INPUT_X] ==1 ){
sp -= 1;
if(sp < -dmsp)
sp = -dmsp;
}
}
if(map[y1][x1]!=0 || map[y2][x1]!=0){//左判定
x =x2*32;
sp =0;
}
if(map[y1][x2]!=0 || map[y2][x2]!=0){//右判定
x =x1*32;
sp =0;
}
xh.x += xh.xsp/4;
//↑速さ調整しました。
//ジャンプの動き
if( Key[ KEY_INPUT_Z ] == 1 && jp==0){
jps=-20;
jp =1;
PlaySoundMem(sound2,DX_PLAYTYPE_BACK);//効果音
}
if(jps < 9)//落下速度制限
jps ++;
y += jps;
if(map[y1][x1]!=0 || map[y1][x2]!=0){//上判定
y =y2*32;
jps=0;
}
if(kabe[y2][x1]!=0 || kabe[y2][x2]!=0){//下判定
y =y1*32;
jps=0;
jp =0;
}
Xを押すとダッシュできるようにしています。
ダッシュの状態のマックススピードがdmspです。
どこか間違っているでしょうか><
x1 = x/32;
y1 = y/32;
x2 = (x+31)/32;
y2 = (y+31)/32;
//右方向の動き
if( Key[ KEY_INPUT_RIGHT ] == 1 ){
sp += 1;
if(msp < sp && Key[KEY_INPUT_X]==0)
sp = msp;
if( Key[ KEY_INPUT_X] ==1 ){
sp += 1;
if(dmsp < sp)
sp = dmsp;
}
}
//左方向の動き
if( Key[ KEY_INPUT_LEFT ] == 1 ){
sp -= 1;
if(sp < -msp && Key[KEY_INPUT_X]==0)
sp = -msp;
if( Key[ KEY_INPUT_X] ==1 ){
sp -= 1;
if(sp < -dmsp)
sp = -dmsp;
}
}
if(map[y1][x1]!=0 || map[y2][x1]!=0){//左判定
x =x2*32;
sp =0;
}
if(map[y1][x2]!=0 || map[y2][x2]!=0){//右判定
x =x1*32;
sp =0;
}
xh.x += xh.xsp/4;
//↑速さ調整しました。
//ジャンプの動き
if( Key[ KEY_INPUT_Z ] == 1 && jp==0){
jps=-20;
jp =1;
PlaySoundMem(sound2,DX_PLAYTYPE_BACK);//効果音
}
if(jps < 9)//落下速度制限
jps ++;
y += jps;
if(map[y1][x1]!=0 || map[y1][x2]!=0){//上判定
y =y2*32;
jps=0;
}
if(kabe[y2][x1]!=0 || kabe[y2][x2]!=0){//下判定
y =y1*32;
jps=0;
jp =0;
}
Re:マリオ系2Dアクション。ブロックに当たったら。
xh.x += xh.xsp/4;
//↑速さ調整しました。
↑がわからないですけど。
多分あたり判定の上に
x+=sp
x1 = x/32; //一つ余分に書いてました…
x1 = x/32;
y1 = y/32;
x2 = (x+31)/32;
y2 = (y+31)/32;
が必要。
y+=jpsの後にも
x1 = x/32;
y1 = y/32;
x2 = (x+31)/32;
y2 = (y+31)/32;
これが必要。
=========
>>else if(sp<0)sp++;
これも忘れてる…
ボタンを押してないとき
スピードを0に近づける処理…
===================
できたようでよかったです。
がんばってください。
//↑速さ調整しました。
↑がわからないですけど。
多分あたり判定の上に
x+=sp
x1 = x/32; //一つ余分に書いてました…
x1 = x/32;
y1 = y/32;
x2 = (x+31)/32;
y2 = (y+31)/32;
が必要。
y+=jpsの後にも
x1 = x/32;
y1 = y/32;
x2 = (x+31)/32;
y2 = (y+31)/32;
これが必要。
=========
>>else if(sp<0)sp++;
これも忘れてる…
ボタンを押してないとき
スピードを0に近づける処理…
===================
できたようでよかったです。
がんばってください。
