ブロック崩しの反射角は、どうやって操作に変えているか
遊びを見つける執筆にClaudeを使用しています。

ブロック崩しで、バーの右端ぎりぎりでボールを受けると、ボールは右へ鋭く飛んでいきます。中央で受ければ、ほぼ真上に戻ります。慣れた人は、これを使って「あのブロックの列を狙う」と決めてからバーを動かします。ところが、画面のどこにも「当たった位置で角度が変わります」とは書かれていません。 壁やブロックでの反射は、物理の感覚どおりで説明がつきます。バーだけは、物理とは別のルールが入っているように見えます。この記事では、そのルールが何をしているのかを、遊ぶ人が自分で数えて見分けられる手順にします。あわせて、作る人が最小のコードで再現できる形も示します。結果の数値は書きません。確かめるのは、読者が手元の作品で行う観察です。
純粋な反射なら、バーの位置は関係ない
まず比較の基準を決めます。平らな面にボールが当たり、跳ね返るとき、素直な計算は「面に垂直な向きの速度だけを反転する」ことです。バーは水平なので、縦方向の速度の符号を変えるだけです。
- 縦の速度 vy は、上向きと下向きが入れ替わります。
- 横の速度 vx は、そのまま残ります。
この方式では、バーのどこに当たっても出ていく角度は入ってきた角度の鏡像です。右上から来たボールは右上へ、左上から来たボールは左上へ戻ります。プレイヤーが角度を変える手段は「当たる前の軌道を読む」ことだけです。バーの位置は、当たるか外れるかを決めるだけの役割になります。
多くのブロック崩しがこの方式のままだと、同じ軌道がずっと続きます。壁とブロックの反射だけでは、プレイヤーが狙う余地が小さいのです。そこで、バーに当たる瞬間だけ「どこに当たったか」を角度に反映する設計がよく使われます。これが題名の「見えないルール」の正体です。
位置を角度に変える最小の式
定番の考え方は、三つの手順で説明できます。
- 当たった位置を、バーの中心からのずれとして求め、−1〜+1に正規化します。左端が−1、中央が0、右端が+1です。式は hit = (ボールのx − バー中心のx) ÷ (バー幅 ÷ 2) です。
- その値に「最大角度」をかけて、出ていく角度にします。たとえば最大角度を60度にすれば、右端では垂直から右へ60度、中央では0度です。
- 速さは一定のまま、角度から速度成分を作ります。vx = 速さ × sin(角度)、vy = −速さ × cos(角度) です。
これは設計の一例で、すべての作品がこのとおりに作られているわけではありません。ただ、この形にはよくある利点が三つあります。
- 出ていく角度が、入ってきた角度に依存せず、当たった位置だけで決まります。操作と結果が一対一になり、プレイヤーが覚えやすくなります。
- 最大角度を決めておけば、水平に近い角度になりすぎません。水平に近いと縦の進みが遅く、ボールがいつまでも往復して退屈になります。
- 速さを一定に保てるため、角度を変えても難易度が勝手に上がりません。
一方、別の作り方もあります。出ていく角度を上書きせず、今の横速度に位置の影響を足す方法です。バーの動く速さをボールに加える「スピン」の方式もあります。どれを採っているかは、外から見るだけでは分かりません。次の節の記録で見分けます。
自分の遊ぶ作品で確かめる記録の取り方
ブロック崩しを一つ選び、バーに当たる場面を記録します。コードが見られない作品でも、観察だけで型の見当がつきます。
準備するもの
- 遊ぶ作品(ブラウザで動くもので構いません)
- スマートフォンの録画、またはスクリーン録画。可能ならスロー再生できる形式
- 下の表を書き写した紙か表計算シート
区画に分けて数える
バーを左右に5等分し、当たった区画を番号で記録します。左端から1、2、3(中央)、4、5です。バーに目印がなければ、録画を止めて、ボールの中心がどの区画の上にあるかで判断します。
1回の当たりごとに、次の4項目を書きます。
- 当たった区画、記録のしかた:1〜5
- 入ってくる向き、記録のしかた:左上から/右上から/ほぼ真上から
- 出ていく向き、記録のしかた:左へ/右へ/ほぼ垂直
- 出ていく浅さ、記録のしかた:水平に近い/中間/垂直に近い
あわせて、「バーが動いていたか(左へ/右へ/止まっていた)」と、「出た後の速さが変わったように見えたか(はい/いいえ)」も書きます。速さは見た目の印象になるので、後で扱いを説明します。
回数の目安は、区画ごとに最低5回です。5区画で25回、入ってくる向きを分けるなら50回です。ボールの動きに慣れてくると偏りが出るため、狙った区画に当てる意識で、わざとバラけさせます。1区画ずつ「今回は区画4で受ける」と決めて練習すると、記録が偏りません。
記録を読んで型を見分ける
記録が揃ったら、次の問いで型を見分けます。結果は読者自身の記録から読み取ります。
- 同じ区画なら、入ってくる向きが違っても出ていく向きと浅さが同じ。 角度を位置だけで決める「上書き型」の可能性が高くなります。
- 同じ区画でも、入ってくる向きで出ていく向きが変わる。 位置の影響を元の横速度に足す「加算型」や、純粋な反射に位置の補正を加えた型の可能性があります。
- 同じ区画で、バーが動いていたときと止まっていたときに出方が違う。 バーの移動をボールに伝える「スピン型」の可能性があります。
- どの区画でも、出ていく向きが入ってきた向きの鏡像。 バーの位置は角度に反映されていません。純粋な反射です。
- 中央付近では垂直に近く、端ほど浅い。 上書き型や加算型の多くで見られる並びです。ただし、この並び自体は型を区別しません。
速さの変化は、見た目の印象が当てになりにくい項目です。角度が浅いと、画面上の横の動きが目立ち、速くなったように感じます。確かめるなら、録画をコマ送りにして、ボールが一定コマ数で動く距離を、当たる前と後で比べます。1コマの移動距離を、斜めの長さで比べるのがコツです。縦だけ、横だけで比べると、角度の変化と速さの変化が混ざります。
試作で確かめる
型の違いは、手を動かすと実感できます。下は、「上書き型」と「純粋な反射」を切り替えられる最小のバーとボールです。HTMLファイル1つで動きます。マウスやタッチでバーを動かし、バーに当たるたびに、ブラウザの開発者ツールのコンソールに位置と速度が出ます。
<canvas id="c" width="320" height="400" style="background:#123;touch-action:none"></canvas>
<p><button id="m">mode: angle</button></p>
<script>
const c=document.getElementById('c'),g=c.getContext('2d');
const P={x:130,y:380,w:60,h:8},MAX=Math.PI/3,S=4;
let mode='angle',B;
function serve(){B={x:160,y:300,vx:2,vy:-3.4,r:5};}
serve();
c.onpointermove=e=>{const r=c.getBoundingClientRect();
P.x=Math.max(0,Math.min(c.width-P.w,e.clientX-r.left-P.w/2));};
document.getElementById('m').onclick=e=>{
mode=mode==='angle'?'mirror':'angle';e.target.textContent='mode: '+mode;};
function step(){
B.x+=B.vx;B.y+=B.vy;
if(B.x<B.r||B.x>c.width-B.r)B.vx=-B.vx;
if(B.y<B.r)B.vy=-B.vy;
if(B.vy>0&&B.y+B.r>=P.y&&B.y+B.r<=P.y+P.h+B.vy&&B.x>=P.x&&B.x<=P.x+P.w){
const hit=(B.x-(P.x+P.w/2))/(P.w/2);
if(mode==='angle'){const a=hit*MAX;B.vx=S*Math.sin(a);B.vy=-S*Math.cos(a);}
else B.vy=-B.vy;
console.log(mode,'hit='+hit.toFixed(2),'vx='+B.vx.toFixed(2),'vy='+B.vy.toFixed(2));
}
if(B.y>c.height)serve();
}
function draw(){
g.clearRect(0,0,c.width,c.height);g.fillStyle='#fc6';
g.fillRect(P.x,P.y,P.w,P.h);
g.beginPath();g.arc(B.x,B.y,B.r,0,7);g.fill();
}
(function loop(){step();draw();requestAnimationFrame(loop);})();
</script>試すときの観点は三つあります。
- angle モードで、バーの端と中央で受け、コンソールの hit と vx の対応を見ます。hit の符号と vx の符号が、どう対応するかを確かめます。
- ボタンで mirror に切り替え、同じ位置で受けます。hit を変えても、vx が変わらない様子を確認します。
- MAX の値を小さく、また大きく書き換え、端で受けたときの軌道の浅さと、ゲームの進みやすさの変化を観察します。
自分の記録表と同じ観察項目を、このコードの動きに当てはめてみてください。見分けのルールが実感できます。
起こりやすい誤り
観察と実装のどちらにも、つまずきやすい点があります。
- 区画の境界で迷う。 境界上の当たりは、記録から外すか、迷った旨を印にします。無理に振り分けると、型の判定が崩れます。
- 側面への当たりを混ぜる。 ボールがバーの端の横から当たる場面は、別の反射処理が働く作品もあります。上面に当たった記録だけを使います。
- バーを動かしながら受ける。 スピン型の疑いがあるときは、止まって受けたものと分けて記録します。混ぜると、区画の影響とバーの動きの影響が区別できません。
- ブロックとの同時衝突を含める。 バーの直後にブロックに当たると、出ていく向きの観察がずれます。バーを離れてすぐの動きだけを見ます。
- 中央ばかり当てる。 実際のプレイでは中央付近に当たりが集中しがちです。端の記録は意識して取らないと足りなくなります。
- コードで中心を取り違える。 実装では、ボールの中心とバーの中心を基準に計算します。左端を基準にすると、角度の左右が非対称になります。
次の行動
まず、よく遊ぶブロック崩しを1つ選び、5区画×5回の記録表を作ってみてください。25回の当たりを記録すれば、その作品が位置を角度に変えているか、どの型に近いかが読み取れます。自分で作る側に回りたい場合は、上のコードの MAX や S を変えて、遊びやすさの変化を確かめるところから始められます。
アソバースでは、HTMLやZIPをアップロードして作品を公開できます。直下の index.html が入口になるので、上の最小コードを育てた作品を投稿する流れも取れます。角度と初速を決めて軌道を狙う公式作品「小さな軌道」も、操作を軌道に変える別の例として、遊びながら見比べられます。

