|
|
|
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
| |
|
2014/3/12(Wed) 18:27:22|NO.60603
あと、何故か計算上ではいくつかのオブジェクトが同じ動きをしていることになっているのですが
実行されているのは通常通りなんですよ...
|
|
2014/3/12(Wed) 19:13:05|NO.60604
いろいろ問題点がありすぎてどこから指摘していいのやら・・・
[obaq 全体]
obaq で使用している変数(型)すべてを仕様上の物(実数型)に変えましょう。
ほとんどの変数が実数になっていないので、いろいろと問題が発生します。
[obaq領域]
まず、obaq の領域設定なのだけど、横幅 -95〜195 になってるけど、これであってるのかな?
(画面のサイズx2 の設定になっちゃっているので、放射状空間に留まれなくなっている)
[画面上座標と内部座標]
座標指定なんだけど、qcnvaxis で、座標変換を行いましょう。
整数そのままで割り算すると小数点以下は切り捨てされてしまうので位置が変になります。
[多角形オブジェクト生成]
生成確認をしていないみたいなので、オブジェクトが生成できなかった場合も、オブジェクトデータベース(obj)に登録されている。
生成できなかった場合は、-1 が代入されるので、確認してから、obj に登録するといい。
その他は、発射初期位置の赤い点の座標かなー。位置を動かしたときに連動しないので、動作チェックし難い点。
|
|
2014/3/12(Wed) 19:31:42|NO.60605
修正してみます
とりあえず、ありがとうございます
|
|
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
| |
|
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 判定を変えてくださいです。
| |
|
2014/3/13(Thu) 12:58:26|NO.60613
あぁ、言っていなかったけど、弾が真ん中に戻るのは、仕様だよ。
(質問者さんが真ん中に放射吸収を作ってるので[初期質問者提示スクリプト])
qexec を行う前・行った後でのオブジェクトの座標を監視すれば、どっちに進もうとしているかわかるから、それを左に行かないようにすれば弾については戻らなくなる。
もし戻ろうとしているなら、強制的に弾速度を加算して右に向かわせればいい。
弾は弾の種類によって、ちゃんと設定してね。同じグループは衝突判定に入るから、弾同士が当たると変な動きが発生する。
(弾同士があたってアトランダムになる弾とか、なにがあっても突き抜けるとか)
|
|
2014/3/13(Thu) 13:46:05|NO.60614
あなたのソースを実行してみたのですが、私の考えてた挙動がそのまま再現されました。
本当に、ありがとうございます!
|
|