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


HSPTV!掲示板


未解決 解決 停止 削除要請

2014
0312
Shadow Artisan物理演算で初動の球が真ん中に来たりたまに(0,0)地点に球が発生したりします7解決


Shadow Artisan

リンク

2014/3/12(Wed) 18:25:33|NO.60602

今、物理演算を使ってシューティングゲームを作ろうと頑張っているのですが、
初動の球が真ん中に来たりたまに(0,0)地点に球が発生したりして困ってます。
どうやったらこのバグを直せるでしょうか。
教えて頂けるとありがたいです。

#define wxs 760 ; wxs = 画面の横の長さ #define wys 400 ; wys = 画面の縦の長さ px=160 : py=80 ;赤い点のオブジェクトの座標です screen 0,350,220,0,5,5 ; 画面の大きさを指定 title "レポート" screen 2,wxs,wys,0,365,0 ; サブスクリーンの作成です gsel 2 title "テスト" #include "obaq.as" qreset qborder -95,-50,195,50 qaddpoly obj_,4,px/4,py/4,,5,5,,1,2 ; 赤い点のオブジェクトの生成です qtype obj_,type_bind qgravity 0,0 *main redraw 0 time++ color : boxf qexec qblast wxs/8,wys/8,-1 ; 放射状に力を集めてます /////キーボード各種の動き///// stick ky,31 if ky&128 {end} if ky&1 {px--} if ky&2 {py--} if ky&4 {px++} if ky&8 {py++} //赤い点のオブジェクトから出る緑の点のオブジェクトの出現// if ((ky&16)!0)&(time\20=0) { atime(qtime)=time qtime++ qaddpoly obj(qtime),4,px/4,py/4,,5,5,,2,1 ; 出現 qweight obj(qtime),,1200 ; モーメントの指定 qpush obj(qtime),,,7.5,0 ; オブジェクトの射出スピードを指定 } /////緑の点のオブジェクトの動き///// repeat qtime qgetpos obj(cnt),objx(cnt),objy(cnt),objr(cnt) ; objx=X座標,objy=Y座標,objr=角度 if objx(cnt)>200 {qdel obj(cnt)} ; オブジェクトが消える条件 loop qdraw qview 4,4 /////サブウィンドの操作///// gsel 0 redraw 0 color : boxf : color ,255 if qtime<10{atime=qtime : btime=0} if qtime>9{atime=10 : btime=qtime-10} pos 0,0 : mes"ID" pos 80,0 : mes"X座標" pos 170,0 : mes "Y座標" pos 260,0 : mes "角度(ラジアン)" line 0,18,350,18 repeat atime,btime pos 0,absf(btime-cnt)*20+20 mes "obj("+cnt+")" pos 80,absf(btime-cnt)*20+20 mes objx(cnt)*4 pos 170,absf(btime-cnt)*20+20 mes objy(cnt)*4 pos 260,absf(btime-cnt)*20+20 mes objr(cnt) loop redraw gsel 2 redraw await 16 goto *main



この記事に返信する


Shadow Artisan

リンク

2014/3/12(Wed) 18:27:22|NO.60603

あと、何故か計算上ではいくつかのオブジェクトが同じ動きをしていることになっているのですが
実行されているのは通常通りなんですよ...



MillkeyStars

リンク

2014/3/12(Wed) 19:13:05|NO.60604

いろいろ問題点がありすぎてどこから指摘していいのやら・・・

[obaq 全体]
obaq で使用している変数(型)すべてを仕様上の物(実数型)に変えましょう。
ほとんどの変数が実数になっていないので、いろいろと問題が発生します。

[obaq領域]
まず、obaq の領域設定なのだけど、横幅 -95〜195 になってるけど、これであってるのかな?
(画面のサイズx2 の設定になっちゃっているので、放射状空間に留まれなくなっている)

[画面上座標と内部座標]
座標指定なんだけど、qcnvaxis で、座標変換を行いましょう。
整数そのままで割り算すると小数点以下は切り捨てされてしまうので位置が変になります。

[多角形オブジェクト生成]
生成確認をしていないみたいなので、オブジェクトが生成できなかった場合も、オブジェクトデータベース(obj)に登録されている。
生成できなかった場合は、-1 が代入されるので、確認してから、obj に登録するといい。

その他は、発射初期位置の赤い点の座標かなー。位置を動かしたときに連動しないので、動作チェックし難い点。



Shadow Artisan

リンク

2014/3/12(Wed) 19:31:42|NO.60605

修正してみます
とりあえず、ありがとうございます



Shadow Artisan

リンク

2014/3/12(Wed) 23:27:09|NO.60609

んー
発射初期地点を動くようにした瞬間qborderが無効になってしまいますね
P.S


