2004年11月26日

クイックスタイプのゲームで遊びたい

ふと、クイックスタイプのゲームで遊びたいと思った。
どうせなら作ってしまおうと思って、アルゴリズムなどを少し検討するが、それほど難しくはなさそうだ。
でも、メインの部分以外を作るのは面倒臭い。
そこで、吉里吉里2で出来ないか検討してみた。
パッドには対応しているようす。
KAGを少しいじり、ゲームシステム部分をプラグインとして実装すればできそうな感じ。
TJSで実装してもいいのだけれど、重そう。
なんで、やっぱりプラグインだな。
さて、どういう風な実装にするかなぁ。

投稿者 Takenori : 12:21 | トラックバック

2004年11月27日

クラス図を書く

とりあえず、ゲームのクラス図を書いてみる。
結構いろいろと詰めないといけなさそうだなぁ。

TJSスクリプトで少し書いてみる。
すべてTJSスクリプトで書くのは速度的にちょっと不安だけど、プロトタイプとしてはいいかも。
速度的に問題なければ、そのままでもいいし。

投稿者 Takenori : 10:14 | トラックバック

2004年11月29日

いきなり面倒臭くなる

TJSで当たり判定でも実装するかいなと思って書いていたが、すげー面倒だ。
Rectクラス、Pointクラスなどを作ったが、これって初めからないんだろうか?
リファレンスには見当たらないが・・・
で、Listクラスを作っていて嫌になってきた。
これは面倒臭い。

とりあえず、TJSで実装すると言うのはやめた。
やはり、C++か?
とりあえず、描画周りと当たり判定、ゲームシステム辺りは、昔作っていたDirectDrawを使ったやつを使用して進めるのがいいかな。

投稿者 Takenori : 03:15 | トラックバック

2005年08月11日

敵の動きをスクリプトで?

敵の動きや弾の動きはスクリプトで記述できるようにする。
キャラクターや画像は簡単に差し替えできるようにする。
まずは移動の部分だけでも作ろう。

投稿者 Takenori : 23:09 | コメント (2) | トラックバック

2005年08月13日

yaneSDK3rdを使ってみる

yaneuraoGameSDK3rdをビルドして、プロジェクト作って、線だけ引いてみた。
InsideYaneSDKを参考にした。ただし、少しだけディレクトリ構造が変わっているようだ。

線を引くというか、矩形塗りつぶしは、ISurface::GeneralEffect(CSurfaceInfo::eSurfaceFill,&rc) って感じで書けばいいよう。
他にもやり方がありそうな気がするけど、とりあえずこれで引いた。

投稿者 Takenori : 15:10 | トラックバック

2005年08月15日

Windowのサイズや名前

yaneSDK3rdの話。
CAppBaseを継承したCAppMainWindowで、OnPreCreateをオーバーライドすれば、ウィンドウのキャプションなど変更できるよう。

opt.caption = "新アプリ";
opt.classname = "NEW_APPLICATION";
opt.size_x = 800;
opt.size_y = 600;
opt.style = WS_MINIMIZEBOX | WS_CAPTION | WS_SYSMENU;

ってな感じでやった。

投稿者 Takenori : 13:28 | トラックバック

移動を線上に限定

ボタンを押している間はいろいろと動けるけど、押していないときは線の上しか移動できない。
そこで、まずは線の上だけ移動できるようにすることにした。

はじめはすべての線を調べることを考えたが、そんなことしなくても現在のっている線と、その両隣さえ調べれば事足りるので、その3本だけ調べることにした。
現在の位置とベクトルで移動可能かどうかと次の位置を調べる方法を考える。
平行かどうかを調べてからかなと、内積を使うことを一瞬考えるも、普通にif文の塊の方がいいかということで、そうした。
まず、水平か垂直か調べて、現在の位置がその線の中に入っているか見て、ベクトルを足してもまだ中かどうか調べる。はみ出たら、線の端の位置を次の位置へ、はみ出なかったら単に加算した位置。
斜め移動はしないことにしてるので、とりあえずはこれでいいや。
斜め移動が追加されても、すぐに追加できるはず。

次は線を引っ張って、領地を増やす部分だな。
これが出来れば、とりあえずはそれっぽく動く。

