“RUN” それは魔法の言葉

私とコンピュータの思い出を、だらだらと綴ります。

75.HSPでゲーム&ウォッチのファイアを作ろう その5

問題が判明した落下人の処理を作り直す。

それぞれの落下人の位置を文字列で表す方針は変えない。
同時に全部動かすなら、先頭の一文字を処理して末尾に回す必要はない。代わりに文字数分、ループして処理を行う。

文字列を取り出す、書き込むのは、文字列操作関数を使うのではなく、peek命令と、poke命令で行うのが良さそうと判断。peek、pokeと聞くと、なんだかマシン語みたいと思った。
実際にはバイト単位でのリードライトなので、その感想はある意味正しかった。

困ったのは、HSPにはタイマーによる割り込みイベントがないこと。ON TIMER GOSUBというようなBASIC的な命令があると思ったのだが…
拡張モジュールを使えばありそうなのだが、そこまでは求めないことにした。
BASIC!で採用した、タイマー割込みでの処理ではなく、別の方法を考える。

今は一つのループが、約1/60秒単位で進むようにしているが、これを1サイクルにすると早すぎるため、1ループごとに加算するカウンタを作り、それを特定の数値で割った余りが0の時に、落下人の移動処理を実行するようにした。
救助隊の移動操作は、全ループ中受け付けるので、落下人よりも救助隊の方を理論上早く動かせるはず。

特定の数値を変数として定義しておき、得点の増加とともに、減算していけば、サイクルがどんどん短くなって、落下スピードを早くできるようにもなる。

救急車に入って、ランプがついたところで、スコアを1プラスして、落下人の位置を管理している文字列から1文字削除して詰める。
と、思って作ってみたが、ループ処理の途中で文字列長が変わってしまうので、配列の添え字が範囲を超えてエラーになるのでこいつはだめだった。

代わりに、poke命令で半角スペースに置き換えて、ループを抜けた後に、strtrim命令で、半角スペースをトリム(取り除く)処理にした。

*fallmanmove ;落下人移動ルーチン
	fallmancnt = strlen(fmanpos) ;現在の落下人数
	
	if gamecnt\g_speed=0 { ;g_speedの値フレームごとに1つ処理する
		if fallmancnt>0 { ;1人以上落下しているとき
			repeat fallmancnt
				pt=peek(fmanpos,cnt)-65
				poke fmanpos,cnt,pt+66
				pos fx(pt),fy(pt)
				gmode 2:celput 3,pt
				if pt=22 {
					;ループ中に文字列長を変えてエラーにならないよう、スペースと置き換え
					poke fmanpos,cnt,32
					poke fmancatch,cnt,32
					;スコア加算
					score++
				}
			loop
			if missflg=1 : return

			;得点によって、最大落下人数を変更する
			maxfallman=1+(score>2)+(score>9)+(score>19)+(score>29)+(score>49)+(score>69)+(score>89)+(score>119)
			if fallmancnt < maxfallman {
				;必ず1コマ以上間隔をあけて人を追加する
				if instr(fmanpos,0,"B") < 0 & (rnd(10) > 2) {
					fmanpos=fmanpos+"A"
					fmancatch=fmancatch+"0"
				}
			}
			;得点した場合、スペースが文字列にあるので取り除く
			fmanpos = strtrim(fmanpos,3,32) 
			fmancatch = strtrim(fmancatch,3,32)
		} else {
			;単純に誰も表示されていなければ、一人追加
			fmanpos=fmanpos+"A"
			fmancatch=fmancatch+"0"
		}
	} else {
		repeat fallmancnt
			pt=peek(fmanpos,cnt)-65
			if pt >= 0 { ;スペースが含まれていた場合の対策
				pos fx(pt),fy(pt)
				gmode 2:celput 3,pt
			}
		loop
	}
		
	return

こういう風に書くと簡単そうだが、いろいろ試行錯誤してたどり着いた。
実際に動かしたときに変数の内容がどうなっているかを確認する方法がログに出力するか、assert命令を書いて、デバッグウィンドウを表示して確認しなくてはならず、自分で考えた通りになっていない原因を探すのに苦労した。