#define wxs 760.0 ; wxs = 画面の横の長さ #define wys 400.0 ; wys = 画面の縦の長さ px=160.0 : py=80.0 ;赤い点のオブジェクトの座標です screen 0,350.0,220.0,0,5.0,5.0 ; 画面の大きさを指定 title "レポート" screen 2,wxs,wys,0,365.0,0 ; サブスクリーンの作成です gsel 2 title "テスト" #include "obaq.as" qreset qborder -95.0,-50.0,105.0,50.0 ; これは、表示範囲ぴったりです(但し、第三パラメーターはオブジェクトの削除を画面外で行うため(画面+10.0)がされている) qgravity 0,0 *main redraw 0 time+=1.0 color : boxf qexec qblast wxs/8,wys/8,-1 ; 放射状に力を集めてます /////キーボード各種の動き///// stick ky,31 if ky&128 {end} if ky&1 {px-=3.0} if ky&2 {py-=3.0} if ky&4 {px+=3.0} if ky&8 {py+=3.0} //赤い点のオブジェクトから出る緑の点のオブジェクトの出現// if ((ky&16)!0)&(time\20=0) { atime(qtime)=time qtime+=1.0 gosub *objcleate } /////赤い点のオブジェクトの更新///// qdel mainobj qaddpoly mainobj,4,px/4,py/4,,5,5,,1,2 ; 赤い点のオブジェクトの生成です /////緑の点のオブジェクトの動き///// repeat qtime qgetpos obj(cnt),objx(cnt),objy(cnt),objr(cnt) ; objx=X座標,objy=Y座標,objr=角度 if double(objx(cnt))>200 {qdel obj(cnt)} ; オブジェクトが消える条件 if (double(objx(cnt))=0.0)&(double(objy(cnt))=0.0)&(double(objr(cnt))=0.0){qdel obj(cnt)} loop qdraw qview 4,4 /////サブウィンドの操作///// gsel 0 redraw 0 color : boxf : color ,255 if qtime<10{atime=qtime : btime=0} if qtime>9{atime=10 : btime=qtime-10} pos 0,0 : mes"ID" pos 80,0 : mes"X座標" pos 170,0 : mes "Y座標" pos 260,0 : mes "角度(ラジアン)" line 0,18,350,18 repeat atime,btime pos 0,absf(btime-cnt)*20+20 mes "obj("+cnt+")" pos 80,absf(btime-cnt)*20+20 mes objx(cnt)*4 pos 170,absf(btime-cnt)*20+20 mes objy(cnt)*4 pos 260,absf(btime-cnt)*20+20 mes objr(cnt) loop redraw gsel 2 redraw await 16 goto *main *objcleate qaddpoly obj(qtime),4,px/4,py/4,,5,5,,2,1 ; 出現 if obj(qtime)=-1{goto*objcleate} qweight obj(qtime),,1200 ; モーメントの指定 qpush obj(qtime),,,7.5,0 ; オブジェクトの射出スピードを指定 return



MillkeyStars

リンク

2014/3/13(Thu) 12:27:44|NO.60611

最初に qaddpoly の戻り値の説明が間違っていた件をお詫びいたします。
正確には、-1 以下の数値はエラーとなります。

また、オブジェクト管理システムを実装したスクリプトを作成しましたので参考にしてください。

