したらばTOP ■掲示板に戻る■ 全部 1-100 最新50 | |
レス数が1スレッドの最大レス数(1000件)を超えています。残念ながら投稿することができません。

おちゃめくらぶ掲示板

2056御茶目菜子:2014/05/14(水) 23:37:19
ボールを使ったゲームを作るときに知っておくべきこと
私は先日書いたようにプチコンで卓球ゲームを作っているにょ。
といっても、勢いで試作品を作って熱が冷めたのでここから完成までもっていけるかどうか
は微妙なところにょ。(試作品は動けばいいので簡単にできるけど実際に公開するならば
速度や短さなどもそれなりに重視しているし、何よりゲームそのものがつまらないと公開には
至らなくなるため簡単に作って公開というわけにもなかなかいかない)
その後、私以外にもプチコンで卓球ゲームを作ろうとしている人がいるというのをネット上で
見かけたにょ。
しかし、ボールの跳ね返り処理がよく分からないとのことにょ。
というわけで、ボールを使ったゲームを作る際に役立つ(かもしれない)ボールの動きを
プチコンで再現する方法についてまとめてみたにょ。
http://twitpic.com/e3n4wo

では、このまとめの解説と補足をしていくことにするにょ。
まずは、ボールが壁(2Dゲームだと直線や矩形)にぶつかったときにはどうなるかと
いうと跳ね返る角度は等しくなっているにょ。
これは平面ではなく曲面であればぶつかった場所における接線に対して考えればいいので
とりあえず、円と直線(正確には線分)との当たり判定が行えればいいにょ。
その前に簡単な「円と円」「矩形と矩形」の当たり判定について書いておくにょ。
実は円と円の当たり判定というのは極めて簡単でそれぞれの円の半径さえ分かればその和で
衝突したかどうかが分かるにょ。
半径10の円と半径20の円はお互いの円の中心の距離が30以下であれば衝突したと判断する
ことが可能になるということにょ。(中心間距離は三平方の定理で求まる)
矩形と矩形も簡単でX方向、Y方向の当たり判定の大きさが分かっているから2つの物体の
中心点からのX、Y方向のそれぞれの距離を求めてそれが一定の範囲内に収まっているかどうか
ということを調べればいいだけにょ。(円がX、Y方向を一緒にして判定するのに対して
矩形はX、Y方向を別々に考えるというだけの違い)

壁を矩形として考えた場合には円と矩形の当たり判定が必要になっていくるけどそれを
正確に求めようとするならば矩形の辺に円が入り込んでいるか、角が円に入り込んでいるか、
円そのものが矩形に入っているかという判定を行う必要があるにょ。
辺に入り込んでいるかどうかというのは円と線分の当たり判定をするということにょ。
では円と線分との当たり判定はどうかというと実はこれはベクトルの外積を用いる必要が
あるため高校生(理系)以上でないと難しいにょ。(ベクトルの外積の考えを使わずに
三角関数だけでも求めることはできる)
しかし、実際に縦横斜めの壁が混在するようなゲームを作る機会はほとんど無くて多くの
場合は縦(画面に対して90度)、横(画面に対して0度)の壁(地面)だけで構成されている
ようなゲームではないかと思うにょ。
こういった画面上で斜めの壁がないならば当たり判定はかなり難易度が下がってくるにょ。
ボールの半径をR、ボールのX座標をBX、Y座標をBY、ボールのX方向の速度をVX、Y方向の
速度をVYとしたときには下記のようにできるにょ。

 横方向にある壁
 座標(BX+SGN(VX)*R,BY)が壁かどうかで判断 → 壁の場合はVX=-VXになる
 縦方向にある壁
 座標(BX,BY+SGN(VY)*R)が壁かどうかで判断 → 壁の場合はVY=-VYになる

