残りゲーム制作体力10%な人のためのずぼらゲームライブラリcrisp-game-lib

を目指してまた自作ゲームライブラリを作っている。

ゲーム制作体力が無いならゲーム作りをやめればいいのだが、ウン十年とゲームを作り続けているゲーム制作ジャンキーはそんなことでは立ち止まれないので、より短時間で体力が尽きる前にゲームを完成させるためのライブラリを再発明し、今日もゲーム制作RTAを走るのだ。1時間くらいで完走できるのが理想。

crisp-game-libは短時間で手軽にブラウザゲームを作るためのJavaScriptライブラリだ。2014年に50個のミニゲームを作ったが、そのときにはそれらゲームを作るためHaxeライブラリmglCoffeeScriptライブラリmgl.coffeを合わせて作った。その後も懲りずにミニゲームとライブラリ作りを続けた経験を活かし、クラシックでアーケードライクなミニゲームを作るために必要最小限な機能を備えたライブラリを目指して、crisp-game-libは作られている。

crisp-game-libを使ったゲームもすでに40個以上作っていて、十分にドッグフーディングされていると思う。ゲームのtitledescription、1秒間に60回呼びだされるupdate関数を単一のJavaScriptファイルとして書くだけで、PCとモバイルで動作するブラウザゲームが作れる(下の画像をクリックすると遊べます)。

pressm screenshot

箱・線・弧・テキスト・キャラクタなどの描画機能と、

ref_drawing screenshot

それら描画機能と一体化した衝突判定機能

ref_collision screenshot

マウス・タッチパネル両対応の入力取得機能、鳴らしたい音名を選択するだけの効果音機能と、ミニゲームに必要な機能を一通り用意した。

また、オプションisPlayingBgmtrueにするだけで自動生成されるBGM、isReplayEnabledtrueにするだけで有効になるリプレイ機能、themeを設定するだけでレトロなCRT風やドット絵風などに見た目を変化させる機能、characters配列で簡単に定義できるドット絵など、ゲームをジューシーにするための機能も備えている。生成された音が気に入らなかったらseedに適当な整数を与えると音が変わるので、気に入った音が出るまで乱数シードガチャを引き続けて欲しい。

TypeScriptでの型定義も備えているので、VSCode上でインテリセンスの恩恵を十分に受けることができるのも、短時間でのコーディングに役立つと思う。

Super HexagonVVVVVVの開発者として知られるTerry Cavanaghさんが書いてくれたcrisp-game-libに関する記事もあるので、合わせて読んでもらいたい。

ゲーム制作体力と合わせてゲーム遊ぶ体力も落ちてきているとなると、サクッと遊べるゲームをサクッと作れる環境が欲しくなる。なのでこんな感じのゲームライブラリ車輪再発明を繰り返している気がする。本来この辺の役割を担うのは、PICO-8に代表されるファンタジーコンソールやScratch、HSPなどで、これらのほうがより高機能なのは間違いない。だが、より機能を削ぎ落とし、自分に合った形に自作ゲームライブラリを作るのも、それはそれで楽しいので良しとしたい。皆もゲームライブラリ自作沼に肩まで浸かって温まりましょう。

個人サイトをリニューアルして自作ゲーム一覧を作ったら250個くらいあった

ABA Games

前々から今まで作ったゲームを整理して、その一覧が見られるようにしたいと思っていたので、覚悟を決めてホームページのリニューアルをした。作ったゲーム(一部ゲームじゃないのもあるけど)は250個くらい。ミニゲームを量産していたのでそれなりの数はあるだろうな、と思っていたけど、思ったより多かった。

ゲームはその動作プラットフォーム別に分けて見られるようにした。

うちのゲームで比較的ちゃんとしているたぐいのものはだいたいWindows用だから、ここがメインページ。

最近作っている、ブラウザで遊べて数分で終わるミニゲーム群はこのページ。アニメーションGIFでだいたいどんなゲームか分かるようにしているつもり。

今は亡きFlashのページ。ミニゲームとはいえ、それなりの数作ってるので、これらがそのまま遊べなくなるのはちょっと悲しい。Ruffleとかの互換Flash Playerの成熟に期待している。

その他。昔作った弾幕記述言語BulletMLとか、いにしえ+マイナーなプラットフォーム、WonderWitch、P/ECEPalm向けゲームなど。この辺のゲームをいまさら動かす人はあまりいないだろうから、自分史的な感じだ。本当はMSX時代とかに作ったゲームもリストアップしたいんだけど、そんなものが手元に残っているはずもなく、それらがそのまま失われてしまうのはしょうがないね。ベーマガとかのプログラム投稿雑誌にバリバリ掲載されていた人は記録が残っていそう。

