Skip to content
xyspg
Go back

Socket.IOを用いた「指令ゲーム」の電子化実装

216
この記事はAIによって中国語から翻訳されました。 原文を見る
Socket.IOを用いた「指令ゲーム」の電子化実装

WebSocketベースのSocket.IOライブラリを使用して、私の所属する書院の伝統的なゲームである「指令ゲーム」を電子化したプロジェクトの紹介です。

前言

「指令ゲーム(Instruction Game)」は、私が所属する北大附中の書院で、毎年恒例となっている新入生オリエンテーションの伝統的なプロジェクトです。ルールは非常にシンプルです。ゲーム開始時、司会者が参加者全員に指令が書かれたカードをランダムに配布します。全員が自分の指令を順番通りに実行し、誰か一人でも間違えたら、ゲームは最初からやり直しになります。例えば:

カード1

大きな声で「皆さん注目してください、ゲームが始まりました」と叫ぶ

カード2

「ゲームが始まりました」という言葉を聞いた後、照明のスイッチを見つけて2回オンオフし、席に戻る

カード3

照明が2回オンオフされたら、左から3番目の同級生を誘って、円の中で一緒に3回ジャンプし、その同級生と一緒に席に戻る

とても簡単そうに聞こえませんか?最初、誰もがそう思いました。しかし、「間違い」の判定には、動作の間違い、順番の間違い、スムーズに繋がらなかった場合(明らかな詰まり)、そして誰かが喋ってしまうことが含まれます。

「指令ゲーム」の進行中、会場内は非常に静まり返り、全員が指令を実行している生徒を注視しています。このような重苦しいプレッシャーの中では、緊張のあまり動作をミスしたり、順番を忘れたりと、様々な事故(特に「右側にいる5人の同級生の名前を言う」という指令などは難関です)が起こりやすくなります。——そして、現実はその通りでした。私が「指令ゲーム」に参加した時は、たった1回のゲームを完遂するのに、午後いっぱい(4〜5時間)を費やしました。そして、新入生の代になっても、状況は改善されていませんでした。

否定できないのは、「指令ゲーム」はその活動内容を通じて、新入生同士がより親密になり、お互いを知るための興味深い手段であるということです。新入生間のチームワークを養い、いち早く集団に馴染ませることができます。また、精神を集中させ、自己をコントロールする能力を鍛えることもでき、これは附中での生活において非常に重要です。

附中での学習生活は非常に自律的であり、受け取る通知のすべてが極めて重要です。そのため、このゲームを通じて、指令の実行能力と厳格さを徐々に重視してほしいと考えています。今後の学園生活で受け取る指令は、課題であったり、通知であったり、あるいはチームでの協力作業であったりします。不注意や油断によって、チャンスを逃したり、成績を落としたり、さらには周囲からの信頼を失うことさえあるかもしれません。そのため、入学教育の期間中、先輩である私たちは、このゲームを通じて皆さんの仲を深めるだけでなく、活動から何かを学び、反省し、より良い附中生活を迎えてほしいと願っています。——『活動企画書』より

sit

実際のゲーム過程で私が気づいたのは、時間の大部分が「間違えた後の指令カードの回収と再配布」に浪費されているということでした。誰かが指令を間違えた後、先輩たちがカードを回収し、シャッフルして、配り直す。このプロセスに毎回およそ2〜3分かかります。この繰り返される2〜3分の待ち時間の間に、参加者の忍耐と情熱は次第に削られ、後半になるにつれてプレッシャーは増大し、全体の規律も緩み始めます。この焦燥感を伴う待ち時間が、「諦め」の感情を引き起こしてしまうのです。

ゲームが終わった時、多くの参加者が感じたのは、おそらく「達成感」や「集団としての名誉」よりも、むしろ「解放感」だったのではないでしょうか。

そこで、ユーザーエクスペリエンス(UX)のデザイン思考によって、このゲームを改善できないかと考えました。

ニールセンのユーザーインターフェース設計の法則(Nielsen’s Law of User Interface Design)によれば、ユーザーの忍耐力は1秒以上の待ち時間で低下し始め、10秒を超えると完全に失われる可能性があります。 したがって、ミスした後のリセットと指令の配布は、参加者の注意力とゲームの連続性を維持するために、可能な限り迅速に行われるべきです。電子化されたゲームは、その有効な解決策となるでしょう。

電子デバイスを通じて指令を配布することで、物理的なカードの回収や再配布にかかる待ち時間を削減し、参加者が指令の実行にエネルギーを集中できるようにします。さらに、電子システムならミスが発生した瞬間にリセットが可能で、待ち時間が発生しないため、参加者の不安感を和らげることもできます。

同時に、使いやすいユーザーインターフェースとインタラクションモードを設計することで、ゲームのルールや現在のステータスを一目で把握できるようにし、ゲームの流暢性とプレイアビリティを向上させます。このような設計は、ゲームの核心的な理念を維持しつつ、ゲーム体験を最適化し、参加者の情熱をより引き出し、チームワークや指令実行能力を育むのに役立ちます。

明確需求

