|
|
my:ban_ban_don_diary [2020/07/08 06:57] kijima 作成 |
— (現在) |
====== BBD,日誌 ====== | |
| |
===== 書き換え ===== | |
| |
tank -> characterなど。 | |
| |
===== キャラ選択 ===== | |
| |
キャラによって銃撃の特性が異なる。爆風がないのもある。 | |
まずは、ポーズメニューからキャラ選択をするようにしたい。いきなりスタート画面から選ぶのもいいのだが、デバッグが面倒になりそうな気がしたので。 | |
| |
==== カーソル移動 ==== | |
ボーズでの選択画面を作る。 | |
カーソル移動。ふだん直感的に使ってるが、少しやるのも大変だ。 | |
| |
[-1, 2, 2] | |
というようにカーソルの横位置を保持するようにした。 | |
| |
現在yが異なっても、保持しているものを表示するようにしたい。 | |
| |
==== 決定ボタン ==== | |
あとは決定ボタンでキャラと、難易度を選択して変数に書き込むようにすればOKだ。 | |
でも肝心のほうがまだなので、そっちをやろう。 | |
powerupsが参考になるとは思う。 | |
基本的にtankを継承すればOK、オーバーライドしていく…画像、射撃の効果、移動速度…など。 | |
| |
==== キャラ、武器 ==== | |
| |
キャラが変われば、その下にある多くが変わる。…bullet, explode、立ち絵…。 | |
ほとんどは武器関連だ。武器によって特定の組み合わせを作る。ピストル、グレネード、刀。 | |
要するに1つ層を追加するということだ。 | |
| |
現在は、characterが直付けされているから、それに1層追加するという形になる? | |
| |
==== 弾丸数 ==== | |
銃ごとに異なる弾丸数を設定する。 | |
| |
==== 分割 ==== | |
分割の順番。カンタンそうなのからやる。 | |
| |
まずメインになる、GameObjectを継承するクラスを作る。 | |
initializeで、super(object_pool)でobject_poolを渡してGameObjectのinitializeを読み込んでから、下位のcomponentのインスタンスを作る。ExplosionGraphics.new(self)とか。たいてい自分のインスタンスを渡すことになる。 | |
| |
で、それからファイルを作る。分割してコピペしていく。 | |
| |
==== 順番 ==== | |
| |
リファクタリングの手順が結果がメインで載っていてわけわからなくなったので本をもう一度みて再現する。 | |
紙幅のせいで一度にすべてをリファクタリングする手順で書かれていて確認できない。なのでひとつひとつ動かしながら確認できるように書いていく。 | |
追うのが大変だったが、やっと理解できた。自分でやってみるのがいやおうなしに考えることになって一番はやい。 | |
| |
チャプター5のリファクタリング(component)は結局のところ、play_stateで生成したobject_poolを綿々と送り出していく作業にほかならない。心臓のようなものだ。それをどうやるかっていう手段で、継承…initialize,super()をうまく使って最小限でやるというわけだ。インスタンス生成にobject_poolが必要になり、それをinitializeで密かにインスタンス変数にする。それを繰り返して送り出す。そういう影、繰り返すつまらないことをやらせるために継承元を作る。 | |
| |
そして、たくさん入れたobject_poolで一気にupdateやらdrawする?。すごい。 | |
| |
Componentの働きがよくわからない。componentを継承したやつ(bullet_physicsとか)は、initializeでgame_objectを受け取り、objectに代入して使えるようにする。呼び出し元ではselfを渡す。 | |
| |
なぜinitializeでメソッドxやyを定義する?object.xなど呼び出しているのが見える。呼び出し元のxやyにアクセスできるというのはわかるが、単なるx(どこで定義してる)とobject.xがあるのは何?? | |
| |
componentのdrawやupdateは自動で実行される。 | |
| |
==== ひとつずつがムリ ==== | |
| |
前回はexplodeだけなんとか分離してリファクタリングできた。 | |
しかし、bullet関係だけというのができない。explodeはbulletだけいじればよかったのだが、bulletはtankをいじる必要があるためだ。tankをいじると相互に関連してすべていじらないといけない…。たとえばplay_stateのupdateをいじるとすると、同じupdateでもやっていることが異なるのでうまくいかない。引数も違う。ほかのupdateは引数がobject_poolだが、characterのupdateはcameraをとる、など。よってinitializeも違う。 | |
| |
新しいのはobject_poolに突っ込むが、以前はそうではない。 | |
リファクタリングを独立してやるのは難しい。 | |
かといって、そのまま移すことはダメな気がする。 | |
gitにも、めちゃくちゃなコミットログが残る。 | |
| |
==== 結局、どう作るかは自分で学ばないといけない ==== | |
| |
リファクタリングの結果だけがバーっと羅列されてるが、どういう手順でこれらをやったのかがわからない。 | |
順番どおりではない。単に印刷上の都合で並んでいる。 | |
働きを変えずに、内容をいじらないといけないが、それをどうやってこう大胆に変えることができるんだろうか。一つを変えると全部変えないといけないような根本的な変化…。 | |
| |
コピーにならないようになんとか書いていき、途中でエラーを解消していくが、スタックトレースがでなくなる。 | |
たまに出たりするが。よくわからない。また最初からか…。 | |
| |
==== とりあえずできた ==== | |
| |
動くようになった。これからどうしていこうか。 | |
残弾数の表示を画面端でやろう。 | |
| |
==== message.drawの色指定ができない ==== | |
| |
色がつかない。できた。 | |
1.0を追加した。 | |
''@message.draw(x1, y1, 300, 1.0, 1.0, FONT_COLOR)'' | |
キーワード引数で指定したかったのだがわからなかった。まあいいだろう。 | |
| |
残り弾薬を画面に表示するようにしたら、少しそれっぽいものになった。 | |
| |
==== 衝突エリアの追加 ==== | |
| |
ほとんど本通りになるが、いちおう追加しておく。 | |
puts "#{object.instance_variables}" | |
=>[:@components, :@object_pool, :@input, :@x, :@y, :@physics, :@graphics, :@sounds...] | |
| |
本に間違い?があって、そのままでは動かない。←間違いではなく、@physics.boxのアクセスメソッドをboxで作っていた。本にはそのことが書かれていなかった。 | |
character_graphics.rbの''object.box.each_slice(2)''を''object.physics.box_slice(2)''にする。わかってみれば単純だ。なんとなく関係がわかって来た。 | |
| |
また、characterのアクセサにgraphicsがなぜかないので、追加した。instance_variables()などでインスタンスを調べたりするとよい。一覧にあるのに見つからない場合は、アクセサを見る。たぶん。 | |
無事動くようになった。 | |
| |
マークがつく。 | |
| |
==== 衝突の追加 ===== | |
| |
車体の衝突と、弾丸の衝突。 | |
何かがおかしい。 | |
| |
車体は、横方向がやたら大きい判定が出る。 | |
弾丸は、**たま**にエラーになる。斜めにぶつかったとき? | |
| |
全くわからん。 | |
判定範囲の描画はうまくいっている。しかし、現れている問題は範囲の問題に見える。 | |
| |
nearbyの引数max_distanceに目をつけた。これによって前と後の座標を比較して、衝突しているか判定を出している。 | |
distanceを大きくすれば範囲は大きくなる。元の値は100。 | |
なぜか左だけ?影響を受けているように見える。40にすると、左右への変な張り出しがなくなった。 | |
意味不明。 | |
| |
命中すると車体にも当たり判定が発生している?音がして、止まる。重要なヒントだ。 | |
3発以上同時に出るとundefined method boxが出る。????意味不明。 | |
| |
進行方向に発射すると自弾の当たり判定に引っかかる。bulletのcheck_hitをオフにしてても引っかかるから、車体側が何かおかしいようだ。 | |
| |
隅々まで読んだり(あまり理解できない)試してみて、ここしかないというところまで問題のスコープを絞った。 | |
でも問題なさそうだったのでコピペしてみたら動いた。diffを見てみると""j = i""が""j = 1""になっていたという些細なもので笑った。 | |
| |
==== 自弾との衝突 ==== | |
| |
進行方向で自弾と衝突して、そのまま進むとエラーになる。 | |
変な当たり判定と同じ理由かと思っていたが、別問題のようだ。 | |
| |
解決。 | |
game_objectでbox,collideメソッドが用意されてなかったよう。 | |
空のメソッドなのだが、当然オブジェクトがメソッドを持ってないとエラーになる。 | |
このようにして、特定のオブジェクトだけが持つメソッドを実行させたりスルーさせたりするんだな。 | |
これで、衝突判定は出るがエラーがでなくなった。 | |
修正した最初は反映されてなかったような気がする…。こういうのがあるのが怖い。 | |
| |
つぎに""next""で発射元の弾丸場合はスルーするようにする!完了。 | |
| |
==== ガタガタする ==== | |
| |
地形ペナルティーを追加する。 | |
単に同じコードを書くだけだが、問題発生。 | |
追加した地形、砂浜の上でガタガタする。低速では起きない。 | |
| |
speed,shift関連が怪しいと思う。そこがパタパタしている? | |
| |
仕組みを見る。 | |
putsで@speedをみると、ほとんど0でたまにアクセルの数値が変わっているのがわかる。 | |
''@speed > 0''で、shiftに代入して、その分座標に足される。 | |
一度shiftを経由するのはupdate_intervalに合わせて調整するためだ。 | |
@speedは初期化されてる?でも蓄積するよな。 | |
| |
''camera.rb''を見ると、同じ仕組みで座標を計算していることがわかる。 | |
ところが、引数は''@target.physics.speed''だ。つまり@speedだ。 | |
''character_physics.rb''では、ペナルティ調整後のspeedが渡されている。 | |
つまり、カメラと移動体で渡されるspeedが異なる。…でもガタガタするのはよくわからない。 | |
| |
結局cameraとphysicsのどちらもshiftがほしいらしいので、@shiftにアクセサをつけてcameraも@shiftを使うようにすると解決した。cameraは地形調整前のspeedなんて必要ないから。 | |
| |
しかし、これはたぶん何かが間違っている。サンプルは普通に動いていたのだから。と思ったが、サンプルのcameraを見てみると違う感じになっている。何か別のリファクタリングが重なったようだ。 | |
つまり、それも含めてやるとちゃんと動くが、途中で動かすことはできない種類のなのかもしれない。 | |
…単純な、オレのミスかもしれない。 | |
| |
==== AIの射撃がおかしい ==== | |
| |
追っているときに反対側を射撃する。 | |
射撃関連がおかしいのだが、わからない。 | |
| |
砲塔の回転はしっかりしている。drawなので関係ないか? | |
| |
target_x, target_yを表示するようにすると、やはり明後日の方向を向いている。 | |
target_x, yは自位置と方向と距離で求められた目標座標である。そのどれかがおかしいんだ。 | |
| |
うまい具合に止まる状態を作って角度をチェックしてみると、反射角みたいな角度でおかしくなっていることがわかる。 | |
1時の方向だったら5時みたいなさ。 | |
| |
gun_angleをどこで更新してるのかわからない。自機のときはplayer_inputでマウスカーソルの位置だけど、それじゃないだろ。gun.rbか…でも異常は見当たらない… | |
| |
結局、Utilsが間違っているのを発見。今までもおかしかったが気づいてなかった模様。 | |
今までできてから考えなくていいだろうというのは捨てたほうがよさそうだ。ちゃんとたどっていけばだいたいの筋道はつく。 | |
| |
==== 弾丸の動作の変更 ==== | |
| |
武器を抽象化する。 | |
爆発は武器によっては使う。 | |
| |
で、どうしたらいいんだろう。 | |
| |
要するに武器によってBulletPhysics,BulletGraphicsの動作を変えたいということだ。あとキャラの外見も。 | |
武器はcharacter生成時に決定する。 | |
| |
まずcharacter.rbでCharacterWeapon.new()。 | |
character_weapon.rbのコンストラクタで@bulletの具体クラスを決定する。Bulletを継承したHandgunBulletとかを入れる。もちろんインスタンスは生成しない。 | |
| |
character#shoot時に、さきほど指定したインスタンスを生成する。 | |
| |
bulletでexplode()をオーバーロードすることで爆発はするorしないができるようになったが、根本的にいじるためにはphysicsやgraphicsをいじる必要がある。再利用性が…。 | |
| |
全部継承を用意するのはクソに思える。少くとも3*3ファイルが増えるのはひどい。 | |
必要なのは、 | |
* 発射音(sound) | |
* 弾丸の画像(graphics) | |
* 弾丸の軌跡(graphics) | |
* ダメージ(physics) | |
* 範囲(physics) | |
* 速度(main) | |
* 爆発物か否か(main) | |
ほとんど全部数値が変わるだけだ。要するに武器とはこの数値の組み合わせのことだ。 | |
object_poolで全部渡せばよくないか? | |
| |
各派生弾丸クラスでinitializeで数値を定義したい。super()に追加していたい。でも引数を5つ書くのがいやだ。 | |
| |
==== 発射音が再生されていない問題 ==== | |
| |
今まで気づいてなかったが、発射音が出ていない。 | |
爆発音は発生しているが…。サンプルでも発射音は出てないようだ。同じ仕組みで書けるように思える。そして同じようにかかれているのに、音が出ていない。 | |
| |
音の問題か?単に聞こえづらかっただけ。変えたら聞こえる。 | |
| |
==== 画像の変更(未) ==== | |
| |
オリジナル感がないので画像を変えよう。どういじったらいいかわからないのでそこからだが…。 | |
* キャラ画像 | |
→画像を8方面単に回転させているかわりに、画像を読み込むようにする。横、上、下、斜めの4種類? | |
* マップ | |
→都市マップに。障害物も生成しないといけない…。 | |
* 弾丸 | |
→それぞれ用意。完了。 | |
| |
よく元のゲームを観察してみると、基本はキャラクターの進行方向に向かって画像が変化する((マウスの位置は関係ない。そもそも元のゲームはタッチペンだからどこを狙ってるか決めようもないのだが))。けっこうアニメーションする。 | |
で、銃撃した場合は銃を上げたアニメーションになって銃撃方向を1秒くらい向く。だから移動方向とキャラの絵が逆だってこともある。でもそれでなんか臨場感がある。 | |
| |
* 方向の違う画像を読み込むようにする。 | |
* キャラによってセットを変える | |
* 銃撃したときの挙動を追加 | |
| |
==== キャラ画像 ==== | |
| |
RPGのキャラの歩行画像を見ると、24個だ。 | |
8方向で、それぞれに1つの静止時と2つの歩行グラフィックがある。 | |
…メンドクサイ。ソフトで生成するが、jsonで指定するのも面倒な作業だ。一つ一つ…。一度作ればキャラに関しては再利用できるんだろうが、それにしたって。ソフトでできないんだろうか?調べるが出てこない。 | |
| |
ところで画像をjsonから読み込んでいる元のソースを見てると、たぶんこれはそのままweaponにも応用できるんだろうと思う。 | |
| |
* 角度: 静止, 歩行1, 歩行2 | |
* 0: 4, 5, 6 | |
* 45: 7, 8, 9 | |
* 90: 14, 15, 16 | |
... | |
みたく指定していくようにしたい。 | |
| |
==== 砂浜地形で弾丸が描画されない ==== | |
| |
ほかは問題ないので、重なりとかではない?完全なる保護色か? | |
色を変えると見えるのを確認した。完全に同じだったな…。 | |
| |
==== JSONに注意 ==== | |
| |
JSONでよみこむようにしてなぜかLauncherだけ動かない問題。発射した弾が動かない。爆発してない。 | |
最初はどっか変数の修正ミスで、explosion関係だと思っていた。 | |
丸々中身を変えてみると動く。考えてみれば変なことで、全部データは数値が違うだけなんだから間違ってはいないと踏んだ。いろいろ試してみて原因はspeedだと判明。to_iにしていたため、0.6のスピードが0になっていた、というだけのものだった。もしほかの値が1より小さかったらわからなかったかも。 | |
| |
JSONで数字を読みこむときは十分注意しよう。 | |
| |
==== 当たり判定が見えるようにする(未) ==== | |
| |
当たり判定をどうするのかが問題だ。 | |
今のままでは弾丸が小さすぎる。単なる円だからな。画像と当たり判定は、一致してるか?そこらへんの実装がよくわかっていない。 | |
| |
==== 武器によるエフェクトの変更 ==== | |
| |
パラメータを変えることですべて対応する予定だが、できるんだろうか…。 | |
読み込む画像を変えてできた。jsonでやればカンタンに。 | |
| |
==== 横向きのキャラクター ==== | |
| |
今は戦車だから単に画像を回転させるだけでOKだが、キャラでそれやると頭の上しか見えないのでやや斜めにする。そうすると回転だけじゃダメなので絵や仕組みを追加する必要がある。 | |
| |
==== とりあえず完成させよう ==== | |
| |
細かいことはあとにして、まずゲームとして完成させよう。クリア条件の追加とか、キャラ選択だ。 | |
| |
==== 木が揺れない ==== | |
| |
本の通りだが揺れない。 | |
キャラの当たり判定はある。つまりcharaのon_collisionは働いているが、treeのon_collisionは働いていない。 | |
そもそもon_collisionを調べてみる。どこから実行されてるんだろう? | |
| |
on_collisionがわからない。ためしにputsを入れてみても反応しない。 | |
衝突音がなってるから確実に実行されてるのに?音を出してるのはcharacter_physicsだった。(#character_sound.collide) | |
| |
つまり…charaのon_collisionも働いていない。 | |
| |
衝突を判定する変数を導入してないためだった。本に載ってないパターンのやつ。 | |
| |
==== 木に命中しない ==== | |
| |
木に命中しない。 | |
| |
いっぽう新しく追加した箱には命中しHPが減少し、爆発する。 | |
| |
tree.rbの少しの違いだと思うが、わからない。healthは共通のものを使用しているし…。 | |
mapでgenerate_treesでTree.newの代わりにBox.newを入れると問題なく箱は爆発する。Tree以下の何かがおかしい…。 | |
| |
boxがひとつのときの動作が定義してなかったのが原因だった。 | |
Utils#point_in_polyは複数のbox間に、座標が入っているか試す。 | |
treeのboxはひとつしかないため(試しにboxを複数にすると動く)、point..は常にfalseを返す。 | |
| |
そのため、1つの場合としてifにobject.treeか?を追加する。これはboxが含まれているかでなく、距離 < 10 で判断する。 | |
| |
同様の視点からexplosionを見てみると、treeには動いていないことがわかる。 | |
見てみるとこっちはobj.class == Characterとなっているので動かない。HPを持つあらゆるものに当たるハズなので、利便性からobj.respond_to?を用いる。 | |
| |
==== レーダー ==== | |
| |
視野外にいる敵の方向を示すカーソルを表示するようにしたい。 | |
| |
敵の座標と自分の座標で角度を求め、その角度にあたる画面端にアイコンを表示する。 | |
ある距離に達すると消去するようにしたいが…。 | |
| |
==== 四本木 ==== | |
| |
を導入。ひとつひとつ本に掲載されていないのであたりをつけてdiffしてみて行く…。 | |
object_poolをいじるのでかなり広い影響があった。 | |
game_objectがobject_poolを使い、ほかのオブジェクトがgame_objectをつかう。コンストラクタに渡すのが変わるのでnewするすべてで変える必要がある。 | |
| |
で、移動が関係するすべてをmoveを使ったものに書き換える。object#moveを通してしか移動できない。今まではobject.x, object.yをつかっているため、書き換える。同時にattr_readerなどもすべて削除する。 | |
取得するだけのやつ、レーダーとか、の動作にはまったく影響はない。座標を書き換えるときに代わりにメソッドが必要だということ。 | |
| |
==== Array#sample ==== | |
| |
Array#sampleは配列から1つ選んで返すらしい。超便利。例で使われているのに、今まで気づかなかった。gosu_texture_packerのメソッドかと思っていた。 | |
| |
==== health_powerupでrequireエラー ==== | |
| |
ほかは同じなのに、なぜかhealth_powerup.rbだけ読み込めない。 | |
継承元のPowerupを認識してくれない。 | |
ひとまずコメントアウトして、Mapでの読み込みもなくしておいた。 | |
| |
require_relativeでのエラーなので、継承の順番的に先にPowerupを読み込めということなのだろうと思ったが、ほかのは問題なくできてるからな。なぜHealthPowerupだけ問題が…。意味がわからない。 | |
| |
==== アイテム取得時の音がでない ==== | |
| |
PowerupSoundsでplayは動作していることを確認した(putsで)。 | |
一応再生はしている? | |
音が入っていないか、ボリュームが0になっているのだと思う。 | |
| |
再生音を変えるとできた。解決はできたが謎だ…。 | |
何回かチェックしたがやっぱりpowerup.mp3ではできない…。 | |
| |
==== 爆発後に跡が残る ==== | |
| |
たまに爆発後に跡になにか画像が残るときがある。謎の。 | |
| |
==== 被弾時に音を鳴らす ==== | |
| |
character_health#inflict_damageで音を鳴らすことができた。 | |
ずっとほかのcollideでいろいろやってできなかった…physicsにあるほうが自然な気がして。 | |
まだまだ新しい仕組みを理解してなさすぎる。 | |
| |
==== 音を鳴らす仕組み ==== | |
| |
character_healthで鳴らしたのはテストで、StereoSampleを使ったものではない。 | |
なので本式のそっちにしようと思うのだが、どうもUtilsで引っかかってしまう。 | |
| |
==== 音 ==== | |
| |
(bullet-hit.mp3) | |
被弾音はとりあえず https://sonicwire.com/product/26621/single?page=86 | |
のサンプルがイメージに近い。フリーではないので後で差し替える。 | |
| |
==== 被弾、与ダメージ ==== | |
| |
被弾と与ダメージをスコアとして記録する。 | |
healthのinflict_damageに追加していく。 | |
| |
今のhealthの仕組みだと被弾しか記録できない。sourceを導入する。つまりダメージは誰が与えているのが何かということ。bulletがsourceを持っているので、それを渡す。で、体力を処理するとともにsourceのスコアも処理する。 | |
explosionにも影響がある。 | |
| |
==== スプライト ==== | |
| |
サンプルのtreeのスプライト処理のやり方。ランダムに生成したseedからスプライト内の画像を読み取る方法。**画像の個別の名前を知る必要がない**。 | |
| |
frame_list = trees().frame_list # jsonから読み込む。.frame_listで配列にまとめる。 | |
i = (frame_list.size * seed).round # seedは0.00~0.99, perlin_noiseで生成 | |
frame = frame_list[i] # 画像の名前になる | |
@tree = trees.frame(frame) # 画像を読み込む | |
| |
ただし、画像数が少ないと(51枚以下?)、インデックスiが配列の要素数より大きくなってしまうことがある。当然エラー。51枚のとき、0.99をかけても50.49になり、四捨五入して50。元の数と同じになることはない。これが50枚のときx0.99で49.5で50。50になることがある。 | |
| |
==== load_tiles ==== | |
| |
mapやexplosionでは画像の読み込みにload_tilesを使っている。 | |
load_tilesはピクセル数で分割して配列に入れるよう。128*128で分けるとか。 | |
jsonがいらなくてOK。 | |
| |
1→2→3/ | |
4→5→6/… | |
という風に配列に格納されるようだ。 | |
| |
==== 爆風と地面へのエフェクトの時間差 ==== | |
| |
Thread.newとsleepで実行されていることがわかった。 | |
sleepを普通に使うと全体が止まってしまう。 | |
Threadで爆風と地面への処理部分を並列化してsleepすると全体が止まらず、爆風と地面へのエフェクトの時間差を表現できる。 | |
| |
ということはわかったのだが、画像の表示がおかしくなる。画面内の何か一部分が表示される(HUDのどこかの部分が多い)。表示される場所は都度かわり、意味不明。 | |
前から起こっていた問題だった。 | |
| |
この処理はhealth#after_deathにかかれていたため、launcherの爆発では発生していなかった。とりあえずThreadの部分を削除したが、同時に表示されるのはやっぱり変に思えてきた。 | |
| |
問題のポイントは、damageが初期化されてないうちに呼び出されることだと思う。 | |
damageは最初だけファイルから読み込みを行う。後はそれをメモリから呼び出すのだが、どうもスレッド中で最初に呼び出されると後はずっとおかしくなる。 | |
まだhealthにスレッド処理があったときは、launcherのときは問題がおきないことが多かった。たぶんスレッドを使わない処理のときに初期化されていたためだ。 | |
| |
試しに、play_state.rbにdamage.new(@object_pool, 0, 0)を書いてみた。画面の1番端が焦げて始まるのだが、スレッドを使っても問題なく描画され、もちろんsleepも効いている。 | |
| |
初期化とアニメーション生成は同時である。 | |
キャラとか、マップとかカメラは、最初に決まった数が一気に処理される。 | |
| |
いっぽうでbullet、explosion、damageは都度生成される。画像のロードは初回のみ行われる。…ここが厄介だ。ロードのみ初回で一気にしてほしいと思う。 | |
| |
スレッドをいじる方向か、最初で実行する2つがあるが、後者が素直に思える。 | |
無害な方法で最初に一通り生成したい。new(..).mark_for_removalで跡は残らない…。ダサい方法だが、これで良い? | |
| |
==== 銃弾にboxをつける ==== | |
| |
画像の大きさで銃弾の大きさを決定するようにする。 | |
それだけではできない。銃弾の当たり判定は単に中心からの距離で求めるようになっているので、boxの中に入っているかで判定するようにする。 | |
| |
車体の当たり判定を参考にして書き換えた。collides_with_polyはboxとboxの当たり判定をしてくれるのでうまくやる。 | |
| |
==== boxと画像が微妙にずれてる ==== | |
| |
微妙に左にズレていて気持ち悪い。なぜ? | |
| |
==== ヒット時に白くする ==== | |
| |
Gosuの機能だけではできそうにないので、Rmagickを使う。 | |
@bodyを詠み込んで加工して、@bodyに再び入れればよさそうだ。 | |
適当にやったらできた。 | |
@bodyを1ピクセルの画像にすれば消えたように見える。 | |
| |
こうなるとキャラだけでなくほかの木とか箱にもできるようにしたいが、今のままだと仕組みが違って再利用しにくい。 | |
キャラ画像は常に向かっている方向を読み込まんでいるので、一瞬挿し込んでもすぐにまた新しい画像を読み込む。 | |
| |
木や箱は一度変えると二度と戻らないので元を保持しておく必要がある。 | |
| |
==== 重なりがおかしい ==== | |
| |
レーダーと木が重なったとき、木が上になる。木のzは5、レーダーのzは1。 | |
レーダのzを200にした。あ、数字が高いほうが上に来るんだな。今までテキトーにやってた…。後から困るかもしれない。 | |
| |
==== 木の揺れ ==== | |
| |
ダメージを受けたときに揺れるようにする。 | |
bulletにちょうどtree専用の(boxが一つしかないので)判定があるので、そこに書く。 | |
爆発でも揺れるようにしたい。より根本的には、healthでいじる必要があるな。bulletを参考にして同様に… | |
| |
これは木だけじゃなくて箱にも使えそうだ。キャラクターは変えたい。 | |
| |
==== ヒット時の点滅 ==== | |
| |
前作ったやつだが、1フレーム限定なので改良したい。FPS60になると見にくいし。 | |
health#inflictで@hit=2とかにして、graphics#updateでif @hit..でデクリメントしてやればできそう。 | |
| |
==== 射程距離を伸ばしたい ==== | |
| |
クリックした点で消えるんでなくて、しばらく伸ばしたい。 | |
自分とクリックした点、2点の延長線上の座標で求められる。 | |
| |
やや汚い感じだ。 | |
| |
以前使ったような気がして調べてみると、AIの射撃線の表示はpoint_at_distanceだ。 | |
これはangleがあれば距離を指定して利用できて便利だが、今回は見送る。 | |
| |
==== 勝利条件 ==== | |
| |
バージョン1.0にするために、勝利条件をまず作る。それから細部を追加していこう…。 | |
敵を全滅させたら勝ち、自機のHPがゼロになったら負け。 | |
勝ちと負けの条件はかんたんにできた。OOPすごいなぁ…。 | |
| |
で、あとは勝ち負けのアニメーションするメッセージをサウンドとともに描画する。 | |
エンターを押して終了だけできるようにする。 | |
キーボードの意味が変わるのでplay_stateの切り替えとしてやればいいかもしれない? | |
その場合はinitializeでメッセージを生成すればいい。 | |
| |
だが…背景はそのまま動くようにしたい。今の考えだと、背景は真っ黒になってしまうように思える。インスタンスの変数は保持したままで、というとこだからgame_stateの変更(switch)は違うな。 | |
メインメニューのコンティニューがヒントになるように思える。 | |
Gosu::KbC && @play_state | |
で、@play_stateがあるときだけ動作を受け付けるようになっている。 | |
同様に…play_stateで死んだときのキーを条件追加すればいいように思える。 | |
| |
* updateで終了を検知→アニメーション(かちorまけ)を表示→enter待ち→終了 | |
アニメーション専用のクラスを定義する。…ほかにはスタート時とか表示する機会がある。 | |
graphicsを定義したほうがいいのか? | |
announceをどんなクラスにすればいいんだろう。 | |
| |
there is no rendering queue for this operation | |
| |
勝利や敗北に応じて描画できた。が、非常に使い勝手がよくない。 | |
| |
==== announce ==== | |
| |
↑の考え方は間違っている気がする。 | |
annouceは常にインスタンスがある状態だが、アナウンスのインスタンスを都度生成するというほうが自然だ。 | |
そのときごとに音と画像が出る。bulletのようなものだ。 | |
| |
今announceに書いている条件をplay_stateに書いて、生成をannounceに任せるのがいいかもしれない? | |
| |
まあいい。従来の方式、Annouceインスタンス常時生成方式で。 | |
音を出すのはどうしよう。 | |
| |
==== 終了後の移動音を消したい ==== | |
| |
win!!が出たときに移動音がそのまま出たままになるのをどうにかしたい。 | |
moving?が真のとき出る。それを判断しているのは@speed > 0。 | |
だから@speed = 0とするが変わらない。 | |
| |
チェックしてみると、どうも爆発した相手から出ている?普通に倒したときは音は、というかcharacterオブジェクトは削除されるので消えないが、最後に倒したときは音が残る。自分は歩いてないのに音がする。 | |
| |
オブジェクトごと消えてsoundもなくなるはずだが再生されているということは、オブジェクト削除がうまくいっていないということだ。 | |
| |
…結局、after_deathにスレッドでexplosionとobject.mark_for_removalの間にsleepを入れることで足音が消えるようになった。正直よくわからないが、とにかく同時だとよくないらしい。 | |
| |
==== クリア表示をアニメーションさせたい ==== | |
| |
上から出てくる感じで。 | |
powerupsのアニメーションと同じようにした。 | |
| |
死んで(勝って)から2秒くらいしてから出してアニメさせたくなった。この遅延に少し手こずる。 | |
drawは常に動いてるから(パラパラ漫画だ)、それぞれをスレッドを作って遅延させるわけにはいかない。 | |
最初だけ、遅延させたい状態。 | |
| |
これは、@startをスレッド内で遅延させて生成し、drawで@startがあるときだけ描画させるようにすることで解決した。効果音のように一回きりで遅延させることはできるので、そこに@startの処理を追加する。 | |
| |
音は1回きりだが、画像は常に描画しないいけない違いがある。この性質の違いを認識しておく。 | |
| |
==== キャラのデータ構造 ==== | |
| |
データ構造を決める。 | |
選択肢の前に、データを外部から決定できるようにすることが必要。 | |
| |
シナリオ | |
* 敵キャラ | |
| |
キャラ | |
* グラフィック | |
* 武器 | |
* 体力 | |
* AI | |
| |
武器 | |
* グラフィック | |
* 弾数 | |
* 攻撃力etc | |
| |
今は、画像に1~24の番号をふり、character.jsonでそれぞれの番号を3つごとに配列に格納している。 | |
3つずつ8方向。 | |
これで画像を対応付けている。[2][1][3]...拡張性のない方法だ。 | |
| |
元から画像に名前を振っておいて、それを対応づけに利用したい。 | |
静止はs-0を利用、歩行はd-0,d-1,d-2...を利用etc...いくらでも増やせるし、再利用も容易だ。 | |
名前で分けてグループ分けする必要がある。それはそれで、ダサいような気もするが…。 | |
| |
jsonで読み込んだ画像の名前の一覧を取得するにはどうしたらいいんだろう? | |
まずそれが必要だ。 | |
| |
いやまずは小さくいこう。character.jsonの方向別配列をいちいち指定するのが面倒だから、そこを共通化しよう。 | |
| |
==== 銃弾を撃った方向に向く ==== | |
| |
今は押した方向にそのまま向いている。それに、撃った方向を向くための処理を挿入する。 | |
| |
画像を180度反転させる必要がある。 | |
rmagickを使えばよさそうだが、どうやって?Gosuではtexture_packerから詠み込んでいる。 | |
Gosuのオブジェクトが使えたらよさそうだが、うまくいかない? | |
| |
方向転換の仕方が判明した。 | |
scaleをマイナスにすればよい。scale_xをマイナスにすれば水平方向の反転になる。 | |
だから… | |
@weapon.draw_rot(x, y, 2, object.direction + 90, 0.5, 0.5, -1) | |
みたいになる。(0.5はcenter_xで、デフォルトが0.5) | |
| |
==== 選択肢を進む ==== | |
| |
再利用可能な形にするために、選択肢データ渡しは引数でやる。引数を元にjsonを検索し、テキスト、画像を見つける。 | |
さらに、選択肢一つ一つで元のstateに戻り、結果を格納するようにする。 | |
| |
@difficulty = branch("difficulty") | |
| |
state間でどうやりとりしたらいいんだろう。 | |
menu_stateのアクセサに書き込むようにした。 | |
menu_stateではそのアクセサの値によって分岐するようにして、選択肢を進めるように。 | |
updateにその分岐を書くと、なぜかcharacter_graphicsのupdateがおかしくなる。よくわからない。 | |
オーバライド?うーん。 | |
| |
ほかのところに置くと問題なく動く。 | |
別に何回も繰り返すわけではないので、updateに置くのはおかしいと思ってenterに置いておいた。 | |
stateの実装を理解していない…。 | |
| |
選択肢を経由するとannouce後enterで戻れないことが判明。 | |
play_stateを生成する処理は何も変わらないように見えるが、重大な違いがあるのだと思う。 | |
→ 単純なことで、選択肢のインスタンス変数を初期化してないだけだった。 | |