キャラクターのジャンプについて

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

キャラクターのジャンプについて

#1

投稿記事 by はね » 18年前

お久しぶりです。
早速質問なのですが、今、大学の授業でアクションゲームを作っています。
ところが、キャラクターをジャンプさせる所で詰まってしまいました。

こちらの「27.ジャンプの仕方」を参考にして作ってみたのですが(全く同じですが^^;)
上キーを押すと一瞬で画面の端まで動いてしまいうまくいきません。

文系だったもので物理はさっぱりです^^;

if( Key[ KEY_INPUT_UP ] == 1 ){
time1 = GetNowCount();
Player1.jumpflag=1;
}
if(Player1.jumpflag==1){
time2 = GetNowCount() ;
t = (double)(time2 - time1) / 1000.000;
Player1.y = (int)((sqrt ( 2.000 * g * y_max) * t - 0.500 * g * t * t ) * 480.000 / y_max);
if(Player1.y>=0)
DrawRotaGraph((int)Player1.x,(int)Player1.y,1.0f,0.0f,img_char1[0],TRUE);
else
Player1.jumpflag=0;
}

一応こんな感じにしたのですが、何が悪いのでしょう?
助言お願いします

Justy

Re:キャラクターのジャンプについて

#2

投稿記事 by Justy » 18年前

 表示座標(Player1.y)を 480から引いてみては?
 すくなくともhttp://dixq.net/g/#27のサンプルでは引いてます。

はね

Re:キャラクターのジャンプについて

#3

投稿記事 by はね » 18年前

素早い返答ありがとうございます
あ、確かに引いていました^^;見逃していたみたいです

で、480から引いてみたのですが
今度はキーを押したら一瞬で下まで移動してしまいます

Justy

Re:キャラクターのジャンプについて

#4

投稿記事 by Justy » 18年前

>今度はキーを押したら一瞬で下まで移動してしまいます
 最初はどこにいたのでしょう?

 一瞬というのは1秒くらいかけて、とかではなく、
何の途中の課程もなく瞬時に、ということでしょうか?

 gや y_maxの値はサンプルのままですか?

はね

Re:キャラクターのジャンプについて

#5

投稿記事 by はね » 18年前

>最初はどこにいたのでしょう?
今はとりあえず、x=200 y=400に設定しています。

>一瞬というのは1秒くらいかけて、とかではなく、
何の途中の課程もなく瞬時に、ということでしょうか?
そうです、何の課程もなく瞬時にです。

>gや y_maxの値はサンプルのままですか?
そうです。
g が9.8067で、y_maxが2.000です。

Justy

Re:キャラクターのジャンプについて

#6

投稿記事 by Justy » 18年前

 なんとなくわかってきましたので、確認します。
 位置はともかく、ジャンプはしていますか?

はね

Re:キャラクターのジャンプについて

#7

投稿記事 by はね » 18年前

>ジャンプはしていますか?
とおっしゃいますと、動きはともかく
ジャンプするフラグが立っているか?と言うことでしょうか?
それなら立っています。画像の表示を切り替えて確認しました。

Justy

Re:キャラクターのジャンプについて

#8

投稿記事 by Justy » 18年前

 位置はおかしいけど、ジャンプっぽい動きはしてるかな、と思ったんですけど、
してなさそうですね。
 ということは、画面下でずっと止まったままということですか?


 んー、なんだろう。
 上のプログラムですと、ジャンプ中の時だけ DrawGraphを使って描画していますが、
普通に歩いているときはどうしているのでしょう?

 別のところに DrawGraphがあるのでしょうか?


 歩いているときには別のところで DrawGraphしているけど
ジャンプ中は上の if文の中で DrawGraphしていて、
その2つの表示方法がうまく整合性がとれてなくて、ジャンプ中は
一瞬で移動してしまっている、と思ったのですが。

 上のソースを見るとジャンプ開始時のキャラが表示される y座標は
(直前の値が幾つであろうと)必ず 480付近になってしまいます。

 これがワープの原因だと思いますが、ジャンプの動き自体が
うまくいっていない理由がよくわからないですね。


#ビルド・再現できるソースがあると話が早いのですが・・・。

はね

Re:キャラクターのジャンプについて

#9

投稿記事 by はね » 18年前

>ということは、画面下でずっと止まったままということですか?
最初は初期化した座標(x=200 y=100)にキャラがいます。そして上キー(ジャンプボタン)を押すと、本当はジャンプさせたいのですが、現在は上キーを押すと一瞬で画面端までワープしてしまう状況です。