投稿者 Takenori : 13:31 | トラックバック

2005年08月16日

ボスはどっち?

ボタンを押しながら引っ張っているライン(以降、アクティブラインと言う)の衝突判定や、周りの固定ラインの衝突判定をif文とかでゴリゴリ書いた。

この辺の仕様
アクティブラインは、後方へ戻せない。(前方か90度曲げる以外不可)
アクティブラインは、アクティブラインと衝突することが出来ない。衝突する直前の位置より前へは進めない。
アクティブラインは、固定ラインと衝突した時、固定ラインとなり領地が増える。
領地が増える時、ボスのいる領域が残る。

ボスがどっちの領域にいるかの判定はどうする? と少し悩む。
矩形で…とか、全領域にフラグ立ててとかアホなことを考えるが、ふと思い付く。
単にボスの位置から垂線を下ろして、最初に当たった固定ラインを含む方が残る領域になると。
もし、アクティブラインに当たったら、次に当たった固定ラインはボスのいない領域となる。アクティブラインに当たるごとに、いる、いないと反転していけばうまくいきそう。
よし、それで行こう。

投稿者 Takenori : 21:49 | トラックバック

2005年08月18日

画像の入れ替え

自陣になった領域は画像が入れ替わる。
で、それをどのようにするか検討した。

1. 自陣かどうかのマスク画像を準備し、それを参照してどちらからコピーしてくるか判断する。
2. 矩形リストを持ち、どちらの領域か判断し、コピーする。
3. 領域を取得した時、画像をコピーしてしまい、以後、画像が覚えているということにする。

1. 案が良いかなとも思ったが、3. 案が速くて、用途的にも十分な気がする。
ただ、画像を再構築することを考えると、2. のコピー矩形リストがあったほうが良いかもしれない。矩形リストよりもマスク画像の方がいいかな?

考え中のこと
積分のようにして塗りつぶす。
矩形リストが出来る。
湾のようになっているところはどうする?
シルエットを考えると、マスク画像の方がやりやすい?
矩形リストでも、シルエットを塗りつぶすような処理をすれば同じ?
ポリゴンを塗りつぶす時の最大-最小法のように横の1ラインごとに塗りつぶす領域を持つ方がスマート?

投稿者 Takenori : 13:14 | トラックバック

2005年09月08日

ボス位置判定改

いる・いないと切り替えながら交差判定を繰り返していくのではなく、最初にアクティブラインに当たった場合、その位置からボスの方向を覚えて固定ラインに交わるところまでたどっていった方が良さそう。
交差判定の繰り返しでは、ボスから下ろした垂線と、アクティブラインが重なってそのまま固定ラインと交わった場合にうまく判定できない。
後、たどっていった方が、その後の固定ラインを構築するところでもやりやすそうだ。
と言っても、当たらなかったパターンを作ればどっちでも一緒になるような気がするが。

ただ、周囲にラインがある場合は、ボスから垂線を下ろして…で良いが、中心から囲っていく場合はそうはいかない。
ボスが囲んだ中にいるかどうかの判定が必要。
囲んだ中にいるかどうかの判定ならどちらでも使えるので、汎用的なような気がするが…
少し考えよう。

投稿者 Takenori : 02:04 | トラックバック

2005年09月11日

ボスの内外判定

ボスから垂線を…の方法で実装してみた。
まだ1箇所問題があるが原因はわかっているので、対策すればうまく動くようになるはず。
ただ、この方法は場合分けが多すぎる。
もっとシンプルに出来そうな気がする。
また、線分の交差判定も、if分の塊ではなく、数学的な判定の方がスッキリしそうだ。

ボスのいる領域の判定についていろいろと考えてみた。
周りが囲まれていて、そこから囲んでいくのと、中心にはじめの領域があって、そこから囲んでいくのでは性質が違う気がしてきた。
中心から広げていくと言っても、画面外の矩形に囲まれていることになると考えられる。
つまり、2つの領域があることになる。(塗りつぶす時を考えると)
周りからの場合は、領域は1つになる。
また、周りにあるのは狭めると言った感じで、中心にあるのは広げていくと言う印象を持つ。
で、肝心なことは、この二つでアルゴリズムが共有できるかどうかってことだ。

