“RUN” それは魔法の言葉

私とコンピュータの思い出を、だらだらと綴ります。最近はHSP3でのゲーム作り日記です

61.ゲーム&ウォッチのオクトパスを作ろう その2

今回も画像を準備するところからスタートした。

こちらもそこそこきれいな画像がネットにあったので、拝借。
まずは液晶パターンを全部消して、ゲーム&ウォッチの筐体と、セロファン部分を残すよう、画像加工を始めた。

はじめは、潜水夫とタコの足パターンだけを消せば終わりと思っていたが、潜水夫はセロファンの奥側に表示されている…
「マンホール」も、同じだったと思うのだが、こちらは海藻の向こう側に潜水夫がいたり、タコが手前に出ていたりしないといけないので、無視できない。
面倒だが、3層に分けて画像を用意することにした。

  1. ゲーム&ウォッチの筐体
  2. 潜水夫やタコなどの液晶パターン
  3. セロファン部分

BASIC!は、画像オブジェクトの若い順から下に重なっていく表示になるので、この順序でオブジェクトを表示すれば、液晶パターンの上にセロファンが表示されているものを再現できる。

f:id:CORO3:20210109173757j:plain

次は、液晶パターンの切り出し。これも面倒だった。
タコの足は全部で5本出てきて、それぞれが4個か5個の節になっており、それが1つずつ伸びたり縮んだりする。
「マンホール」の時のように、水平に並んでれば切り出しも簡単だけど、足は複雑に伸びるので、節ごとに切り出すのは面倒だった。
さらに、それぞれの節の座標も合せないといけないとなると、最初の作業でくじけそうだったw

そこで、伸びていくときには、1つ前の節も表示していることを利用して、節が増える単位でまとめて切り出すことにした。
これなら、根元の座標値をすべて同じにしておけば、上から重ねて表示して、そのうち1つだけを表示すればいい。

f:id:CORO3:20210109180642j:plain

潜水夫も面倒だった。それは次のエントリーで。

60.ゲーム&ウォッチのオクトパスを作ろう その1

マンホールが作れたので、別のゲーム&ウォッチも再現してみようと考えた。

題材に選んだのは、「オクトパス」。持ってはいなかったが、友達にずいぶん遊ばせてもらった記憶がある。

f:id:CORO3:20201110015852p:plain

潜水夫がタコの足をかいくぐって、宝箱から金貨をゲットして船に戻るゲーム。
金貨は何回も取ることができ、そのたびに1点が入る。
1枚でもゲットして船に戻れば3点が入る。
タコの足に捕まらないようにして、ずっと金貨だけをとってスコアを稼ぐことも、ちまちま船に戻ってスコアを稼ぐこともできる。
プレイスタイルが分かれる面白いゲームだった。

「マンホール」で満足のいく再現ができたので、オクトパスも楽勝だと思っていたが、そうは行かなかった。

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

59.ゲーム&ウォッチのマンホールを作ろう その6

最後はゲームの微調整。

得点に絡むイベントは、
 ・得点が加算されると徐々にスピードがあがる
 ・一定の得点に達すると、スピードが緩やかになる
 ・200点と500点で、ミスがクリアされるボーナスがある。
これを作りこむ。

得点を加算した後に、MOD関数を使って、20で割った余りが0の時にTIMER.CLEAR命令でタイマーをクリアして、タイマーの間隔を少しずつ短くしていく。
こうすると、短い間隔で通行人の処理が呼ばれるので、スピードが上がる。
20点ごとにスピードが上がって、100点ごとにもとに戻すようにした。

200点と500点で、ミスが1つでもあれば、ミスマークを点滅させて、クリアするアニメーションを見せる。
ミスを0に戻せば、ボーナスイベントが完成。

!通行人スピードアップ・ダウン処理

!20点ごとにスピードを増す
IF MOD(sc,20) = 0 & sc > 0 THEN
 TIMER.CLEAR
 IF itv > 500 THEN %際限なくは早くしない
  itv-=25
 ENDIF
 TIMER.SET itv
ENDIF

!100点ごとにスピードを戻す
IF MOD(sc,100) = 0 & sc > 0 THEN
 TIMER.CLEAR
 !ミスクリア
 IF (sc=200 | sc=500) & miss>0 THEN
  SOUNDPOOL.PLAY sp,4,0.99,0.99,1 
  FOR t=1 TO 5
   FOR q=1 TO miss
    GR.HIDE ms_obj[q]
   NEXT
   GR.RENDER
   PAUSE 500
   FOR qq=1 TO miss
    GR.SHOW ms_obj[qq]
   NEXT
   GR.RENDER
   PAUSE 500
  NEXT 
  FOR q=1 TO 3
   GR.HIDE ms_obj[q]
  NEXT 
  miss=0
 ENDIF

 itv=600
 TIMER.SET itv
ENDIF

!999点でカウンターストップ→0に戻す
if sc=1000 then sc=0