問題はどうやってその座標に壁があるかどうかを判断するかだけど壁をGRPで描画した場合
にはGSPOITを用いて壁で使用している色かどうかで判断すればいいので簡単にょ。
BGであればBGREADを使えばいいにょ。
BGREADはキャラ単位であるためドット単位の座標から判断をするためにはX、Y座標をそれぞれ
8で割る必要があるにょ。(BGを使う場合には背景をスクロールさせたらそのスクロール分も
考慮して計算する必要がある)
こんなことをしなくてもスプライトで壁を描画すればSPHITで一発という考えもあるけど
プチコンの場合はスプライトは管理できるのが100個までという制限があるし、当たり範囲の
大きさを微調整するのが面倒だし、矩形同士の当たり判定しかできないため座標を元に
手動で判断するのがベターにょ。
SPHITを使わず手動で判断するならばあえてスプライトで壁を描画する意味は無くなるにょ。
もちろん、壁はGRPやBGではなくコンソール文字でも問題ないにょ。
これならば普通にPRINT命令で表示できるのでお手軽にょ。(この場合はボールの座標を8で
割ってCHKCHR関数を使って判断する)

斜め線や曲線の壁がないならばこれでだいたい当たり判定が可能になるけど実際はこれでも
不十分になる場合もあるにょ。
それはボールの速度が速い場合にょ。
ボールの速度となるメインルーチン1回当たりのボールの移動量(要するにVX、VYの値)が
壁の厚さを上回ってしまったら壁をすり抜けてしまうからね。(私がポケコンで作った
ピーチバレーもこの問題に悩まされてしまった)
あと上記の当たり判定は壁を矩形と考えた場合にはその角の部分には当たり判定がほぼ無い
状態となっているにょ。
ボールの中心が壁を通過しない場合は壁との衝突が100%起きないだけではなく中心が壁を
通過した場合でも「壁の厚さ>ボールの移動量」にもかかわらずボールの速度によっては
頻繁に壁をスルーしてしまうにょ。
この問題はボールの(進行方向ではなく画面上における)縦方向、横方法のみではなく
斜め方向にも当たり判定を行えば緩和できるにょ。
ただし、その場合は角に当たって縦横どちらの向きにボールが跳ね返るかを判断するのは
簡単には計算はできないにょ。(後述のネットの当たり判定と同じ要領でボールが壁に
当たった瞬間の座標を求めそれで横から当たったか縦から当たったかを判断すればいい)

では、確実な当たり判定を行うためにはどうしたらいいかというと最も簡単な方法は壁が
あるか否かを画面上から読み取るのではなく壁の座標を元に判断するという方法にょ。
例えばX方向の左画面外に壁があるという場合にはBX-Rが負数ならば壁に当たったと判断が
可能になるにょ。
これならばボールがどれだけ速かろうと判定漏れは起きないにょ。
これと同じ方法は他の3方向でも可能にょ。
外周の壁はこれが最も簡単で確実だけどこれを外周以外で行うのは難しいにょ。
ボールを使った競技でコートの内部でよく必要になる判定はネットとの当たり判定にょ。
例えばバレーやテニスや卓球といったネットを使ったゲームにおいてネットをGLINEを使用
して幅1ドットで描画した際にはそのネットとの当たり判定は1ドット分しか無くなってしまう
ことになり、VXの値が1以下でないと正常な判定は行えないためボールはほとんどネットを
素通りしまくってしまうにょ。
そこで外周と同じく座標のみで判断するという方法を使えばいいけどそれは結局見えない
矩形の当たり判定を行うのと同じにょ。
当たり判定を狭くすれば速いボールはネットを素通りしてしまうし、当たり判定を広く
すればネットに当たらないのに跳ね返ったように見えてしまうため非常に不自然なものに
なってしまうにょ。

