はじめまして、ジャグラーと申します。
ゲームプログラミングの館を見てC++を導入し、いまWriteCirclegameのようなものを作ろうとプログラムをしています。
一応紹介ページを載せておきます。
ttp://www.vector.co.jp/magazine/softnews/010317/n0103171.html
このゲームにおけるあたり判定を行う際に、私はflg[480][480]という大きな配列を取ってすべてのビットにおいてあたり判定を行っています。
たとえば
まずflg配列をすべて0に初期化しておいて、線が通ったビット位置に対応するflg配列をすべて1にセットしていきます。
線が1ビット移動するたびに自分のいる位置のflgをチェックして、1ではなかったらflgを1にセットという具合です。
逆にflgが1だったらぶつかったことになるのでゲームオーバーです。
ですが、これだと無駄が多いと感じています。
配列を動的にとるというやり方もありますがC++でのやり方がわかりません。
どうすると効率のよいあたり判定を作ることができるでしょうか?
あたり判定について
Re:あたり判定について
いや、そのやり方でもわかりやすくていいんじゃないかと思いますよ。
20万個BYTE型の要素を用意しても0.2MBですし。
数が多くても当たり判定の計算は今いる位置を調べたらいいだけだから問題ないと思います。
もし「誰が通ったか」じゃなく純粋に「通ったか」だけの情報でよければ更にその1/8のデータ量で済みます。
あと、こんなのも使えます。
先日のDXライブラリのバージョンアップでこんな関数が増えました。
http://homepage2.nifty.com/natupaji/DxLib/dxfunc.html
「ドット単位で画像にアクセスしたい関係」
今まさにモニタに反映しようとしている画面の画像データに直接アクセスが出来る関数です。
例えば背景が黒で、通ったところを赤で表示しているのならこれを調べてやることでそこが通ったところかどうかわかります。
ただ、毎回画面を書き換えるなら通った場所のデータを保存しておかないと、ややこしいですよね。
ん~やっぱ最初の方法でいいと思います。
20万個BYTE型の要素を用意しても0.2MBですし。
数が多くても当たり判定の計算は今いる位置を調べたらいいだけだから問題ないと思います。
もし「誰が通ったか」じゃなく純粋に「通ったか」だけの情報でよければ更にその1/8のデータ量で済みます。
あと、こんなのも使えます。
先日のDXライブラリのバージョンアップでこんな関数が増えました。
http://homepage2.nifty.com/natupaji/DxLib/dxfunc.html
「ドット単位で画像にアクセスしたい関係」
今まさにモニタに反映しようとしている画面の画像データに直接アクセスが出来る関数です。
例えば背景が黒で、通ったところを赤で表示しているのならこれを調べてやることでそこが通ったところかどうかわかります。
ただ、毎回画面を書き換えるなら通った場所のデータを保存しておかないと、ややこしいですよね。
ん~やっぱ最初の方法でいいと思います。
Re:あたり判定について
素早い回答ありがとうございます。
確かにこのやり方でも容量はたいしてとらないから大丈夫だろうなぁと思ったんですが、配列を
flg[480][640]とウィンドウサイズに合わせてとるとなぜかセグメントエラー(?)が起きたんです。
だから容量とりすぎてダメなのかなぁと思ったので質問させてもらったのです・・・が・・・
いま上の配列を取ってやってみたらなぜかエラーでませんでしたw
うーん、なぜ前はエラーが起きたのだろう、他のところで間違えていたのかな。
ありがとうございました、問題が解決できました!
確かにこのやり方でも容量はたいしてとらないから大丈夫だろうなぁと思ったんですが、配列を
flg[480][640]とウィンドウサイズに合わせてとるとなぜかセグメントエラー(?)が起きたんです。
だから容量とりすぎてダメなのかなぁと思ったので質問させてもらったのです・・・が・・・
いま上の配列を取ってやってみたらなぜかエラーでませんでしたw
うーん、なぜ前はエラーが起きたのだろう、他のところで間違えていたのかな。
ありがとうございました、問題が解決できました!
Re:あたり判定について
あぁローカル変数は容量に制限があるんですよ。 静的変数にするか、グローバル変数にすればいいです。 つまり・・ 今 int main(){ BYTE flag[600][600]; } みたいに書いてるんじゃないかとおもいます。これを int main(){ static BYTE flag[600][600]; } こうするか BYTE flag[600][600]; int main(){ } こうすればエラーが出なくなると思います。
Re:あたり判定について
なるほど、作り始めた時はすべての処理をmain関数で行っていましたがプログラムを発展させるために
処理を複数の関数に分けて作り直していました。
そのさい、最初はローカル変数として置いていたflgをグローバルに変更していたのでエラーがなくなったのですね。
staticにしても制限がなくなるということは、すぐに消えてしまうかもしれないデータ(ローカル変数)にたくさん容量をとってられないよ!ということですか。
ようやく謎が解けました。
本当に素早い回答ありがとうございます!非常に助かりました。
処理を複数の関数に分けて作り直していました。
そのさい、最初はローカル変数として置いていたflgをグローバルに変更していたのでエラーがなくなったのですね。
staticにしても制限がなくなるということは、すぐに消えてしまうかもしれないデータ(ローカル変数)にたくさん容量をとってられないよ!ということですか。
ようやく謎が解けました。
本当に素早い回答ありがとうございます!非常に助かりました。
Re:あたり判定について
スタックサイズはデフォルトで1Mだったと思います。
640*480でスタックサイズオーバーになるということは、配列をint型で作っているのではないでしょうか?
int型は2の32乗まで数えられますが、意味がないですよね。
256まで数えられるchar型で十分だと思います。
もっと言えば、1ビット単位でフラグ立てるなら
char flag[480][640/8];
でいけると思います。
char型は8バイトですから、最大8個のフラグ管理が出来ますよね。
まぁそうするとプログラムが少々ややこしくなるので、
最初は普通にcharで[480][640]で作るといいと思います。
640*480でスタックサイズオーバーになるということは、配列をint型で作っているのではないでしょうか?
int型は2の32乗まで数えられますが、意味がないですよね。
256まで数えられるchar型で十分だと思います。
もっと言えば、1ビット単位でフラグ立てるなら
char flag[480][640/8];
でいけると思います。
char型は8バイトですから、最大8個のフラグ管理が出来ますよね。
まぁそうするとプログラムが少々ややこしくなるので、
最初は普通にcharで[480][640]で作るといいと思います。
Re:あたり判定について
確かにint型にしていました。これだとサイズだけ大きくて無駄ですね。
char型が8バイトと書かれていますが8ビットの間違いでしょうか?
1ビットずつでフラグ管理をすればかなり効率的になりますね。
すでに簡単なゲームとしてはできあがったのでいろいろ新しい機能、条件などを追加したらこの方法によるフラグ管理もやってみたいと思います。
細かいご指摘ありがとうございます。
char型が8バイトと書かれていますが8ビットの間違いでしょうか?
1ビットずつでフラグ管理をすればかなり効率的になりますね。
すでに簡単なゲームとしてはできあがったのでいろいろ新しい機能、条件などを追加したらこの方法によるフラグ管理もやってみたいと思います。
細かいご指摘ありがとうございます。