ジャンプについて

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

ジャンプについて

#1

投稿記事 by ニャガバル » 12年前

プログラミングを勉強している大学生です。

『龍神録プログラミングの館』に載っている「龍神録」をDLさせていただき、それを基に2Dの横スクロールのゲームを作成しています。

今回、スーパーマ〇オのようなジャンプを組み込みたいと思い様々な方法を試してみましたが上手くいかず、この掲示板にやってきました。

※20章の内容から派生してプログラムを書き換えています。

コード:

#include "../include/GV.h"

void calc_ch(){
	ch.cnt++;
	ch.img=(ch.cnt%24)/6;
	if(CheckStatePad(configpad.left)>0)//左キーが押されていたら
		ch.img+=4*2;//画像を左向きに
	else if(CheckStatePad(configpad.right)>0)//右キーが押されていたら
	    ch.img+=4*1;//画像を右向きに
	
	if(CheckStatePad(configpad.left)>0)//左が押されていたら
                ch.x-=3;//座標を左に
    if(CheckStatePad(configpad.right)>0)//右が押されていたら
                ch.x+=3;//座標を右に
	if(FIELD_Y == 478){
	    if(CheckStatePad(configpad.up)>0)
		        ch.y-=3;}
	else ch.y+=3;
}
予想ではこれで、upの入力に対して上に進みその後FIELD_Yの初期位置(478)に戻ってくる、と考えました(ちゃんとしたジャンプではないですが)。
しかし実行後、すぐに下へ落ちて行ってしまいました。

これにジャンプのプログラムを組み込むにはどうしたらいいのでしょうか。
ご返答をお願いします。

アバター
パコネコ
記事: 139
登録日時: 13年前
住所: 大阪

Re: ジャンプについて

#2

投稿記事 by パコネコ » 12年前

私自身はマリオのジャンプ(前回の座標を参照)を使わないのですが、一応こちらのサイト様で式が乗ってます。
http://d.hatena.ne.jp/Gemma/20080517/1211010942

とりあえず
if(FIDLD_Y==478)
が、地面判定として仮定させていただきます。
//でもFIDLD_Yって変数?
そして新しい変数、
y_old(yと同じ型)
を仮定させていただきます。
y_oldは、前回の座標です。

コード:

int F=0;
if(地面判定){
	F=0;//消してもいいけどね
	if(ボタン判定){
		F=10;//じゃんぷ♪
	}
}
else F=-1;//落下修正
if(F!=0){
	int y_temp=ch.y;//今の座標を保存
	ch.y+=(ch.y-ch.y_old)-F;//ジャンプの移動修正
	ch.y_old=y_temp;//保存した座標を過去のものとして保存
}
とりあえず参照サイトのを改良いたしました。
テストしてないんで保証はしませんが、
参考程度にはなるかと思います。
仕組みが分からなければ、どこが分からないのか書き込んでいただければ、解説します。
(プログラムミスってたらすいません)

//////
ミスが合ったので修正中
修正しました。
//////
さらに修正。
ちなみに、
値を追ってみた

コード:

座標/移動量/座標/前座標/F
0
-3	-3	=	0	-	0	-3
-5	-2	=	-3	-	0	+1
-6	-1	=	-5	-	-3	+1
-6	0	=	-6	-	-5	+1
-5	1	=	-6	-	-6	+1
-3	2	=	-5	-	-6	+1
0	3	=	-3	-	-5	+1
行わない	=	0	-	-3	0
ニャン!!\(゜ロ\)(/ロ゜)/

jay
記事: 314
登録日時: 13年前
住所: 大阪市
連絡を取る:

Re: ジャンプについて

#3

投稿記事 by jay » 12年前

う~ん・・・、取りあえずよく分からないのがこの辺りですね

コード:

if(FIELD_Y == 478){
        if(CheckStatePad(configpad.up)>0)
                ch.y-=3;}
    else ch.y+=3;
直訳するなら"FIELD_Yが478でなお且つCheckStatePad(configpad.up)の戻り値が0以上なら(つまり上キーを入力していたら)ch.yを-3させる(上に移動させる)"
"FIELD_Yが478以外ならch.yを+3させる(下に移動させる)"
ですよね

そもそも
FIELD_Yの初期位置(478)
と言っているにも関わらず
if(FIELD_Y == 478)
とif文で判定している意味が分かりません。 FIELD_Yは定数ではなく変数なのでしょうか?

そして実行後にすぐ下に落ちるということは恐らく
else ch.y+=3;
の部分が処理されているのだと思います。


以下にジャンプの処理についての考え方を書いてみますね。 参考にしてみてください

①上キーが入力されているかどうか判定する

②入力されていた場合ジャンプが可能かどうか判定する
 要は地面に足を着いているかどうかですね。

③ジャンプが可能ならばジャンプさせる
  移動量の変数を用意して、最初は大きく上に移動させ(地面を蹴った瞬間が一番上方向へのエネルギーが大きいからですね)
  (重力によって)徐々に上方向へのベクトルを小さくし最終的に下方向への移動量にさせる(もちろん下へ移動を始めてからも下への加速は続く訳ですが)
  というのが一般的だと思います。 場合によっては下への移動量に制限を掛けたりしますけどね。
  物理の話になるのでややこしくなりますが、この辺りも参考になる・・・かもしれません。
  http://dixq.net/g/30.html

④地面との当たり判定を行って、当たった場合は着地させる


こんな感じでしょうか
行ってることが分からなければスルーしてもいいです(オイ)
♪僕たちは まだ森の中 抜け出そう 陽のあたる場所へ

ニャガバル

ご返答ありがとうございます

#4

投稿記事 by ニャガバル » 12年前