そこで使用するのが円と線分の当たり判定にょ。
ただし、これはちゃんとやると三角関数が必須となってしまうためここでは中学生でも分かる
ような簡単な方法を書いておくにょ。(プチコンは三角関数が超速いから別に問題ないけど
ポケコンの中でも高速なレベルのPC-E500でさえSIN(A)の値を求めるのはプチコンでGCOPYに
よる1画面丸々GRPコピーと同じくらい時間がかかってしまう重い処理であるためできるだけ
メインルーチン内では使用しない方法を考える必要があった)
例えばネットが GLINE 128,96,128,191,15 で描かれているとするにょ。
ボールの半径はR=8、ボールの座標はBX=120、BY=97、ボールの速度はVX=10、VY=-10とした
場合にこのボールは次のフレームにはBX=130、BY=87となりネットの向こう側に達して
いるにょ。
このボールは本当にネットの上を通過したかどうかはBX=128のときの座標で判断すればいい
けどそれはフレームとフレームの間なので分からないにょ。
しかし、このフレームの間はボールが1次関数的に動いていると見なせば線分と線分の当たり
判定となり、それが交わるかどうかで通過したかどうかを判断が可能にょ。
上記のボールの場合はBX=128の時はBY=89となり、ボールの半径の8を加算すると97になるにょ。
ネットの一番高い部分のY座標が96だけどそれよりも低い位置を通過したと考えられるため
このボールは「ネットに当たった」と判断が可能になるにょ。
この方法だとボールがどれだけ速くてもネットを素通りすることはないにょ。
また、BX=128の時のBYの値が96以上のときはネットを直撃だけどBYの値が96未満ではあるけど
そこからボールの半径を加算したときに96以上になるという場合にはネットをかすめたことに
なるにょ。

上記例だとかなり薄く当たっているためネットに当たることによる減速は微量に止まるにょ。
ネットをかすめた量によってVX、VYの値を上手く変化させればネットに当たったときの挙動を
それっぽくできるにょ。(ネットは壁ではなくたるんだ部分が伸びるだけなのでかすめた量が
極めて微妙であればVXの符号が反転することはなく単に速度が遅くなるに止まる)
このネットの判定は私がポケコンで作ったピーチバレーなど多くのゲームで使用しているにょ。
この方法はあくまで簡易的な当たり判定だけど衝突シミュレーションを作っているのではなく
単なるゲームであれば全く問題がないレベルの誤差となっているにょ。
そのネットとの当たり判定の方法を図で説明したのがこれにょ。
http://twitpic.com/e3pvpg

このボールとネットの当たり判定を使って実際にボールを動作させると当たり判定が壁とは
異なることに気が付くと思うにょ。
ネットとの当たり判定はボールの中心を基準としているためボール半分まではネットに埋まる
形になっているにょ。
しかし、ネットは堅い壁ではないためボールがぶつかったらネットは伸びるにょ。
つまり、ネットに当たった状態でボールが中央ラインを超えることはごく当たり前のことにょ。
これを正確に計算してネットに触れた時点で当たったと見なして跳ね返せば頑丈な1枚板の
ように見えてしまうにょ。
これは判定が楽になると同時にネットの衝突表現としては自然な感じになっているという
ことで一石二鳥といえるにょ。


当たり判定はこれくらいにしておいて肝心のボールの動きについて書いていくにょ。
やはり、知っておくべきなのは重力がある場合の動きにょ。
これは5月7日にも少し書いたけどもっと基本的な部分から書いてみるにょ。
まず、ボールの初速をVでAラジアンの角度で斜め上方にボールを打ち出した時は下記の
ようになるにょ。

 VXの初速=COS(A)*V
 VYの初速=-SIN(A)*V

 ※SINの前にマイナスが付いているのはプチコンの画面は上向きの方がY座標が小さくなって
  いるため(上記のまとめの図ではVXの方にマイナスがついているけど単純なミス)