領域内にボスがいるかどうかの判定で、まず思い付いたのが、領域を三角形に分割し、全ての三角形で内か外かを判定し、一つでも内になればボスはその領域内、すべてで外となればその領域にはいないことになる。
シェーダトゥディ 第3回 ラスタライズアルゴリズムの最近のラスタライズアルゴリズムの特徴で、三角形の内か外かの判定の解説がある。
ただ、三角形に分割するのが少し嫌な感じがする。まあ、三角形の集合にしてしまえば、塗りつぶす時に楽になりそうではあるが。
しかし、よくよく考えると領域の内か外の判定はありがちな処理な気がしてきたので、調べてみた。
するとピッタリのが見付かった。
計測と検索の一番下、図形の検索でうまくいきそうだ。
ボスから垂線を下ろして…と言う方法は結構いい線いってたのかも。

投稿者 Takenori : 01:31 | トラックバック

線を引けるかどうか

ボタンを押している時は、新たに線を引くことが出来る。
で、その線を引ける方向かどうかの判定をどうするか考えていた。
まず思いついたのが、回転方向で見分けると言うもの。
次の図のような感じだ。

赤矢印の方は移動不可で青は可。
現在いる辺の2点と移動しようとしている点で回転方向を求める。

問題は、常に領域を囲む線の方向を一定に保たなければならないと言うこと。
これはかなり面倒だ。
で、囲んでしまった領域のマスク画像を持っていたほうが楽ではないかと思い始めた。
メモリを喰うが、単純に既に塗っているかどうかで移動できるかどうかが判定できる。
これで行こうかと考えていたのだが、内外判定の方法を見付けた後、再度考えると、内外判定を使えばすんなりいくことに気付いた。
つまり、内側には移動できるけど、外側には移動できないようにすればいい。
ただし、この方法だと囲まれているタイプと中心からのタイプで論理が逆になる。
囲まれているタイプは内側へ移動可、中心からのタイプは外側へ移動可となる。
まあ、そこは仕方ないか。
ただし、単にこれだけではライン上の移動が判定できない。
ライン上の移動かどうかをまず判定した方が良さそう。
現在は、ボタンを押した時はラインを引く方向にしか移動出来なくしているが、ボタンを押している時で、線からはみ出した時に初めて線を引き始めるようにしたほうが良さそうだ。

投稿者 Takenori : 09:30 | トラックバック

2005年09月13日

交差する線の数で判定

少し前に書いたようにボスから下方へ線を延ばし、その線と交差する線の数が奇数かどうかで判定するようにした。
かなりスッキリした。
次は外側へ出れないようにする判定を加えよう。

投稿者 Takenori : 03:07 | トラックバック

2005年09月14日

塗潰し領域の判定

囲んだ領域は、画像が切り替わるので、その部分は塗潰し処理が必要になる。
で、その領域はどうやって判定するのか少し悩んだが、簡単だとすぐに気付いた。
線を引いた領域で、ボスの居る方と居ない方があるが、その居ない方が塗潰すべき領域となる。
ボスの居る方が残る領域となるので、当たり前と言えば当たり前か。

投稿者 Takenori : 01:24 | トラックバック

塗潰し処理

内外判定の時、コンピュータ・ジオメトリのページがヒットして、あれ?この本持ってると思って関連するところを読んだ。
が、結局は少し前にリンクを張った計測と検索を元に内外判定は組んだ。
で、塗潰し処理の段になって、コンピュータ・ジオメトリに載っていた処理と似た方法で実装できることに気付いた。
コンピュータ・ジオメトリでは、複数領域の中から、指定した点がどの領域に属するかを判定する処理について書かれていた。
だから、少し異なる目的だが、ほとんどそのまま使えると思い、実装してみた。
具体的には…
塗潰したい領域の全ての点のX座標値のところに縦線を引く。
塗潰し説明画像A
で、この線で囲まれている矩形を塗潰す。
ただそれだけ。
塗潰す領域は、上から塗る、塗らないと交互に表れるので判定は簡単。
本来であれば、横線も記憶し判定材料にするのだが、斜め線はないので、単にY座標値が同じなら線があるものとして処理することにした。

