MAGNITUDE−Μ

9999-00-00

ここは、あんすこえむのHSP作品に関するサポートページ兼開発日誌Blogです。

2016/12/01 「Temples Trick」がHSPプログラムコンテスト2016「審査員奨励賞・うすあじ賞」を受賞しました。

2016/10/31 パズルアクションゲーム「Temples Trick」をHSPコンテスト2016HSPTV部門にエントリーしました。ID#1323

2015/12/01 「宇宙海賊キャプテン・オニオン」がHSPプログラムコンテスト2015「秀和システム賞」を受賞しました。

2015/10/16 リアルタイム・ストラテジー・ゲーム「宇宙海賊キャプテン・オニオン」をHSPコンテスト2015HSPTV部門にエントリーしました。No.1056

続きを読む

トラックバック - http://d.hatena.ne.jp/ANSUKOEMU/99990000

2016-12-01

[]「うすあじ賞」を受賞

今回、スクリプトのコーディング期間は実質2日でした。

ルールやステージ案とかは9月あたりから検討はしていたものの、なんだかんだで時間がとれず、10月最後の土日(29,30)は自室に引篭もってコーディング。

Kacotte!同様マス目移動のため、例のvardup,posclcサブルーチンと、キー入力判定ロジックは流用しましたが、あと使えたのはハイスコア処理くらい。

面データを除いても全体の8割は新規コーディングが必要で、この2日間の集中度は半端では無かったです。

(以上、結果が出たのでカミングアウト)

例年に増して無謀でしたが、受賞できて良かった。


さて、気になったその他の作品について。

総合優秀賞の「オオツルギ2」。これはくると思っていましたよ。大方の予想通りではないでしょうか。

前回上位賞の時点でも伸びしろを感じましたが、がっちり進化させてきました。

こういうのをアーケードとかギャラリー見守る中で(若い時に)プレイしたかったなー。

トラックバック - http://d.hatena.ne.jp/ANSUKOEMU/20161201

2016-11-27

[]Ver1.15更新登録

無駄な処理を削って、機能を増やしました。

ステージクリア、スキップの達成状況がわかるように、画面左上スコア欄に表示。

5面区切りで、クリアした面の場所に「*」をGameOverしたところに「X」が入ります。

ハイスコア登録の際も、達成状況を送信します。

Ver1.15でのハイスコア登録が増えないと表示がガタガタになりますが…

あと、タイトル画面のハイスコア表示について色数を増やしてみました。

トラックバック - http://d.hatena.ne.jp/ANSUKOEMU/20161127

2016-11-20

[]ステージデータ展開

順番前後しましたが、スクリプト内でのステージデータの展開について。

>9x9のフィールドデータ部分は、横3マスをASCII文字1Byteで表現しており、81マスで27文字使います。

>これに、敵と赤ポーションの数を示す1文字を付けた構造で、1ステージ分を正味28バイトの文字列データとします。

たとえば、スクリーンショットの面(Ver1.12では20面)の文字列データは "X@pZ@r@h@@B@PGP@B@@h@ZRrX@pL" です。

先頭から27バイト分を元に、以下のようなスクリプトで魔石オブジェクトとグランドマップへ展開しています。

memset mapg,255,EMAPNUMSZ
lpoke c1
repeat PLFNUM
	c1+:gosub *vardupc1
	e0t=(peek(mg,cnt/DTW)>>(cnt\DTW))&9,cnt+PLFOFSET+(cnt/PLFW)*PLFGAP,1 ; オブジェクトデータ登録
	gosub *posclc:emapg=(e0t=1) ; グランドマップ更新
loop

あらかじめ#constされている各シンボルは、以下のような意味と値になっています。

EMAPNUMSZ マップ配列のバイト数、15*11*4→660

PLFNUM プレイフィールドのマスの数 9*9→81

DTW ASCII文字1バイトで現わすマスの数 3

PLFOFSET マップにおけるプレイフィールド開始位置 15+1→16

PLFW プレイフィールドの幅 9

PLFGAP 2つの段のプレイフィールド間にある壁の厚さ 15-9→6


まず、memsetはグランドマップの中を255(&HFF)で埋めています。

配列整数型なので、1要素4バイト分として考えると&HFFFFFFFF、つまり-1で埋まるのと同義です。

ループ内ではプレイフィールドのみ操作するので、81回ループしています。(壁は触りません)

c1をオブジェクトID(1〜82)として用いるので、ループ前にlpoke c1で0クリア、ループ最初でインクリメントしています。

おまじないのサブルーチンvardupc1をコールした後、オブジェクト情報の定義をします。

e0tは該当オブジェクトについての管理テーブル先頭要素で、ここからカンマ区切りで、マスのタイプ、位置、移動カウントを代入。

