マガジン

加速のないレースゲームでは、コースの難しさは何で決まるか:一定速度だけの操作を試す

遊びを見つける

執筆にClaudeを使用しています。

一つだけ空いた場所へ、丸い駒を置こうとする初めての一手。
記事のテーマをもとに制作したAI生成の写真風イメージ。

レースゲームから加速とブレーキを取り除き、車は常に同じ速さで進み、操作は左右だけにする場面を考えてみます。ふつうのレースゲームでは、直線でアクセルを踏み込み、急カーブの手前で減速するという「速さの使い分け」がコースの面白さの大半を担っています。それを奪われると、コース作りは何を頼りに難しさを決めればよいのでしょうか。 この記事の仮説は、速度が固定されると「道の形」と「操作できる横の速さ」の比だけが難しさの骨格になる、というものです。さらに、同じ難しさの指標でもカーブが来る間隔(時間)が変わると体感が変わるのではないか、という点も確かめます。結果は書きません。数十行のコードを動かし、条件を一つずつ変えて、読者自身の手で答えを出すための設計書です。

この記事の目次
  1. 速度が固定されると、何が一つの式になるのか
  2. 準備:二十数行で動く最小のコース
  3. 手順:変えるのは一度に一つだけ
  4. 記録の取り方と結果の読み方
  5. 起こりやすい誤り
  6. 次の行動

速度が固定されると、何が一つの式になるのか

速度を一定値 v(1秒に進むピクセル数)にすると、画面上の「距離」と「時間」は比例します。10秒走る道は v×10 ピクセルの長さです。コースの長さを決めることと、プレイ時間を決めることが同じ操作になります。

もう一つ、道の形から必要な操作量が計算できます。道の中心線が左右にずれていく速さ(道の傾き)に v を掛けると、「車が追従するのに必要な横方向の速さ」になります。たとえば中心線が amp × sin(距離 × freq) という波形なら、傾きの最大値は amp × freq です。必要な横速度の最大値は v × amp × freq になります。

プレイヤーが出せる横移動の速さを side とすると、次の比 R が作れます。

R = v × amp × freq ÷ side

R が1を下回る設定は、道の中心線を原理的に追い続けられます。1を超える設定は、中心線への完全な追従はできません。ただし道には幅があるので、追従できないからといってすぐ脱線するとは限りません。その境目がどこに現れるかは、実際に走って確かめるところです。

もう一つの量は、カーブが来る間隔です。波形の一周期にかかる時間は T = 2π ÷ (v × freq) 秒です。R が同じでも、v と amp の組み合わせしだいで T は変わります。問いは次の二つです。

  1. R を上げていくと、走れる距離はどう変わるか。
  2. R を同じにして T だけを変えると、走れる距離は変わるか。

準備:二十数行で動く最小のコース

必要なものは、キーボードのあるパソコンとブラウザ、テキストエディタ、メモ用の表計算かノートです。次のコードを index.html として保存し、ブラウザで開きます。外部ライブラリは使わず、通信もしません。

html
<canvas id="c" width="320" height="480"></canvas>
<script>
const P={v:120,side:140,amp:40,freq:0.02,half:40};
const g=c.getContext('2d');
let d=0,x=160,k={},last=0,out=0,best=0,run=true;
onkeydown=e=>{k[e.key]=1;if(e.key==' '&&!run){d=0;x=160;run=true}};
onkeyup=e=>k[e.key]=0;
const cx=y=>160+P.amp*Math.sin(y*P.freq);
function step(t){
  const dt=Math.min((t-last)/1000,0.05);last=t;
  if(run){
    d+=P.v*dt;
    x+=((k.ArrowRight?1:0)-(k.ArrowLeft?1:0))*P.side*dt;
    if(Math.abs(x-cx(d))>P.half){run=false;out++;best=Math.max(best,d)}
  }
  g.fillStyle='#222';g.fillRect(0,0,320,480);
  g.fillStyle='#666';
  for(let s=0;s<480;s+=4)g.fillRect(cx(d+400-s)-P.half,s,P.half*2,4);
  g.fillStyle='#fc3';g.fillRect(x-6,400,12,16);
  g.fillStyle='#fff';
  g.fillText('距離 '+(d|0)+' / 最長 '+(best|0)+' / アウト '+out,8,16);
  if(!run)g.fillText('スペースで再開',110,240);
  requestAnimationFrame(step);
}
requestAnimationFrame(step);
</script>

操作は左右の矢印キーで、道の外へ出ると止まり、スペースで再開します。止まった瞬間の「距離」が、その走行の記録です。

設定値の意味は次のとおりです。

  • v:前進の速さ(ピクセル/秒)。加速も減速もなく、常にこの値です。
  • side:左右キーを押したときの横移動の速さ。
  • amp:道の蛇行の振れ幅。
  • freq:蛇行の細かさ。大きいほどカーブが短い間隔で来ます。
  • half:道の半幅。大きいほど余裕があります。

初期値の R は 120 × 40 × 0.02 ÷ 140 で約0.69、T は約2.6秒です。この計算は式から出る値で、走った結果ではありません。