#include "obaq.as" #define wxs 760 ; wxs = 画面の横の長さ #define wys 400 ; wys = 画面の縦の長さ //ステータス画面 screen 0,350,240,0,5,5 : title "Status Window" //obaq画面 screen 2,wxs,wys,0,365.0,0 : title "obaq Window" //変数初期化 px=160 : py=80 ;赤い点のオブジェクトの座標です px_e = 0.0 : py_e = 0.0 ;オブジェクト座標変換用 //オブジェクト管理用変数 //内訳 //(0) = フラグ //(1) = オブジェクトID //(2) = 座標x(画面) //(3) = 座標y(画面) //(4) = 角度(内部) ddim obj,5,16 repeat length2(obj) obj(0,cnt) = -1.0 ,0.0 ,0.0 ,0.0 ,0.0 loop //obaq システム設定 qreset qborder -95.0 ,-50 ,105.0 ,50.0; 横幅の右側のみサイズ可変 qgravity 0.0 ,0.0 //赤いオブジェクト(発射地点表示) qcnvaxis px_e ,py_e ,px ,py ,1 //座標変換 : 画面座標から obaq 座標に変換 qaddpoly obj_ ,4 ,px_e ,py_e ,0.0 ,5.0 ,5.0 ,0 ,1 ,2 qtype obj_,type_bind qblast px_e,py_e,-1 ; 放射状に力を集めてます //メインループ開始 *main //放射状に力を集めます。 qcnvaxis px_e ,py_e ,380,200,1 qblast px_e,py_e,-1 ; 放射状に力を集めてます time++ //キー入力処理 stick ky,31 if ky&128 : end if ky&1 : px-- : gosub *red_object_redraw if ky&2 : py-- : gosub *red_object_redraw if ky&4 : px++ : gosub *red_object_redraw if ky&8 : py++ : gosub *red_object_redraw //赤い点のオブジェクトから if ((ky&16)!0)&(time >= 0) : gosub *objcreate //オブジェクト範囲外消去 repeat length2(obj) if ( obj(0,cnt) == -1.0) : continue qgetpos obj(1,cnt),spx,spy,spz qcnvaxis px_e ,py_e ,spx ,spy ,0 //座標変換 : obaq 座標から画面座標に変換 if ( px_e >= 780 ) : qdel int(obj(1,cnt)) : obj(0,cnt) = -1.0 // 画面座標 x.780 を超えると消去 loop qexec gosub *ObjectExec //オブジェクトデータ管理更新 gosub *status_window_redraw redraw 0 color : boxf qdraw redraw 1 await 16 goto *main //ステータスウィンドウの更新 *status_window_redraw gsel 0 redraw 0 color : boxf : color ,255 pos 0,0 : mes"ID" pos 80,0 : mes"X座標" pos 170,0 : mes "Y座標" pos 260,0 : mes "角度(ラジアン)" line 0,18,350,18 line 0,220,350,220 pos 0,222 : mes "オブジェクト管理有効最大数 : "+ActiveObjectMax+" ("+length2(obj)+")" chc = 0 repeat length2(obj) //表示の座標・角度はすべて内部座標です。 if ( obj(0,cnt) == -1) : continue pos 0,chc*20+20 : mes "("+cnt+") : "+int(obj(1,cnt)) pos 80,chc*20+20 : mes ""+obj(2,cnt) pos 170,chc*20+20 : mes ""+obj(3,cnt) pos 260,chc*20+20 : mes ""+obj(4,cnt) chc++ if chc >= 10 : break loop redraw 1 gsel 2 return //オブジェクト管理データを更新 *ObjectExec ActiveObjectMax = 0 repeat length2(obj) if ( obj(0,cnt) == -1.0 ) : continue qgetpos int(obj(1,cnt)),obj(2,cnt),obj(3,cnt),obj(4,cnt) ActiveObjectMax++ loop return //オブジェクト管理から空きを探す *ObjectEmpty TrueEmpty = -1 repeat length2(obj) if ( obj(0,cnt) == -1.0 ) : TrueEmpty = cnt : break loop if ( TrueEmpty != -1 ) : return obj(0,length2(obj)) = -1.0 ,0.0 ,0.0 ,0.0, 0.0 TrueEmpty = length2(obj) - 1 return //赤いオブジェクトの表示位置更新 *red_object_redraw qcnvaxis px_e ,py_e ,px ,py ,1 //座標変換 : 画面座標から obaq 座標に変換 qpos obj_ ,px_e ,py_e ,0.0 return //緑のオブジェクトの生成と発射処理 *objcreate gosub *ObjectEmpty qcnvaxis px_e ,py_e ,px ,py ,1 _TempObj = -1 qaddpoly _TempObj ,4 ,px_e ,py_e , ,5 ,5 , ,2 ,1 ; 出現処理(チェックを含む為、テンポラリにIDを格納) if _TempObj < 0 : return obj(0,TrueEmpty) = 1.0 ,double(_TempObj) ,px_e ,py_e ,0.0 qweight int(obj(1,TrueEmpty)),,1200 ; モーメントの指定 qpush int(obj(1,TrueEmpty)),,,7.5,0 ; オブジェクトの射出スピードを指定 time = 0 return

質問者さんのスクリプトだと、撃つ数によって、obj配列数が増えていってしまう為、長時間行うとスタックエラーになってしまうのでこれを対策したものです。
また、撃つ間隔を短くしておりますので、time 変数の if 判定を変えてくださいです。



MillkeyStars

リンク

2014/3/13(Thu) 12:58:26|NO.60613

あぁ、言っていなかったけど、弾が真ん中に戻るのは、仕様だよ。
(質問者さんが真ん中に放射吸収を作ってるので[初期質問者提示スクリプト])

qexec を行う前・行った後でのオブジェクトの座標を監視すれば、どっちに進もうとしているかわかるから、それを左に行かないようにすれば弾については戻らなくなる。
もし戻ろうとしているなら、強制的に弾速度を加算して右に向かわせればいい。

弾は弾の種類によって、ちゃんと設定してね。同じグループは衝突判定に入るから、弾同士が当たると変な動きが発生する。
(弾同士があたってアトランダムになる弾とか、なにがあっても突き抜けるとか)



Shadow Artisan

リンク

2014/3/13(Thu) 13:46:05|NO.60614

あなたのソースを実行してみたのですが、私の考えてた挙動がそのまま再現されました。
本当に、ありがとうございます!



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