マガジン

画像を1枚も使わずにゲームを作ると何が変わるか:図形と文字だけの画面で見た目と速さを確かめる実験

遊びをつくる

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

ゲームを実際に動かしながら、下書きの説明カードを鉛筆で確かめる手元。
記事のテーマをもとに制作したAI生成の写真風イメージ。

画像ファイルを一切使わず、円・四角・線・文字だけでゲーム画面を組むと、見た目と動作の速さはどう変わるのでしょうか。「素材がないぶん軽くなる」「素っ気なくなる」といった予想は立てやすい一方で、本当にそうなるかは、自分の画面と自分のゲームで測らないと分かりません。この記事は、その答えを自分で出すための実験の設計書です。結果は書きません。 問いは二つに分けられます。一つは見た目の問いで、図形と文字だけで、プレイヤーに「何をすればよいか」と「今どうなっているか」がどこまで伝わるかです。もう一つは速さの問いで、コードで毎フレーム描く方式と、一度描いた結果を使い回す方式とで、描画にかかる時間がどう違うかです。 たとえば、小さなシューティングを作る場面を考えてみます。敵を三角形、弾を細い線、得点を文字で表すとします。このとき、敵が数十体に増えても滑らかに動くのか、遠目に見て敵と弾を区別できるのかが気になります。この二点を、記録の取り方まで決めて確かめます。

この記事の目次
  1. 問いを二つに分けて仮説を立てる
  2. 準備するもの
  3. 速さを測る手順
  4. 見た目を確かめる手順
  5. 結果の読み方
  6. 起こりやすい誤り
  7. 次の行動

問いを二つに分けて仮説を立てる

実験の前に、結果の読み方を決めておくための仮説を書き出します。

  • 見た目の仮説:図形の色・大きさ・動きだけで、味方と敵と得点の区別がつく。
  • 速さの仮説:同じ見た目なら、毎フレーム図形と文字を描く方式より、描いた結果を別のキャンバスに保存して貼る方式のほうが、描画命令にかかる時間は短い。

速さの仮説は、実際には外れることもあります。図形が単純なら毎回描いても差が出ないことがありますし、文字の描画は図形より重くなりやすいので、文字の量に左右される可能性もあります。外れたらそのこと自体が結果です。仮説は紙に書いて残しておきます。

ここでいう「画像を使わない」とは、PNGやJPEGなどの画像ファイルを読み込まないという意味です。速さの比較に使う「描いた結果を別のキャンバスに保存して貼る」方式は、画像ファイルを使わずに実現できるので、この制約の中の選択肢として扱います。

準備するもの

  • パソコンのブラウザ。できれば普段ゲームを遊ぶ環境と、性能が低めの端末(古いスマートフォンなど)の両方。
  • テキストエディタ。下のコードを index.html として保存します。外部ライブラリもサーバーも不要です。
  • 記録用の表。列は「端末、ブラウザ、方式、個数、フレーム間隔の平均、フレーム間隔の最大、描画命令の平均」にします。
  • 見た目の確認用に、画面を見せられる人が2〜3人。いなければ、自分が時間を置いて見直す方法でも構いません。

速さを測る手順

次の最小構成は、同じ見た目の図形と文字を N 個動かし、300フレームごとに計測値を表示します。1 キーで毎フレーム直接描画、2 キーで保存した結果の貼り付け、上下キーで個数を100ずつ増減します。

html
<!doctype html>
<meta charset="utf-8">
<canvas id="c" width="640" height="360"></canvas>
<pre id="o">1:直接 2:貼り付け ↑↓:個数</pre>
<script>
const g=c.getContext('2d');
let N=200,mode='direct',items=[],log=[],last=performance.now();
const sp=document.createElement('canvas');
sp.width=sp.height=32;
function shape(ctx,x,y){
  ctx.fillStyle='#f6c';ctx.beginPath();
  ctx.arc(x,y,10,0,6.283);ctx.fill();
  ctx.fillStyle='#fff';ctx.font='14px sans-serif';
  ctx.textAlign='center';ctx.textBaseline='middle';
  ctx.fillText('星',x,y);
}
shape(sp.getContext('2d'),16,16);
function make(){
  items=[];
  for(let i=0;i<N;i++)items.push({x:Math.random()*640,y:Math.random()*360,
    vx:Math.random()*2-1,vy:Math.random()*2-1});
  log=[];
}
function report(){
  const d=log.slice(30);
  const avg=a=>a.reduce((s,v)=>s+v,0)/a.length;
  const f=d.map(v=>v[0]),w=d.map(v=>v[1]);
  o.textContent=`mode=${mode} N=${N}\nフレーム間隔 平均${avg(f).toFixed(1)}ms 最大${Math.max(...f).toFixed(1)}ms\n描画命令 平均${avg(w).toFixed(2)}ms`;
  log=[];
}
function frame(now){
  const dt=now-last;last=now;
  const t0=performance.now();
  g.fillStyle='#123';g.fillRect(0,0,640,360);
  for(const p of items){
    p.x=(p.x+p.vx+640)%640;p.y=(p.y+p.vy+360)%360;
    if(mode==='direct')shape(g,p.x,p.y);else g.drawImage(sp,p.x-16,p.y-16);
  }
  log.push([dt,performance.now()-t0]);
  if(log.length>=330)report();
  requestAnimationFrame(frame);
}
addEventListener('keydown',e=>{
  if(e.key==='1')mode='direct';
  if(e.key==='2')mode='cache';
  if(e.key==='ArrowUp')N+=100;
  if(e.key==='ArrowDown')N=Math.max(100,N-100);
  make();
});
make();requestAnimationFrame(frame);
</script>