画像表示に関しては、書き込みした内容には書いていませんでしたが
例えば右キーを押すと画像表示、といったようにそれぞれに割り当てています。


すみません、ソースupしようと思ったのですが容量が大きいらしくupできませんでした。

Justy

Re:キャラクターのジャンプについて

#10

投稿記事 by Justy » 18年前

>現在は上キーを押すと一瞬で画面端までワープしてしまう状況です
 ワープした後はそのまま画面端のまま、ということでしょうか?
 画面端とはどの方向でしょうか?


>例えば右キーを押すと画像表示、といったようにそれぞれに割り当てています
 ジャンプ中のDrawRotaGraphの第二引数は今 480から Player1.yを引いた値に
なっていますよね?
 他の描画命令(右押したときとか)も統一してありますか?


>ソースupしようと思ったのですが容量が大きいらしくupできませんでした
 どっかのアップローダーを使うか、あるいはプレイヤー操作・表示に絡む
ソースだけならアップ可能でしょうか?

はね

Re:キャラクターのジャンプについて

#11

投稿記事 by はね » 18年前

ワープした後は一瞬だけ下(y+)方向に表示され消えてしまいます。

一応キャラの移動+表示に関係するソースをアップしましたのでよければご覧ください

Justy

Re:キャラクターのジャンプについて

#12

投稿記事 by Justy » 18年前

 わかりました。

 上を押したときに time1に時間を保存しているのに、
次にPlayerControl()が呼ばれた時に time1は前回の値を覚えていないので、
不定な値になっています。

 従って正しく tの値を計算できていません。

Justy

Re:キャラクターのジャンプについて

#13

投稿記事 by Justy » 18年前

 てっとり早く修正するなら、time1だけ、static intの型にするか、グローバル変数に
してみてください。

 それでジャンプしたときのワープは直るかと思います。

はね

Re:キャラクターのジャンプについて

#14

投稿記事 by はね » 18年前

なるほど。
ではtime1の値を一度保存させたら継続して使えるようにすればいいんですね

大変長い時間お付き合いいただきありがとうございました。
色々と考えてみます
これで先に進めそうです^^

Justy

Re:キャラクターのジャンプについて

#15

投稿記事 by Justy » 18年前

 あ、あとワープしてしまう問題はジャンプの公式に手を加えて初期y座標を
足してあげるとワープしなくなると思います。


 それはそれとしてざっとソースを見ると、いろいろ今後拡張していく上で、
いろいろ辛そうな点や問題点が幾つかありました。


・ DrawRotaGraphが複数箇所ある
 メンテナンスの点からプレイヤー1つに対して1個の DrawRotaGraph()に纏めないと
1カ所引数とかを変更したときに全部直さなければなりません。

 又、ジャンプ中に右とか左とか押すと二重にプレイヤーが描画されることがありますので、
そういう排他制御をしなくて済むよう、描画は1カ所にした方がいいと思います。



・ 時間
 このようにソースのあちこちで GetNowCount()を呼び出し、その時間差に応じた
処理をさせるのはあまり良い処理とは言えません。

 なぜならば、第1にプレイヤーのジャンプは保存したフレームとの実時間における差分を元に
算出するのに対し、通常の左右の移動は実時間とは何の関係もなく動いています。
 これでは処理としてはちぐはぐです。

 第二にプレイヤー側で保存したフレームとの時間差に応じて動作をするなら、
当然エネミーの移動についても同様に時間に応じた処理が必要になります。
 そこでも別途 GetNowCount()を使う呼び出して使う場合、細かいことは省略しますが、
同じフレームでプレイヤー・エネミー「双方」で時間を保存し、次のフレームで双方で
時間差を計ると、それぞれ異なる数値になることがあります。

 つまり、プレイヤーとエネミーが同時(同じフレームで)に同じ式・パラメータで
ジャンプしたとしても、着地のタイミングがわずかにずれる可能性があります。

 では、どうすればいいかというと、大元のメインループの先頭で時間を計測し
システムに記憶させます。
 で、プレイヤーやエネミーはその値を取得して各々で値を保存するようにすれば
それぞれで統一された時間を元に動かすことができます。

 ただ、時間ベースでキャラを動かす必要が本当にあるのかは検討しなければならないと思います。
 マルチタスクOS下では、裏の処理が重かったりするとキャラの動きが飛び飛びのになって、
何がなんだか判らないような動きになったり、あたり判定に失敗して抜けてしまったりする
危険性があるので、よほど実時間ベースでなければならない理由がない限り、
FPSを一定化した上でフレームベースの処理にした方がすっきりすると思います。
 

