LoginSignup
14
12

More than 1 year has passed since last update.

リアルタイムでダイスロールを共有するWEBアプリを作ってみた

Last updated at Posted at 2018-11-25

目次

  1. 背景
  2. TL;DR
  3. 使用した技術
  4. 手順アウトライン
  5. 手順詳細
  6. 実用性

1. 背景

  • 友人たちとTRPGをするようになった。
  • セッションはSkype越しにやっており、皆が個別のダイスツールを使っているので、虚偽の報告が可能(しないとは思ってるけど、まぁ、可能)。
  • 「ダイスロールの結果を共有できるツールがあったら良いんじゃね?」
  • 調べたらいっぱいあるんだけど、なんか妙に多機能で何をすれば良いのかわからなかったり、アカウント作ったりと面倒。
  • 「部屋にいる人とだけダイスロールの結果を共有することだけを目的とした、ログインとかいらない、見やすいツールを作ろう」
  • ちょうどAngularも勉強してたし、いい機会だと思った。
  • Web Socketという技術にも興味があったし、ちょうどよかった

2. TL;DR

ロビー画面の様子
1543147433168.jpg

部屋の様子
1543147738791.jpg

3. 使用した技術

  • node.js (v8.10.0)
    • express(v4.16.4) - node.jsの有名なフレームワークのパッケージ
    • socket.io (v2.1.1) - サーバーサイドでweb socketのライブラリを使用するためのパッケージ
    • socket.io-client (v2.1.1) - クライアントサイドでweb socketのライブラリをしようするためのパッケージ
    • @types/socket.io-client (v.1.4.32) - Angularのフレームワーク内でsocket.io-clientを利用するために必要なパッケージ(データ型の情報などがあるんだと思ってる)
  • @angular-cli (v1.6.8) - Angularのプロジェクトを始めたり、ビルドしたり、運用したりするためのツール

4. 手順アウトライン

  1. 調査
    1. Web Socketについて
  2. 開発
    1. プロジェクトの土台を作成
    2. 画面の作成
    3. ロジックの作成

5. 手順詳細

1. 調査

1-1. Web Socketについて

  • ちょっとWeb Socketについて調査
  • この記事が超簡単に説明してくれてるので、概要を知りたい場合は読むべし。
  • 基本的にわかったことは…
    • イベント名で処理を分ける。
    • emitでイベント名と共にデータを送る。
    • サーバー側もクライアント側も考え方は同じ。
server.js

// パッケージのインポートなど
const express = require('express');
const app = express();
const http = require('http');
const server = http.Server(app);
const io = require('socket.io')(server);

// クライアントがつながったら
io.on('connection', (socket) => {

  // クライアントからのsocket.ioの<eventName>イベントのリクエストを受け取り、渡された[arguments...]を受け取って処理をする
  socket.on('<eventName>', ([arguments...]) => {

     /* 何らかの処理 */

     // つながっているクライアント全員に<eventName>イベントで<dataToSend>を送る
     io.emit('<eventName>', <dataToSend>);

     // <roomName>にjoinしているクライアント全員に<eventName>イベントで<dataToSend>を送る
     io.to('<roomName>').emit('<eventName>', <dataToSend>);
  });

});

2. 開発

2-1. プロジェクトの土台を作成

  • @angular-cliのおかげで簡単に土台を作ることが可能。
  • 基本的に以下を覚えていれば問題ないと思う
ターミナル
$ ng new <プロジェクト名>          # 新たなAngularプロジェクトのフォルダを作成してくれる
$ ng g component <コンポーネント名>    # コンポーネントのファイルを作ってくれる
$ ng g service <サービス名>        # サービスのファイルを作ってくれる

2-2. 画面の作成

  • 画面作成時に意識したのは、レスポンシブデザインとクロスブラウザ対応。
  • Bootstrapとか使わずに自分で考えたstyleを使ってみたかった。
  • あと、自分はよく暗い部屋でやるので、眩しすぎないように全体的に暗い色合いを使う。
  • あとはみやすさ…かな

そんなこんなを考えながらイメージを紙に適当に書いていく…

こんな感じでイメージを少しずつに固めていく(もはやただの落書き)
4077.jpg

  • 補足: Internet Explorerに対応させるためにpolyfillを有効化しないといけない。
    • src/polyfill.tsファイルがあるので、コメントを外す。
src/polyfill.ts

/* (省略) */

// 以下の箇所にコメントがかかってるはずだから全部外す
/** IE9, IE10 and IE11 requires all of the following polyfills. **/
import 'core-js/es6/symbol';
import 'core-js/es6/object';
import 'core-js/es6/function';
import 'core-js/es6/parse-int';
import 'core-js/es6/parse-float';
import 'core-js/es6/number';
import 'core-js/es6/math';
import 'core-js/es6/string';
import 'core-js/es6/date';
import 'core-js/es6/array';
import 'core-js/es6/regexp';
import 'core-js/es6/map';
import 'core-js/es6/weak-map';
import 'core-js/es6/set';

/* (省略) */

2-3. ロジックの作成

  • 「ロジックの作成」ではかなりざっくりなので、分解すると…
    • ルーティングのロジック
    • 新しい部屋を作るときのロジック
    • 部屋に参加するロジック
    • 部屋の有無を確認するロジック
    • 部屋に誰か入ったときに、それを部屋の人全員に伝えるロジック
    • 部屋に誰か入ったときに、部屋に今現在誰が入っているかを伝えるロジック
    • 部屋に誰かが入ったときにIDを割り振るロジック
    • 部屋に誰かが入ったときにランダムな表示名を割り振るロジック
    • ユーザーが任意に表示名を変更するロジック
    • ダイスを振るロジック
    • ダイスの出目をみんなに伝えるロジック
    • ダイスの出目をログするロジック
    • ログを消去するロジック
    • 誰かが退室したときのロジック

上記をすべて考える必要があった。

6. 実用性

個人的な意見だが、実用性は結構あると思う。理由を以下に挙げる…

  • 部屋を作って、番号を教えるだけだから誰でも手っ取り早く使えるし、アカウント登録とか必要ない。
  • UI/UXを気にして、できるだけシンプルにしたので、見やすく、直感的に使いやすい。
  • 機能が少ないので画面がごちゃごちゃしてない。またしても見やすい。
  • レスポンシブデザインなのでスマホ・タブレットに対応している。
  • 表示名を変えれるようになってるから誰が誰だかちゃんと分かる。

自画自賛もここまでくればキモいけど、まぁまぁの出来だと思っている。
ベースがこれなら機能も追加しやすいだろうし。
ただ、もうちょっとデザインやレイアウトをうまくできたら嬉しかった…
まぁ、これもいい経験ということで…

14
12
4

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
14
12