丁寧に解説・指摘をしていただき感謝申し上げます。

>パコネコ様
ご返答ありがとうございます。

FIELD_Yは定数でした。キャラクターの初期位置の定義としてdefine.cppにすでに書いており、単純な勘違いでした。すいません。
if文の中では変数の変化に対応して処理を行うということですね。
Fというのはサイト様にあった「その瞬間の力」を定義した、ということですよね?

そして

コード:

ch.y+=(ch.y-ch.y_old)-F;//ジャンプの移動修正
この文を説明していただけないでしょうか?お願いします。

>jay様
ご返答ありがとうございます。

その文は間違いでした。本来define.cppにて定数の定義をされていたFIELD_Yを変数扱いで書いてしまいました。

ジャンプの処理についての考え方、も提示していただきありがとうございます。
そのまま実行すると②の基準がないことになってしまい、上入力を入れるとそのまま上昇を続けるということになりますからね。

ニャガバル

#5

投稿記事 by ニャガバル » 12年前

続けて失礼します。

>パコネコ様
本来は左下の座標に立って(とりあえずは)左右に動くのですが、ご指摘の文を書き加えたところ、
初期位置に現れず、右下の画面外にいると思われます。

コード:

else F=-1;//落下修正
            if(F!=0){
                ch.y_temp=ch.y;//今の座標を保存
                ch.y+=(ch.y-ch.y_old)-F;//ジャンプの移動修正
                ch.y_old=ch.y_temp;//保存した座標を過去のものとして保存
}
申し訳ありませんが、この文の解説をしていただけませんか?

アバター
パコネコ
記事: 139
登録日時: 13年前
住所: 大阪

Re: ジャンプについて

#6

投稿記事 by パコネコ » 12年前

返信させていただきます。

ch.y+=(ch.y-ch.y_old)-F;//ジャンプの移動修正
の説明ですが、
(ch.y-ch.y_old)
から説明させていただきます。

これは現在の座標から前回の座標分を引いた値、
つまり前回からの移動した値を意味します。

コレにより前回の移動量分移動させる事ができます。

次にFですが、ボタンを押した瞬間は「10」となりその後、地面に当たるまでは「−1」となります。
では、前回の移動量分-Fをしてみましょう。

前回の移動量は元々は0です。
まぁ移動してませんからw

ボタンを押したらどうなるでしょうか?
Fの値を10にするので、
前回の移動量-10
となります。
よって、0-10により、-10となります。
では元々この式は、ch.yに足すためのものなので、足しましょう。
y+=-10;
によりy-10です。
yの値が減るという事は上に上がります。

次に、上に上がったという事は地面とのあたり判定は外れているという事になります。
(頭打つようなとこだと微妙ですが...)
なので、次はF=-1としましょう。

前回からの移動量は-10ですので、
y+=(-10)-(-1);
となります。
つまり
y+=-10+1=-9
です。
次はyの値から9引いてあげましょう。
前回減った値が10で今回が9です。
このまま計算を続けるとどんどん増えて行きます。
(-10 -> -9 -> -8 -> ... ->0->1->2->3)

あの式についてはこんな感じで良いと思います。
まだ分からない点がありましたらまた質問してください。

で、
バグについてですが、
考えられる点をいくつか上げさせていただきます。
*単に私のミス。
*ch.y_oldの初期化し忘れ。
(まぁoldの値の更新を移動時のみではなく毎回にしたら楽なんですけどね。
一番上と一番下に書かなきゃ行けなくなるからな...説明しづらいのでまとめてますが...)
*当たり判定が間違っているため堕ち続ける。
(ちなみに当たり判定を行うときは普通は当たった位置に戻してあげる処理が合った方がいいです。)

いったいどのくらいのサイズの子なのかはワカリマセンが、当たり判定が地面のみなら、

コード:

if(地面のy座標ー物体の大きさ<物体のy座標){
	物体のy座標=地面のy座標ー物体の大きさ;
}
があると便利かと思います。

少し長文になってしまいましたが、こんな感じではないかと思います。
ニャン!!\(゜ロ\)(/ロ゜)/

アバター
パコネコ
記事: 139
登録日時: 13年前
住所: 大阪

Re: ジャンプについて

#7

投稿記事 by パコネコ » 12年前

連投失礼します。

コード:

if(F!=0){
      ch.y_temp=ch.y;//今の座標を保存
      ch.y+=(ch.y-ch.y_old)-F;//ジャンプの移動修正
      ch.y_old=ch.y_temp;//保存した座標を過去のものとして保存
}
コレの解説をさせていただきます。といっても先ほどの投稿のときに、

コード:

ch.y+=(ch.y-ch.y_old)-F;//ジャンプの移動修正
については説明させていただいたので省略させていただきす。

if(F!=0)
ですが、そのまんまです。
Fが0以外なら処理を行います。
地面に面しているときはFは0になります。
が、地面に面しているときにジャンプボタンを押すと、Fは10になります。
(10というよりも、定数と言った方がいいかも...)
そして逆に地面に面してないときは-1となります。
つまり地面に面してないときか、ボタンを押したときに処理を行います。
(消そうと思えば消せますけどね...)

次はifの中身です。
3行のうち2行目は既に解説ずみなので、とりあえず飛ばして、
残りの1行目と3行目に付いてですが、
これは、移動を行うとyの値が書き換えられてしまうため、一旦バックアップを取っているだけです。
そして、移動が終わった後にバックアップのデータを過去のものとして保存してます。

とただそんだけですw
分からない所があれば質問を書いといていただければ、解答いたします。
ニャン!!\(゜ロ\)(/ロ゜)/

閉鎖

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