この斜めに打ち出されたボールには下向き(サイドビューのゲームならば画面下方向)に
重力がかかるため等加速度運動となるにょ。
そのためメインルーチンを1回実行ごとに重力加速度の分だけY方向の速度を変化させる必要が
あるにょ。
重力加速度がGならばVY=VY+Gとなるということにょ。(上向きに飛んでいるボールに対して
逆方向の力が加わっていると考えればGの値は負数の方が分かりやすいけどGが負数の場合は
VY=VY-Gとしなくてはない)
画面の1ドットが5cmであれば60fpsで動作しているゲームの場合はG=0.54程度の値になるけど
これは物理シミュレーションでないならばゲームによって適切な値に変えて問題はないにょ。
私がいろいろ数値を変えて試したらプチコンの画面解像度でノーバウンドでボールを打ち返す
サイドビューのゲームならばG=0.1前後がちょうどよい感じがしたにょ。
X方向は等速運動となっているため何も難しいことはないにょ。
基準となる速度VをX、Y方向に分解するため三角関数を用いているけどこれは投擲競技のように
角度が必須というわけでなければ三角関数は不要にょ。
例えばVが5ならばVXが4の時三平方の定理によってVYは自動的に3になるにょ。
角度が必要でないならばこのように元になる速度とVXもしくはVYを定めてやることでもう
一方の大きさは求まるにょ。


サイドビューのボールゲームならば「地面に当たったボールが跳ねる」という動作は頻繁に
起こるにょ。
バレーの場合はノーバウンドで相手コートに返す競技であるため地面にボールが付いた時点で
攻守交代をすれば地面のバウンド処理は要らないけどテニスや卓球ではワンバウンドで相手
コートに返すことができるにょ。
そのためにもバウンド処理もきちんとしておきたいにょ。
もしも、上記の壁との衝突のように地面に衝突する際に普通にVY=-VYなんてしていたら
ずっとボールは同じ勢いで跳ね続けてしまうけど実際はこんなことはあり得ないにょ。
それは地面との衝突によってボールのエネルギーが一部失われてしまうためにょ。
ボールと地面や壁との衝突に欠かせないのが反発係数にょ。
これはボールや壁の素材を考えて衝突の際に一定の値を掛け合わせるだけでいいので簡単にょ。
反発係数をEとしたら VY=-VY*E になるということにょ。
E=1の時は衝突の際にエネルギーが失われないため完全弾性衝突と呼ばれているにょ。
普通はEの値はどれくらいかというと壁が堅ければ0.8〜0.95程度の値になるにょ。(衝突
する物体が十分に堅くても衝突の際に音や熱に変わる分があるため普通はに1に近くなっても
1に等しくなることはない)

テニスゲームならばこの反発係数を変えることでハードコートとクレーコートとグラス
コートの違いを表現をすることができるにょ。
反発したボールがどこまでの高さまで跳ねるかは反発係数で決まるけど進行方向の速度の
変化は摩擦によって発生するにょ。(上記の式はその摩擦による進行方向の速度減少が
ないと考えた場合のもの)
グラスコートは反発係数が低いためバウンドしたボールは低くバウンドするけどボールの
回転による摩擦の影響を受けにくいため進行方向の速度はあまり落ちずに「速いボール」
となるにょ。
ハードコートの場合は反発係数が高いためバウンドは高くなるけど進行方向の速度減少は
グラスコートよりも大きいにょ。
クレイコートは反発係数はハードとグラスの間だけど進行方向の速度減少はハードよりも
大きいため「遅いボール」となるにょ。
端的に言えばバウンドしたときのVXとVYの減少率を独立してコントロールするだけにょ。


