いくらでも寝れそうだ。
TRPGやろうということでSW2.0のルールブックI改訂版を買ってきて読んでた。旧SWよりだいぶシンプルになってるのねぇ。戦闘は一見難しそうだけど実際の運用は楽そうでいい感じだ。シナリオ作らないとなぁ。
しばらく手をつけられずにいたゲーム作りを再開した。
何から手をつけようかとメモを眺めて、ステージエディタを作ろうかと。 ちゃんとした(?)ステージエディタを作るのは大変なのでAAで二次元のマップを書く程度でよかろう。
AAでマップを書くのは編集がそこそこ楽でいいんだが、制限もいろいろついてくるのが困る。
基本的に1マスに1つの記述しかできないので三次元的な表現はやりづらい。二次元で書いてるのでそりゃそうだ。
しかし三次元とまで言わずとも、床の上に敵を置くのも難しかったり。床が一種なら敵の下には床があると仮定しちゃってもいいんだけど。
あと単純に文字の割り当てが難しい。壁が#
で床が空白でスタート地点AはA
でスタート地点BはB
で他マップのスタート地点Aに飛ぶイベントがa
で……と割り振っていくとよくわからなくなってくるし、割り当てやすい文字がどんどん減っていってしまってあとで困りそうだ。
とかなんとか考えてはいたけど、実際作ってみたらそうでもなかった。
今までのマップ定義は下のような感じ。さっぱりわからん。
map :start do
start :left, x: 0, y: -4, z:0
start :right, x: 0, y: 99, z:0
wall x: -11.. 11, y:-5..100, z:-10..0, render: true
wall x: -11..-10, y:-5..100, z: 0..10, render: true
wall x: 10.. 11, y:-5..100, z: 0..10, render: false
wall x: -10.. -3, y:-5.. -4, z: 0..1, render: true
wall x: 3.. 10, y:-5.. -4, z: 0..1, render: true
goto x: -10.. 10, y:-15..-5, z:-10..10, name: :hoge, pos: :right
wall x: -10.. -3, y:99..100, z: 0..10, render: true
wall x: 3.. 10, y:99..100, z: 0..10, render: true
goto x: -10.. 10, y:100..110, z:-10..10, name: :hoge, pos: :left
wall x: -10..10, y:10..50, z:0..1, render: true
end
新しいマップ定義は下のような感じで、サイズと敵が置かれてるかどうかが違うくらい。
layer
にAAを渡すとブロックに二次元の位置と文字が渡ってくるのであとは適当になんとかするというだけ。
map :start do
on_cell = proc {|layer, cell|
y, x, z = cell.cols, cell.rows, cell.z
case cell.name
when :x then wall x: x, y: y, z: (0+z)..(10+z), render:true
when :y then wall x: x, y: y, z: (0+z)..(10+z), render:false
when :z then wall x: x, y: y, z:(-10+z)..(0+z), render:true
when :h then wall x: x, y: y, z: (0+z)..(2+z), render:true
when :a then goto x: x, y: y, z:(-10+z)..(10+z), name: :map1, pos: :B
when :b then goto x: x, y: y, z:(-10+z)..(10+z), name: :map1, pos: :A
when :A then start :A, x: x.first+1, y: y.first+1, z: z
when :B then start :B, x: x.first+1, y: y.first+1, z: z
when :e then cell.each_points {|c| enemy x: c.y+1, y: c.x+1, z: z }
end
}
layer <<-LAYER, z:3, scale:2, &on_cell
e
e
e
e
LAYER
layer <<-LAYER, scale:2, &on_cell
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
x hhhhhhhhhhhhhhhhhhh x
x hhhhhhhhhhhhhhhhhhh x
a hhhhhhhhhhhhhhhhhhh b
aA hhhhhhhhhhhhhhhhhhh Bb
a hhhhhhhhhhhhhhhhhhh b
y hhhhhhhhhhhhhhhhhhh x
y hhhhhhhhhhhhhhhhhhh x
yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyx
LAYER
layer <<-LAYER, scale:2, &on_cell
zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz
zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz
zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz
zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz
zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz
zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz
zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz
zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz
zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz
LAYER
end
ちょっと長くなるけど、見た目でマップの雰囲気くらいはわかる。一番下は律儀に床のマップ書いてるけど実は必要ないんだよなこれ。
レイヤーということで1マップ定義にAAを何枚でも書ければいいだけだった。 ある文字が来た時に何をすればいいかというのもレイヤー毎に定義できればいいだけなので文字種もあんまり考えなくてよかった。
高さ値はレイヤー毎とか文字毎とかで適当に設定してしまえば三次元のマップも面倒なく作れた。
あと1マスで壁一つとか作ってしまうと数が多くて衝突判定や描画がとても大変なことになってしまうので、 同じ文字がつながってるところは長方形単位でまとめてからブロックに渡すようにした。
もっと沢山マップ作り始めるとこれではめんどくさすぎるかもしれないが、それはその時考えよう。
見た目は全然かわってない。マップくらいしかいじってないので当然か。
マップを比較的わかりやすく作れるようになったので調子に乗って敵も置いてみたが、 敵やらアイテムやらの作りが微妙なことになっていてマップの切り替えと上手く連動しづらいのがわかった。
ゲーム全般を管理してるオブジェクトの下にステージとプレイヤーと敵とアイテムと……が並列に存在しているんだけど、マップ切り替えた時にその中に存在してる物も切り替えてほしいよね。ということは敵とかアイテムはステージの下にくっつかないとだめかー。というあたりをこれから直していきたい。
HTML UIの表示がバグってんで、という報告をうけたので修正。パッチではなかったけど間違ってる箇所を指摘してもらったのでそこをそのまま直すだけでよかった。ありがたい。
OSXでPeerCastStationを再起動したりするとソケットがBindできなくて落ちちゃうーと言われてたのを調査した。
たまにある現象だが原因をすっかり忘れていたので調べるとTIME_WAIT状態というのになったソケット?アドレス?は一定時間経過しないと解放されてくれなくて、プロセスを終了してもそのアドレスを占有してしまうとのこと。なんでそんな状態になってるのかはいまいちよくわからなかったが、あまり気にせずそういうものとしておこう。 ソケットのオプションを設定するとTIME_WAIT状態になってるアドレスにも強制Bindできちゃうよという話なのでSetSocketOptionでReuseAddressを設定してやった。 手元で上手く再現できてないのでまだ試してないけど、きっと大丈夫じゃないかなー?再現できないのは一番困るよね。
スリープから復帰後に落ちるというのを調査した。 が、俺のところでは起きてないのでなんとも難しい。 報告を良く読むとスリープ復帰後視聴をしようとすると落ちるとのことだがいまいちわからんな。 ログからはSystem.Windows.Forms.dllでInvalidOperationExceptionで落ちてるのがわかるので、 UI外のスレッドからコントロールにアクセスしたか、死んでるウィンドウのコントロールにアクセスしたかのどちらかだろうか。
思い当たるところはさっぱりないが、もしかしたらウィンドウ非表示のままスリープ→復帰するとウィンドウだけが作り直されたり死んだりするってことはあるかもしれない。考えづらいけどなぁ。しかしスリープして試すのがちょっと大変なので一旦保留とした。
あるYPブラウザから終了させようとすると終了しないどころかプロセスが増えたりなんだりするとのこと。そもそも外から終了させるって難しいんだけどどうやってるのかな?
調べるとPeerCastには-killをつけて起動すると既に起動しているインスタンスを殺すという機能があるようだ。これ実装してないなぁ。実装してやればいいのか。
今でも多重起動回避のために名前付きのMutexを使って、開ければ多重起動なのでそのまま終了、開けなければ最初のインスタンスなので新しく作るということをやっていた。このMutexをEventにしてセットされたら終了するように変更しよう。
変更は簡単だったけどEventの共有がmonoでも動くか不安。調べたところ、ソース的には大丈夫そうに見えたので大丈夫だということにした。あとでOSXで動かしてみよう。
チャンネル終了時に終わったことをバルーン通知してほしいという要望があったので実装したい。 バルーン通知自体は簡単だけど、終わったことの検出がめんどくさいな。単に接続先がなかったりしてエラー終了したのかとトラッカーが穏当にチャンネルを切ったのかの判別はできればしたいところ。要望だとそこまでは書いてなかった気がするけどなー。
ソースを眺めてたら、接続終了時の原因は内部的に取ってるのを思い出した。こいつを公開してやればいいだけじゃね……?ということでチャンネル切断時に発生するイベントの引数に接続終了要因を渡すようにして完了。通知の表示自体はちょっと前に汎用的に行えるようにしてあったので、それを使って簡単に表示できた。
PeerCastだとチャンネル接続時とかチャンネル情報変更時の通知もあったけどそこまではいらないかなぁ?あればあったでいいかもしれないけど、また今度ということで。
YPの設定をしたんですけどチャンネル一覧にチャンネルが出ないんです、どうやったら見れるんですか?という質問が来た。PeerCastStationはYPブラウザの機能はなくてただのPeerCastの置き換えなので別途YPブラウザを使ってくださいね、という回答をしておいたが、俺も最初同じこと思ったわーという人が意外に結構いた。
一時期YPブラウザの機能をつけようとしたことはあるものの別にみんなYPブラウザ使うから必要ないかとやめたんだよな。でもまあ勘違いする人が出るくらいなら簡易な物でも付けておくとちょっと嬉しいかもしれないなぁ。別なYPブラウザは使うかもしれないけど、あればあったでまあいいかな的な。検討しておこう。それまではYP登録の設定は配信掲載YPの登録に名前を変更しておくか。正確には配信掲載用というわけでもないんだが、実際は配信掲載用にしか使ってないからなぁ。