手順:変えるのは一度に一つだけ

条件を二つ以上同時に動かすと、何が効いたのか分からなくなります。次の三つの実験を、それぞれ基準設定から一つだけ動かして行います。基準は初期値(v=120、side=140、amp=40、freq=0.02、half=40)です。

実験A:速度 v を変える

v を 80、120、160、200 に変えます。amp と freq は固定なので、R は v に比例して上がります(計算上は約0.46、0.69、0.91、1.14)。

実験B:道の幅 half を変える

half を 25、40、60 に変えます。R と T は変わらず、余裕だけが変わります。ここで R が1を超える設定(v=200)にも half を振ってみると、追従不能な道を幅がどこまで救うかが分かります。

実験C:R を揃えて、カーブの間隔 T だけを変える

この記事の中心の実験です。次の二組を比べます。

  • ゆったり、v:60、amp:80、freq:0.02、R(計算値):約0.69、T(計算値):約5.2秒
  • せわしない、v:120、amp:40、freq:0.02、R(計算値):約0.69、T(計算値):約2.6秒

どちらも必要な横速度の最大値は同じです。違うのは、同じ操作量を求められる場面が何秒おきに来るかという点です。「ゆったり」では amp が大きく、道が画面の端寄りまで振れます。見た目の印象も変わるので、記録とは別に感じたことをメモしておくと、後で読み返せます。

記録の取り方と結果の読み方

記録の単位と回数

1つの設定につき5走します。各走で止まった瞬間の「距離」を、設定名と走った順番と一緒に表へ書き込みます。最長の1回だけを残すのではなく、5回すべてを残します。人の操作にはばらつきがあり、平均より中央値(大きさ順に並べた3番目の値)のほうが外れた1回に引きずられにくいためです。

  • A: v=80、1走目:、2走目:、3走目:、4走目:、5走目:、中央値:

この道は同じ波形が繰り返されるので、乱数による走るたびの違いはありません。差が出るなら、それは設定の違いか操作の違いです。

結果の読み方

出た数字は、次の基準で読みます。

  • 実験A:R が上がるにつれて中央値が下がるなら、R が難しさの目安として働いています。R が1に届く前から中央値が大きく落ちる設定があれば、中心線を追う前提そのものが実際の操作に合っていません。人間がキーを押し直す手間や反応の遅れが効いている可能性があるので、side の実効値を疑います。
  • 実験B:幅を広げて中央値が伸びるなら、余裕がミスを吸収しています。R が1を超える設定でも幅しだいで長く走れるなら、傾きの最大値が続く時間が短いために中心線から外れ切らないのかもしれません。この点は断定せず、記録で確かめます。
  • 実験C:二組の中央値がほぼ同じなら、難しさは R で決まり、カーブの間隔は影響が小さいと読めます。差があるなら、同じ操作量でも要求の来る頻度が難しさを動かしています。どちらが難しいかは、予想を書いてから走ると、自分の直感との差も見えます。

差の大きさの目安は、5走のばらつき(最小と最大の幅)と比べます。二つの設定の中央値の差が、各設定の5走の幅より小さいなら、「差がある」と言い切らないでください。走る回数を増やして、もう一度比べます。

起こりやすい誤り

  • 慣れの混入:後に走る設定ほど有利になります。順序をくじ引きで決めるか、最初に走った基準設定を最後にもう一度走って、前後の差を確かめます。この差が設定間の差と同じくらい大きいなら、その実験は信頼できません。
  • キーの押し方のぶれ:矢印キーを連打すると、押しっぱなしとは違う操作になります。毎回押しっぱなしで操作する、という決め方で揃えます。
  • 画面の別タブ化:ブラウザは非表示のタブで描画を止めることがあります。走行中は表示したままにします。コードは一度に進む時間に上限(0.05秒)を設けています。そのため、処理が重いと画面上の進みが実際の時間より遅れることがあります。ほかのアプリを閉じて走ってください。
  • 車の幅を無視している:判定は車の中心点だけです。見た目では道に触れていても、アウトにならない場合があります。この条件は全設定で同じなので、比較には影響しませんが、結果を他の人と比べるときは前提として添えます。
  • R だけで難しさを語る:R は道の形と操作の速さの比にすぎません。道の幅、カーブの間隔、画面の見やすさは別の要因です。R が同じでも体感が違えば、それは実験Cで測りたい差が出ているということです。

次の行動

まず基準設定で5走し、表を埋めてから実験Aを始めてください。実験Cで差が見えたら、freq を自分で決めて、もう一組作ってみます。「ゆったり」と「せわしない」の間に、何秒おきのカーブなら気持ちよく走れる設定があるかを探すことが、加速のないレースゲームの設計そのものになります。

この HTML は外部通信を使わず、ファイルも1つなので、完成したらアソバースへ投稿することもできます。index.html をアップロードして内容を確認し、メールアドレスの確認が済めば公開できます。投稿画面の下書き保存を使えば、設定を変えた版を何本か用意して見比べることもできます。