リバーシ・マインスイーパー・ブロック崩し
/lua/apps/ の3本 — pico.game のタイルマップ・スプライト・状態・画面ボタンで作るゲーム
ゲームエンジン pico.game の使い方の実例として、リバーシ・マインスイーパー・ブロック崩し(とテトリス)は全部エンジンの上に作ってあります。ウィジェット(Button Label Canvas など)は1つも作らず、game.new が作る Canvas 1枚の中で、画面ボタン・状態・タイルマップ・スプライトだけで組み立てています。
リバーシ(/lua/apps/リバーシ/)
- 盤面はタイルマップ(
tiles.pimg。24x24のタイル4枚: 空のマス・黒石・白石・打てる場所の印)。石を置く・裏返すはmap:set()だけ - タップは
g.touch(キャンバスの中の座標)から(x - 盤面の左) // 24でマスを求める - 流れは
g:stateの3つ:play(打つ)・pass(置ける場所が無い側を知らせる。タップか1.8秒で続く)・over(結果。タップでもう一度)。ダイアログは使わないので、ゲームの流れが1つのファイルの中で追える - 「戻る」「リセット」は
g:button。g:pressed("reset")で読む
マインスイーパー(/lua/apps/マインスイーパー/)
- 盤面はタイルマップ。難易度ごとにマスの大きさが違う(初級20px・中級16px・上級14px)ので、画像も難易度ごとに1枚(
tiles20.pimgtiles16.pimgtiles14.pimg)。タイルの値は 1=閉じたマス 2=空き 3〜10=数字1〜8 11=旗 12=地雷。0マスの連鎖で何十マス開いても、map:set()したマスだけが描き直される - 難易度を選び直すたびに
g:clear()してタイルマップを作り直す - 画面は
menu(難易度を選ぶ)→play→done。状態ごとにshowButtons{...}で見せる画面ボタンを入れ替える(隠したボタン(b.visible = false)はタッチも受けない) - 最初の1手は必ず安全(最初にタップしたマスを避けて地雷を置く)
ブロック崩し(/lua/apps/ブロック崩し/)
- ブロックはタイルマップ(
tiles.pimg。29x14のタイル7枚: 速さの段1〜6と壊せない灰色)。壊すとmap:set(c, r, 0)。ボールの周りのマスだけをmap:get(c, r)で引いて当たりを調べるので、ブロックが何個あっても重くならない - ボール・パドル・アイテムはスプライト。ボールは
drawで円を描く。アイテムはvyを持たせるだけでエンジンが落とし、パドルとの重なりはg:collide("paddle", "item", fn)で拾う - ボールの位置と速さは自前(
cxcydxdy)。1フレームを6px以下に刻んで壁・ブロック・パドルへ当てる(エンジンの1回の移動だと、速いボールがブロックをすり抜けるため) - ステージクリア・ゲームオーバー・全クリアは
g:stateの枠(draw)で出し、タップかAで進む - ステージは
lib.luaのSTAGES(形・速さの段・壊せない壁を3つの関数で組み合わせ、詰みを機械的に除く)。自動プレイ(右上の「自動」)はバッテリーの消費を測るときの放置プレイ用
共通するコツ
- 画面ボタンの名前をコントローラーのボタン名にしておくと、
g:down/g:pressedが画面とコントローラーを同じ形で読む(テトリスの操作ボタン) - スプライトの
drawはwxhの外へはみ出させない。pico.fill_circle(x, y, r, c)は直径2r+1画素なので、半径4のボールなら枠は 9x9 - 画面全体を描き直したいとき(状態の切り替え)は
g:go()が行う。一部だけならg:dirty(x, y, w, h)