・ ジャンプ
 たしかにジャンプの公式としては合っていますが、シミュレータでもサンプルでもなくゲームなので、
この式のままではいろいろ不都合があります。
 
 将来的にジャンプ中に左右のキーで軽く移動したいかもしれないですし、滞空したくなるかもしれません。
 そもそもこの式の為にプレイヤーの画面上の座標を 480から引くというわかりにくい処理を
する羽目になっています。
 
(これって他のエネミーとかのあたり判定をとらなければならないオブジェクトとかも
480から引いて表示するか、或いはあたり判定を調べるときに 480から引いてから調べないと
いけないわけで、結構大変な事に)
 
 
 それを解決するにはこの式を変形して別の形で処理してあげる必要があるのではないでしょうか。
 
 
 
 とりあえずこれらを解決した(つもりな)サンプルを作ってみましたので、もしよければどうぞ。
 例の #27のサンプルを改造したものなので、それが動く環境なら動くと思います。
 キーボード上下左右とスペースキーで操作します。

(JUMP_ACTION_MODEの値を 0か 1にするかでジャンプの挙動が若干変わりますので、お試しを)。

はね

Re:キャラクターのジャンプについて

#16

投稿記事 by はね » 18年前

おぉ!こんなに素晴らしいソースを作っていただいて本当にありがとうございます
早速色々と改良してみたいと思います。

> DrawRotaGraphが複数箇所ある
前にこちらのサイトを参考にさせていただいてSTG作っていましたが、
やはり動きの多いアクションではSTGと同じ、と言う風にはいかないみたいですね^^;

>時間
なるほど、1つ時間で処理してしまうと
他のオブジェクトも時間で処理しないと計算が合わなくなってまずい事になるわけですか。
このような事は全く思いつきませんでした。まだまだ勉強は始まったばかりみたいですw

何から何まで教えていただきありがとうございました。

やはりプログラミングは参考書を開くより場数をこなす方がはるかに勉強になります

はね

Re:キャラクターのジャンプについて

#17

投稿記事 by はね » 18年前

すみませんがわからない所があったので質問させてください

初歩的な所で申し訳無いのですが、

構造体にあるvec posとはどのような役割なのでしょう?

お時間がある時で結構ですのでお答えいただければ幸いです

Justy

Re:キャラクターのジャンプについて

#18

投稿記事 by Justy » 18年前

構造体にあるvec posとはどのような役割なのでしょう?


 pos/vec共に floatの xと yをメンバに持つ構造体です。

 posはポジションの略で、位置を表します。
 ほぼそのままのこの値を DrawRotaGraph()に表示座標として与えています。

 vecはベクトルの略で、そのフレームにおける移動べくトル(移動方向と量)を表しています。
 毎回
[color=#d0d0ff" face="monospace]   player.pos.x += player.vec.x;
   player.pos.y += player.vec.y;[/color]
 と、vecの値を posに足していますよね?

 vec.xが 0なら水平方向の位置は変化しませんが、
vec.xが 1なら、毎フレーム1ピクセルずつ右に向かって移動します。

 同様に vec.yが 0なら垂直方向の位置は変化しませんが、
vec.yが -1なら毎フレーム1ピクセルずつ上に向かって移動します。

 ジャンプの時(JUMP_ACTION_MODE=0の方式の場合)は、一瞬だけ少し強めに -y方向になるよう
vec.yに値を入れると、後は勝手に上に上がっていきます。

 で、重力の計算としては毎フレーム vec.yに対して下向きに力を加えているので、
いつかは上昇を止めて下降する、というわけです。
(毎フレーム重力がかかっているので、床にめり込まないよう毎回調整が必要に
なってしまいます)。

 vec.xvec.yの値を画面に表示してみるとどういうふうに動いているか判りやすくなると思います。


 でつまり結論としては、直接 posをいじって位置を変えるのではなく、
あくまで移動方向 vecを変更することで位置 posを変えていく、という構造になっています。

 この方式は加速・減速が表現しやいですし、移動方向が明確になるのでアクションゲームでは
一般的な方式なのではないでしょうか。
(着地の時にバウンドする処理も簡単にこのパラメータの制御だけでできますし、
氷の表面をすべっているかのごとく、方向キーを離しても惰性で動く、なんてことも
簡単です)

はね

Re:キャラクターのジャンプについて

#19

投稿記事 by はね » 18年前

なるほど
x,yのvecを変えることでposが変化して
結果動くということですか。
ソースを見ていると時々このvec,posが出てくるのですが意味が分からずにスルーしていましたが
これでスッキリできました。
ありがとうございました^^

閉鎖

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