上述のゲーム内容の紹介に基づき、以下の要件を構築できます:

サーバーとクライアント間のリアルタイムな双方向通信が必要

client server

管理者ユーザーとプレイヤーユーザーを区別する必要がある

オンラインユーザーの表示

ゲーム開始ごとに、すべてのプレイヤーに1枚のカードをランダムに割り当てる

管理者はゲーム開始、ゲームリセットの指示を出せる

プレイヤーの実名制

エラー処理:予期せぬネットワーク切断に対する対策

……

系统构建

要件を明確にした後、システムの構築に着手できます。

サーバーの双方向通信には、WebSocketベースのSocket.IOライブラリを採用しました。Socket.IOはイベント駆動型のアーキテクチャを持ち、イベントのトリガーとリスニングを通じて、サーバーとクライアント間のメッセージ伝達とデータ同期を容易に実現できます。ゲームの特定のニーズに合わせて、独自のイベントとハンドラを定義できます。また、Socket.IOには自動再接続メカニズムがあり、クライアントとサーバーの接続が切断された場合、自動的に再接続を試みます。さらに、エラー処理の仕組みも提供されており、接続エラーやタイムアウト、その他の例外状況をキャッチして処理できます。

sequence diagram

サーバー側のバックエンドには、拡張性を考慮してNode.jsベースのExpressフレームワークを選択しました。これにより、一つのシステムをWebアプリケーション、アプリ、さらにはWeChatミニプログラムにも応用できます。

プログラムの核心部分——コマンドの割り当てとシャッフルの実装:

function assignCommands(users, commands) {
  const shuffledCommands = shuffle([...commands]);
  return users.reduce((acc, user, idx) => {
    acc[user] = shuffledCommands[idx];
    return acc;
  }, {});
}

function shuffle(array) {
  for (let i = array.length - 1; i > 0; i--) {
    const j = Math.floor(Math.random() * (i + 1));
    [array[i], array[j]] = [array[j], array[i]];
  }
  return array;
}

ユーザーリストとコマンドの配信:

// Server Side
socket.on('start_game', (username) => {
    if (socket.isAdmin) {
      userCommands = assignCommands(users, commands);
      io.emit('game_started', userCommands);
      io.emit('command_list_update', userCommands);
    }
  });

  socket.on('refresh', (username) => {
    if (socket.isAdmin) {
      userCommands = assignCommands(users, commands);
      io.emit('commands_refreshed', userCommands);
      io.emit('command_list_update', userCommands);
    }
  });

  socket.on('disconnect', () => {
//接続が切断されたユーザーをリストから削除
    const index = onlineUsers.indexOf(socket.username);
    if (index !== -1) {
      onlineUsers.splice(index, 1);
      io.emit('user_list_update', onlineUsers);
    }
  });
});
// Client Side
socket.on("game_started", userCommands => {
  const command = userCommands[username];
  document.querySelector("#command").textContent = `${command}`;
});

socket.on("commands_refreshed", userCommands => {
  const command = userCommands[username];
  document.querySelector("#command").textContent = `${command}`;
});

socket.on("user_list_update", userList => {
  const list = document.querySelector("#user-list");
  list.innerHTML = "";
  userList.forEach(user => {
    const div = document.createElement("div");
    div.textContent = user;
    list.appendChild(div);
  });
});

成果展示

現在実装されている機能

ホワイトリストに含まれるプレイヤーのみがログイン可能

Image

管理者がゲーム開始、指令の更新をコントロール

Image

オンラインプレイヤーリストのリアルタイム更新

Image

全プレイヤーの指令を表示

Image

ユーザー権限の検証:管理者のみがゲーム開始、指令更新の操作を実行可能

ネットワーク切断時のプロンプトと自動再接続

Image

完全なデモ動画:

Image

TODO: 電子化された「指令ゲーム」の大きな課題の一つは、参加者が電子デバイスを手にすると、ついついWeChatや他のアプリに切り替えてしまう可能性があることです。この問題を解決するために、問券星などの試験用ページを参考に、Event Listenerを使用して画面の切り替えを検出し、警告を表示する機能を検討しています。

TODO:オンラインユーザーの追跡。現在、オンラインユーザーの配列はサーバーのメモリに保存されています。この方法では、サーバーの再起動や水平スケーリング(複数インスタンス化)の際にすべてのデータが失われてしまいます。より複雑なアプリケーションでは、データベースや中央集中型のストレージ(Redisなど)を使用してこれらのデータを保存する必要があるでしょう。

TODO:オフラインユーザーのレポート、およびより高度な再接続戦略。

TODO:より美しく、ゲーム性の高いインターフェースデザインとインタラクション。

总结

「指令ゲーム」は書院の入学教育から受け継がれてきた伝統ですが、その過度なプレッシャーや冗長なゲームプロセスは批判の対象でもありました。「指令ゲーム」を電子化することで、ゲームの核心的な理念や新入生研修における役割を維持しつつ、ゲームのフローとプレイヤー体験を向上させたいと考えています。



Next Post
Pretext Matteflow Demo

评论

No comments yet

支持 Markdown