Jewel-mmo開発日記

RubyでMMORPGを作る過程を記録する日記。 Yokohama.rb 発起人。
2005-01-09

[アイデア]Easy Rocket インターフェース案

適当に書きながらイメージを固めていきたい。

2D

まずウィンドウの生成と 2D 表示。 とりあえずウィンドウ生成のオプションは置いておく。

requre 'er'
screen = ER::Screen.new

prim = ER::PrimImage.new screen
prim.position = 100,100,0
prim.disp

次のような実装もありかと思うがどうだろう。違うかな。

prim = screen.create_image_prim

3D

次に 3D オブジェクト。

requre 'er'
screen = ER::Screen.new

model = ER::Model.new screen, data
model.position = 100,100,0
model.disp
model.anim anim_id

シンプルだけどモデルをグループ分けしてソートしたり、ライティングを考慮してない。あ、視点のコントロールができない。カメラも追加しよう。

requre 'er'
screen = ER::Screen.new
ot = ER::OT.new screen

camera = ER::Camera.new
screen.camera = camera

model = ER::Model.new data
model.position = 100,100,0
model.disp
ot.add_obj model
ot.disp

model.anim anim_id

OT は任意で生成すればいいか。カメラは複数存在する可能性があって、切り替える場合はスクリーンの設定を変更すればよい。

画面分割

画面分割する場合を考えてみる。例えば、画面を上下に分けて対戦できるマリオカートとか、レースゲームのバックミラーのような処理の場合。

まずモデルオブジェクトは複数の画面でもひとつのものを使いまわすべきだろう。む、 カメラと OT はどうだろう。難しい。あくまでクライアントの都合だけで考えよう。そう考えると使いまわせてもいいし、別々のものを使ってもいいがいいかな。

screen1 = ER::Screen.new
screen2 = ER::Screen.new
ot = ER::OT.new screen1

あ、これだと OT が使いまわせない。そうか、 OT と Model はポリモルフィズムというやつでないとダメだ。 2D プリミティブもこの「描画オブジェクト」の仲間だ。スクリーンがこの仲間に入るかどうかは微妙。

screen1 = ER::Screen.new
screen2 = ER::Screen.new
ot = ER::OT.new
screen1.add_obj ot
screen2.add_obj ot

とすればいいか。以下のように続けて、

camera1 = ER::Camera.new
screen1.camera = camera1
camera2 = ER::Camera.new
screen2.camera = camera2

カメラはこれで OK 。ひとつのカメラを使ってもよい。

model = ER::Model.new data
model.position = 100,100,0
model.disp
ot.add_obj model
ot.disp

ここまではいいか。いや、よくないな。ウィンドウがひとつなのか複数なのかが明示されていない。

win = ER::Window.new
screen1 = ER::Screen.new win, rect
screen2 = ER::Screen.new win, rect

のようにすればいいか。 Window.new は省略できる方向で。

OT 単位でソート

次に OT 単位で描画の優先順位を設定することについて考えてみる。

screen = ER::Screen.new
ot1 = ER::OT.new
ot2 = ER::OT.new
screen.add_obj ot1
screen.add_obj ot2

ot1.z = 0
ot2.z = 1
#ot1.position = 0,0,0
#ot2.position = 0,0,1

単にこれでいいか。

OT を省略

screen = ER::Screen.new
prim = ER::PrimImage.new screen
prim.disp

最初にこう書いたけど、これまでの考察で行くと次のようにならなければいけない。

screen = ER::Screen.new
prim = ER::PrimImage.new
prim.disp
screen.add_obj screen

前者の方がいい気がするが。次のようなパタンもありか。

screen = ER::Screen.new
prim = ER::PrimImage.new
prim.parent = screen
prim.disp

むむむ。こんがらがってきた。親と子は相互リンクだろうか。少なくとも子は親を知っていなければならないはず。子オブジェクトから階層関係を考慮してワールド座標を取得するときとか。親は子を知る必要があるだろうか。描画プライオリティは階層関係を超えて設定したいから内部的には描画オブジェクト自体から……まあ複雑な話は考えてもあまりあてにならないからいいか。

下の図を考えていたら気づいたが、描画プライオリティは階層関係を超えてはいけない。スクリーン内に描画されたウィンドウの表示順序を帰るときに不便だし、そもそも OT の意味がない。

クラス階層図

これまでの考察を踏まえると、こんな感じだろうか。

DrawObject(OT) …… position(x,y,z),disp,hide
 |
 +--DrawPrim …… size(w,h,d)
     |
     +--Window
     |
     +--Screen …… camera 
     |
     +--Prim2D
     |   |
     |   +--PrimImage
     |
     +--Model3D

この中で new の引数に parent をとれないのは Window だけ。Window 生成の省略系があるからその限りではないか。

省略なし

win = Window.new nil
screen = Screen.new win
prim = PrimImage.new screen

win 省略

screen = Screen.new
prim = PrimImage.new screen

ただ実際はスクリーンサイズくらいは設定したい。

screen = Screen.new 640,400
prim = PrimImage.new screen

としたいけど確か Ruby でこういうのできない。

def ER.CreateScreen w,h,x=nil,y,nil
  screen = Screen.new DefaultWindow,640,400
end

を用意しておいて、

screen = CreateScreen 640,400
prim = PrimImage.new screen

とすればいいか。

これは画像表示 new にも言える事だな。難しい。

まとめ 1( 間違い版 )

2D プリミティブ表示。

requre 'er'

screen = ER::CreateScreen 640,400
prim = ER::PrimImage.new screen
prim.position = 100,100,0
prim.disp

3D モデル表示。disp はデフォルトでいいか。

requre 'er'

camera = ER::Camera.new
screen = ER::CreateScreen 640,400
screen.camera = camera

ot = ER::OT.new screen

model = ER::Model.new ot
model.position = 100,100,100
model.anim anim_id

次に画面分割。あれ、このクラス構造だとダメだ。むむむ。カメラが描画するというアプローチが必要か。いや、スクリーンは描画オブジェクトじゃなくて表示領域だ。ウィンドウとスクリーンを描画オブジェクトに入れたのが間違いだ。

まとめ 2

2D プリミティブ表示修正版。

requre 'er'

screen = ER::CreateScreen 640,400
prim = ER::PrimImage.new
prim.position = 100,100,0
screen.add_obj prim 

3D モデル表示修正版。

requre 'er'

camera = ER::Camera.new
screen = ER::CreateScreen 640,400
screen.camera = camera

ot = ER::OT.new
screen.add_obj ot

model = ER::Model.new ot
model.position = 100,100,100
model.anim anim_id

画面分割

win = ER::Window.new
screen1 = ER::Screen.new win, 640,400
screen2 = ER::Screen.new win, 640,400

ot = ER::OT.new nil
screen1.add_obj ot
screen2.add_obj ot

camera1 = ER::Camera.new
camera2 = ER::Camera.new
screen.camera1 = camera1
screen.camera2 = camera2

model = ER::Model.new ot
model.position = 100,100,100
model.anim anim_id

--

あ、ライトを忘れてた。ライトはカメラと同じようにスクリーンに追加すればよさそうだ。ただライトは複数設定することができる。

light1 = ER::Light.new
light2 = ER::Light.new
screen.lights << light1
screen.lights << light2

こういう書き方できただろうか。

screen.push_light light1
screen.push_light light2

ダメならこれで。

クラス階層図 ( 修正版 )

Window
Screen …… camera,lights 

DrawObject(OT) …… position(x,y,z),disp,hide
 |
 +--Prim2D …… size(w,h)
 |   |
 |   +--PrimImage
 |
 +--Model3D