跳ねたボールもどんどんY方向の速度が減速していくとボールが接地した状態が続くことに
なるにょ。(VYがG以下になったらバウンドの処理から転がり処理に切り替える)
この接地によって地面との摩擦が発生してそれによってボールは地面を転がり始めるにょ。
(つまり、摩擦抵抗がないとボールは転がらない)
そのボールも徐々に遅くなっていき最終的にはボールは完全に停止するにょ。(接地による
摩擦は上記のようにバウンドするボールの進行方向の速度減少にも影響を与える)
では、転がり始めたボールがどんどん遅くなるような動作をさせるためには転がり抵抗に
よって発生する逆方向の力の分だけ減速させていけばいいにょ。
この転がり抵抗は動摩擦力の一種なので速度に関係なく同じ組み合わせ(同じ形状)の
物質同士であれば一定の値となるにょ。
つまり、Cを転がり抵抗とした場合には VX=VX-SGN(VX)*C となるわけにょ。
私がいろいろ試した結果ゲームで使うならばCの値はGに設定した値の1/5〜1/10程度が妥当に
感じたにょ。(転がりにくさを表現するならばGと同じ〜Gの1/2程度にするのもあり)

ゴルフの場合はボールが止まるまでの競技なのでこの転がり処理は非常に重要になって
くるにょ。
ゴルフクラブは大きく分けて低い角度で跳びよく転がるボールが打てるため長い飛距離が
稼げるウッドと高い角度で跳びあまり転がらないアイアンにグリーン上のみで使うパターを
加えた3種類があるにょ。
ウッドの場合は転がり処理をどの程度行うかが重要になってくるにょ。
アイアンではあまり転がらない反面でスピンをかけやすいにょ。(バックスピンをかけた
場合にはバウンドの時に進行方向とは逆向きの力が加わり、その回転量によっては落ちた
地点から手前に戻ることさえある)
ウッド、アイアンと一括りにしても番手によってその特性は異なるにょ。
アイアンの中でもウェッジと呼ばれるPWやSWはロフト角が特に大きく刻んで寄せるための
クラブとなっているにょ。
グリーンやフェアウェイでは転がりやすい(バックスピンの影響も受けやすい)けどラフや
バンカーではほとんど転がらないためそれを再現するとゴルフっぽくなるにょ。
またゴルフの場合はボールの速度や軌道はライ(ボールがある場所)の影響を受けやすい
ためそれも考える必要があるにょ。
ティーアップした状態ならば100%の力をボールに加えることができるけどラフやバンカー
といったライの状態が悪い場合はウッドを使って打つのは難しく目玉状態のバンカーだと
砂をかき分けて打つ必要があるためボールの飛ぶ向きや初速は乱数の要素が大きくなるにょ。
グリーン上の場合は転がりのみを考えればいいけどグリーンの傾きや芝目による影響を加味
する必要があるにょ。

ボールを転がす競技といえばボウリングがあるにょ。
ボウリングではボールに回転を付けることでそのボールの軌道を曲げることができるにょ。
その前にボウリングのレーンについて書いておくとボウリングのレーンの手前部分には
オイルが塗られていてその間はレーンとボールの摩擦抵抗は極めて小さくなっているにょ。
そのためボールの回転の影響をほとんど受けずにほぼ直進するにょ。
ピンの近くになるとレーンとの摩擦によって回転方向に力が加わるためボールは大きく
曲がり始めるにょ。
これを表現するためには直進するゾーンと曲がるゾーンを分けてしまえば簡単にょ。
ボールの進行方向がX方向としたら曲がるゾーンでは転がり抵抗による速度減少を行いそして
それと同じことをY方向に対しても行えばいいにょ。
ただし、ボールの軌道をそれっぽくできてもボウリングの場合はボールとピンの当たり判定は
非常に複雑にょ。
むしろ、ピン同士の当たり判定が非常に複雑といえるにょ。
そのため、それっぽいピンの挙動を作るだけでもかなり難しいにょ。
当たり判定においてはおはじきのような円盤状態として考えれば円と円の当たり判定になる
ため難易度は大きく下がるにょ。(1フレームごとにボールを含めた11個のオブジェクト間の
当たり判定をすべて行う必要があるけどプチコンの速度ならば問題ないはず)
壁のように動かないものにボールが当たったら上記のように反発係数を元にどのような速度
減少があるかは簡単に分かるけどピンのように動くものに当たる場合には速度の減少には
重量を加味する必要があるにょ。(力学的エネルギー保存の法則があるため転がることで
地面との吸収されたエネルギーを除けば基本的に遅くなったボールの運動エネルギーの分
だけピンの運動エネルギーへと変わる)


