[アイデア]Easy Rocket インターフェース案 (2)
よく考えたら Easy Rocket インターフェースはサーバーへの接続とその操作だ。
requre 'er' er = ER.new 'localhost', port screen = ER::Screen.New er, nil, 640, 400 prim = ER::PrimImage.new er prim.position = 100, 100, 0 screen.add_obj prim prim.delete screen.delete er.close
それともこうだろうか。
requre 'er' er = ER.new 'localhost', port screen = er.createScreen nil, 640, 400 prim = er.createPrimImage prim.position = 100, 100, 0 screen.add_obj prim prim.delete screen.delete er.close
後者のほうがいい気がする。違うかな。うーむ、これ考えてどうなる問題でないな。
一瞬、プリミティブはコネクションを使わずに生成してもいいかと思ったが、それはどっちの意味でもなさそうだ。
ループ
ループ部分を含めるとこんな感じだろうか。それと、今後は A.b の書き方を使うことにする。
requre 'er' er = ER.new 'localhost', port screen = ER.Screen.New er, nil, 640, 400 prim = ER.PrimImage.new er prim.position = 100, 100, 0 screen.add_obj prim vx = 1 vy = -10 ay = 1 while true prim.x += vx prim.y += vy vy += ay er.flush ER.sync 0 end prim.delete screen.delete er.close
er.flush でサーバーに対して命令がまとめて送信される。
描画処理はサーバーで行われているので、別プロセスであるクライアントとの間でうまく同期を取らないと微妙におかしくなりそうだが、その辺の考察はとりあえず置いておく。内部的に解決できそうな気もする。
物理シミュレーション
Easy Rocket では簡単な物理シミュレーション機能でオブジェクトの座標を操作したいと思っている。今までは上記のように毎フレーム座標を設定し続けていたのだが、今になって考えてみると、こうした方がクライアントの実装がシンプルになる気がする。
例えば格闘ゲームの停止、歩く、停止というアクションの場合、方向キーが入力されている間だけ座標を加算するという実装が普通だ。この場合、キーが押されたタイミングと離されたタイミングの間では等速直線運動になっているので、キーが押されたタイミングで加速するという実装にすればもっとシンプルになるのではないかというアイデア。
上記のループ部分は次のようになる。
prim.speed 1, -10, 0 prim.acceleration 0, 1, 0 while true er.flush ER.sync 0 end
キャラの X 方向の移動は次のようになる。
while true if 右が押された? prim.speed.x = 1 elsif 右が離された? prim.speed.x = 0 end er.flush ER.sync 0 end
衝突判定
3D のモデリングの衝突はおいて置いて、ここでは格闘ゲームで「方向キー上」が押されたときにジャンプする処理を考えたい。 例えばこんな感じか。
prim.acceleration 0, 1, 0 # 重力加速度の設定 jump = false while true # 地面とキャラの衝突判定 if jump && prim.y <= 0 prim.speed.y = 0 if 右が押されている? prim.speed.x = 1 elsif 右が離されている? prim.speed.x = 0 end jump = false end # アクション開始判定 if prim.y == 0 if 右が押された? prim.speed.x = 1 elsif 右が離された? prim.speed.x = 0 end if 右が押された? prim.speed.y = -10 jump = true end end er.flush ER.sync 0 end
着地時の加速度設定が余分な気もするが、実際のゲームだと着地時にアニメーションの変更などのイベントが入るだろうからこれはいいか。で、この着地判定を自動処理にしたかったのだけど、イベントが入るからこの例がよくないな。ボールで考えてみよう。
むずかしい。とりあえず思いつくままに書いてみる。あれ、 vx メソッドと speed は同じものか。 velocity で統一しよう。
e = 0.8 # 跳ね返り係数 ball.acceleration 0, 1, 0 # 重力加速度の設定 ground = ClashObj.new "y=0" ball.add_clash_obj ground, e while true if key_on? ball.velocity.y += -10 end er.flush ER.sync 0 end
イメージとしてはこんな感じか。"y=0" とかかなり適当だけどこんなことできるだろうか。
座標クラス
オブジェクト指向的にというか Ruby 的にというか次のような書き方できるだろうか。
ball.position = x, y, z ball.position.x = x ball.position.x += dx ball.position += dpos pos = ball.position x, y, z = ball.position
試してみよう。
position の型は何なのかという話か。 Vector クラスというのがあったが遅い模様。ここで使うのはそもそも間違っているのかも知れない。
Vector3D というクラスを自作したほうが速度以外の意味でも正解かも。
class Vector3D < Array def x ; self[0] ; end def x=v ; self[0] = v ; end def +dpos self[0] += dpos[0] self[1] += dpos[1] self[2] += dpos[2] self end end
次のようなコードが動いた。
ball = Ball.new x = y = z = 100 dx = 10 dpos = Vector3D[1, 2, 3] ball.position = Vector3D[x, y, z] ball.position.x = x ball.position.x += dx ball.position += dpos pos = ball.position x, y, z = ball.position p pos p x,y,z