2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ゲームをプレイしていて「今のミス、なかったことにしたい!」と思ったことはありませんか?かつては不可能だったその願いを、現代の技術は「巻き戻し(リワインド)」という形で実現しています。

今回は、時間を巻き戻す技術の仕組みと、Nintendo Switchで採用されている技術との比較、そして実際に動くサンプルコードを交えて、その裏側を解説します。


1. コンピュータにおける「時間」の正体

現実の時間は一方向にしか進みませんが、コンピュータにとっての時間は**「データの状態」**の連続に過ぎません。

例えば、キャラクターが右に移動したとき、コンピュータの内部では「X座標:10」というデータが「X座標:11」に書き換わります。この「書き換わる前の値」を捨てずにどこかへ保存しておけば、それを呼び出すだけで、一瞬で過去に戻ることができます。

つまり、巻き戻し技術の本質は**「過去の状態のバックアップと復元」**なのです。


2. Nintendo Switchの「巻き戻し」はどう動いている?

Nintendo Switch Onlineのファミコンやスーパーファミコンのソフトで使える巻き戻し機能は、非常に強力な**「スナップショット方式」**を採用しています。

スナップショット方式とは

デジカメで写真を撮るように、ある瞬間の「メモリの内容すべて」を丸ごと保存する方法です。

  • Switchの仕組み: ゲーム機(エミュレータ)が、プレイヤーが遊んでいる裏側で、数フレーム(1秒の何十分の1)ごとのメモリの状態をビデオ録画のように記録し続けています。
  • メリット: どんなに複雑なゲームでも、確実にその瞬間に戻れます。
  • デメリット: 保存するデータ量が膨大になります。最新の豪華なグラフィックのゲームでこれをやると、一瞬でメモリが足りなくなってしまいます。

3. もうひとつの手法:「入力記録方式」

一方で、対戦格闘ゲームのリプレイやオンライン対戦などで使われるのが、**「入力記録方式(キーログ方式)」**です。

  • 仕組み: 「最初にどの地点にいたか」と、その後「いつ、どのボタンを押したか」という操作データだけを記録します。
  • メリット: 保存するデータが非常に小さくて済みます。
  • デメリット: 巻き戻す際に、最初から計算し直す(早送り再生する)必要があるため、一瞬で戻るのが難しく、計算が少しでもズレると過去が変わってしまうリスクがあります。

4. プログラミングで実装してみよう

では、JavaScriptを使って、簡単な「巻き戻し機能」を実装してみましょう。ここでは、理解しやすい「スナップショット方式」を採用します。

サンプルコード:キャラクターのタイムマシン

/**
 * 時間を管理するクラス
 */
class TimeMachine {
    constructor(limit = 100) {
        this.history = []; // 過去のデータを貯めるリスト
        this.limit = limit; // 何ステップ前まで覚えているか
    }

    // 今の状態を記録する
    record(state) {
        // オブジェクトをコピーして保存(参照を切るため)
        this.history.push({ ...state });

        // 記憶の限界を超えたら古いものを消す
        if (this.history.length > this.limit) {
            this.history.shift();
        }
    }

    // 1つ前の状態に戻す
    undo() {
        if (this.history.length <= 1) return null;
        
        // 現在の状態を捨てて、1つ前のデータを取り出す
        this.history.pop(); 
        return this.history[this.history.length - 1];
    }
}

// --- 実際の動かし方 ---

let player = { x: 0, hp: 100 }; // 今のプレイヤー
const machine = new TimeMachine();

// 移動するたびに記録
console.log("移動中...");
player.x = 10; machine.record(player);
player.x = 20; machine.record(player);
player.x = 30; machine.record(player); // ここでミス!

console.log(`ミスした時の位置: ${player.x}`);

// 巻き戻し実行
player = machine.undo();
console.log(`1回巻き戻した位置: ${player.x}`); // 20に戻る

player = machine.undo();
console.log(`2回巻き戻した位置: ${player.x}`); // 10に戻る

5. 技術的な課題:メモリとの戦い

このコードはシンプルですが、実際の製品レベルでは**「メモリの節約」**が最大の壁になります。

Switchの巻き戻し機能も、実は「過去数分間だけ」という制限があります。無限に過去を保存しようとすると、ゲーム機自体のメモリを使い果たしてしまうからです。

エンジニアは、以下のような工夫をしてこの課題に挑んでいます。

  • 差分保存: 「全部」を保存するのではなく、前回から「変わった場所だけ」を記録する。
  • 間引き: 1秒前は細かく記録し、10秒前は1秒おきに記録する、といった調整を行う。

6. まとめ:巻き戻しは「試行錯誤」を支える技術

時間を巻き戻す技術は、単にミスを帳消しにするためだけのものではありません。それは、プレイヤーが**「失敗を恐れずに新しいことに挑戦できる環境」**を作るためのものです。

  • Nintendo Switchは、レトロゲームの楽しさを現代に伝えるために、この強力な「やり直し魔法」を標準搭載しました。
  • プログラミングにおいては、データのバックアップと復元をいかに高速・軽量に行うかという知恵の結晶です。

次にあなたがゲームで巻き戻しボタンを押したとき、その裏側でコンピュータが必死に「過去の記憶」を掘り起こしている様子を想像してみてください。


比較まとめ

特徴 Nintendo Switch方式(スナップショット) 入力記録方式(リプレイなど)
戻り方 瞬時にその時点へジャンプ 操作を最初から再実行して再現
データ量 大きい(メモリ全体をコピー) 非常に小さい(ボタン操作のみ)
確実性 100%(絶対に同じ状態になる) わずかな計算誤差でズレる可能性あり
主な用途 巻き戻し機能、中断セーブ オンライン対戦、リプレイ動画

プログラミングの世界では、このように「何を実現したいか」によって、時間の扱い方も変わってくるのです。

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?