最近は作ったものをGitHub上に置いていたりしていて、自作ゲームもいろんなサイトにバラバラにある感じだったので、こういう形でリスト化できたのは良かった。継続は力なり、もしくは三つ子の魂百までを可視化できている。

これからもゲームをちまちま作っていってリストを拡充していきたい。願わくばブラウザというかHTML5というかJavaScriptが安定して将来も互換性を保って動作してくれて、作ったゲームを簡単に遊び続けられる時代が続いて欲しいね。

クイックソート VS 挿入ソート、ファイッ!

コードとライブデモはこちら。

アルゴリズムの王道ソートアルゴリズムでコードバトリングをしてみたかったので作った。左(赤)のコードが昇順に、右(青)のコードが降順に同一の配列をソートしようとして戦う。昇順に揃ったら左の勝ち、降順に揃ったら右の勝ち。

コードは普通のJavaScriptとして書く。以下の2つの特殊な関数がある。

  • get(i): 配列からi番目の要素を取得する
  • swap(i, j): 配列のi番目とj番目の要素を交換する

setはできない。setを許すとコード内のメモリに配列を逃しておいてソート、一気に書き込むというインチキができるから。右の降順側のgetは要素のマイナスの値が帰ってくるので、右のコードもアルゴリズム自体は昇順にするものを書けば良い。

コードは左と右で交互に実行する。実行はJS-Interpreterのstep()で行う。

コードはなるべく実行速度が速く、頻繁にswapして配列をかきまわせる方が強い。速度はJS-Interpreterのstep()の解釈粒度に依存するが、コードがコンパクトな方がもちろん速い。

クイックソートと挿入ソートだと挿入ソートの方が圧倒的にコンパクトで、配列の長さが10くらいだとその実行速度でクイックソートを圧倒して勝つことが多い。配列が長くなると多分勝敗は変わってくるんだろうけど、試していない。

ソートアルゴリズムは別のアルゴリズムが配列をいじるなんてことは想定していないので、実行が終わった時点でちゃんとソートされている保証は無い。なので実行が終わったあとは実行状態をリセットして再度実行される。クイックソートは実装によっては外部から配列をいじられると配列のバウンダリを超えた操作が発生してエラーになることもある。その場合も再実行。

で、これがちゃんとしたゲームとして成り立つかというと、どうだろう。このアルゴリズムがこのアルゴリズムに強い、みたいな三すくみ的な面白さがあるかというと、微妙だ。あとは相手方向に揃いそうだったら積極的に崩す、とかいう防御的仕組みを入れたバトリング向け特殊ソートアルゴリズムが強かったりするなら面白そうなんだけど、そういった工夫をする余地があるかなあ。

いい感じのビジュアルをランダムになんとなく作り出す

なにかを作った。めざせジェネレーティブアートジェネレータ!

screenshot

クリック/タップで別の絵を作ります。

この手のものの難しさは、

という具合に自由度を高くしていろんなバリエーションを作ろうとすると見てて面白いものができあがる打率が減って、逆に打率を上げようと面白くなさそうなものをフィルタリングしていくと自由度が低くなること。

自由度を高くするにはランダムにするものを増やせばいい。今回は座標と線の太さと色を表す数式を乱数で作った。といってもあまりに適当にすると打率が下がるから、

パラメトリック方程式

この辺に出てくる数式をぐっとにらんでよく使われてそうな関数を適当にチョイスする。今回は

a + b, a - b, a * b, a / b, 
sin(a), cos(a), exp(a), pow(a, b), noise(a), 
a > b ? c : d

を使った。noiseはp5.js組み込みのパーリンノイズ。あと、sinとcosはパラメトリック方程式に頻出しているような印象があるので多少出現頻度を上げる。

a, b, c, dのところには、

  • 上記関数を再帰的に、ただし再帰が深くなるにつれ抑制する
  • 開始からの秒数を表す変数t
  • 先頭から何番目の点であるかを表す変数i
  • 2から10のランダム整数aまたはb

のどれかを当てはめる。これで簡単にランダムな数式が作れる。

この数式をつかって点のX/Y座標、線の太さ、色(HSB)を算出する。点は10~100個用意し、その間を線でつなぐ。

あとX/Y座標の数式のパターンとして、X座標のsin, cosをcos, sinに入れ替えてY座標の数式とするという小細工を半分の確率でする。数式を作っているコードは以下。