そこは歴史の長いHSP。ちょっと検索すると、knowbugというツールがあった。
これを組み込むと、HSPでプログラムをステップ実行(1行ずつ実行)ができ、変数の内容も都度表示できる。
knowbugがなかったら、なかなか開発が進まなかっただろうなぁ。ありがたい。

そうして作成したのがこれ。
youtu.be

うん。なかなかそれっぽくなってきたよ。

憧れだったコンピュータ達:8.Amiga(コモドール)

今回の憧コンは、Amiga

f:id:CORO3:20210316235943j:plain

聞き慣れないパソコンかもしれないが、テレビで使われているCG作品にはAmigaが使われていた。
Amigaに憧れた要因は、もはや伝説になったテレビ番組「ウゴウゴルーガ」。

この番組は、フルCGで動くアニメに、ウゴウゴくん、ルーガちゃんを合成したもの。子供番組としては至極シュールだった。
まさにその名の通り、曜日代わりのキャラには「シュールくん」がおり、人気だった。そしてミカン星人もこの番組から出てきた。

閑話休題
結局CGを作りたいと思ったが、使い道が他になく、買ってどうする?と、購入を思いとどまったパソコンだった。

74.HSPでゲーム&ウォッチのファイアを作ろう その4

いよいよ落下人の処理を作る。
画像は考えた末、1ファイルずつ読み込むのは面倒だし、処理も面倒なので、1つのPNGファイルにまとめ直した。これを読み込み、celdiv命令とcelput命令を組み合わせて表示することにした。
地味に切り出した画像のサイズが違ったので、画像編集ソフトで調整しながら、同じサイズにまとめ直すのが面倒だった…

次は、落下人の状態を管理する処理を作る。
BASIC!では、リストを使って管理したが、HSPにはリストを扱う関数が用意されていない。有志の方がHSPでリスト構造を使用できるライブラリを作ってくれているが、単純に先頭を取って、末尾に追加するだけに使うにはオーバースペックで、使いづらかった。

そこで、文字列で管理しようと考えた。表示場所が23か所(救急車に入ったときのランプ含む)あるので、場所をA~Wの文字列で表す。
1文字取得したら、文字コードを求めて、Aの文字コード分を引けば、0~23の数字にできる。

Aの文字コード:65
Bだったら
 → Bの文字コード-Aの文字コード
  → 66-65=1
   → 2番目の位置(0から始まるので)

実際に作って動かすと、あら不思議。2人目を表示したら、BASIC!の時と同じように処理落ちした。
よーく考えたら当たり前だった…

実機では、落下人が次の場所に移動するとき、同時に全員動くのではなく、少しずつタイミングがずれて、次の位置に表示される。
なので、1サイクルごとに1人だけ動かせば再現できると思っていた。これが大きな間違い。
この方法だと、人数が増えるほどに、移動処理がどんどん遅くなるだけ(先送りになる)だった…

この間違ってるロジックを組み直す。まずは、同時に全部の落下人を動かしてみよう。
3カ所の位置で受け止める必要があるが、落下人が同時に落ちることになると、必ずミスになるので、ゲームとして成り立たない。ここをどうするかが問題だ。

続きは次のエントリーで。

憧れだったコンピュータ達:7.TERADRIVE(セガ/IBM)

今回の憧コンは、異色な存在だった、TERADRIVE(テラドライブ)。
f:id:CORO3:20210317000437j:plain

メガドライブと、IBMのAT互換機(現在のパソコンの源流)が合体。
単位のメガの上になるテラを名前に冠した。

ニコイチになっただけならそれほど興味も無かったのだが、メガドライブ側とAT互換機側が同時に動き、連携出来る仕様だったので、これはすごいものができるのでは!と期待した。

が…AT互換機側のCPUは80286で、386がもう出始めていたころなので、がっかりだし、連携したものすごいソフトは記憶する限り、発売されていない。
Windowsマシンとして使用したくても、Windows95には未対応だったので、メガドライブを持っていれば使い道がない、残念マシンだった。