で、内側のみに移動出来るようにした後、塗潰し処理も組んで少し触ってみた。
が、何か囲んでも反転しない領域が出来た気がした。
でも、しぱらく再現できなかったのでなんだろう? と思っていると再現した。
了解。
次の図のような時に問題が発生する。
塗潰し説明画像B
この図で赤線の部分は本来存在しないはずの線だが、単にY座標値が同じかどうかだけで線の有無を判定していたので、このような場合線があると判定してしまい、その下の領域を塗潰されなくなっていた。
やっぱり線も記憶して判断材料にしないとダメか。
記憶しなくても、その両端を含む線が存在するかどうか判定しても良いが、覚えておく方が、速くて簡単かな?
縦線との交差判定をする時に、Y座標値をキーにしたmultisetに入れとくほうがいいかな?
データ構造とともに少し考えよう。

投稿者 Takenori : 01:48 | トラックバック

2005年09月16日

ラインの有無を持つようにした

塗潰し処理で、縦線クラスにY座標値のみを格納していたのを、Y座標値+左ラインの有無に変更して対処した。
左ラインの有無だけでは、斜め線が加わった時に対応できないが、斜め線が入ると実際にコピーしている部分を矩形ではなく、三角形に変更しなければならないなどいろいろとあるので、左ラインの有無だけで対処することにした。
現状斜め線は考えていないし。

これで前回書いた不具合は解消された。
後は、ボタンを押してライン上を移動出来て、はみ出した時に初めてラインを引き始めるようにする処理と、現在何パーセントぐらい占有しているかを表示するための処理が出来れば、ライン関連の処理は一通り出来たことになるかな。
で、敵と当たり判定を入れれば、とりあえずはゲームとして成立することになるな。

投稿者 Takenori : 17:42 | トラックバック

2005年09月20日

システム的な部分

ゲームのメインとなる部分のアルゴリズムなどは何とかなりそうなので、システムの核となる部分を考えることにした。
こんな感じかな。

クラス図

基本的には、毎フレームISceneControlのOnMoveとOnDrawを呼ぶことによって、ゲームが進行する。
SceneControlは、SceneFactoryを使って支持されたシーンを生成、保持し、そのシーンのOnMoveとOnDrawを呼ぶ。
OnMoveとOnDrawはシーンが保持しているTaskControllerを通じて、各タスクをコールする。
各タスクの実体は、スプライトのOnMoveとOnDrawになる。
各スプライトのOnMoveとOnDrawは、実行順序に違いがあるので、タクスを分離している。
各タスクはmediaterを経由して、OnMoveとOnDrawをコールする。
シーンの変更は、SceneがSceneControlを使って行う。
スプライトがSceneへシーンの変更を指示する場合もある。
と言ったところだろうか?
よく見たらいくつか足りない関連があるけど……

ゲームのメインとなる部分のクラス図は考え中。
スプライトとして大体の部分はシーンに持たせてしまえばいいかな。

投稿者 Takenori : 02:24 | トラックバック

2005年09月22日

メニューを作った

最近深夜にブログを更新しようとすると反応が異様に遅かったり、CGIがエラーになる。
誰かDBを使ったバッチ処理でも動かしているんだろうか?
いい迷惑だ。
それはともかく昨日書けなかったので今書く事に。

クラス図を元にメニューの部分を実装した。
若干関連を変更した。
で、実際にPNGを読み込んでメニューを表示させようとしたら、PNGが読めずに真っ暗。
? YaneSDK 3rdはPNG読めないの? 読めると思っていたのに。
そこで、SUSIEプラグイン経由で読むことにしようと、spiを直下に置いて実行しても変化なし。
ソースコードを追ってみると、SUSIEプラグインはSPIというフォルダを作ってそこに置く必要があるようだ。
で、そのようにしたらプラグインの読み込みには成功したのだが、画像サイズを読むところでアクセス違反。
どうも関数ポインタがNULLっぽい。
違うPNGプラグインにしても症状は変わらず。
仕方ないので、libpngを使って読み込むようにしようと組み始めるが面倒になってきて、とりあえず画像ファイルBMPにしてメニューを作った。
近いうちにlibpngで読むようにしないとな。

次はゲーム部分の構造を考えないと。

投稿者 Takenori : 15:59 | トラックバック

タスクのプライオリティ