formula.ts

打率を制御するのは難しい。面白いかどうかはコンピュータには分からないから。

まあでも画面に何も写っていないのは面白くないだろう。なので数式から出る数値を多少いじる。

X/Y座標、線の太さ、色の各点の数値の最小値と最大値を記録しておいて、それら数値が所望の範囲に収まるように補正する。X/Y座標は画面サイズの横/縦のピクセル数、先の太さは画面サイズの1/8くらいまで、色を表すHSBは0~360, 50~100, 50~100に。以下のコードのformulaRangesを使ってその辺の調整をしている。

main.ts

それ以外の調整はしてない。あとはひたすらクリック。なので現状たまに面白いビジュアルが出るのは、たまたまだね。たまたま出た面白パターンをGitHubのREADMEに置いてある。

https://github.com/abagames/folmura

こうやって何かを作る手法を、個人的にガチャ指向プログラミングと呼んでいる。ランダムに絵や音やレベルやゲームが出てくる仕組みを作って、あとはひたすら面白いものが出るまでガチャを引き続ける。プログラムを書くことなくいろんなバリエーションを得ることができるから最高に楽だ。問題は、そのガチャの仕組みを作るのが楽じゃないところだね。というかこれはプログラムパラダイムではないね。

マップを書くだけでゲームが作れる環境が欲しかった

ので、テキストでタイルマップを書くとゲームになるrj-10ってのを作った。ブラウザで遊べる

rj-10 screenshot

これを作ろうと思ったのはPix64っていうファンタジーコンソールを見つけたから。Pix64は画像1枚を描くだけでゲームが作れる。ピクセルの色がプレイヤーとか敵とかの種別を決めているのと、矢印状のパターンを書くと矢印の方向にパターンが進むというルールを使ってゲームを作る。

Pix64 screenshot

画像を描くのすら面倒な私は単にテキストを使うことにした。以下のようなテキストを書くと、

-----------
|  v   v o|
   r   r g
|         |
|         |
|         |
|@   ^    |
 c   r
-----------

以下のゲームになる。

lv3

テキストは基本レベルのタイルマップを表しているけど、途中のrとかgとかだけからなる列は特殊で、その上の列のテキストに色を付ける働きをする(redとgreen)。

いくつかルールがある。

  • 色が付いたテキストはアクター(ゲーム内オブジェクト)になる
  • cyan, blueはプレイヤー、red, purpleは敵、yellow, greenはゴール、grayは壁
  • プレイヤーがゴールに到達するか、ゴールが無い場合は10秒敵を避ければ勝ち
  • アクター内のキャラクタがアクターの動作を規定する
  • @のキャラクタは矢印キーで操作可能
  • ^Z>nvz<Nのキャラクタは向いている方向に進み、-|/\にぶつかると反射
  • RLのキャラクタは右/左手法で壁沿いに進む
  • Fのキャラクタは隣接する別のアクターを一定時間ごとに発射する
  • 同色の隣接するテキストは一つのアクターになる
  • sfに隣接するキャラクタはその動作が遅く/速くなる

これらを駆使すると、

謎の跳ねながら実を落とす木、

lv6

かろうじてシューティングゲーム

lv8

フラッピ鳥めいたなにか、

lv13

などを作ることができる。

まあほぼレベルエディタなんだけど、ルールを駆使することによって、ちょっと毛色の違ったレベルを作ることもできるので、かろうじてゲーム開発環境と呼べなくもない、のか?

こういったタイルマップを描くことでゲームを作れる環境って他にどんなのがあるんだろう。タイルマップのエディタが備わっているゲームはいにしえの倉庫番とかからあるけれど、

Sokoban

これはやはりレベルエディタそのもので、ルールの違う別のゲームを作れる感じはしない。

ロードランナーとか、

Lode_Runner

レベルによってパズル寄りだったりアクションゲーム寄りだったりするタイプのゲームだと、ちょっとゲームを作っている感じが出てくる。

この手のもので一番進んでいるのはスーパーマリオメーカーかなあ。

Super_mario_maker

スーパーマリオメーカーは膨大なキャラクタ+その組み合わせを用意することでありとあらゆるギミックを可能にしている。

〇〇とisと××を組み合わせるパズルゲームであるBaba Is Youも、

Baba_is_you

レベルエディタができたらかなりのバリエーションが作れそう。これも××のバリエーションがかなりある。

