Jelly Blocks Lab
← Back to Journey

JellyBlocks 誕生記
プルプル揺れるジェリーブロックを作った日——著作権を回避しながらテトリスを超えろ

PROLOGUE

「ブルーハワイの感じで、プルプルしたジェリーゲームが欲しい」

リクエストはシンプルだった。ブルーハワイのような背景の色で、プルプル揺れるジェリーっぽいブロックのゲームが欲しい。

落下ブロックを積み重ねてラインを消す——誰もが知っているあのゲームを参考にするのは自然な発想だ。ただし、テトリスそのままでは著作権がグレーゾーンになる。ゲームメカニクス(落下・積み重ね・ライン消去)自体は保護されないが、あの7種テトロミノのピース形状の組み合わせは核心部分だ。

ならばピースの形を変えて、ジェリーという視覚スタイルで別物にする。著作権への対処がそのまま、ゲームのアイデンティティになった。

いちご ピーチ レモン オレンジ スイカ ぶどう ライム
BUILD

ジェリーを「ジェリーらしく」見せる技術

ピースを独自定義してテトリスから切り離す

7種のピースはフルーツの名前がついた独自形状で定義した(いちご=2×2スクエア、ピーチ=J-blob、レモン=3横 など)。さらに「ジェリーマージ」——同色3個以上が隣接するとボーナス点——を追加して、テトリスにはない独自のゲームプレイ要素を加えた。

// 独自形状のピース定義(フルーツ名でキャラクター付け) // ジェリーマージ: BFS で同色連結グループを判定 → 3個以上でボーナス const BASE_SHAPES = [ [[0,0],[0,1],[1,0],[1,1]], // いちご — 2×2 square [[0,0],[1,0],[1,1],[1,2]], // ピーチ — J-blob [[0,0],[0,1],[0,2]], // レモン — 3-horizontal ... ];

プルプル揺れと「ぷにっ」着地の実装

ジェリー感を生み出しているのは3つの仕組みだ。

まずプルプル揺れ——落下中のピースに sin/cos でセルごとに位相をずらした揺れオフセットを加算する。全セルを同じ位相で動かすと板が揺れるだけだが、セルごとに位相をずらすと「生き物感」が出るのがポイントだ。

次に着地のぷにっ——ロック時に gridSquish 値を1にセットし、毎フレーム 0.055 ずつ減衰させながら縦スケールに反映する。最後に透明感グラデ——roundRect に線形グラデーションとグロスハイライトを2段重ねして、透けるジェリーの質感を出した。

// セルごとに位相をずらすのが「生き物感」の核心 const wx = Math.sin(time * 4.5 + phase) * 2.8; const wy = Math.cos(time * 3.2 + phase * 1.4) * 1.6; // 着地スカッシュ: gridSquish が 1 から 0 に減衰する間 scaleY を縮める const sq = gridSquish[r][c] > 0 ? 0.55 + 0.45 * (1 - gridSquish[r][c]) : 1;

レベルが上がると海が宇宙になる

レベル進行に合わせて背景テーマが変わる5段階の演出を実装した。海(ブルーハワイ)から夕焼け、深海、星空、宇宙へと。テーマ間の切り替えはRGB線形補間(lerpCol)で60フレームかけてフェードする。背景が変わるたびに「次のステージに来た」という感覚が生まれる。

コンボシステムとフィーバーモードも追加した。連続ライン消去でコンボが積み上がり、コンボ3以上でフィーバーモードが発動(10秒間スコア2倍・金色グロー演出)。フィーバーの閾値を5ではなく3にしたのは、序盤から体験できるようにするための調整だ。

TROUBLE

踏んだバグたち

BUG 01
ピンクの壁紙しか表示されない
update() 内で gridSquish を初期化前に参照していた。initGrid()startGame() で呼ばれるため、タイトル画面の時点では配列が undefined。1フレーム目でTypeErrorが起きてゲームループが即死していた。if(state !== 'playing') return の後ろにスカッシュ処理を移動して解決。
BUG 02
Vercel CLI でパス渡しがエラー
vercel <path> の形式はWindowsパスと相性が悪い。cd でディレクトリに移動してから vercel --prod を実行するのが正解。deploy.sh を修正した。
BUG 03
コンボがリセットされない
コンボは「ライン消去ができなかった手」でリセットすべきだが、clearLines() がラインなしで早期returnしていたためリセットされないケースがあった。else { combo = 0; } を明示的に追加して解決。

「ピンクの壁紙しか表示されないよ?」

Canvasの draw() が呼ばれていないのに drawBg() の結果(ピンクグラデ)だけが残っていた。原因は初期化順序バグという、ありふれているが見つけにくい種類の問題だった。3行直したら動いた。バグを修正前にプッシュしてしまったのは反省点。次からはローカル確認してからプッシュする。

INSIGHT

学びと発見

⚖️

著作権はビジュアルで回避できる

ゲームメカニクス(落下・積み重ね・ライン消去)自体は著作権で保護されない。ピースの形と視覚スタイルを変えれば法的にクリーンな独自ゲームになる。

🌊

暗い背景でブロックが映える

パステル背景では半透明ジェリーが埋もれる。ディープオーシャンブルーにしたとたん、ブロックが「浮き上がって」見えた。コントラストが透明感を引き出す。

📐

sin/cos の位相ずらしが肝

全セル同位相だと板が揺れるだけ。セルごとに位相をずらすと「ぷよぷよした生き物感」が出る。この差は実際に動かして初めてわかる。

🔥

フィーバーの閾値は低めに

コンボ5以上にすると高レベルでしか起きない。コンボ3以上にすることで序盤から体験できて「また狙おう」という気持ちが生まれる。

テトリスへのリスペクトを保ちながら、ジェリーという独自アイデンティティで別ゲームとして成立させた。制約がアイデアを生む、という体験。

SUMMARY

「ブルーハワイの感じで、プルプルしたジェリーブロックのゲームが欲しい」というリクエストから、1日でJellyBlocksを完成させた。著作権問題の回避がそのままゲームの個性になり、sin/cosの位相ずらしによるジェリー揺れ、着地スカッシュ、フルーツ7色ブロック、ジェリーマージ、コンボ&フィーバーモード、レベル別背景テーマ——ひとつひとつは地味でも、全部重なると「ちゃんと遊べるゲーム」になる。バグを3つ踏んで全部直した。バグを踏んで直すのがいちばん覚える。

ALL UEFN × Verse Lab Log