このゲームを屋外で遊ぶことを考えると、音は出せないこともあるなと。マンホールでは、通行人が通ると、ピッとビープ音が鳴る。そうすると、別の場所に移動しても通行人は落ちない。
この音が重要で、連続して通行人を通れるようにするときは音を聞いてから次、次と移動させる。
音自体は、wavファイルを作って鳴らせたが、聞こえないとなると困るなと。

そこで調べていると、VIBRATE命令なるものがあり、スマホのバイブを動かせる。
これで、音と同時にバイブを振動させることによって、音を消していても十分遊べるようになった。

!バイブレーションパターンの配列
ARRAY.LOAD vpt[],1,150 
VIBRATE vpt[],-1

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

なにも考えず、仕様も練らずに思い付きで付け足して作ったので、あまり良いプログラムでは無いけど、作って動かして遊ぶ。という昔のBASICの懐かしさを、存分に味わうことができた。
これもAPKファイル化して、普段使っているスマホにインストールして、暇な時間に遊んでいる。

58.ゲーム&ウォッチのマンホールを作ろう その5

問題は通行人の出現パターンだった。
ゲーム&ウォッチなので、何らかのロジックでパターンを発生させていると想像はできるのだが、いかんせん、法則がわからない。
ここで、できる人は、ロジックで何とかするんだろうけど、作っているのは凡人の私。じゃあ、力業だ!と通行人の出現パターンをデータで持つことにしたww

パターンといっても単純ではない。なんせミスターマンホールは1か所しか支えられない。
だから、同時に穴に落ちるような通行人の出現パターンが存在してはならないということ。
画面いっぱいに通行人が埋まっても、ちゃんとさばけるようにならないとだめ。それが脳汁がでるこのゲームの醍醐味♪

Excelにパターンを作って、その登場するタイミングと上下のどちらかを表す文字列を関数で生成した。
上下段はUかDで表した。タイミングはタイマーイベントごとにカウントアップするカウンタを用意して、その値を後ろにくっつけた。
なので、U11,D16のような文字列で出現パターンを表した。

f:id:CORO3:20210104225954p:plain

!通行人出現パターン
ARRAY.LOAD pa_ptn$[],"D11","U21","D31","U41","D48","D56",~
"D63","D67","U76","D83","D90","U96",~
"D100","U104","U110","D117","U121","U125","U129","U133",~
"U137","D142","U148","D153","U157","U159","D165","D169",~
"D171","U175","U177","D183","U187","U189","U194","U196",~
"D200","U204","U211","D212","D220","U221","U227","D228",~
"D234","U235","U241","D242","D247","D253","U257","U259",~
"U261","D265","D267","U271","D275","D277","D279","U283",~
"D293","D295","U301","U306","U308","U313","D318","D320",~
"U326","D331","D336","D338","U343","U345","U349","U351",~
"D355","D357","U361","D365","D367","D369","U373","U377",~
"U379","D383","U387","U391","D395","D397","U401","U403",~
"U405","D409","D411","U415","U417","U419","U421","U423",~
"D427","D429","U433","U435","U437","D441","D443","D447",~
"U455","D461","D468","D475","U480","D484","D488","D492",~
"U496","U502","D503","D509","U513","U515","D519","U523",~
"U525","D529","U533","D537","D539","D543","D545","U549",~
"D553","U557","D561","D563","U567","U569","U571","D575",~
"D579","D581","U585","U587","U589","D593","D595","D600",~
"U604","U606","U608","D612","D614","U618","U620","U622",~
"D626","D628","D630","D632","D634","U642","U646","D647",~
"D654","D656","U660","D661","D665","D667","D669","D673",~
"U677","U679","U681","U683","D687","D689","U691","D698",~
"U700","U702","D706","D708","U710","U715","D717","D719",~
"D721","D723","U725","U727","U729","U731","U733","D737",~
"D739","U741","U743","U745","D747","D751","U753","U755",~
"U757","U759","D761","D765","U767","U769","U771","D778",~
"D780","D786","U792","D796","U800","U804","U806","U808",~
"D814","D822","U823","D828","U830","U832","U834","U836",~
"D838","D843","U845","U847","U849","U851","D853","D855",~
"D857","U859","U864","D866","D868","D870","D872","U874",~
"U876","U878","U880","D882","D887","U889","U891","U893",~
"D895","D897","D899","D901","D903","U907","U909","D911",~
"D913","U924","U929","U931"
ARRAY.LENGTH pa_size,pa_ptn$[]

前回のエントリーで書いたように、タイマーで処理を繰り返すようにしたので、そのたびにカウンタを+1するようにして、文字の後ろの数字とカウンタの数値が一緒になったら、通行人を追加するようにした。

!通行人を追加
IF count=VAL(MID$(pa_ptn$[pa_count],2)) THEN
 IF LEFT$(pa_ptn$[pa_count],1)="U" THEN
  upa += 512
 ELSE
  dpa += 512
 ENDIF
 pa_count+=1
 IF pa_count>=pa_size THEN pa_count=1:count=0
ENDIF

これを組み込んで、パターンに矛盾がないかをチェックしつつ、気持ちよく遊べるように調整した。