HSPポータル
サイトマップ お問い合わせ


HSPTV!掲示板


未解決 解決 停止 削除要請

2018
0623
簡易弾性衝突プログラム3解決


リンク

2018/6/23(Sat) 20:29:28|NO.84648

バルーンファイトっぽい衝突をするプログラムを組んでいるのですが
反発係数1で実行をしているとV最大値(移動量の総和)が
だんだん増加していくのですがどこに問題があるのでしょう?


#define global ctype dist2p(%1,%2,%3,%4) sqrt(((%1)-(%3))*((%1)-(%3))+((%2)-(%4))*((%2)-(%4))) #define FPS 60 //fps #define SPMAX 60 //球数 #define GRAVITY 4.0 //重力 #define REBOUND 1.0 //反発係数 #define YOKO 800 //スクリーン横 #define TATE 600 //スクリーン縦 #module #defcfunc get_fps //fps計測 if timeo!=gettime(6):ans3=fpsCount:timeo=gettime(6):fpsCount=0 fpsCount++:return ans3 #defcfunc eds_hit int id //球同士衝突判定 ans2=-1 repeat SPMAX@ if cnt==id:continue if dist2p(spX@.id,spY@.id,spX@.cnt,spY@.cnt)<=32:ans2=cnt:break loop return ans2 #deffunc eds_bound int _p1,int _p2,double _p3 //弾性衝突計算 ans=atan(spY@._p2-spY@._p1,spX@._p2-spX@._p1) cc=cos(ans)*cos(ans):sc=sin(ans)*cos(ans):ss=sin(ans)*sin(ans) s1x=moveX@._p2*cc+moveY@._p2*sc-moveY@._p1*sc+moveX@._p1*ss s1y=moveY@._p1*cc-moveX@._p1*sc+moveX@._p2*sc+moveY@._p2*ss s2x=moveX@._p1*cc+moveY@._p1*sc-moveY@._p2*sc+moveX@._p2*ss s2y=moveY@._p2*cc-moveX@._p2*sc+moveX@._p1*sc+moveY@._p1*ss moveX@._p1=s1x*REBOUND@:moveY@._p1=s1y*REBOUND@:moveX@._p2=s2x*REBOUND@:moveY@._p2=s2y*REBOUND@ d=(_p3-dist2p(spX@._p1,spY@._p1,spX@._p2,spY@._p2))/2 //めり込み補正 spX@._p1-=d*cos(ans):spY@._p1-=d*sin(ans) spX@._p2+=d*cos(ans):spY@._p2+=d*sin(ans) return #global randomize screen 0,YOKO,TATE gmode 2 buffer 1,80,80 color:boxf color 255,0,0:circle 1,1,31,31,0 //球表示 color 100,255,0:line 31,16,1,16:line 22,12:line 22,20:line 31,16 //方向表示 gsel 0 ddim spX,SPMAX ddim spY,SPMAX ddim moveX,SPMAX ddim moveY,SPMAX ddim rot,SPMAX repeat SPMAX //球初期配置 spX.cnt=1.0*rnd(YOKO-32)+16 spY.cnt=1.0*rnd(TATE-32)+16 moveX.cnt=0.1*(rnd(30)-15) moveY.cnt=0.1*(rnd(30)-15) loop repeat //メイン redraw 0:color:boxf gosub *vert gosub *hit gosub *draw pos 0,0:color 255,255,255:mes "FPS:"+get_fps():mes"V総量:"+energy:mes"V最大値:"+energy2 mes "反発係数:"+REBOUND:mes"重力:"+GRAVITY redraw 1 await 1000/FPS loop *hit //球同士のヒットと反発 repeat SPMAX a=eds_hit(cnt) if a=-1:continue eds_bound cnt,a,32.0 loop return *vert //球と壁の反発 energy=0.0 repeat SPMAX energy+=moveX.cnt+moveY.cnt moveY.cnt+=GRAVITY/60 if spY.cnt<16:spY.cnt=16.0: moveY.cnt*=-REBOUND if spY.cnt>TATE-16:spY.cnt=double(TATE)-16.0:moveY.cnt*=-REBOUND if spX.cnt<16:spX.cnt=16.0: moveX.cnt*=-REBOUND if spX.cnt>YOKO-16:spX.cnt=double(YOKO)-16.0:moveX.cnt*=-REBOUND loop if energy2<energy:energy2=energy return *draw repeat SPMAX //球描画 spX.cnt+=moveX.cnt spY.cnt+=moveY.cnt pos spX.cnt,spY.cnt grotate 1,0,0,atan(moveY.cnt,moveX.cnt),32,32 loop return



この記事に返信する


あらや

リンク

2018/6/24(Sun) 15:15:26|NO.84649

文字だけだと説明が難しいのですが、
球が落下して床と接触したときの処理に問題があるのかと思います。

床との接触時
>if spY.cnt>TATE-16:spY.cnt=double(TATE)-16.0:moveY.cnt*=-REBOUND
運動量だけ見ると実際には床と球が交差しているか、もしくは球が床よりも下にある
という状態ですが(以下 めり込んだ状態とします)、
表示位置だけ画面内に修正していて運動量の修正をしていないために
めり込んだ分の運動量がそのまま残り、
バウンド時に前よりも高い位置まで上昇して、再度落下していき
また床と接触したときにはめり込んだ分の運動量が残り……
というループで床との反発時にどんどん運動量が増えていくのだと思います。

球数を1つにしてバウンドしたときに
どこまで上昇するか見てみるとわかりやすいかもしれません。



リンク

2018/6/24(Sun) 20:02:12|NO.84651

なるほど!
めり込みを補正しても運動量は反転するだけだから
構わないと考えていましたが重力加速度ありの場合には、
同じ運動量を保持したまま位置エネルギーを与えてしまっていますね。
真面目に実装しようとすると…
めり込みがあった場合、実際に床に当たった時点の速度を
計算しなおさないとあかんのでなかなか面倒な気はしますね。
ありがとうございました。



リンク

2018/6/24(Sun) 20:02:30|NO.84652

解決です



ONION software Copyright 1997-2021(c) All rights reserved.