更新確認

HSPTVブラウザで、Temples Trick がVer1.12に更新されない環境があるようです。
OSやHSPのバージョンとの関係は不明だけど、うちの環境だと、主力開発機がVer1.05のまま。
予備機は説明がVer1.05で、動作バージョンが1.12。HSPを入れなおしてみたけど改善せず。


まあ、気を取り直して今回はマップ情報の持ち方について解説。
例によって1次元配列を使っています。
2次元で考えると横15、縦11。プレイフィールドは9x9ですが、画面がすべてマップ配下として覆われるサイズにしています。


マップ情報は2種。便宜上、グランドマップとフィールドマップと呼ぶことにします。
グランドマップは壁と床(空き、魔法陣)の情報を持ちます。ステージデータから展開される固定情報で、赤魔石が魔法陣の上にあるかどうかのチェックに使います。
初期化時は、まずマップ配列全体を-1(&HFFFFFFFF)で埋めて、9x9のプレイフィールドに対応する要素についてステージデータを展開し、魔法陣があれば1、なければ0としています。
フィールドマップはその場所にある障害物(壁、魔石)のオブジェクトIDを格納します。こちらはフレームごとに更新します。
壁の位置は固定ですが、これもフィールドマップに書き写すことで、移動可能な場所かはフィールドマップだけでチェックできます。
ちなみに、グランドマップ→フィールドマップの転記は、以下のようなコードで床描画をするタイミングに行っています。

	lpoke pcnt ; 魔法陣個数クリア
	c1=128:gosub *vardupc1 ; Workエリア準備  ここのc1は床面彩度初期値とワーク用オブジェクトIDを兼用
	repeat EMAPNUM
		e1p=cnt,1:gosub *posclc; 座標計算、Pos設定、マップ値参照のdup対応を行う。
		if(emapg){color 200,200}else{ hsvcolor 92>>(hlcx&1),c1,200} ; 床色決定
		c1^64 ; チェック模様のため床面彩度変更
		grect egx,egy; 床面描画
		celput ,emapg+1	;オブジェクト描画(魔法陣、壁)
		pcnt+(emapg=1)	;魔法陣の個数をカウントする
		emapf=emapg&128	;フィールドマップへ壁情報を反映(空きID=0、壁ID=128に変換)
	loop