描画処理については、単なる前後関係で処理してもらえば事足りる。
各スプライトがZ値を返すようにして、その値を元にソートして処理してもらえればいい。
問題は動きの処理だ。
単純に敵の移動、自機の移動、当たり判定という流れだと、親子関係を持つ敵などを処理できないので困る。
動きの処理の方はタスクをやめて、スプライトが親子関係を持つようにして、それらのOnMoveを呼び出したら順次チェインをたどって呼び出していくようにした方が良いかな。
で、その処理の後でZ値に変化があった場合、DrawTaskの変更を行うようにすれば良さそうだ。
と言うことで、基本的な部分のスプライトをツリーでまとめてみた。

スプライト

これでうまくいくかな。

投稿者 Takenori : 23:47 | トラックバック

線の当たり判定と交点

斜めはないと思っていたけど、各フレームで敵の移動ベクトルと固定ラインが当たらないようにしないとまずいと思って線の当たり判定を探して見つけたが、その前に実際に移動後の位置が内側か外側かの判定のみで移動可不可を判定するようにして敵を動かしてみた。
細い領域を見事に突っ切っていく敵。。。
やっぱり、移動ベクトルが固定ラインと当たらないようにしないとダメか。
実際の処理方法は、線と線の当たり判定にあった。
久しぶりにベクトルの計算を思い出しながら式の変形を追った。
で、このソースをもらうことにした。

だけど、当たり判定だけでなく、交点が必要なときもある。
と言うことで今度は交点計算を思い出してみる。
y = ax + b (1)
y = cx + d (2)
と言う連立方程式を解けば交点が出てくるはず。
a = c の時は、平行なので交点は存在しない。
2点の座標値からy = ax + bの式の形にするには、yの差分 / xの差分で傾きを出し、b = y - axへどちらかの点を代入すれば出る。

連立方程式は、加減法か代入法で解けるはず。
加減法で解くと、(1)式から(2)式を引いて、yを消し、xの項を移項する。
すると、(c-a)x = (d-b) ってな感じになる。
で、x = (d-b) / (c-a) にして、初めのy = の式に代入、整理。
y = (bc - da) / (c - a)
を解けば、y値が出る。
xは、a=0なら x = (y - d) / cで、そうでない時は x = (y - b) / a
両方が0と言うことは平行でない限りないので、どちらかで解ける。
片方の式がx = bなどの時は、もう片方の式に直接代入すれば出る。
誤差を考えると割算は出来るだけ後でやった方がいいけど、そんな精度は必要ないかな。
ただ、これだけでは交差するかどうかわからない。
交点が両方の線分の中にあるかどうか判定しなければならないが、前述の当たり判定を先にやって当たったら交点を計算する方が楽そうだ。
ほとんどの場合は当たらないはずなので、その方が効率的のようにも思える。
と言うことで、そのような方法で実装することにした。

投稿者 Takenori : 23:50 | トラックバック

2005年09月24日

DrawTaskは毎回全登録

各スプライトのZ値が更新された時のみ、位置の入れ替えを行うようにしようと思っていたが、描画のたびにすべて消して、OnMoveで毎回すべて登録するようにすることにした。
なぜかと言うと、スプライトが消された時に、タスクも消す必要があるが、タスクを消すためにはタスクコントローラーへの参照がないといけない。
タスクコントローラーのポインタはOnDrawとOnMoveの引数で渡されるクラスへの参照の中に入ってる。
つまり、スプライトは知らない…… って、OnMoveで登録する時に、登録したタスクコントローラーを覚えておけば万事OKなんじゃ。。。
これを書いていて気付いた。
毎回全登録だったら、なんかコマンドっぽいなぁと思っていたが、毎回全登録しなくても良さそうだな。
登録した時にタスクコントローラーを持って、必要な時のみ入れ替えるようにしよう。
で、渡されたタスクコントローラーが変わっていたら、前のタスクコントローラーから自分のタスクを消して、新しい方に登録し、新しいタスクコントローラーを持つ。
削除される時は、持っているタスクコントローラーを使って自分のタスクを消す。
やっぱり、Z値が変わらないスプライトが多いから、必要な時のみ位置を変えるようにしていた方が良さそうだな。

投稿者 Takenori : 19:50 | トラックバック

 
Total : Today : Yesterday :