レス数が1スレッドの最大レス数(1000件)を超えています。残念ながら投稿することができません。
おちゃめくらぶ掲示板
-
プチコンで3Dゲームを作ろう
11月20日に書いたプチコンでのタッチパネル(下画面)の利用だけど下画面に表示できる
ものには制限があると書いたものの後からそれは全部可能であることが分かったにょ。
とはいえ、スプライトに関しては下画面では定義できる数量が少ないためそれだけでは
下画面の制約があると言えるにょ。
さて、今回はプチコンを使って3Dゲームを作ろうと思うにょ。
とはいっても、3D立体視ではなく3Dポリゴンでもなくただの疑似3D表示ゲームだけどね。
疑似3Dは見た目に遠近感があるというだけのものだけど端的に言えばゲーム内で奥行きを
示すパラメータを用意して遠くにあるものは小さく、近くにあるものを大きくすればいい
というだけのものにょ。(ゲーム内で奥行き感が表現されていればそれは疑似3Dといえる
と思う)
最も手っ取り早い疑似3Dを実現する方法はスプライトの拡大縮小を使用することにょ。
プチコンではスプライトを1%〜200%のサイズで表示可能だからね。
スプライトによる疑似3Dはアーケードゲームにおいてもスペースハリアー、アフター
バーナー、アウトランなど多数のゲームで採用されているにょ。
スプライトによる疑似3D表示を行う場合に注意すべき点は下記の2つにょ。
(1)拡大率の変化
(2)表示座標
(1)単純にZ座標によってサイズが比例すると考えた場合には遠くからやってくる物体が
どんどん遅くなったように見えるという問題があるにょ。
GPAGE 0
SPPAGE
SPSET 0,176,0,0,0,0
VISIBLE 1,,,,1,1
GLINE 0,96,255,96,2
GLINE 128,0,128,191,2
X=128
Y=96
@LOOP
FOR P=1 TO 200
SPSCALE 0,P
SPOFS 0,X,Y
NEXT
VSYNC 1
GOTO @LOOP
赤い線の交点(X座標128、Y座標96)が原点(要するに消失点)となっているにょ。
これを実行してみると速度に関しては気になるレベルではなくむしろ表示座標の方が
気になると思われるにょ。
本来ならば原点上をどんどん近づいているのに右下に移動しているように見えるからね。
これはスプライトの座標の基準が左上にあるためにょ。
そこでまず(2)について考えてみるにょ。
(2)スプライトのサイズは標準サイズ(100%)で16x16ドットとなっているため拡大率
100の時は縦横8ドット分だけ表示位置を補正する必要があるにょ。(正確には縦横7.5ドット
分だけ補正するべきなのだけどそこまで0.5ドット単位で補正しても差異はないし、拡大率
によって補正量が比例しなくなるためここでは簡易化のため8ドットの補正とする)
同じく拡大率200の時は32x32ドットであるため16ドット分の補正が必要にょ。
つまり、Pの値の1/12.5だけの補正が必要というわけにょ。
GPAGE 0
SPPAGE
SPSET 0,176,0,0,0,0
VISIBLE 1,,,,1,1
GLINE 0,96,255,96,2
GLINE 128,0,128,191,2
X=128
Y=96
@LOOP
FOR P=1 TO 200
SPSCALE 0,P
SPOFS 0,X-P/12.5,Y-P/12.5
NEXT
VSYNC 1
GOTO @LOOP
これをY座標下方向に移動させてみるにょ。
ここで重要になるのがY座標をどのように変化させるかということにょ。
拡大率200の時に画面中央の真下に来るようにするのにはどのようにすれば良いかという
ことを考えると下に来たときには32x32ドットのスプライトが画面下(Y座標191)に達する
ときには左上の基準座標のY座標は160になっているにょ。
つまり拡大率が200変わる間に原点を基準に考えると64ドット移動しているにょ。
ただし、すでにY座標はスプライト中央に補正済みなので合計80ドット移動しなくては
ならないためループ1回当たりのY座標の移動量は80/200=0.4となるにょ。
GPAGE 0
SPPAGE
SPSET 0,176,0,0,0,0
VISIBLE 1,,,,1,1
GLINE 0,96,255,96,2
GLINE 128,0,128,191,2
X=128
Y=96
@LOOP
FOR P=1 TO 200
SPSCALE 0,P
SPOFS 0,X-P/12.5,Y-P/12.5+P*0.4
NEXT
VSYNC 1
GOTO @LOOP
これを実行すれば(1)で書いたように「近づくにつれ遅くなっているように見える」と
いうのが理解できると思うにょ。
原点での表示では遠近感がないため速度がよく分からなかったというだけのことであり
それがY座標の移動が加わることではっきりと目視できるようになったというわけにょ。
ぶっちゃけそこまで気にしなくてもゲームによっては気にならないけど今回は疑似3Dが
テーマであるためその移動速度に違和感のないようなゲームを作るにょ。
違和感が生まれる原因となっているのは当然のことながら遠くにあるはずの小さな
物体と近くにある大きな物体が同じ速度で動作しているためにょ。
そのため見た目上の移動速度は変わっていなくても相対的に考えれば近づくにつれて
遅くなっているように見えるにょ。
この原因となっているのが拡大率が時間と比例していることにあるにょ。
比例ではなく指数関数的な増加になる必要があるにょ。
ループ200回で200倍のサイズにするためにはループ1回につき200^(1/200)≒1.0268倍に
すればいいにょ。
もっともプチコンの演算精度はそこまで高くはないから1.026倍でも変わらないにょ。
GPAGE 0
SPPAGE
SPSET 0,176,0,0,0,0
VISIBLE 1,,,,1,1
GLINE 0,96,255,96,2
GLINE 128,0,128,191,2
X=128
Y=96
P=1
@LOOP
FOR I=1 TO 200
SPSCALE 0,P
SPOFS 0,X-P/12.5,Y-P/12.5+P*0.4
P=P*1.026
NEXT
VSYNC 1
GOTO @LOOP
これで、「近づくにつれて遅くなっているように見える」ということもなくなり普通に
等速で近づいているように見えると思うにょ。
X座標も同様に変化させればどの座標であっても擬似3D表示を自然な感じで行うことが
可能になるにょ。
それを踏まえてゲームを作ってみることにしたにょ。
とはいっても1画面で作るとなればできることは限られるにょ。
疑似3Dレースゲームを・・・と思ったけどここはやはりシンプルにスキーにするにょ。
スキーゲームといえばPRINT文でスクロールさせるようなゲームを思いついた人や作った
ことのある人はたくさんいると思うにょ。
確かにそういうスキーゲームは作りやすいからね。
というわけで疑似3Dのスキーゲームを作る前に速攻で作ってみたにょ。(「ワンキー
ゲーム」でキーを押せば右へ離せば左へ進むもので画面の左右から出たり旗の間をくぐり
抜けられなかったらゲームオーバーとなるシンプルな内容)
http://ww5.tiki.ne.jp/~ochame/petitcom/image/1key_ski.jpg
疑似3Dにおいてもスキーゲームは非常に作りやすいにょ。
というのもスキーゲームは旗を疑似3D表示できればそれっぽいゲームにできるからね。
そして、できたのがこの「プチコン スキー」にょ。
http://www.youtube.com/watch?v=GMp1RYM63hg
http://ww5.tiki.ne.jp/~ochame/petitcom/1page.htm#ski
シンプルなゲームながら一応スキーっぽくはなってると思うにょ。
しかし、上記でスプライトで疑似3Dを行う方法について書いたけど実際に旗の表示は
スプライトを使ってないにょ。
人物キャラに関してはプリセットデータで剣を両手に持たせたらストックっぽく見えるから
それで良しとしたけど旗の代わりになるデータが無かったからにょ。
とはいえ、考え方そのものは上記のスプライトによるものと何ら変わりないにょ。
要するに拡大率と表示座標に気を付ければいいだけだからね。
私は10年以上前にポケコンでも疑似3Dゲームである「シュプール」を作ったにょ。
http://ww5.tiki.ne.jp/~ochame/E500/SOFT/SPUR2.HTM
これは私が考案した描画システムであるOPASをフルに使い普通にGPRINTで表示するよりも
30倍程度の描画速度になっているもののそれでも8fps程度の速度でしかないにょ。
ポケコンでしかもオールBASICでこの速度は驚異的だと思うけどやはり快適にプレイする
ならば最低でも30fpsは欲しいからね。
そのため8fpsでもゲームとして成立するように様々な工夫を凝らしたにょ。(マイナー
バージョンアップの度に操作方法などにシステムを変えまくったくらい)
その点、プチコンならばよほど凝った処理をしない限りは30fpsは楽勝で出るにょ。
この「プチコン スキー」も「シュプール」で行っている遠景の横スクロールや地面の
疑似3Dスクロールは取り入れてないもののVSYNCによるウエイトを入れても60fps近くで
動作しているくらいだからね。(16行にあるVSYNC 1を取り除けば300fps以上で動作する)
「シュプール」は旗の拡大画像をあらかじめ演算しておいてそのデータを取り込みゲーム内
ではあらかじめ演算済みのデータの中から必要な部分だけを取り出す作業(これがOPASの
役割となっている部分)のみを行っているのに対して「プチコン スキー」は当然全部
リアルタイムで演算、処理しているにょ。
演算速度、表示速度ともに60〜100倍程度速いから可能なことにょ。
この「プチコン スキー」は1画面でやれる範囲内のことはすべてやり尽くしたにょ。
「シュプール」では出来なかった左右旋回を交互に行って減速するというのもプチコンの
速さがあってからこそ可能になったにょ。(「シュプール」は減速しないように進むのが
基本となっている)
当初は恐ろしく難易度が高かったけど速度調整には気を配って何とかプレイできる
難易度まで下がったし、それでも難しいという人への配慮として当初は考えていなかった
進行方向のガイドラインを付けることにしたにょ。(遠景スクロールがないためどちらに
進んでいるのか分からないので操作に慣れている私でさえようやく何とかなる程度の
難易度だったため)
それができたのもキー入力判定の簡略化ができたお陰にょ。
何せ (K+1)%3-1 でLRボタンだけではなく十字ボタンでの左右移動が可能になるにょ。
これはパターン化されたIF文は簡略化することができるからにょ。
http://ww5.tiki.ne.jp/~ochame/E500/TECH/TECH016.HTM
ただし、それでも当たり判定だけはやや不満が残るにょ。
恐らくプログラムリストを見て何でこんな処理にしたのか一番理解に苦しむ部分ではないか
と思うにょ。
これは当たり判定を置く場所が悪いし、1画面に収めるためにょ。
そのためかなり甘めに設定しているにょ。
正確にいえば最大10ドット余裕を持たせているにょ。
表示してプレイヤーキャラのX座標を加算処理した後に当たり判定を行っているために
移動量である M/4 の分だけマイナスしないといけないにょ。
Mの値は最大40であるため移動量は最大で10ドットに達するにょ。
厳格な当たり判定を行うためには21行を次のようにしなくてはならないにょ。
Z=ABS(X+M)>V-6 → Z=ABS(X+M*0.75)>V-16
まぁ実際には限界まで左右旋回をしている状態であっても最大で10ドットのずれしかない
ために身体が過半数通過していれば通過と見なされる程度であり完全にずれているのに
通過になるわけではないのでそれほど問題はないにょ。
1フレーム遅れで通過できるはずのものが通過したことになるだけだから恐らくプレイして
いて「ギリギリ通過できた」と感じるだけであり、違和感を感じることはあまりないの
ではないかと思うにょ。
それに当たり判定を見た目通りに厳格に行っているゲームなんて実際にはあまりなく
見た目よりプレイヤーに甘くなっていることの方が多いにょ。(実際シューティング
ゲームとかでは当たり判定が自機の中心の数ドット分しかないゲームもある)
次回は1画面で作る疑似3Dレースゲームについて書いてみることにするにょ。
あと「1画面で作るシリーズ(?)」のテーマを募集中にょ。(次回の3Dレースの次は
現時点は未定)
1画面で作って欲しいものがあれば遠慮なく言ってにょ。
とはいえ、1画面(29文字×24行)で作るためには相当アレンジや端折る必要があるため
あまり具体的なテーマ(例えば「オセ○ゲーム」など)だと実現が不可能な場合がある
けどね。
|
|
|
掲示板管理者へ連絡
無料レンタル掲示板