マスのタイプ(空白:0、魔法陣:1、紫魔石:8、赤魔石:9)は、文字列変数mgより該当する1バイトを参照し、シフト&マスク(9)で取得。

位置は、cntの値に<プレイフィールドの段数>×<壁の厚さ>とオフセットを加算した値。

オブジェクト情報に位置と移動カウントが入ったらposclcを呼び、魔石オブジェクトの下準備(現在位置のx、y情報登録など)を行います。

空き床や魔法陣についても構わずオブジェクト登録していますが、メインルーチンではタイプ8,9だけが魔石として扱われるので問題ありません。

posclcにてemapgに該当位置のグラウンドマップがdupされるので、タイプが1なら魔法陣(1)、それ以外は空き床(0)を代入します。


微々たる量ですがサイズが肥大化しないよう、配列添字の隠蔽と、計算式削減を念頭にスクリプトを書いています

要所に出てくるvardupc1,posclc(もしくはvardup,posclceg)などに共通化できる定型処理をまとめておき、マップ配列はできるだけdupされた変数が使えるようにしています。

シフトの計算については1マス1ビットシフトで済むタイプ値を採用し、式が大きくならないようにしています。

また、処理全体として1次元のデータとして扱うことで、ループ多重化も回避。

トラックバック - http://d.hatena.ne.jp/ANSUKOEMU/20161120

2016-11-19

[]更新確認

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として転記をしています。

トラックバック - http://d.hatena.ne.jp/ANSUKOEMU/20161119

2016-11-16

[]Ver1.12

更新登録しておきました。反映待ち。

先の機能変更に加えて「じっくりモード」を実装しました。

頭を使う方での集中プレイを考慮した措置です。

ハイスコア登録の都合上、無得点扱いにしちゃってます。

トラックバック - http://d.hatena.ne.jp/ANSUKOEMU/20161116

2016-11-15

[]ステージデータ

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

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行で記述。

各面の区切りがCRLFになるので、メモリーノートパッド関連の命令が使えます。

スクリプトの都合上、ステージ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マスに割り当てるビットをA,B,Cで表現するとCCBBAAです。シフト量を2倍する際に8バイト使いますのでもったいない。

これに対し、2,3の代わりに8,9を使えば、マスク値は9(2進数で1001)が使えるため、有効ビットが被らないように

ORを行う場合に1ビットずつのシフトでOKとなります。(CBACBAのビット割当)

トラックバック - http://d.hatena.ne.jp/ANSUKOEMU/20161115

2016-11-12

[]更新準備

次回更新の準備をしております。

(SoupSeedからのStart.ax更新が制限中なので更新登録はまだしていません。)

スクリプトのスリム化および以下の調整を行いました。

・面スキップ円滑化のため受付タイミングと待ち時間を調整(ほぼmmplayの待ちのみ)。

・ギブアップ/1ミスの際、Escape長押しで強制GAMEOVER。

・現行の全16面から全30面に増量。

・面数増加に伴せて、問題内容、難易度、順序、青ポーション付与数を調整。

・敵の当たり判定と移動速度を1割ほど小さめに修正。

トラックバック - http://d.hatena.ne.jp/ANSUKOEMU/20161112

2016-11-03

[]TVで動確

事務局にてStart.axの差し替えを対応していただけたようです。お手数をおかけしました。

HSP3.4のブラウザでも動作するようになりました。

HSPTV掲示板の方に3.5BetaよりAXサイズが小さくなるという情報がありましたが、

解説データにあるサイズ記載の方は、次回の作品データ更新時に修正します。

次期バージョンではスクリプトのスリム化も進めるので全25面以上にできる可能性もあります。


蛇足事項の追加

パズル要素的には同時に動く魔石は1個で十分なのですが、本作では操作感向上のために、

魔石が動いている間でもプレイヤーの移動を開始したり別の魔石を押したりできます。

(プレイヤーや魔石の移動を1フレーム内で並行処理するスクリプト構造にしています。)

トラックバック - http://d.hatena.ne.jp/ANSUKOEMU/20161103

2016-11-01

[]登録確認

あー、HSP3.5beta環境でコンパイルしたStart.axを登録してしまったようです。

HSP3.5betaのブラウザでは問題ないですが、HSP3.4からでは起動しないです。

とりあえず、3.4のみ導入しているマシンでStart.axを作り、事務局へ送付しました。


開発機には評価用に3.5も入れていますが、コンテスト作品の開発はずっと3.4環境

だったはず…と思っていたら、間もなく原因判明。

スクリプトファイル(*.HSP)をダブルクリックすると3.4のエディタが起動するのに、

デスクトップショートカットからHSPエディタを起動すると3.5Betaでした。

トラックバック - http://d.hatena.ne.jp/ANSUKOEMU/20161101