子供たちを呼べるようなブース企画、その2はコンピューターゲームです。それも宇治川商店街を舞台にしたゲームを作ろうということになりました。
制作過程は後にして、まずは完成品を示します。下のリンクを開くと実際にゲームができます。(音が出るので注意してください)
また、こちらはお祭り当日、子供たちが実際に遊んでいる様子です。パソコンのキーボードではなくフットペダルで操作しています。
ゲームの背景は宇治川商店街に実在するお店になっています。お店の名前は予備調査に行ったときに歩き回って調べました。

集めるアイテムは宇治川音楽祭に関係した音符としました。回復アイテムは食堂「こふじ」の大盛ごはんです。じゃまをする敵キャラは、港町神戸ということでカモメにしました。

歩く人はウサギにしたかったのですが、お祭りの日には間に合いませんでした。
特別なインストールをしなくても、ブラウザさえ開けばパソコンでもスマホでも、iPhoneでもAndoroidでも動くよう、プログラムはJavaScriptで書きました。
"enchant.js"という、ループ処理やスプライト処理を補助するライブラリを使用しています。
// メルカロード GOGO! enchant(); window.onload = function() { // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ // 定数・変数 // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ // 定数 var screenWH = 320; // ゲーム画面の幅=高さ var btnW = 100; // スタートボタン等の幅 var btnH = 24; // スタートボタン等の高さ var btnY = 286; // ボタンのY位置 var btnRX = 210; // 右側のボタンのX位置 var btnLX = 10; // 左側のボタンのX位置 var btnF = 0; // ボタンのフラグ var pnlH = 36; // 操作パネルの高さ var pnlBtnWH = 28; // 操作パネルのボタンの幅=高さ var pnlBtnMgn = 4; // 操作パネルのボタンのマージン(XY) var pnlMsgH = 18; // 操作パネルのメッセージの高さ var pnlMsgMgn = 8; // 操作パネルのメッセージのマージン(Y) var tlpH = 42; // テロップ(クリア、ゲームオーバー等)の高さ var tlpY = 80; // テロップ(クリア、ゲームオーバー等)のY位置 var sttX = 0; // ステータス表示枠のX位置 var sttY = 0; // ステータス表示枠のY位置 var initHitPoint = 100; // ヒットポイントの初期値(100) var initGetItem = 0; // 取得アイテム数の初期値(0) var initExpGetLostWait = 50; // アイテムゲット/ロスト表現の表示時間 var initExpDamageWait = 10; // ダメージ表現の表示時間 var expWH = 32; // ゲット/ロスト/ダメージ表現の幅=高さ var expHideXY = -32; // ゲット/ロスト/ダメージ表現を隠す時のXY位置 var initSpeed = 5; // 歩く速度(Speed=1、Angle=0.125) var initMeX = 10; // 自分のX 初期値 var initMeY = 250; // 自分のY 初期値 var initMeFNum = 8; // 自キャラのアニメの構成コマ数 var initMeFWait = 2; // 何フレームで次のコマに切り替えるか(=表示ウェイト) var initKamomeDamage = 10 // カモメにあたった時のダメージ var initKamomeFNum = 5; // カモメのアニメの構成コマ数 var initKamomeFWait = 6; // 何フレームで次のコマに切り替えるか(=表示ウェイト) var initKamomeSpdA = 5; // カモメの落下速度生成のパラメーター1 スピードの差異の幅 var initKamomeSpdB = 3; // カモメの落下速度生成のパラメーター2 底上げ var initKamomeNum = 6; // カモメの数 var initKamomeInterval = 36; // カモメのX方向の発生間隔。32だと窮屈。36より大きいと安全圏ができてしまう var initKamomeSafety = 64; // カモメのXオフセット。ゲーム開始早々にぶつかることを防ぐ。 var initItemX = 288; // アイテムの出現位置X。Yは 288-(288*initAngle/initSpeed)で算出 var initItemRatio = 640; // アイテムの出現確率 // 変数(ここでは宣言のみ) var HitPoint = 0; // ヒットポイント(初期値 initHitPoint) var GetItem = 0; // 取得アイテム数(初期値値 initGetItem) var cntExpGetLostWait = 0; // アイテムゲット/ロスト表現の表示時間カウンタ var cntExpDamageWait = 0; // ダメージ表現の表示時間カウンタ var cntMeFWait = 0; // ウェイトのカウント用 var cntMeFNum = 0; // 表示コマのカウント用 var flgMeMove = 0; // 前進フラグ。画面タッチ中は 1 var flgTouchOn = 0; // タッチで前進させたとき立てる。これが立っている間、キー入力無効 var flgKeyOn = 0; // 右カーソルキーで前進させていた時立てる。これが立っている間、クリア画面やゲームオーバー画面のキー入力無効。解除には一度キーを離す var sprKamome = new Array(); // カモメのスプライト管理の配列 var cntKamomeFNum = new Array(); // カモメのアニメのコマカウントの配列 var cntKamomeFWait = new Array(); // カモメのアニメのコマウェイトの配列 var ItemType = 0; // いま落ちているアイテムの種類。0なら得点アイテム、1なら回復アイテム。 // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ // ゲームオブジェクトの生成と設定 // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ var game = new Game(screenWH, screenWH +pnlH); game.fps = 30; // 素材ファイルのパス指定 var pnlBack = "common/pnl_back.png"; // パネル背景 var pnlBtns = "common/pnl_btns.png"; // パネルに置くボタン var imgTelops = "common/img_telops.png"; // クリアやゲームオーバーの文字(共通) var imgBtns = "common/img_btns.png"; // スタートボタンや戻るボタン、その選択枠など(共通) var seGameStart = "common/se_game_start.mp3"; // ゲームスタートの音楽(共通) var seGameClear = "common/se_game_clear.mp3"; // クリアの音楽(共通) var seGameOver = "common/se_game_over.mp3"; // ゲームオーバーの音楽(共通) var imgSttFrame = "common/img_status_frame.png"; // ステータス表示のフレーム var imgSttHP = "common/img_status_hp.png"; // ステータス表示のグラフ(HP) var imgSttItem = "common/img_status_item.png"; // ステータス表示のグラフ(アイテム) var chrExps = "common/chr_exps.png"; // +1、-1、衝突などの表現 var seItemGet = "common/se_item_get.mp3"; // 効果音 アイテムゲット var seItemLost = "common/se_item_lost.mp3"; // 効果音 アイテムロスト var seDamage = "common/se_damage.mp3"; // 効果音 ダメージ var imgTitle = "ujk/img_title.png"; // タイトル画像 var imgBack = "ujk/img_back.png"; // ゲームの背景画像 var imgRoad1 = "ujk/img_road1.png"; // 道1 var imgRoad2 = "ujk/img_road2.png"; // 道2 var pnlMsgs = "ujk/pnl_msgs.png"; // パネルに出すメッセージ var chrMe = "ujk/chr_me.png"; // 自キャラ var chrKamome = "ujk/chr_kamome.png"; // カモメ var chrItem = "ujk/chr_item.png"; // 得点アイテム・回復アイテム var seStep2 = "ujk/se_step1.mp3"; // 足音(高) var seStep1 = "ujk/se_step2.mp3"; // 足音(低) var seRecovery = "ujk/se_recovery.mp3"; // リカバリー音 // 素材ファイルの読み込み game.preload(pnlBack, pnlBtns, imgTelops, imgBtns); game.preload(seGameStart, seGameClear, seGameOver); game.preload(imgSttFrame, imgSttHP, imgSttItem, chrExps); game.preload(seItemGet, seItemLost, seDamage); game.preload(imgTitle, imgBack, imgRoad1, imgRoad2, pnlMsgs); game.preload(chrMe, chrKamome, chrItem, seStep1, seStep2, seRecovery); game.onload = function() { // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ // タイトル画面の生成と設定 // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ var scnTitle = new Scene(); // タイトル画像 var sprTitle = new Sprite(screenWH, screenWH +pnlH); sprTitle.image = game.assets[imgTitle]; sprTitle.x = 0; sprTitle.y = 0; // スタートボタン var sprBtnStart = new Sprite(btnW, btnH); sprBtnStart.image = game.assets[imgBtns]; sprBtnStart.frame = 0; sprBtnStart.x = btnRX; sprBtnStart.y = btnY; var sprBtnStartF = new Sprite(btnW, btnH); sprBtnStartF.image = game.assets[imgBtns]; sprBtnStartF.frame = 3; sprBtnStartF.x = btnRX; sprBtnStartF.y = btnY; sprBtnStartF.opacity = 0.5; // 戻るボタン(タイトル画面) var sprBtnHome1 = new Sprite(btnW, btnH); sprBtnHome1.image = game.assets[imgBtns]; sprBtnHome1.frame = 1; sprBtnHome1.x = btnLX; sprBtnHome1.y = btnY; var sprBtnHome1F = new Sprite(btnW, btnH); sprBtnHome1F.image = game.assets[imgBtns]; sprBtnHome1F.frame = 3; sprBtnHome1F.x = btnLX; sprBtnHome1F.y = btnY; sprBtnHome1F.opacity = 0.5; // スプライトの追加 scnTitle.addChild(sprTitle); scnTitle.addChild(sprBtnStart); scnTitle.addChild(sprBtnStartF); scnTitle.addChild(sprBtnHome1); scnTitle.addChild(sprBtnHome1F); // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ // タイトル画面のタッチイベント // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ // タッチスタートイベント▼ scnTitle.addEventListener('touchstart', function(touch) { // スタートボタンが押された if (touch.y > btnY && touch.x > btnRX) { sprBtnStartF.opacity = 1; btnF = 1; } // 戻るボタンが押された if (touch.y > btnY && touch.x < btnLX +btnW) { sprBtnHome1F.opacity = 1; btnF = -1; } }); // タッチエンドイベント▼ scnTitle.addEventListener('touchend', function(touch) { // スタートボタンが押されていて、それを離した if (touch.y > btnY && touch.x > btnRX && btnF == 1) { sprBtnStartF.opacity = 0.5; btnF = 0; // ゲームの変数やプロパティの初期化 scnPlayInit(); // プレイ画面(scnPlay)に切り替え var sound = game.assets[seGameStart].clone(); sound.play(); game.replaceScene(scnPlay); } // 戻るボタンが押されていて、それを離した if (touch.y > btnY && touch.x < btnLX +btnW && btnF == -1) { window.location.href = "../info.html"; // home.htmlに戻る } // 押したボタンから指が外れた sprBtnStartF.opacity = 0.5; sprBtnHome1F.opacity = 0.5; btnF = 0; }); // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ // タイトル画面のキー入力イベント // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ scnTitle.addEventListener(Event.ENTER_FRAME, function() { var input=game.input; if (input.right) { // ゲームの変数やプロパティの初期化 scnPlayInit(); // プレイ画面(scnPlay)に切り替え var sound = game.assets[seGameStart].clone(); sound.play(); game.replaceScene(scnPlay); } else if(input.left) { window.location.href = "../info.html"; // home.htmlに戻る } }); // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ // プレイ画面の変数やプロパティの初期化 // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ function scnPlayInit() { HitPoint = initHitPoint; // ヒットポイント初期化 GetItem = initGetItem; // 取得アイテム数初期化 sprSttHP.width = HitPoint; // ヒットポイントのグラフ設定 sprSttItem.width = GetItem*10; // 取得アイテム数のグラフ設定 sprExpGetLost.x = expHideXY; // アイテムゲット/ロスト表現のx位置。初期値は画面外。 sprExpGetLost.y = expHideXY; // アイテムゲット/ロスト表現のy位置。初期値は画面外。 cntExpGetLostWait = 0; // アイテムゲット/ロスト表現の表示時間カウンタ sprExpDamage.x = expHideXY; // ダメージ表現のx位置。初期値は画面外。 sprExpDamage.y = expHideXY; // ダメージ表現のy位置。初期値は画面外。 cntExpDamageWait = 0; // ダメージ表現の表示時間カウンタ // 自分スプライトのアニメーション初期化 cntMeFWait = 0; cntMeFNum = 0; // 道スプライト×2の位置の初期化 sprRoad1.x = 0; sprRoad1.y = 200; sprRoad2.x = 2000; sprRoad2.y = 200; // カモメスプライト位置やスピードなどの設定 for(var i=0; i0.2) { ItemType = 0;} else { ItemType = 1;} sprItem.frame = ItemType; sprItem.x = initItemX + Math.random()*initItemRatio; sprItem.y = 288; } // カモメが下まで落ちた場合 if (sprKamome[i].y > 320){ sprKamome[i].y = -32; sprKamome[i].speed = Math.random()*initKamomeSpdA + initKamomeSpdB; sprKamome[i].rotation = sprKamome[i].speed * -5 + 10; // 速度にあわせて角度設定 } } // 前進フラグが立っていたら、あれこれ動かす if (flgMeMove == 1) { // 道を動かす sprRoad1.x = sprRoad1.x -initSpeed; sprRoad1.y = sprRoad1.y; if (sprRoad1.x == -2000) { sprRoad1.x = 2000; sprRoad1.y = 200; } sprRoad2.x = sprRoad2.x -initSpeed; sprRoad2.y = sprRoad2.y; if (sprRoad2.x == -2000) { sprRoad2.x = 2000; sprRoad2.y = 200; } // アイテムを動かす sprItem.x = sprItem.x -initSpeed; sprItem.y = sprItem.y ; // アイテムの取得判定 if (sprMe.x + 32 > sprItem.x) { if (ItemType == 0) { // 得点アイテムだった場合 GetItem = GetItem + 1; sprSttItem.width = GetItem*10; sprExpGetLost.frame = 0; sprExpGetLost.x = 40; sprExpGetLost.y = 280; cntExpGetLostWait = initExpGetLostWait; // 10個集まったらクリアー画面へ if (GetItem == 10) { var sound = game.assets[seGameClear].clone(); sound.play(); game.pushScene(scnGameClear); } var sound = game.assets[seItemGet].clone(); sound.play(); } else { // 回復アイテムだった場合 HitPoint = 100; sprSttHP.width = HitPoint; // sprExpGetLost.frame = 1; // sprExpGetLost.x = 40; // sprExpGetLost.y = 240; cntExpGetLostWait = initExpGetLostWait; var sound = game.assets[seRecovery].clone(); sound.play(); } // アイテムを設置し直す。たまに回復アイテムを設置。 if (Math.random() > 0.2) { ItemType = 0;} else { ItemType = 1;} sprItem.frame = ItemType; sprItem.x = initItemX + Math.random()*initItemRatio; sprItem.y = 288; } // カモメを動かす for(var i=0; i 0) { cntExpGetLostWait = cntExpGetLostWait -1; if (cntExpGetLostWait == 0) { sprExpGetLost.x = expHideXY; sprExpGetLost.y = expHideXY; } } // ダメージ表現の表示 if (cntExpDamageWait > 0) { cntExpDamageWait = cntExpDamageWait -1; if (cntExpDamageWait == 0) { sprExpDamage.x = expHideXY; sprExpDamage.y = expHideXY; } } }); // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ // ゲームクリア画面 // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ var scnGameClear = new Scene(); // テロップ var sprGameClear = new Sprite(screenWH, tlpH); sprGameClear.image = game.assets[imgTelops]; sprGameClear.frame = 0; sprGameClear.x = 0; sprGameClear.y = tlpY; // もう一度ボタン var sprBtnRetry = new Sprite(btnW, btnH); sprBtnRetry.image = game.assets[imgBtns]; sprBtnRetry.frame = 2; sprBtnRetry.x = btnRX; sprBtnRetry.y = btnY; var sprBtnRetryF = new Sprite(btnW, btnH); sprBtnRetryF.image = game.assets[imgBtns]; sprBtnRetryF.frame = 3; sprBtnRetryF.x = btnRX; sprBtnRetryF.y = btnY; sprBtnRetryF.opacity = 0.5; // 戻るボタン(ゲームクリア画面) var sprBtnHome2 = new Sprite(btnW, btnH); sprBtnHome2.image = game.assets[imgBtns]; sprBtnHome2.frame = 1; sprBtnHome2.x = btnLX; sprBtnHome2.y = btnY; var sprBtnHome2F = new Sprite(btnW, btnH); sprBtnHome2F.image = game.assets[imgBtns]; sprBtnHome2F.frame = 3; sprBtnHome2F.x = btnLX; sprBtnHome2F.y = btnY; sprBtnHome2F.opacity = 0.5; // スプライトの追加 scnGameClear.addChild(sprGameClear); scnGameClear.addChild(sprBtnRetry); scnGameClear.addChild(sprBtnRetryF); scnGameClear.addChild(sprBtnHome2); scnGameClear.addChild(sprBtnHome2F); // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ // ゲームクリア画面のタッチイベント // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ // タッチスタートイベント▼ scnGameClear.addEventListener('touchstart', function(touch) { // もう一度ボタンが押された if (touch.y > btnY && touch.x > btnRX) { sprBtnRetryF.opacity = 1; btnF = 1; } // 戻るボタンが押された if (touch.y > btnY && touch.x < btnLX +btnW) { sprBtnHome3F.opacity = 1; btnF = -1; } }); // タッチエンドイベント▼ scnGameClear.addEventListener('touchend', function(touch) { // もう一度ボタンが押されていて、それを離した if (touch.y > btnY && touch.x > btnRX && btnF == 1) { sprBtnRetryF.opacity = 0.5; btnF = 0; // ゲームの変数やプロパティの初期化 scnPlayInit(); // プレイ画面(scnPlay)に切り替え game.popScene(); // ゲームオ-バー画面消去 var sound = game.assets[seGameStart].clone(); sound.play(); game.replaceScene(scnPlay); } // 戻るボタンが押されていて、それを離した if (touch.y > btnY && touch.x < btnLX +btnW && btnF == -1) { game.popScene(); // クリア画面消去 sessionStorage.setItem("ujk_flg", 1); // セッションストレージのこの区のフラグON window.location.href = "../info.html"; // home.htmlに戻る } // 押したボタンから指が外れた sprBtnHome2F.opacity = 0.5; btnF = 0; }); // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ // ゲームクリア画面のキー入力イベント // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ scnGameClear.addEventListener(Event.ENTER_FRAME, function() { var input=game.input; if (input.right && (flgKeyOn == 0)) { // ゲームの変数やプロパティの初期化 scnPlayInit(); // プレイ画面(scnPlay)に切り替え game.popScene(); // ゲームオ-バー画面消去 var sound = game.assets[seGameStart].clone(); sound.play(); game.replaceScene(scnPlay); } else if (input.right && (flgKeyOn == 1)) { } else if (input.left){ window.location.href = "../info.html"; // home.htmlに戻る } else { flgKeyOn = 0; } }); // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ // ゲームオ-バー画面 // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ var scnGameOver = new Scene(); // テロップ var sprGameOver = new Sprite(screenWH, tlpH); sprGameOver.image = game.assets[imgTelops]; sprGameOver.frame = 1; sprGameOver.x = 0; sprGameOver.y = tlpY; // もう一度ボタン var sprBtnRetry = new Sprite(btnW, btnH); sprBtnRetry.image = game.assets[imgBtns]; sprBtnRetry.frame = 2; sprBtnRetry.x = btnRX; sprBtnRetry.y = btnY; var sprBtnRetryF = new Sprite(btnW, btnH); sprBtnRetryF.image = game.assets[imgBtns]; sprBtnRetryF.frame = 3; sprBtnRetryF.x = btnRX; sprBtnRetryF.y = btnY; sprBtnRetryF.opacity = 0.5; // 戻るボタン(ゲームオ-バー画面) var sprBtnHome3 = new Sprite(btnW, btnH); sprBtnHome3.image = game.assets[imgBtns]; sprBtnHome3.frame = 1; sprBtnHome3.x = btnLX; sprBtnHome3.y = btnY; var sprBtnHome3F = new Sprite(btnW, btnH); sprBtnHome3F.image = game.assets[imgBtns]; sprBtnHome3F.frame = 3; sprBtnHome3F.x = btnLX; sprBtnHome3F.y = btnY; sprBtnHome3F.opacity = 0.5; // スプライトの追加 scnGameOver.addChild(sprGameOver); scnGameOver.addChild(sprBtnRetry); scnGameOver.addChild(sprBtnRetryF); scnGameOver.addChild(sprBtnHome3); scnGameOver.addChild(sprBtnHome3F); // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ // ゲームオ-バー画面のタッチイベント // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ // タッチスタートイベント▼ scnGameOver.addEventListener('touchstart', function(touch) { // もう一度ボタンが押された if (touch.y > btnY && touch.x > btnRX) { sprBtnRetryF.opacity = 1; btnF = 1; } // 戻るボタンが押された if (touch.y > btnY && touch.x < btnLX +btnW) { sprBtnHome3F.opacity = 1; btnF = -1; } }); // タッチエンドイベント▼ scnGameOver.addEventListener('touchend', function(touch) { // もう一度ボタンが押されていて、それを離した if (touch.y > btnY && touch.x > btnRX && btnF == 1) { sprBtnRetryF.opacity = 0.5; btnF = 0; // ゲームの変数やプロパティの初期化 scnPlayInit(); // プレイ画面(scnPlay)に切り替え game.popScene(); // ゲームオ-バー画面消去 var sound = game.assets[seGameStart].clone(); sound.play(); game.replaceScene(scnPlay); } // 戻るボタンが押されていて、それを離した if (touch.y > btnY && touch.x < btnLX +btnW && btnF == -1) { window.location.href = "../info.html"; // home.htmlに戻る } // 押したボタンから指が外れた sprBtnRetryF.opacity = 0.5; sprBtnHome3F.opacity = 0.5; btnF = 0; }); // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ // ゲームクリア画面のキー入力イベント // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ scnGameOver.addEventListener(Event.ENTER_FRAME, function() { var input=game.input; if (input.right && (flgKeyOn == 0)) { // ゲームの変数やプロパティの初期化 scnPlayInit(); // プレイ画面(scnPlay)に切り替え game.popScene(); // ゲームオ-バー画面消去 var sound = game.assets[seGameStart].clone(); sound.play(); game.replaceScene(scnPlay); } else if (input.right && (flgKeyOn == 1)) { } else if (input.left){ window.location.href = "../info.html"; // home.htmlに戻る } else { flgKeyOn = 0; } }); // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ // 実行 // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ game.pushScene(scnTitle); } game.start(); }
屋外で遊ぶのに、パソコンのキーボードで操作するのはせせこましいという意見から、フットペダルで操作してもらうことにしました。
しかしUSB接続のフットペダルは結構な値段がするので、HT82K629AというKBコントローラーチップを使って自作しました。ペダルを踏むと、USB接続のキーボードで[→]キーを押した状態をシュミレートします。

(こんなことをしなくても、マウスをこじ開けてクリックのスイッチにフットペダルからの配線をハンダ付けしてもよかったのですが、フットペダルが二台つながっていることからも想像がつくように、当初はもう少しいろんな操作ができるゲームを目指していたのです。この機械はその名残です。)