冒頭で呼び出しているサブルーチンvardupc1は、c1で指定されたオブジェクトについて、オブジェクトテーブル配列をe1p等の変数にDup処理し、テーブルを操作しやすくする処理。
後で位置計算するサブルーチンposclcを使うために、オブジェクトID128をワークエリアとして準備しています。
EMAPNUMはマップ配列の要素数で、Repeat中のcntはマップ上の位置を指定します。
オブジェクト情報に指定位置と移動カウント1を入れてサブルーチンposclcを呼ぶと、対応するグランドマップ、フィールドマップの要素をそれぞれ emapg、emapf にDupし、egx,egyに画面上の描画座標(pos済)を格納するようになっています。
床色は、壁か魔法陣(emapgが0ではない)なら黄色、空きなら水色をベースにチェック模様とスタン時の効果を付加。
床色の彩度パラメータc1は、1マスごとに128と192が交互に使用され、1段が奇数マスなのでチェック模様になります。
前もってgmode 2,48,48と指定したサイズでgrect。
その上に、あらかじめbuffer 1に用意した壁(Cell#1)と魔法陣の六芒星(Cell#2)の画像をcelputでかぶせます。
グランドマップでは壁は-1、魔法陣は1なので、Cell#の指定はマップ値を⁺1するだけ。
描画は画面全体にわたり、プレイエリア以外すべて壁(煉瓦色)で覆われます。フレームごとの画面クリアは不要です。
空き床についても描画処理されますが、Cell#1に用意されているのは透明色だけの画像であるため床色のまま。
最後にフィールドマップへの変換。
グランドマップの値を128でANDすることで、移動可能な場所(魔法陣と空き床)は0、壁のみID128として転記をしています。

ステージデータ

スクリプト内でのステージデータを保持方法についてメモしておきます。

9x9のフィールドデータ部分は、横3マスをASCII文字1Byteで表現しており、81マスで27文字使います。
これに、敵と赤ポーションの数を示す1文字を付けた構造で、1ステージ分を正味28バイトの文字列データとします。
エンコードの際、各マスについて取りうる4値を、空白:0、魔法陣:1、紫魔石:8、赤魔石:9 と置き、
1マス毎に1ビットシフトした値をORして 0〜63 とし、63でなければ+64して文字コードにします。
これで"@"(64)〜"~"(126)と"?"(63)の文字コードが得られます。
元が63の場合は+64すると制御コードのDEL(127)になってしまうのでそのまま63→"?"で扱っています。
ポーションの個数(0〜7)と敵の数(0〜7)については、敵の数×8+赤ポーションの数 で0〜63の値を作り、
同様に1文字のコードに変換しています。


スクリプト内での変数代入については、{"〜"}による文字列データ複数行表記を使って1面1行で記述。
各面の区切りがCR+LFになるので、メモリーノートパッド関連の命令が使えます。
スクリプトの都合上、ステージ1の前にCR+LFが1つ、最終ステージの後にNUL終端の1文字を要するので、
30面で(2+28)*30+1=901Bytesとなります。1面あたり30Bytesのデータ量です。
デコード時、取り出したフィールドデータは、シフトしながらマスク値9でAndして、各マスの種類にします。


ここでのポイントその1
「オフセットが+64、元の値が63のときにはオフセットしない」という変化ルールは一見複雑ですが、
デコード処理の視点で考えると、下位6Bitが不変なのでオフセットを気にせずシフト&マスクできます。
簡単に+63のオフセットで"?"〜"~"とすることもできますが、その場合、デコードの際にもシフト&マスク
の前に-63(もしくは+1)しなければならず、かえってコストがかかります。


ポイントその2
マスの4値を0,1,2,3とせずに0,1,8,9としたのは、cntで操作するマスを進めつつ、フィールドデータの方はcntを3で
割った余りでシフトさせたかったので、シフト量とマス操作が一致している方が都合が良いからです。
0,1,2,3は2進で00〜11なので1マス分のマスク値は3(2進数で11)となりますが、連続したビットを使っているため
有効ビットが被らないようにORを行なうには、2ビットずつシフトする必要があります。
3マスに割り当てるビットをAa,Bb,Ccで表現するとCcBbAaです。シフト量を2倍する際の掛け算で8バイト使うのはもったいない。
これに対し、2,3の代わりに8,9を使えば、マスク値は9(2進数で1001)が使えるため、有効ビットが被らないように
ORを行う場合に1ビットずつのシフトでOKとなります。(CBAcbaのビット割当)

更新準備

次回更新の準備をしております。
(SoupSeedからのStart.ax更新が制限中なので更新登録はまだしていません。)
スクリプトのスリム化および以下の調整を行いました。
・面スキップ円滑化のため受付タイミングと待ち時間を調整(ほぼmmplayの待ちのみ)。
・ギブアップ/1ミスの際、Escape長押しで強制GAMEOVER。
・現行の全16面から全30面に増量。
・面数増加に伴せて、問題内容、難易度、順序、青ポーション付与数を調整。
・敵の当たり判定と移動速度を1割ほど小さめに修正。

TVで動確

事務局にてStart.axの差し替えを対応していただけたようです。お手数をおかけしました。
HSP3.4のブラウザでも動作するようになりました。
HSPTV掲示板の方に3.5BetaよりAXサイズが小さくなるという情報がありましたが、
解説データにあるサイズ記載の方は、次回の作品データ更新時に修正します。
次期バージョンではスクリプトのスリム化も進めるので全25面以上にできる可能性もあります。


蛇足事項の追加
パズル要素的には同時に動く魔石は1個で十分なのですが、本作では操作感向上のために、
魔石が動いている間でもプレイヤーの移動を開始したり別の魔石を押したりできます。
(プレイヤーや魔石の移動を1フレーム内で並行処理するスクリプト構造にしています。)

登録確認

あー、HSP3.5beta環境でコンパイルしたStart.axを登録してしまったようです。
HSP3.5betaのブラウザでは問題ないですが、HSP3.4からでは起動しないです。
とりあえず、3.4のみ導入しているマシンでStart.axを作り、事務局へ送付しました。


開発機には評価用に3.5も入れていますが、コンテスト作品の開発はずっと3.4環境
だったはず…と思っていたら、間もなく原因判明。
スクリプトファイル(*.HSP)をダブルクリックすると3.4のエディタが起動するのに、
デスクトップのショートカットからHSPエディタを起動すると3.5Betaでした。

応募完了

ANSUKOEMU2016-10-31

毎年恒例の駆け込み応募です。
パズルアクションゲーム「Temples Trick」、HSPTV部門ID#1323です。
2種類のポーション(スタンと魔石消去)を使い、敵の接近をかわしながら、すべての魔法陣を封じるとステージクリア。
魔石を押して(モーション的には蹴ってるようにも見えるけど)、魔法陣まで移動させます。
ステージによって、難解パズルにしたり、アクション寄りに振ったりしています。


では、これまた恒例となります蛇足事項をつらつらと。
今年はHSPTV素材の珠音(tamadot.bmpMIDIのBGM)を使うことを念頭に開発しています。
そして、ステージ生成を乱数に頼るのではなく、面データとしてスクリプト内に保持するというのも課題の1つとしました。
「Temples Trick」は、HSPTV枠で面データを抱えるならこのカテゴリーかなー、と漠然と考えていたネタです。
パズルとしてはよくあるルール「パーツを決められた地点まで押して移動させる」を採用しています。
倉庫番に代表される片付け系で、いまでは非常にオーソドックスなイメージのものです。
パーツの動きもわりと良く見られるタイプで、障害物に当るまでパーツが移動し続けるのと、任意消去できるという点は、往年のアーケードゲーム「PENGO」のIceというと古参にはわかりやすいかもしれません。
クリアには無関係ですが、3個ある★マークが入ったIceを縦か横に並べるとボーナスというルールに燃えました。
(その「3個並べると完成」というギミックをそのままパズルにした「スフィア」というPCゲームプログラムもあって、パーツを動かす手数が各面決まっており、8x8の場外に出してしまってもNGというものでした。)
「魔石消去」は、パズル正解手順に組み込むために回数制限を付けています。面によっては0回もあります。
パズルの得意な方にはさっさとクリアされてしまうと思われるため、アクセントとして敵を出すようにしました。
敵は魔石を透過するので、利用してパズルを解くようなことはありません。
敵は倒せないので終始邪魔をしてきます。ステージによっては多く出現させてぐっとアクション側に寄せたりしています。


なお、申し訳ないことに今回は99%の出来です。
マスからマスへのプレイヤー移動中でもスタン発動を受け付けるようにしていたのですが、バグっていたため、応募間際に慌てて削りました。
そこはいずれデバッグしますが、そんなんでAX的には70Bytesほどまだ空いています。
あと、時間の都合でスリム化が十分ではなく、うまく詰めれば全20面程度のデータが格納できるかもしれません。まあステージ案を考えるのが大変ですが。
ちなみに、いつもならタイトル表示中もゲーム中の画面を表示して敵キャラを動かしたりしているところ、パズル系ということでやらないようにしたため、オープニングがちょっと殺風景でした。