このコードは、画面に出る数値を2種類に分けています。「フレーム間隔」は、前のフレームから次のフレームまでの時間です。「描画命令」は、描く指示をブラウザに出し終えるまでの時間です。最初の30フレームは捨てて、残りを集計します。

測る条件の決め方

個数は、100、300、500、1,000、2,000のように段階を取ります。方式は2種類なので、1端末あたり10条件になります。各条件で、表示が出るたびに値を記録します。1条件につき最低3回、条件の切り替えを挟んで測ります。切り替えるたびに計測がリセットされるので、同じ条件で3回の表示を待てば足ります。

同じ端末では、他のタブやアプリを閉じ、電源に接続した状態にそろえます。ノートパソコンは省電力モードの影響を受けやすいので、設定を記録しておきます。

見た目を確かめる手順

速さの実験と並行して、見た目の実験を行います。ここでは、同じ画面を図形と文字だけで組んだ版を用意します。

  1. 画面に必ず必要な情報を3〜5個書き出します。例は、自機の位置、危険なもの、得点、残り時間、次にすべきことです。
  2. 各情報を、形・色・大きさ・動き・文字のうち、どれで伝えるかを決めます。一つの情報に対して手段を二つ以上割り当てると、色の見分けにくい人にも届きやすくなります。
  3. 人に画面を5秒だけ見せ、画面を隠してから「何が見えたか」「次に何をするか」を聞きます。いなければ、自分で時間を空けて同じことをします。
  4. 答えを、書き出した情報ごとに「言えた/言えなかった」で記録します。人数が少ないので、割合ではなく一覧のまま扱います。

質問は誘導しない形にします。「赤い三角が敵ですよね」ではなく、「この三角は何だと思いますか」と尋ねます。

結果の読み方

速さの結果

まず、個数を増やしたときに、フレーム間隔の平均がどこから伸び始めるかを見ます。ここで見るのは、方式ごとの「伸び始める個数」です。画面のリフレッシュレートが60Hzなら、1フレームは約16.7msが目安です。120Hzの画面ならその半分になるので、自分の端末の値に合わせて読みます。

読み方の目安は次のとおりです。

  • 二つの方式で「伸び始める個数」が大きく違う:その端末では、保存した結果を貼る方式が効いています。
  • ほぼ同じ:図形と文字の量が少ないか、ほかの処理が支配的です。無理に方式を変える必要はありません。
  • 平均は同じでも最大値が大きく跳ねる:ブラウザの処理が一時的に滞っています。滑らかさの印象はこちらで決まるので、平均だけで判断しません。
  • 描画命令の平均は小さいのにフレーム間隔が伸びる:命令を出し終えた後の処理が重い可能性があります。描画命令の時間は、実際の描画が終わるまでの時間ではない点に注意します。

端末ごとの差も重要です。性能の高い端末で差が出なくても、低い端末で出ることがあります。表には端末ごとの列を残し、最も弱い端末で許容できるかを基準にします。

見た目の結果

必要な情報が「言えなかった」場合は、その情報の伝え方を変えます。形・色・大きさ・動き・文字のどれか一つを足して、もう一度確かめます。全員が言えた情報は、削っても伝わるかどうかを試す候補になります。

「何をすればよいか」が伝わっていなければ、図形の工夫より先に、短い文字の指示を足すほうが早いことがあります。文字も、この制約の中で使える強い手段です。

起こりやすい誤り

  • フォントの違いを見落とす:文字はOSやブラウザ既定のフォントで描かれるため、環境によって幅や見え方が変わります。確認は複数の環境で行い、文字の位置が崩れる場合は余白に余裕を持たせます。
  • 描画命令の時間だけを見る:命令を出し終えた時間と、画面に反映された時間は別物です。フレーム間隔の数値とセットで読みます。
  • 最初の数十フレームを含める:起動直後は処理が安定しません。コードは30フレームを捨てていますが、端末によっては足りないことがあるので、条件を変えた直後の値は参考扱いにします。
  • 条件を同時に変える:個数と方式を一度に変えると、どちらの影響か分からなくなります。一つずつ変えます。
  • 一度の計測で決める:表示の値は揺れます。同じ条件で3回以上測って、ばらつきも見ます。
  • 画像を使わないこと自体を目的にする:この実験は、制約が見た目と速さに何をもたらすかを知るためのものです。画像を使えば伝わる場面を、無理に図形で置き換える必要はありません。

アソバースに投稿する場合は、直下の index.html が入口になり、アップロードは20MiB以内という上限があります。画像を使わない作品は、素材の相対パスを気にする必要が減ります。ただし、サイズが小さいことと画面が速いことは別の話です。公開前の「表示の確認」の段階で、実際の表示を確かめてください。

次の行動

上のコードを index.html に保存し、自分の端末で個数と方式を変えて、まず1端末分の表を埋めてください。その後、いま作っているゲームの画面を図形と文字だけで描き直し、必要な情報を3つ書き出して、人に5秒見せる確認まで進めてみましょう。記録した表と仮説を見比べれば、次に図形で続けるか、画像を足すかを自分の数字で決められます。