25
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Life is Tech ! メンターAdvent Calendar 2017

Day 6

Web開発コースでも対戦ゲームが作りたかった。

Last updated at Posted at 2017-12-05

Web開発コースでも対戦ゲームが作りたかった。

こんにちはしげるです!
名古屋のWebコースのメンターしてます。
Web開発コースってサービスばっかりでゲーム作っていないイメージありませんか?
サーバーを使って他の人と対戦したい!って思いありませんか?
ゲームコース楽しそうとか思っているそこの君っ!この記事を呼んでゲームを作ってみよう!!

アイディア

  • 対戦型のオセロを作ろう!

利用技術

  • sinatra
  • web socket

web socketとは

HTML5から利用が可能で、他のクライアントと簡単に相互通信ができる規格。
WebSocketについて調べてみた。

はじめに参加しているユーザーをカウントしてみよう!

テンプレート

 $ git clone https://github.com/4geru/simple-websocket-count.git
 $ bundle # パッケージのインストール
 $ bundle exec rake db:migrate # データベースの構成
 $ bundle exec ruby app.rb # サーバーの起動

オセロ盤を作る

複数のブラウザページを開いて数が増えたり減ったりするのを確認できたらOK!
次に、オセロの板を作ってみよう!for文を使うことでtableを簡単に作ることができます!

html
<table>
  <% for i in 0..7 %>
  <tr>
    <% for j in 0..7%>
      <td onclick="s('<%= i %><%= j %>')"  id='<%= i %><%= j %>'>
        <% # 真ん中のおけないところ %>
        <% if (i == 4 and j == 4) or (i == 3 and j == 3)%>
          <div class='black'></div>
        <% end %>
        <% if (i == 3 and j == 4) or (i == 4 and j == 3)%>
          <div class='white'></div>
        <% end %>
      </td>
    <% end %>
  </tr>
  <% end %>
</table>
css
td{
  background: green;
  width: 100px; height: 100px;
}
table{
  background: black;
}
.black{
  background: black;
  margin: auto;
  width: 80px; height: 80px;
  border-radius: 50%;
}
.white{
  background: white;
  margin: auto;
  width: 80px; height: 80px;
  border-radius: 50%;
}

WebSocketを実装しよう

実際に、WebSocketを使って行きます!
WebSocketは常にサーバーとブラウザが接続されているイメージ!
app.rbの中のsettings.socketsで、接続しているブラウザを全て管理しています。
リクエストを送って来たsocketをwsとして、app.rbの中で使っています。

ws.send("send")で、元のsocketに対して "send" というメッセージを送ることができます!
データは、JavaScriptでは、JSON。RubyではHashで扱いたいけど、sendでは、文字しか送れないので、JavaScirpt・Rubyでそれぞれ変換する必要がります。
複数のデータを送りたい場合は、送る時に、typeを書くと管理しやすいです。

app.rb
get '/websocket/count' do
  if request.websocket? then
    request.websocket do |ws|
      ws.onopen do # 接続を開始した時
        settings.sockets << ws # socketsリストに追加
        c = Count.first # count の数を増やす
        c.count += 1
        c.save
        settings.sockets.each do |s| # 全体へメッセージを転送
          c = Count.first
          s.send({type: 'count', count: c.count}.to_json.to_s)
        end
      end
      ws.onmessage do |msg| # メッセージを受け取った時
        puts 'メッセージを受け取ったよ!'
        data = JSON.parse(msg)
        case data['type']
        when 'open', 'close' # 送られたデータが open or close データだったら
          settings.sockets.each do |s| # 全体へメッセージを転送
            c = Count.first
            s.send({type: 'count', count: c.count}.to_json.to_s)
          end
        when 'board' # 送られたデータが board データだったら
          turn  = data['turn'] == 'black' ? 'white' : 'black'
          puts data
          settings.sockets.each do |s| # メッセージを転送
            s.send({type: 'board', turn: turn, pos: data['pos']}.to_json.to_s)
          end
        end
      end
      ws.onclose do # メッセージを終了する時
        c = Count.first # count の数を減らす
        c.count -= - 1
        c.save
        settings.sockets.each do |s| # 全体へメッセージを転送
          c = Count.first
          s.send({type: 'count', count: c.count}.to_json.to_s)
        end
        settings.sockets.delete(ws) # socketsリストから削除
      end
    end
  end
end
javascript
var countBox = document.getElementById("count");
var turnBox = document.getElementById("turn");

window.onload = function(){
  var count = new WebSocket('ws://' + window.location.host + "/websocket/count");

  // 接続が始まった時
  count.onopen = function() { count.send('{"type":"open"}'); };
  // 接続が終わった時
  count.onclose = function() { count.send('{"type":"close"}'); };
  // メッセージを受け取った時
  count.onmessage = function(m) {
    data = JSON.parse(m.data)
    if(data.type == 'count'){ // サーバーからカウントを変更する命令が来た時
      countBox.innerHTML = data.count         
    } else if(data.type == 'board'){ // サーバーから石を置く命令が来た時
      turn = data.turn == 'black' ? 'white' : 'black'
      turnBox.innerHTML = data.turn
      document.getElementById(data.pos).innerHTML = '<div class=' + turn + '></div>'
      console.log('get board')
    }
  }

  s = function(msg){
    // すでに石が置かれていたら置かない
    if(!document.getElementById(msg).innerHTML.match('div'))
      count.send(JSON.stringify({type:'board', pos: msg, turn: turnBox.innerHTML}));
  }
};

ezgif-4-d808a842d8.gif
ここまでのリポジトリ
なんとか形になるものにはできた。
WebSocketを使ってみたなので、実際のオセロの実装については、また別のお話。

次は

明日は担当はまなみんです!gitの記事を書くみたいです。
gitをソースコード管理以外にもレポート管理にも使えるので、どんな内容か気になります。

25
9
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
25
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?