さて、斜め上に打ち出されたボールはX方向は等速運動、Y方向は等加速度運動と書いたけど
これはあくまで空気抵抗がない場合の話にょ。
ゲームによっては空気抵抗の影響を考える必要があるにょ。
空気抵抗がないとゴルフゲームは風の影響を全く受けなくなってしまうし、バドミントンは
シャトルコックの動きが現実とはまるで違うものになってしまうにょ。
しかし、空気抵抗というのは深く考え出したらきりがないにょ。
同一材質、同一質量の物体でも断面積の大きさや物体の形状でまるで違うものになって
しまうからね。
ボールの表面形状や回転具合によって空気抵抗は変わってくるにょ。
そのため正確な求め方というものはほぼないためこのような一律の係数を設定してやれば
問題ないにょ。(というか、空気抵抗は多くのパラメータを設定して微分方程式を使う
必要があるためまともにに計算するのは非常に難しく大学の流体力学の知識が必要になる)

空気抵抗は単純に考えた場合には速度に比例した大きさになるため空気抵抗係数がKならば
VX=VX-VX*Kとなるにょ。(Y方向にも同様に速度に比例した空気抵抗が加わるけどY方向は
重力との合算値となり、非常に高い場所から自由落下させた場合には重力による等加速度
運動で無制限に速い速度になることはなく実際は空気抵抗係数で上限速度が決まっている)
これは本当にごく簡略化された計算式であるもののシミュレータではなくゲームに使う
ならばこれでもそれほど問題はないと思うにょ。
どんな競技であろうと地球上で行うならば空気抵抗の影響は避けられないにょ。
野球であっても投手が投げるボールは投手の手を離れた直後と比べてミットに収まる直前
ではかなり速度が落ちているにょ。(この初速と終速の差が少ないボールが伸びのある
ボールとなり、伸びるからといって初速よりも終速の方が速くなるわけではない。あと
ストレートの場合は縦回転によって揚力が発生していてそれで思った以上に重力による落下が
ない場合はバットの上にボールが通るという漫画やアニメでよくある感じのことが起きる)
とはいうものの空気抵抗の影響をどこまで考えるかはゲームデザインをする人次第であり
空気抵抗をゲームに入れなければならないとか、どの程度入れるかには正解はないにょ。
ゲームが面白くなるならば大げさに空気抵抗を入れるのもありだと思うにょ。

さて、先ほど出た風の影響というのはボール自体に働く力は風圧で考える必要があるにょ。
しかし、風速だけで決まるのではなくボールの速度や形状など多くのパラメータによって
変化するためちゃんと計算しようとするとすごく大変になるにょ。
したがって、すごく大ざっぱに考えてみるにょ。初速40m/sの速度のボールがあったとして
それが上から見た見下ろし表示と仮定してVX=4、VY=0とするにょ。
それに進行方向に対して垂直に10m/sの風が吹いているとすれば速度の合成をしてやれば
求めたいボールの進行方向と速度が出るにょ。
仮に垂直に10m/sに吹いている風が最大でVX=0、VY=1というボールの速度を変化させる
だけの力があるとすればこの風を加味した場合には十分に長い時間滞空した後にはボールは
(空気抵抗による速度減少分を考えない場合)VX=4、VY=1となるにょ。(1フレームあたり
VYとの差分の数分の1ずつ加算していく)
ここで空気抵抗によって進行方向のボールの速度がどんどん小さくなっていったとすると
相対的に風の影響力がどんどん強くなり徐々に曲がっていく感じになるにょ。(十分な時間
滞空しているボールならばVX=0、VY=1という風による影響力そのまんまのボール速度になる)