作れるものの柔軟性で考えればマインクラフトのレッドストーン回路とか、Factorioの運送ネットワークとかはかなり複雑なギミックも作れるんだろうけど、あまりゲーム作り向きではなさそうな印象を受ける。

個人的な理想は、キャラクタそのもののバリエーションは最小だけど、それらの組み合わせかたは柔軟で、いろんな種類のゲームを簡単に作ることができるタイルマップ型エディタなんだけど、なかなか見つけられない。そういう感じのゲームや開発環境、どこかにありませんかね。

理想のマイコン機械語開発環境を夢見て

PC-6001MSX機械語開発時代にREPL (Read-Eval-Print Loop)環境があったらという妄想のもと、Z80のREPLを作った。

ブラウザ上で遊べる

ソースはGitHubのabagames/z80-replに置いた。

コマンドラインからZ80ニーモニックを書いてEnterを押せば、それが機械語に変換されてPC(プログラムカウンタ)が指すメモリに書き込まれ、そのまま実行される。実行結果は画面上のメモリマップやレジスタリストに反映される。すぐJR -2とかいう悪さをする人がいるかもしれんが、64回ループを回った時点で一時停止する。Enterを単に押せば現在のPC上の機械語がそのまま実行される。ブラウザから開いてそのまま連打すればNOP, NOP, NOPだ。TABを押せばニーモニックの候補も出る。レジスタを直接操作する手段はないので適宜LD、PCを操作する手段も無いので適宜JPすること。

ツイートに書いたように多分これ単体ではあまり実用性はなく、アセンブラのエディタの脇でChrome DevToolsかのようにこのREPLが開いて、動作検証ができるようになっていれば、当時相当楽できたのではないかと思える。ブレークポイントなどのデバッガ機能と統合されていればなお良い。

実際の当時の機械語開発環境といえば、ハンドアセンブルだ。ノートとかにニーモニックを鉛筆で書いて、

LD DE,D0H
LD HL,80H
LD BC,0AH
LDIR
RET

インストラクションセット表を見ながら機械語に手で変換し、BASICのDATA文として書く。

1000 DATA 11,D0,00,21,80,00,01,0A,00,ED,BD,C9,//

DATAを読み取りPOKEで書き込み、EXECだ。

10 RESTORE 1000
20 A=&HE000
30 READ V$
40 IF V$="//" THEN 70
50 POKE A,VAL("&H"+V$)
60 A=A+1:GOTO 30
70 EXEC &HE000

MSX-DOS時代はアセンブラがあったからまだだいぶマシだが、それでも前記のJR -2のようなコードが混入した時点でコードは暴走、プログラムはおしゃかだ。マイコンをリセットし、テープからプログラムを読み直さないといけない。

これらの時代と比べれば今はChrome DevToolsのような超高度なREPL、デバッガ、プロファイラが付いてくるのが当たり前で、とてもいい時代になったものだ。でもたまに昔のアセンブラやBASICを思い出して古き良き時代を思い出したくなることもある。そういったノスタルジーを簡単にちょっとだけ満たすためのツールでした。ノスタルジーを通り越して現役の血が蘇った人は組み込み勢やレトロPC現役開発勢になだれ込むと良いかと思います。

256文字ゲームくらいならコンピュータが作って欲しい

でも物によっては混ぜられないこともない。

例えば

f:id:ABA:20180307173815g:plain

f:id:ABA:20180307174036g:plain

を混ぜて

f:id:ABA:20180307174059g:plain

というゲームにしたり、

これ

f:id:ABA:20180307174158g:plain

f:id:ABA:20180307174213g:plain

を混ぜて

f:id:ABA:20180307174231g:plain

というゲームにしたり、だ。

混ぜ方としては、ゲームを2つのパーツに分ける。マウス操作が反映されるプレイヤー側パーツと、それ以外の物を動かすパーツ。で、2つのゲーム間でそれらを入れ替える。そうするとたまに新しいゲームになる。

もちろんうまくいかないパターンの方が多くて、

f:id:ABA:20180307174249g:plain

f:id:ABA:20180307174306g:plain

を混ぜると

f:id:ABA:20180307174330g:plain

車が無限に落ちる虚しいゲームができる。

こういう混ぜ方でうまくいくのは古典的な避けゲーくらいな気もする。プレイヤーの動作と障害物の動作のバリエーションで新しいゲームを作る。でもそれは避けゲーのステージバリエーション的なもので、新しいゲームと呼ぶのは厳しい気もする。あと動作自体のバリエーションを新しく生成することもできない。

前途多難である。