Edited at

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

More than 1 year has passed since last update.


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をソースコード管理以外にもレポート管理にも使えるので、どんな内容か気になります。