あと回転をかけたボールが曲がるのはマグヌス力によるもので回転によってボールの
周囲の圧力が変わるためにょ。(詳しくは「ベルヌーイの定理」で検索)
それによって進行方向とは垂直の力が働いて曲がるわけだけどこれをプチコンの
プログラムで表現するためには真上から見た視点のゲームにおいてボールがX軸に平行
(つまり画面で真横)に動いている場合はY方向にマグヌス力が発生するにょ。
まっすぐ前に動く力とそれに垂直なマグヌス力の2つを単純に合成しても打者の手元で
変化するという理由にはならないにょ。
打者の手元で変化するのはボールが空気抵抗で徐々に遅くなっているためそれによって
マグヌス力が相対的に大きくなるため結果として曲がるということにょ。(つまり、
速いボールは大きな変化はさせにくく遅いボールの方が大きく変化させやすい)
したがって、「回転をかけたボールが曲がる」というのも間接的には空気抵抗がある
ためにょ。
空気抵抗を考慮しないゲームで曲がるボールを表現したければボウリングのカーブと
同じように曲がらない区間を設けてそれを過ぎたらゆるい放物線のような曲線を描く
動きをすれば簡単に実現できるにょ。
簡単に言えば進行方向に対して垂直に重力みたいな何かの力が発生していると仮定して
やれば良いということにょ。



プチコンでボールを使ったゲームを作る際に必要になることを中学生でも分かるように
説明していったけど実際にシミュレータ寄りのゲームを作ろうとしたらこんなものでは
全然足らないにょ。
とはいえ、これだけ覚えておけば困ることはあまり無いと思うにょ。
しかし、文字で説明しても分かりづらい部分も多いため実際にこれらを使ったサンプル
プログラムを作ってみたにょ。
http://twitpic.com/e3n5vw

キャラはタッチまたは十字キーで自由に画面内を動かせるにょ。(この人物は舞空術が
使えるため空中に静止が可能)
キャラがボールに触れたら触れた場所に応じてボールが飛んでいくにょ。
これで壁や地面にボールを衝突させたりしてその動きを確認してもらうというだけの
プログラムにょ。
Fはボールを打つ強さ、Gは重力、Eは反発係数、Cは転がり抵抗係数、Kは空気抵抗係数
なので適当に変えながら動作をさせてそれぞれの値を変えることによる影響を確認して
自分のゲームで使う際にはどの程度の値にすればいいのかを考えて欲しいにょ。(もちろん
デフォ設定で良ければそのまま自分のプログラムに組み込んでもOK)
ちなみに壁や地面との当たり判定は突き抜け防止のため座標から単純に行っているにょ。
あと衝突音の大きさは速度によって変えているのでそれっぽい感じになっているのでは
ないかと思うにょ。(ただし、これはちゃんとした計算値ではなく大ざっぱな値なので
誤差があるけど音量の多少の誤差は分からないためこの程度のもので問題はない)

ちなみにこのプログラムはリストを見て分かるように即興で作ったためあまり良い出来では
ないにょ。
分かりやすくするためあまりリスト短縮は行ってないため冗長だしね。
さて、プログラムは左右の壁と地面についてはパラメータ変更によって判定漏れが起きない
ように座標で判断しているにょ。
これはパラメータを固定にして判定漏れが起きないと判断したらBGREADによる判定に改造
してもいいかもしれないにょ。
ボールとキャラは最も簡単に処理できるSPHITSPを使っているにょ。
当たり判定の矩形はデフォのままなので見た目より若干小さくなっているにょ。
これはSPCOLで好きなように変えてもいいけどスプライト大きさ分(管理番号0を32x32の
矩形にするか16x16の矩形でSPSCALEに同期するかを選択する)に設定すると見た目では
触れてもないのに当たったと判断されてしまうためあえて定義サイズは変えてないため
微調整をしてちょうど良い感じに設定するのもいいかもしれないにょ。
またコメントアウトしている38行の最初の「'」を消すとタッチで操作した場合にキャラを
動かした速度でボールに与える力が変わるにょ。
ただし、細かいバランス調整はしていないため勢い余るととんでもない速さで飛んで
いったり、当たり判定が狭いため見当違いの方向にボールが飛んでいったりする可能性も
あるためこういうこともできるという参考程度にみておいて欲しいにょ。(ボタン操作の
場合はボールに与える強さは5で固定)
ということで、改造の余地があるプログラムだけど自由に改造して自分が作るプログラムで
使用してOKなのでこういう動きをさせてみたいとかいう場合の参考にしてみてにょ。


たまたま私が卓球ゲームを作っていてなおかつ卓球ゲームの作り方が分からないというのを
見かけたためこのようなものを書いてみたのだけどこれらのことは知っていれば難しいことは
全くないけど知らないため作れない(検索しようにも検索する単語さえ分からない)という
人もいるためやはりまとめておく必要があると思ったにょ。
機会があればこれを講座として書こうかと思ったけどそんなのはいつになるか分からないので
手っ取り早くまとめのみ公開することにしたにょ。
ゲームというのはシミュレータと違って自分が表現したいものを作るということが可能にょ。
そのため上記のような方法を使わずとも自分はこういう動きを表現したいというのならば
その人(そのゲーム)にとってはそれが正解にょ。
ただし、自分が作りたいものはあるけどそれが上手く作れないというのならば上記のような
ものは知っておいて損はないにょ。
どれも基本的なものであるため高校の物理を履修していれば知っていて当たり前のものばかり
だけどね。
それをプチコンユーザーが多い中学生でも理解できるように簡略化して書いているにょ。
しかし、ざっくり書いたつもりだけど終わってみればテキスト量は20KBオーバーで私が
サイト上で書いている講座1回分(短い場合)に匹敵するテキスト量になっているにょ。
講座として書くならば完成したゲームなどのプログラムを用意する必要があるし、それに
沿った内容にしなくてはならない(私はこれを理解したらこういういうことができるとか、
このゲームはこういう部分に気を付けて作る必要があるといった実戦的なものを講座に
求めている)ため思いついたことをそのまま羅列するだけで済む方を今回は選んだにょ。
しかし、今回冒頭部分で書いたまとめはtwitter上で17リツイート、21ファボと結構好評
だったので機会があれば「ボールを使ったゲームの作り方〜卓球編〜」のようにテーマを
決めて講座として書くかもしれないにょ。


《 5月22日 追記 》

上記の当たり判定で矩形の壁とボールとの当たり判定を行った場合には角の部分の当たり
判定を行うことができないにょ。
そこで角の部分も正確に判定を行う方法を書いてみたにょ。
http://twitpic.com/e4a7pu
見ての通り線分と円の中心との距離で判定しているだけにょ。
しかし、その距離は2通りに場合分けしなければ求めることはできないにょ。
線分と円の当たり判定さえできれば線分で囲まれた矩形との当たり判定は簡単にょ。
注意すべき点はボール全体が壁に完全に収まっている状態を判定しなくてはならないと
いうことにょ。

さて、この方法で縦と横のみで構成された壁ならば正確な当たり判定が可能になるけど
斜めの壁との当たり判定は正確には行えないにょ。
それはベクトルを使用すれば可能になるにょ。
http://twitpic.com/e4a8aq
見ての通り線分と円の中心との距離で判定しているだけにょ。
それには2通りの場合分けが必要になるにょ。
つまり、縦横のみで構成された壁と全くやっていることは変わらないのでこれを見れば
ベクトルを習っていない中学生でも理解できるのではないかと思うにょ。
これを使えばその斜め方向を含んだ線分で囲まれた壁(要するに多角形の領域)との
当たり判定も可能になるにょ。
同じくその領域内にボール全体が収まっている状態を判定しなくてはならないにょ。




掲示板管理者へ連絡 無料レンタル掲示板