Full game loop. TODO: Livejoin checks
This commit is contained in:
parent
ecb430e1b7
commit
b7ad52ff6a
4 changed files with 709 additions and 346 deletions
|
|
@ -9,8 +9,38 @@ const socket = io('http://localhost:7777');
|
||||||
var id = '';
|
var id = '';
|
||||||
var drawing_app = null;
|
var drawing_app = null;
|
||||||
|
|
||||||
var game_info = document.getElementById('game_state_info');
|
var did_vote = false;
|
||||||
var pixi_wrapper = document.getElementById('pixi-wrapper');
|
|
||||||
|
const game_info = document.getElementById('game_state_info');
|
||||||
|
const pixi_wrapper = document.getElementById('pixi-wrapper');
|
||||||
|
|
||||||
|
const join_room_btn = document.getElementById('join_room_btn');
|
||||||
|
|
||||||
|
const room_code_input = document.getElementById('room_code');
|
||||||
|
const username_input = document.getElementById('username');
|
||||||
|
|
||||||
|
const game_room_code_label = document.getElementById('game_room_code');
|
||||||
|
|
||||||
|
const game_setup_panel = document.getElementById('game_setup');
|
||||||
|
const game_info_panel = document.getElementById('game_info');
|
||||||
|
|
||||||
|
const copy_image_btn = document.getElementById('copy_image');
|
||||||
|
const download_image_btn = document.getElementById('download_image');
|
||||||
|
|
||||||
|
const current_player_count = document.getElementById('current_player_count');
|
||||||
|
const player_list = document.getElementById('player_list');
|
||||||
|
const pre_game_player_list = document.getElementById('pre_game_player_list');
|
||||||
|
|
||||||
|
const ready_up_btn = document.getElementById('ready_up_btn');
|
||||||
|
const create_room_btn = document.getElementById('create_room_btn');
|
||||||
|
|
||||||
|
const game_leader_input = document.getElementById('game_leader_input');
|
||||||
|
|
||||||
|
const game_hint = document.getElementById('game_hint');
|
||||||
|
const game_topic = document.getElementById('game_topic');
|
||||||
|
const submit_topic_btn = document.getElementById('submit_topic');
|
||||||
|
|
||||||
|
const voting_player_list = document.getElementById('voting_player_list');
|
||||||
|
|
||||||
function setGameInfo(info) {
|
function setGameInfo(info) {
|
||||||
game_info.innerHTML = info;
|
game_info.innerHTML = info;
|
||||||
|
|
@ -24,87 +54,75 @@ socket.on('connect', () => {
|
||||||
console.log('\n*** Startup! ***');
|
console.log('\n*** Startup! ***');
|
||||||
});
|
});
|
||||||
|
|
||||||
document.getElementById('join_room_btn').addEventListener('click', (e) => {
|
join_room_btn.addEventListener('click', (e) => {
|
||||||
var room_code = document.getElementById('room_code').value;
|
socket.emit('join_room', room_code_input.value, username_input.value);
|
||||||
var username = document.getElementById('username').value;
|
|
||||||
|
|
||||||
socket.emit('join_room', room_code, username);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
socket.on('room', (room_id) => {
|
socket.on('join_room', (room_id) => {
|
||||||
// join the room
|
// join the room
|
||||||
console.log(room_id);
|
console.log(room_id);
|
||||||
document.getElementById('game_room_code').innerHTML = room_id;
|
game_room_code_label.innerHTML = room_id;
|
||||||
|
|
||||||
document.getElementById('game_setup').style.display = 'none';
|
game_setup_panel.style.display = 'none';
|
||||||
document.getElementById('game_info').style.display = 'initial';
|
game_info_panel.style.display = 'initial';
|
||||||
|
|
||||||
document.getElementById('copy_image').style.display = 'none';
|
copy_image_btn.style.display = 'none';
|
||||||
document.getElementById('download_image').style.display = 'none';
|
download_image_btn.style.display = 'none';
|
||||||
});
|
});
|
||||||
|
|
||||||
socket.on('room_error', (error_msg) => {
|
socket.on('room_error', (error_msg) => {
|
||||||
alert(error_msg);
|
alert(error_msg);
|
||||||
});
|
});
|
||||||
|
|
||||||
document.getElementById('create_room_btn').addEventListener('click', (e) => {
|
socket.on('topic_error', (error_msg) => {
|
||||||
|
alert(error_msg);
|
||||||
|
});
|
||||||
|
|
||||||
|
create_room_btn.addEventListener('click', (e) => {
|
||||||
// Tell the server we want a new room
|
// Tell the server we want a new room
|
||||||
var username = document.getElementById('username').value;
|
socket.emit('create_room', username_input.value);
|
||||||
socket.emit('create_room', username);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
socket.on('player_data', (player_arr) => {
|
socket.on('player_data', (player_arr) => {
|
||||||
|
console.log('Playerdata!?');
|
||||||
var count = player_arr.length;
|
var count = player_arr.length;
|
||||||
document.getElementById('current_player_count').innerHTML = count;
|
current_player_count.innerHTML = count;
|
||||||
|
|
||||||
var player_list = document.getElementById('player_list');
|
|
||||||
|
|
||||||
player_list.innerHTML = '';
|
player_list.innerHTML = '';
|
||||||
|
|
||||||
player_arr.forEach((player) => {
|
player_arr.forEach((player) => {
|
||||||
player_list.innerHTML += '<li>' + player.player_name + '</li>';
|
player_list.innerHTML +=
|
||||||
|
`<li><input class="player_ready_state" type="checkbox" ${
|
||||||
|
player.ready ? 'checked' :
|
||||||
|
''} disabled />${player.player_name}</li>`;
|
||||||
})
|
})
|
||||||
|
|
||||||
document.getElementById('start_game_btn').disabled = (count < 2);
|
ready_up_btn.disabled = (count < 2);
|
||||||
});
|
});
|
||||||
|
|
||||||
document.getElementById('start_game_btn').addEventListener('click', (e) => {
|
ready_up_btn.addEventListener('click', (e) => {
|
||||||
socket.emit('start_game');
|
socket.emit('ready');
|
||||||
});
|
});
|
||||||
|
|
||||||
socket.on('game_started', () => {
|
socket.on('game_started', () => {
|
||||||
// game_data.game_leader =
|
voting_player_list.innerHTML = "";
|
||||||
console.log('yooo');
|
document.getElementById('pl_container').style.display = "none";
|
||||||
document.getElementById('pre_game_player_list').style.display = 'none';
|
document.getElementById('copy_image').style.display = 'none';
|
||||||
|
document.getElementById('download_image').style.display = 'none';
|
||||||
|
|
||||||
|
pixi_wrapper.innerHTML = "";
|
||||||
|
drawing_app = null;
|
||||||
|
|
||||||
|
pre_game_player_list.style.display = 'none';
|
||||||
});
|
});
|
||||||
|
|
||||||
socket.on('leader_selected', (leader) => {
|
socket.on('leader_selected', (leader) => {
|
||||||
console.log(leader);
|
|
||||||
console.log(id);
|
|
||||||
setGameInfo(`Please wait while the leader ${
|
setGameInfo(`Please wait while the leader ${
|
||||||
leader.player_name} is selecting a hint to be painted`);
|
leader.player_name} is thinking of a topic to be painted`);
|
||||||
if (leader.id == id) {
|
if (leader.id == id) {
|
||||||
setGameInfo(
|
setGameInfo(
|
||||||
'You are the game leader! Please choose a hint and a category that the hint fits in.');
|
'You are the game leader! Please choose a hint and a category that the hint fits in.');
|
||||||
document.getElementById('game_leader_input').style.display = 'initial';
|
game_leader_input.style.display = 'initial';
|
||||||
|
|
||||||
const game_hint = document.getElementById('game_hint');
|
|
||||||
const game_topic = document.getElementById('game_topic');
|
|
||||||
const submit_topic_btn = document.getElementById('submit_topic');
|
|
||||||
|
|
||||||
function updateSubmitButtonState() {
|
|
||||||
submit_topic_btn.disabled =
|
|
||||||
game_hint.value.length < 2 || game_topic.value.length < 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
game_hint.addEventListener('input', (e) => {
|
|
||||||
updateSubmitButtonState();
|
|
||||||
});
|
|
||||||
|
|
||||||
game_topic.addEventListener('input', (e) => {
|
|
||||||
updateSubmitButtonState();
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
submit_topic_btn.addEventListener('click', (e) => {
|
submit_topic_btn.addEventListener('click', (e) => {
|
||||||
socket.emit('topic_selected', game_topic.value, game_hint.value);
|
socket.emit('topic_selected', game_topic.value, game_hint.value);
|
||||||
|
|
@ -112,28 +130,118 @@ socket.on('leader_selected', (leader) => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function updateSubmitButtonState() {
|
||||||
|
submit_topic_btn.disabled =
|
||||||
|
game_hint.value.length < 2 || game_topic.value.length < 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
game_hint.addEventListener('input', (e) => {
|
||||||
|
updateSubmitButtonState();
|
||||||
|
});
|
||||||
|
|
||||||
|
game_topic.addEventListener('input', (e) => {
|
||||||
|
updateSubmitButtonState();
|
||||||
|
});
|
||||||
|
|
||||||
socket.on('topic_selected', (topic, hint) => {
|
socket.on('topic_selected', (topic, hint) => {
|
||||||
console.log(topic, hint);
|
console.log(topic, hint);
|
||||||
document.getElementById('game_leader_input').style.display = 'none';
|
game_leader_input.style.display = 'none';
|
||||||
setGameInfo(`Hint: ${hint}<br />Topic: ${topic}`);
|
setGameInfo(`Hint: ${hint}<br />Topic: ${topic}`);
|
||||||
});
|
});
|
||||||
|
|
||||||
socket.on('game_finished', (leader, player_list) => {
|
socket.on('game_finished', (leader, player_list) => {
|
||||||
var pl = document.getElementById('endgame_player_list');
|
did_vote = false;
|
||||||
|
drawing_app.addBackgroundForDownload();
|
||||||
|
|
||||||
pl.innerHTML = '';
|
document.getElementById('pl_container').style.display = 'flex';
|
||||||
|
document.getElementById('copy_image').style.display = 'initial';
|
||||||
|
document.getElementById('download_image').style.display = 'initial';
|
||||||
|
document.getElementById('current_user_text').style.display = 'none';
|
||||||
|
|
||||||
player_list.forEach((player) => {
|
var idx = 1;
|
||||||
if (player.id == leader.id) {
|
|
||||||
pl.innerHTML += `<li style="font-weight: bold; color: black;">${
|
player_list.forEach((p) => {
|
||||||
player.player_name} (Leader)</li>`;
|
var tr = voting_player_list.insertRow(-1);
|
||||||
} else {
|
|
||||||
pl.innerHTML += `<li style="color: ${player.player_color};">${
|
var c1 = tr.insertCell(-1);
|
||||||
player.player_name}</li>`;
|
c1.innerHTML = `<span id="votecount_${p.id}">?</span>`;
|
||||||
}
|
|
||||||
|
var c2 = tr.insertCell(-1);
|
||||||
|
|
||||||
|
// leader should not be able to vote
|
||||||
|
// spectators should not be able to vote
|
||||||
|
// basically, only show voting button if this players' id is in the list of
|
||||||
|
// voteable players
|
||||||
|
if (player_list.filter(e => e.id === id).length > 0) {
|
||||||
|
var vote_btn = document.createElement('input');
|
||||||
|
vote_btn.type = 'button';
|
||||||
|
vote_btn.value = 'vote';
|
||||||
|
vote_btn.classList.add('vote_btn');
|
||||||
|
vote_btn.addEventListener('click', () => {
|
||||||
|
console.log(p.id);
|
||||||
|
socket.emit('vote_for_player', p.id);
|
||||||
|
|
||||||
|
Array.from(document.getElementsByClassName('vote_btn'))
|
||||||
|
.forEach((element) => {
|
||||||
|
element.disabled = true;
|
||||||
|
element.style.display = 'none';
|
||||||
})
|
})
|
||||||
|
});
|
||||||
|
c2.appendChild(vote_btn);
|
||||||
|
}
|
||||||
|
|
||||||
pl.style.display = 'initial';
|
var c3 = tr.insertCell(-1);
|
||||||
|
c3.innerHTML = `<span id="playername_${p.id}" style="font-weight: bold; color: ${p.player_color}">${
|
||||||
|
p.player_name}</span>`;
|
||||||
|
|
||||||
|
var c4 = tr.insertCell(-1);
|
||||||
|
c4.innerHTML = `<span style="font-weight: bold; color: ${p.player_color}">${
|
||||||
|
idx}, ${idx + player_list.length}</span>`;
|
||||||
|
|
||||||
|
var c5 = tr.insertCell(-1);
|
||||||
|
var chkbox = document.createElement('input');
|
||||||
|
chkbox.type = 'checkbox';
|
||||||
|
chkbox.disabled = true;
|
||||||
|
chkbox.id = `votestatus_${p.id}`;
|
||||||
|
|
||||||
|
c5.appendChild(chkbox);
|
||||||
|
// c5.innerHTML = `<input type="checkbox" disabled />`;
|
||||||
|
|
||||||
|
idx++;
|
||||||
|
});
|
||||||
|
|
||||||
|
socket.on('show_vote_results', (votes) => {
|
||||||
|
votes.players_voted.forEach((pv) => {
|
||||||
|
var e = document.getElementById(`votestatus_${pv}`);
|
||||||
|
if (e) {
|
||||||
|
e.checked = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Object.entries(votes.player_votes).forEach(([k, v]) => {
|
||||||
|
var e = document.getElementById(`votecount_${k}`);
|
||||||
|
if (e) {
|
||||||
|
e.innerHTML = v;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var fake = document.getElementById(`playername_${votes.fake_artist.id}`);
|
||||||
|
if(fake) {
|
||||||
|
fake.innerHTML = `>>> ${votes.fake_artist.player_name} <<<`;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
pre_game_player_list.style.display = "initial";
|
||||||
|
});
|
||||||
|
|
||||||
|
socket.on('update_votes', (votes) => {
|
||||||
|
// update player vote display
|
||||||
|
votes.players_voted.forEach((pv) => {
|
||||||
|
var e = document.getElementById(`votestatus_${pv}`);
|
||||||
|
if (e) {
|
||||||
|
e.checked = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
var ink_bar = document.getElementById('myBar');
|
var ink_bar = document.getElementById('myBar');
|
||||||
ink_bar.style.display = 'none';
|
ink_bar.style.display = 'none';
|
||||||
|
|
@ -186,11 +294,8 @@ socket.on('game_finished', (leader, player_list) => {
|
||||||
|
|
||||||
base64_image.then((str) => {
|
base64_image.then((str) => {
|
||||||
try {
|
try {
|
||||||
navigator.clipboard.write([
|
navigator.clipboard.write(
|
||||||
new ClipboardItem({
|
[new ClipboardItem({'image/png': b64toBlob(str)})]);
|
||||||
'image/png': b64toBlob(str)
|
|
||||||
})
|
|
||||||
]);
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
}
|
}
|
||||||
|
|
@ -200,18 +305,21 @@ socket.on('game_finished', (leader, player_list) => {
|
||||||
|
|
||||||
socket.on('actually_start_game', (player_data) => {
|
socket.on('actually_start_game', (player_data) => {
|
||||||
// Get player with our id to get the correct color
|
// Get player with our id to get the correct color
|
||||||
|
document.getElementById('current_user_text').style.display = 'flex';
|
||||||
|
var ink_bar = document.getElementById('myBar');
|
||||||
|
ink_bar.style.display = 'initial';
|
||||||
drawing_app = new DrawingApp(pixi_wrapper, player_data);
|
drawing_app = new DrawingApp(pixi_wrapper, player_data);
|
||||||
window.drawing_app = drawing_app;
|
window.drawing_app = drawing_app;
|
||||||
});
|
});
|
||||||
|
|
||||||
socket.on('draw_data', (round_num, data) => {
|
socket.on('draw_data', (turn_num, data) => {
|
||||||
console.log('Draw Data: ', round_num);
|
console.log('Draw Data: ', turn_num);
|
||||||
var cur_layer = drawing_app.layers[round_num];
|
var cur_layer = drawing_app.layers[turn_num];
|
||||||
|
|
||||||
cur_layer.drawPointLine(data[0], data[1], true);
|
cur_layer.drawPointLine(data[0], data[1], true);
|
||||||
});
|
});
|
||||||
|
|
||||||
socket.on('advance_round', (round_num, current_player) => {
|
socket.on('advance_turn', (turn_num, current_player) => {
|
||||||
var ink_bar = document.getElementById('myBar');
|
var ink_bar = document.getElementById('myBar');
|
||||||
ink_bar.style.width = '100%';
|
ink_bar.style.width = '100%';
|
||||||
|
|
||||||
|
|
@ -226,7 +334,7 @@ socket.on('advance_round', (round_num, current_player) => {
|
||||||
ink_bar.style.backgroundColor = current_player.player_color;
|
ink_bar.style.backgroundColor = current_player.player_color;
|
||||||
ink_bar.style.visibility = 'visible';
|
ink_bar.style.visibility = 'visible';
|
||||||
|
|
||||||
const cur_layer = drawing_app.layers[round_num];
|
const cur_layer = drawing_app.layers[turn_num];
|
||||||
|
|
||||||
cur_layer.enable();
|
cur_layer.enable();
|
||||||
|
|
||||||
|
|
@ -235,14 +343,14 @@ socket.on('advance_round', (round_num, current_player) => {
|
||||||
|
|
||||||
ink_bar.style.width = ((1.0 - ink_pct) * 100) + '%';
|
ink_bar.style.width = ((1.0 - ink_pct) * 100) + '%';
|
||||||
|
|
||||||
console.log(ink_pct);
|
console.log(ink_pct, old_pos, new_pos);
|
||||||
|
|
||||||
socket.emit('draw_data', [old_pos, new_pos]);
|
socket.emit('draw_data', [old_pos, new_pos]);
|
||||||
});
|
});
|
||||||
|
|
||||||
cur_layer.setFinishedPaintingCallback(() => {
|
cur_layer.setFinishedPaintingCallback(() => {
|
||||||
cur_layer.disable();
|
cur_layer.disable();
|
||||||
socket.emit('round_finished');
|
socket.emit('turn_finished');
|
||||||
});
|
});
|
||||||
|
|
||||||
/*player_data.forEach((p) => {
|
/*player_data.forEach((p) => {
|
||||||
|
|
|
||||||
|
|
@ -116,22 +116,22 @@ export class Layer {
|
||||||
y: oldPos.y - newPos.y,
|
y: oldPos.y - newPos.y,
|
||||||
};
|
};
|
||||||
const deltaLength = Math.sqrt(delta.x ** 2 + delta.y ** 2);
|
const deltaLength = Math.sqrt(delta.x ** 2 + delta.y ** 2);
|
||||||
|
this.ink_used += deltaLength;
|
||||||
|
|
||||||
if (!force) {
|
if (!force) {
|
||||||
this.ink_used += deltaLength;
|
console.log("Force?");
|
||||||
this.live_paint_progress_cb(oldPos, newPos);
|
this.live_paint_progress_cb(oldPos, newPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.ink_used >= max_ink_per_layer) {
|
if (this.ink_used >= max_ink_per_layer) {
|
||||||
this.lifted = true;
|
this.lifted = true;
|
||||||
this.drawingStarted = false;
|
this.drawingStarted = false;
|
||||||
|
if(!force) {
|
||||||
this.finished_painting_cb();
|
this.finished_painting_cb();
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Pass socket.io to tell server?
|
|
||||||
// Or save to array and just pass to server on round-end. Should be easier?
|
|
||||||
|
|
||||||
this.drawPoint(newPos.x, newPos.y);
|
this.drawPoint(newPos.x, newPos.y);
|
||||||
|
|
||||||
if (deltaLength >= brush_size / 8) {
|
if (deltaLength >= brush_size / 8) {
|
||||||
|
|
@ -170,7 +170,6 @@ export class Layer {
|
||||||
|
|
||||||
export class DrawingApp {
|
export class DrawingApp {
|
||||||
constructor(dom_elem, player_data) {
|
constructor(dom_elem, player_data) {
|
||||||
var self = this;
|
|
||||||
this.app = new PIXI.Application({
|
this.app = new PIXI.Application({
|
||||||
width: layer_width,
|
width: layer_width,
|
||||||
height: layer_height,
|
height: layer_height,
|
||||||
|
|
@ -182,13 +181,6 @@ export class DrawingApp {
|
||||||
|
|
||||||
this.layers = [];
|
this.layers = [];
|
||||||
|
|
||||||
const base_render_texture = PIXI.RenderTexture.create({width: 512, height: 512});
|
|
||||||
|
|
||||||
|
|
||||||
/*this.layers.push(new Layer(
|
|
||||||
this.app, base_render_texture, this.brushGenerator, "-1",
|
|
||||||
"0xFFFFFF"));*/
|
|
||||||
|
|
||||||
for (var i = 0; i < player_data.length * 2; i++) {
|
for (var i = 0; i < player_data.length * 2; i++) {
|
||||||
const render_texture =
|
const render_texture =
|
||||||
PIXI.RenderTexture.create({width: 512, height: 512});
|
PIXI.RenderTexture.create({width: 512, height: 512});
|
||||||
|
|
@ -205,5 +197,19 @@ export class DrawingApp {
|
||||||
return this.app;
|
return this.app;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
addBackgroundForDownload() {
|
||||||
|
if(!this.hasBackgroundAlready) {
|
||||||
|
let rectangle = new PIXI.Graphics();
|
||||||
|
rectangle.lineStyle(0.5, 0x999999);
|
||||||
|
rectangle.beginFill(0xFFFFFF); // draw each row of rectangles in different color :)
|
||||||
|
rectangle.drawRect(0, 0, 512, 512);
|
||||||
|
rectangle.endFill();
|
||||||
|
|
||||||
|
this.app.stage.addChildAt(rectangle, 0);
|
||||||
|
|
||||||
|
this.hasBackgroundAlready = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
lock_all_layers() {}
|
lock_all_layers() {}
|
||||||
}
|
}
|
||||||
|
|
@ -25,6 +25,10 @@
|
||||||
color: #FFFFFF;
|
color: #FFFFFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.room_input {
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
|
|
||||||
li {
|
li {
|
||||||
color: #FFFFFF;
|
color: #FFFFFF;
|
||||||
}
|
}
|
||||||
|
|
@ -40,6 +44,11 @@
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.table-center {
|
||||||
|
height: 100%;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
#game_leader_input {
|
#game_leader_input {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
@ -88,15 +97,59 @@
|
||||||
#pl_container {
|
#pl_container {
|
||||||
background-color: white;
|
background-color: white;
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
label {
|
label {
|
||||||
color: white;
|
color: white;
|
||||||
}
|
}
|
||||||
|
|
||||||
#copy_image {}
|
#copy_image {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
#download_image {}
|
#download_image {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#player_list {
|
||||||
|
list-style-type: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.player_ready_state {
|
||||||
|
width: 1.2vmax;
|
||||||
|
height: 1.2vmax;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ready_up_btn {
|
||||||
|
color: black;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ready_up_btn:disabled {
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.additional_info {
|
||||||
|
font-size: 1.5vmax;
|
||||||
|
color: white;
|
||||||
|
margin-top: 50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.additional_info>a:link {
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
|
|
||||||
|
.additional_info>a:hover {
|
||||||
|
color: green;
|
||||||
|
}
|
||||||
|
|
||||||
|
.additional_info>a:active {
|
||||||
|
color: teal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.additional_info>a:visited {
|
||||||
|
color: yellow;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
|
|
@ -111,7 +164,8 @@
|
||||||
</form>
|
</form>
|
||||||
<form>
|
<form>
|
||||||
<label>
|
<label>
|
||||||
Room-Code: <input id="room_code" maxlength="4" type="text" placeholder="Room-Code" />
|
Room-Code: <input class="room_input" id="room_code" maxlength="4" type="text"
|
||||||
|
placeholder="Room-Code" />
|
||||||
</label>
|
</label>
|
||||||
<input id="join_room_btn" type="button" value="Join Room" />
|
<input id="join_room_btn" type="button" value="Join Room" />
|
||||||
</form>
|
</form>
|
||||||
|
|
@ -128,7 +182,7 @@
|
||||||
<ul id="player_list">
|
<ul id="player_list">
|
||||||
</ul>
|
</ul>
|
||||||
<form>
|
<form>
|
||||||
<input id="start_game_btn" type="button" value="Start" />
|
<input id="ready_up_btn" type="button" value="Ready" />
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
|
|
@ -137,18 +191,34 @@
|
||||||
<div id="game_leader_input">
|
<div id="game_leader_input">
|
||||||
<form>
|
<form>
|
||||||
<label>
|
<label>
|
||||||
Category: <input type="text" placeholder="Hint" id="game_hint" />
|
Hint (Everbody sees this!): <input type="text" placeholder="Hint" id="game_hint" />
|
||||||
</label>
|
</label>
|
||||||
|
<br />
|
||||||
<label>
|
<label>
|
||||||
Topic: <input type="text" placeholder="Topic" id="game_topic" />
|
Topic (Fake artist does NOT see this!): <input type="text" placeholder="Topic"
|
||||||
|
id="game_topic" />
|
||||||
</label>
|
</label>
|
||||||
<input type="button" id="submit_topic" value="Start" disabled/>
|
<input type="button" id="submit_topic" value="Start" disabled />
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="game">
|
<div id="game">
|
||||||
<div class="center" id="pl_container">
|
<div class="center" id="pl_container">
|
||||||
|
<table class="table-center">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Votes</th>
|
||||||
|
<th>Vote?</th>
|
||||||
|
<th>Name</th>
|
||||||
|
<th>Turns</th>
|
||||||
|
<th>Has Voted?</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody id="voting_player_list">
|
||||||
|
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
<ul id="endgame_player_list"></ul>
|
<ul id="endgame_player_list"></ul>
|
||||||
</div>
|
</div>
|
||||||
<div id="user_turn_info">
|
<div id="user_turn_info">
|
||||||
|
|
@ -161,10 +231,20 @@
|
||||||
</div>
|
</div>
|
||||||
<div id="pixi-wrapper"></div>
|
<div id="pixi-wrapper"></div>
|
||||||
<div class="center">
|
<div class="center">
|
||||||
<input type="button" id="copy_image" value="Save Image to Clipboard" />
|
<input type="button" id="copy_image" value="Copy to Clipboard (not working in Firefox)" />
|
||||||
<input type="button" id="download_image" value="Download Image" />
|
<input type="button" id="download_image" value="Download Image" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="additional_info" id="original_game_info">
|
||||||
|
This website is a (shitty) implementation of the board game <a
|
||||||
|
href="https://oinkgames.com/en/games/analog/a-fake-artist-goes-to-new-york/">"A Fake Artist goes to New
|
||||||
|
York"</a> by Oink Games Inc.<br />
|
||||||
|
There is also an official digital version on Steam <a
|
||||||
|
href="https://store.steampowered.com/app/1933490/Lets_Play_Oink_Games/">Let's Play! Oink Games</a>
|
||||||
|
</div>
|
||||||
|
<div class="additional_info" id="source-info">
|
||||||
|
Sourcecode available on <a href="https://github.com/">GitHub</a> :)
|
||||||
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
|
|
@ -4,7 +4,7 @@ const http = require('http').Server(app);
|
||||||
const io = require('socket.io')(http);
|
const io = require('socket.io')(http);
|
||||||
const cors = require('cors');
|
const cors = require('cors');
|
||||||
|
|
||||||
const room_chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
|
const room_chars = 'ABCDEFGHJKLMOPRSTUWXYZ';
|
||||||
|
|
||||||
Array.prototype.remove = function() {
|
Array.prototype.remove = function() {
|
||||||
var what, a = arguments, L = a.length, ax;
|
var what, a = arguments, L = a.length, ax;
|
||||||
|
|
@ -34,15 +34,23 @@ const available_colors = [
|
||||||
'#500027', '#006241', '#ffc4e4'
|
'#500027', '#006241', '#ffc4e4'
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
||||||
|
var active_games = {};
|
||||||
|
|
||||||
|
|
||||||
class Player {
|
class Player {
|
||||||
id = null;
|
id = null;
|
||||||
player_name = 'Player';
|
player_name = 'Player';
|
||||||
player_color = '';
|
player_color = '';
|
||||||
|
score = 0;
|
||||||
|
ready = false;
|
||||||
|
|
||||||
constructor(id_, name_, player_color_) {
|
constructor(id_, name_, player_color_) {
|
||||||
this.id = id_;
|
this.id = id_;
|
||||||
this.player_name = name_;
|
this.player_name = name_;
|
||||||
this.player_color = player_color_;
|
this.player_color = player_color_;
|
||||||
|
this.score = 0;
|
||||||
|
this.ready = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -55,35 +63,398 @@ const GAME_STATE = {
|
||||||
}
|
}
|
||||||
|
|
||||||
class Game {
|
class Game {
|
||||||
|
// Const
|
||||||
room_id = '';
|
room_id = '';
|
||||||
|
|
||||||
|
// Change on trigger
|
||||||
topic = '';
|
topic = '';
|
||||||
hint = '';
|
hint = '';
|
||||||
|
current_game_state = GAME_STATE.PRE_GAME;
|
||||||
|
;
|
||||||
|
|
||||||
players = []; // Player Class
|
players = []; // Player Class
|
||||||
actual_players = [];
|
disconnected_during_session = [];
|
||||||
current_game_state = 0;
|
|
||||||
current_player = null;
|
|
||||||
leader = null;
|
leader = null;
|
||||||
fake_artist = null;
|
fake_artist = null;
|
||||||
current_round = 0;
|
// - Per turn
|
||||||
|
current_turn = 0;
|
||||||
|
current_player = null;
|
||||||
|
|
||||||
|
// - Per Game
|
||||||
player_turns = [];
|
player_turns = [];
|
||||||
disconnected_during_session = [];
|
possible_leaders = [];
|
||||||
|
actual_players = [];
|
||||||
|
spectators = [];
|
||||||
|
|
||||||
|
turn_drawdata = []; // 2d array, turn -> then array of draw_data dicts
|
||||||
|
|
||||||
|
can_vote = [];
|
||||||
|
player_votes = {};
|
||||||
|
|
||||||
constructor(room_id_) {
|
constructor(room_id_) {
|
||||||
this.room_id = room_id_
|
this.room_id = room_id_
|
||||||
}
|
}
|
||||||
|
|
||||||
add_player(player) {
|
start_game() {
|
||||||
|
this.current_game_state = GAME_STATE.TOPIC_SELECTION;
|
||||||
|
|
||||||
|
io.to(this.room_id).emit('game_started');
|
||||||
|
|
||||||
|
this.players.forEach((p) => {
|
||||||
|
p.ready = false;
|
||||||
|
});
|
||||||
|
|
||||||
|
this.select_leader();
|
||||||
|
this.prepare_player_turns();
|
||||||
|
this.select_fake_artist();
|
||||||
|
this.notify_leader(); // to choose topic
|
||||||
|
|
||||||
|
this.spectators = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
select_leader() {
|
||||||
|
const leader =
|
||||||
|
this.players[Math.floor(Math.random() * this.players.length)];
|
||||||
|
|
||||||
|
this.leader = leader;
|
||||||
|
|
||||||
|
var remaining_players = this.players.filter(e => e !== leader);
|
||||||
|
this.actual_players = remaining_players.sort((a, b) => 0.5 - Math.random());
|
||||||
|
}
|
||||||
|
|
||||||
|
prepare_player_turns() {
|
||||||
|
this.player_turns = this.actual_players.concat(this.actual_players);
|
||||||
|
|
||||||
|
this.turn_drawdata =
|
||||||
|
[]; // new Array(this.player_turns.length).fill(new Array());
|
||||||
|
for (var i = 0; i < this.player_turns.length; i++) {
|
||||||
|
this.turn_drawdata.push([]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
select_fake_artist() {
|
||||||
|
const fake_artist = this.actual_players[Math.floor(
|
||||||
|
Math.random() * this.actual_players.length)];
|
||||||
|
|
||||||
|
this.fake_artist = fake_artist;
|
||||||
|
}
|
||||||
|
|
||||||
|
notify_leader() {
|
||||||
|
this.topic = '';
|
||||||
|
this.hint = '';
|
||||||
|
|
||||||
|
io.to(this.room_id).emit('leader_selected', this.leader);
|
||||||
|
}
|
||||||
|
|
||||||
|
start_voting() {
|
||||||
|
this.current_game_state = GAME_STATE.VOTING;
|
||||||
|
this.player_votes = {};
|
||||||
|
this.can_vote =
|
||||||
|
this.player_turns.slice(0, [Math.ceil(this.player_turns.length / 2)]);
|
||||||
|
|
||||||
|
this.can_vote.forEach((p) => {
|
||||||
|
this.player_votes[p.id] = 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log('GAME FINISHED!');
|
||||||
|
io.to(this.room_id).emit('game_finished', this.leader, this.can_vote);
|
||||||
|
}
|
||||||
|
|
||||||
|
end_voting() {}
|
||||||
|
|
||||||
|
update_player_list() {
|
||||||
|
io.to(this.room_id).emit('player_data', this.players);
|
||||||
|
}
|
||||||
|
|
||||||
|
update_votes() {
|
||||||
|
var vote_data = {};
|
||||||
|
|
||||||
|
vote_data.players_voted = [];
|
||||||
|
|
||||||
|
const already_voted_players = this.actual_players.filter(
|
||||||
|
a => !this.can_vote.map(b => b.id).includes(a.id));
|
||||||
|
/*this.actual_players.filter( el => {
|
||||||
|
return this.can_vote.some( f => {
|
||||||
|
return f.id == el.id;
|
||||||
|
});
|
||||||
|
});*/
|
||||||
|
|
||||||
|
// console.log(already_voted_players);
|
||||||
|
|
||||||
|
already_voted_players.forEach((p) => {
|
||||||
|
vote_data.players_voted.push(p.id);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (this.can_vote.length == 0) {
|
||||||
|
vote_data.done = true;
|
||||||
|
// everybody voted, send full data
|
||||||
|
vote_data.player_votes = this.player_votes;
|
||||||
|
vote_data.fake_artist = this.fake_artist;
|
||||||
|
this.current_game_state = GAME_STATE.RESULTS;
|
||||||
|
io.to(this.room_id).emit('show_vote_results', vote_data);
|
||||||
|
this.update_player_list();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
io.to(this.room_id).emit('update_votes', vote_data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
advance_turn() {
|
||||||
|
console.log('turn: ', this.current_turn);
|
||||||
|
|
||||||
|
if (this.current_game_state == GAME_STATE.VOTING) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.current_player = this.player_turns[this.current_turn];
|
||||||
|
|
||||||
|
if (this.current_turn >= this.player_turns.length) {
|
||||||
|
this.start_voting();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.disconnected_during_session.includes(this.current_player.id)) {
|
||||||
|
this.current_turn++;
|
||||||
|
advance_turn();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
io.to(this.room_id)
|
||||||
|
.emit('advance_turn', this.current_turn, this.current_player);
|
||||||
|
|
||||||
|
this.current_turn++; // because of this we have to -1 current_turn in some
|
||||||
|
// instances
|
||||||
|
}
|
||||||
|
|
||||||
|
get_next_free_player_color() {
|
||||||
|
var player_color = available_colors[0];
|
||||||
|
|
||||||
|
for (var i = 0; i < available_colors.length; i++) {
|
||||||
|
var free = true;
|
||||||
|
for (var k = 0; k < this.players.length; k++) {
|
||||||
|
if (available_colors[i] == this.players[k].player_color) {
|
||||||
|
free = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (free) {
|
||||||
|
player_color = available_colors[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return player_color;
|
||||||
|
}
|
||||||
|
|
||||||
|
all_players_ready() {
|
||||||
|
// Check if all players are ready
|
||||||
|
// and if we have at least 3 players...
|
||||||
|
if (this.players.length < 3) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const not_ready = this.players.filter((p) => p.ready == false);
|
||||||
|
if (not_ready.length > 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
is_spectator(player) {
|
||||||
|
return this.spectators.some((e) => {
|
||||||
|
return e.id == player.id;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
add_player(socket_, name_) {
|
||||||
|
const player =
|
||||||
|
new Player(socket_.id, name_, this.get_next_free_player_color());
|
||||||
this.players.push(player);
|
this.players.push(player);
|
||||||
|
|
||||||
|
socket_.join(this.room_id);
|
||||||
|
|
||||||
|
socket_.game = this;
|
||||||
|
|
||||||
|
this.update_player_list();
|
||||||
|
|
||||||
|
if (this.current_game_state != GAME_STATE.PRE_GAME) {
|
||||||
|
console.log('adding spectator', player.player_name);
|
||||||
|
this.spectators.push(player);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.current_game_state == GAME_STATE.TOPIC_SELECTION) {
|
||||||
|
socket_.emit('game_started');
|
||||||
|
socket_.emit('leader_selected', this.leader);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send current game state data to socket
|
||||||
|
if (this.current_game_state == GAME_STATE.DRAWING ||
|
||||||
|
this.current_game_state == GAME_STATE.RESULTS ||
|
||||||
|
this.current_game_state == GAME_STATE.VOTING) {
|
||||||
|
socket_.emit('game_started');
|
||||||
|
socket_.emit('actually_start_game', this.actual_players);
|
||||||
|
socket_.emit(
|
||||||
|
'topic_selected', '? (You are a spectator. No cheating!)', this.hint);
|
||||||
|
for (var turn = 0; turn < this.current_turn; turn++) {
|
||||||
|
console.log('StateTurn: ', turn, this.turn_drawdata[turn].length);
|
||||||
|
socket_.emit('advance_turn', turn, this.player_turns[turn]);
|
||||||
|
for (var idx = 0; idx < this.turn_drawdata[turn].length; idx++) {
|
||||||
|
console.log('DrawData: ', turn, idx);
|
||||||
|
socket_.emit('draw_data', turn, this.turn_drawdata[turn][idx]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// console.log(JSON.stringify(this.turn_drawdata));
|
||||||
|
|
||||||
|
if (this.current_game_state == GAME_STATE.RESULTS ||
|
||||||
|
this.current_game_state == GAME_STATE.VOTING) {
|
||||||
|
socket_.emit(
|
||||||
|
'game_finished', this.leader,
|
||||||
|
this.player_turns.slice(
|
||||||
|
0, [Math.ceil(this.player_turns.length / 2)]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
socket_.on('ready', () => {
|
||||||
|
console.log(socket_.id);
|
||||||
|
console.log(this.players);
|
||||||
|
const p = this.get_player(socket_.id);
|
||||||
|
if (p) {
|
||||||
|
p.ready = true;
|
||||||
|
this.update_player_list();
|
||||||
|
|
||||||
|
this.try_start_game();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
socket_.on('draw_data', (arr) => {
|
||||||
|
if (socket_.id != this.current_player.id) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// console.log(this.current_turn - 1, arr);
|
||||||
|
this.turn_drawdata[this.current_turn - 1].push(arr);
|
||||||
|
|
||||||
|
socket_.broadcast.to(this.room_id)
|
||||||
|
.emit('draw_data', this.current_turn - 1, arr);
|
||||||
|
});
|
||||||
|
|
||||||
|
socket_.on('topic_selected', (topic, hint) => {
|
||||||
|
if (this.current_game_state != GAME_STATE.TOPIC_SELECTION) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(topic, hint);
|
||||||
|
|
||||||
|
if (socket_.id != this.leader.id) {
|
||||||
|
// Ignore other people trying to set a topic
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (topic.length < 2 || hint.length < 2) {
|
||||||
|
socket_.emit(
|
||||||
|
'topic_error',
|
||||||
|
'The provided topic/hint are too short (min. 2 characters)')
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.topic = topic;
|
||||||
|
this.hint = hint;
|
||||||
|
|
||||||
|
console.log(this.spectators);
|
||||||
|
|
||||||
|
this.players.forEach((player) => {
|
||||||
|
console.log(player.id);
|
||||||
|
if (this.is_spectator(player)) {
|
||||||
|
io.to(player.id).emit(
|
||||||
|
'topic_selected', '? (You are a spectator. No cheating!)', hint);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (player.id != this.fake_artist.id) {
|
||||||
|
console.log('OK');
|
||||||
|
io.to(player.id).emit('topic_selected', topic, hint);
|
||||||
|
} else {
|
||||||
|
console.log('FAKE');
|
||||||
|
io.to(player.id).emit(
|
||||||
|
'topic_selected', '? (You are the Fake Artist!)', hint);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.current_game_state = GAME_STATE.DRAWING;
|
||||||
|
io.to(this.room_id).emit('actually_start_game', this.actual_players);
|
||||||
|
this.current_turn = 0;
|
||||||
|
this.advance_turn();
|
||||||
|
});
|
||||||
|
|
||||||
|
socket_.on('turn_finished', () => {
|
||||||
|
if (this.current_game_state != GAME_STATE.DRAWING) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var turn = 0; turn < this.current_turn; turn++) {
|
||||||
|
console.log('DrawDataLength: ', turn, this.turn_drawdata[turn].length);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.advance_turn();
|
||||||
|
});
|
||||||
|
|
||||||
|
socket_.on('vote_for_player', (player_id) => {
|
||||||
|
if (this.current_game_state != GAME_STATE.VOTING) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.can_vote.filter(e => e.id === socket_.id).length > 0) {
|
||||||
|
// do vote
|
||||||
|
this.can_vote = this.can_vote.filter(e => e.id !== socket_.id);
|
||||||
|
console.log(this.can_vote);
|
||||||
|
console.log('do vote');
|
||||||
|
|
||||||
|
this.player_votes[player_id]++;
|
||||||
|
|
||||||
|
this.update_votes();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
socket_.on('disconnect', () => {
|
||||||
|
console.log('Player disconnected!');
|
||||||
|
this.remove_player(socket_.id);
|
||||||
|
|
||||||
|
// if this was the last player of our game
|
||||||
|
if (this.players.length == 0) {
|
||||||
|
delete active_games[this.room_id];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.try_start_game();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
try_start_game() {
|
||||||
|
if (this.all_players_ready()) {
|
||||||
|
this.start_game();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
remove_player(player_id) {
|
remove_player(player_id) {
|
||||||
this.players.splice(
|
this.players.splice(
|
||||||
this.players.findIndex(item => item.id === player_id), 1)
|
this.players.findIndex(item => item.id === player_id), 1);
|
||||||
|
this.update_player_list();
|
||||||
|
}
|
||||||
|
|
||||||
|
get_player(player_id) {
|
||||||
|
const idx = this.players.findIndex(item => item.id === player_id);
|
||||||
|
|
||||||
|
if (idx != -1) {
|
||||||
|
return this.players[idx];
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var active_games = {};
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
GameLoop:
|
GameLoop:
|
||||||
- Lobby
|
- Lobby
|
||||||
|
|
@ -94,19 +465,11 @@ game)
|
||||||
- They take turns, only getting to see the image once its their turn (may be
|
- They take turns, only getting to see the image once its their turn (may be
|
||||||
changed, depending) on how boring it gets to wait (maybe only let game leade
|
changed, depending) on how boring it gets to wait (maybe only let game leade
|
||||||
peek)
|
peek)
|
||||||
- Once everybody painted two strokes (two full rounds of the game)
|
- Once everybody painted two strokes (two full turns of the game)
|
||||||
Reveal the image to everybody
|
Reveal the image to everybody
|
||||||
*/
|
*/
|
||||||
|
|
||||||
initGame =
|
app.use(cors());
|
||||||
() => {
|
|
||||||
console.log('Initializing Game!');
|
|
||||||
let count = 0;
|
|
||||||
// Game.map = {};
|
|
||||||
// console.log("Map Created: ", Game.map);
|
|
||||||
}
|
|
||||||
|
|
||||||
app.use(cors());
|
|
||||||
app.use(express.static('static'));
|
app.use(express.static('static'));
|
||||||
|
|
||||||
app.get('/', (req, res) => {
|
app.get('/', (req, res) => {
|
||||||
|
|
@ -116,19 +479,14 @@ app.get('/', (req, res) => {
|
||||||
io.on('connection', (socket) => {
|
io.on('connection', (socket) => {
|
||||||
console.log('User: ', socket.id, ' connected.');
|
console.log('User: ', socket.id, ' connected.');
|
||||||
|
|
||||||
socket.on('draw_data', (arr) => {
|
// Create Room
|
||||||
if (socket.room) {
|
// Join Room
|
||||||
var room_id = socket.room;
|
// Ready Up (Pre-Game and for Replay) -> Start game
|
||||||
var game = active_games[room_id];
|
// Vote cast
|
||||||
|
// Topic selected (Topic + Hint)
|
||||||
socket.broadcast.to(game.room_id)
|
// turn Finished (Finished Drawing, either by lifting the pen or using up all
|
||||||
.emit('draw_data', game.current_round - 1, arr);
|
// ink) Connect / Disconnect (disconnect is especially important to remove
|
||||||
}
|
// players from games/lobbies)
|
||||||
|
|
||||||
console.log(arr[0], arr[1]);
|
|
||||||
});
|
|
||||||
|
|
||||||
// socket.on('')
|
|
||||||
|
|
||||||
socket.on('create_room', (username) => {
|
socket.on('create_room', (username) => {
|
||||||
if (username == '') {
|
if (username == '') {
|
||||||
|
|
@ -136,247 +494,60 @@ io.on('connection', (socket) => {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('New room');
|
|
||||||
var room_id = randomId();
|
var room_id = randomId();
|
||||||
console.log(room_id);
|
while (room_id in active_games) {
|
||||||
socket.join(room_id);
|
var room_id = randomId();
|
||||||
socket.emit('room', room_id);
|
}
|
||||||
console.log(io.sockets.adapter.rooms);
|
|
||||||
|
|
||||||
var game = new Game(room_id);
|
var game = new Game(room_id);
|
||||||
|
|
||||||
var player_color = available_colors[0];
|
|
||||||
|
|
||||||
for (var i = 0; i < available_colors.length; i++) {
|
|
||||||
var free = true;
|
|
||||||
for (var k = 0; k < game.players.length; k++) {
|
|
||||||
if (available_colors[i] == game.players[k].player_color) {
|
|
||||||
free = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (free) {
|
|
||||||
player_color = available_colors[i];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var player = new Player(socket.id, username, player_color);
|
|
||||||
|
|
||||||
game.add_player(player);
|
|
||||||
|
|
||||||
socket.room = room_id;
|
|
||||||
|
|
||||||
active_games[room_id] = game;
|
active_games[room_id] = game;
|
||||||
io.to(room_id).emit('player_data', active_games[room_id].players);
|
|
||||||
console.log(JSON.stringify(active_games[room_id]));
|
socket.emit(
|
||||||
|
'join_room',
|
||||||
|
room_id); // maybe do this in the game instance instead? same as join
|
||||||
|
game.add_player(socket, username);
|
||||||
|
game.update_player_list();
|
||||||
});
|
});
|
||||||
|
|
||||||
socket.on('start_game', () => {
|
|
||||||
if (socket.room) {
|
|
||||||
var room_id = socket.room;
|
|
||||||
var game = active_games[room_id];
|
|
||||||
|
|
||||||
if(game.game_state == GAME_STATE.TOPIC_SELECTION) {
|
|
||||||
// TODO: Check what happens after replay
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
game.game_state = GAME_STATE.TOPIC_SELECTION;
|
|
||||||
|
|
||||||
io.to(room_id).emit('game_started');
|
|
||||||
|
|
||||||
var leader =
|
|
||||||
game.players[Math.floor(Math.random() * game.players.length)];
|
|
||||||
game.leader = leader;
|
|
||||||
|
|
||||||
var remaining_players = game.players.filter(e => e !== leader);
|
|
||||||
game.actual_players = remaining_players.sort((a, b) => 0.5 - Math.random());
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
game.player_turns = game.actual_players.concat(game.actual_players);
|
|
||||||
|
|
||||||
var fake_artist = remaining_players[Math.floor(
|
|
||||||
Math.random() * remaining_players.length)];
|
|
||||||
|
|
||||||
game.fake_artist = fake_artist;
|
|
||||||
|
|
||||||
io.to(room_id).emit('leader_selected', leader);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
socket.on('topic_selected', (topic, hint) => {
|
|
||||||
console.log(topic, hint);
|
|
||||||
|
|
||||||
if (socket.room) {
|
|
||||||
var room_id = socket.room;
|
|
||||||
var game = active_games[room_id];
|
|
||||||
|
|
||||||
if(game.game_state != GAME_STATE.TOPIC_SELECTION) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(socket.id != game.leader.id) {
|
|
||||||
// Ignore other people trying to set a topic
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(topic.length < 2 || hint.length < 2) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
game.topic = topic;
|
|
||||||
game.hint = hint;
|
|
||||||
|
|
||||||
game.players.forEach((player) => {
|
|
||||||
console.log(player.id);
|
|
||||||
if (player.id != game.fake_artist.id) {
|
|
||||||
console.log('OK');
|
|
||||||
io.to(player.id).emit('topic_selected', topic, hint);
|
|
||||||
} else {
|
|
||||||
console.log('FAKE');
|
|
||||||
io.to(player.id).emit('topic_selected', '', hint);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
game.game_state = GAME_STATE.DRAWING;
|
|
||||||
io.to(socket.room).emit('actually_start_game', game.actual_players);
|
|
||||||
|
|
||||||
|
|
||||||
// FIXME: Super slow for some reason
|
|
||||||
// Maybe just do the following:
|
|
||||||
// Have a manual advance on the clients (button, ink empty, on mouse up)
|
|
||||||
// If someone disconnects, just manually advance, no timeout needed
|
|
||||||
game.current_round = 0;
|
|
||||||
|
|
||||||
// game.current_player = game.player_turns[game.current_round];
|
|
||||||
// socket.to(socket.room).emit('advance_round', game.current_round,
|
|
||||||
// game.current_player);
|
|
||||||
|
|
||||||
play_next_turn(game);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
function play_next_turn(game) {
|
|
||||||
console.log('Round: ', game.current_round);
|
|
||||||
|
|
||||||
if (game.game_state == GAME_STATE.VOTING) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (game.current_round >= game.player_turns.length) {
|
|
||||||
game.game_state = GAME_STATE.VOTING;
|
|
||||||
console.log('GAME FINISHED!');
|
|
||||||
io.to(game.room_id).emit('game_finished', game.leader, game.player_turns.slice(0, [Math.ceil(game.player_turns.length / 2)]));
|
|
||||||
game.game_state = GAME_STATE.VOTING;
|
|
||||||
// TODO: Pass fake artist after voting... implement voting in the first
|
|
||||||
// place
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//while(game.current_player)
|
|
||||||
|
|
||||||
game.current_player = game.player_turns[game.current_round];
|
|
||||||
io.to(game.room_id)
|
|
||||||
.emit('advance_round', game.current_round, game.current_player);
|
|
||||||
|
|
||||||
game.current_round++;
|
|
||||||
}
|
|
||||||
|
|
||||||
socket.on('round_finished', () => {
|
|
||||||
if (socket.room) {
|
|
||||||
var room_id = socket.room;
|
|
||||||
var game = active_games[room_id];
|
|
||||||
|
|
||||||
if (game.game_state != GAME_STATE.DRAWING) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log('round finished!');
|
|
||||||
play_next_turn(game);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// socket.
|
|
||||||
|
|
||||||
socket.on('join_room', (room_id, username) => {
|
socket.on('join_room', (room_id, username) => {
|
||||||
|
var upper_room_id = room_id.toUpperCase();
|
||||||
|
|
||||||
if (username == '') {
|
if (username == '') {
|
||||||
socket.emit('room_error', 'Invalid username!');
|
socket.emit('room_error', 'Invalid username!');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!active_games[room_id]) {
|
if (!active_games[upper_room_id]) {
|
||||||
socket.emit('room_error', 'This room does not exist!');
|
socket.emit('room_error', 'This room does not exist!');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var user_count = active_games[room_id].players.length;
|
var user_count = active_games[upper_room_id].players.length;
|
||||||
|
|
||||||
if (user_count > 10) {
|
if (user_count >= 10) {
|
||||||
socket.emit('room_error', 'This room is full!');
|
socket.emit('room_error', 'This room is full!');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var game_state = active_games[room_id].current_game_state;
|
var game = active_games[upper_room_id];
|
||||||
|
game.add_player(socket, username);
|
||||||
if (game_state != GAME_STATE.PRE_GAME) {
|
socket.emit(
|
||||||
socket.emit('room_error', 'This game is already in progress!');
|
'join_room',
|
||||||
return;
|
upper_room_id); // maybe do this in the game instance instead?
|
||||||
}
|
game.update_player_list(); // this could be automated then...
|
||||||
|
|
||||||
|
|
||||||
var game = active_games[room_id];
|
|
||||||
|
|
||||||
socket.join(room_id);
|
|
||||||
|
|
||||||
var player_color = available_colors[0];
|
|
||||||
|
|
||||||
for (var i = 0; i < available_colors.length; i++) {
|
|
||||||
var free = true;
|
|
||||||
for (var k = 0; k < game.players.length; k++) {
|
|
||||||
if (available_colors[i] == game.players[k].player_color) {
|
|
||||||
free = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (free) {
|
|
||||||
player_color = available_colors[i];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var player = new Player(socket.id, username, player_color);
|
|
||||||
active_games[room_id].add_player(player);
|
|
||||||
|
|
||||||
socket.room = room_id;
|
|
||||||
|
|
||||||
socket.emit('room', room_id);
|
|
||||||
io.to(room_id).emit('player_data', active_games[room_id].players);
|
|
||||||
console.log(JSON.stringify(active_games[room_id]));
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// TODO: Refactor/Check what's happening
|
||||||
socket.on('disconnect', () => {
|
socket.on('disconnect', () => {
|
||||||
console.log('User: ', socket.id, ' disconnected.');
|
console.log('User: ', socket.id, ' disconnected.');
|
||||||
|
|
||||||
if (socket.room) {
|
if (socket.game) {
|
||||||
var room_id = socket.room;
|
var room_id = socket.game.room_id;
|
||||||
var game = active_games[room_id];
|
const clients = io.sockets.adapter.rooms.get(room_id);
|
||||||
game.remove_player(room_id);
|
if (clients) {
|
||||||
io.to(room_id).emit('player_data', game.players);
|
for (const clientId of clients) {
|
||||||
|
console.log(clientId);
|
||||||
console.log(socket.id, game.current_player);
|
|
||||||
|
|
||||||
if (game.game_state == GAME_STATE.DRAWING) {
|
|
||||||
game.disconnected_during_session.push(game.players[socket.id]);
|
|
||||||
|
|
||||||
/*console.log(game.player_turns);
|
|
||||||
game.player_turns = game.player_turns.filter(e => e.id != socket.id);
|
|
||||||
console.log(game.player_turns);*/
|
|
||||||
if (socket.id == game.current_player.id) {
|
|
||||||
play_next_turn(game);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -387,5 +558,3 @@ io.on('connection', (socket) => {
|
||||||
http.listen(7777, '0.0.0.0', () => {
|
http.listen(7777, '0.0.0.0', () => {
|
||||||
console.log('Listening on 7777');
|
console.log('Listening on 7777');
|
||||||
})
|
})
|
||||||
|
|
||||||
initGame();
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue