const SCALE = 0.5
const SPACE = 100 * SCALE;
const RADIUS = 30 * SCALE;
const WIDTH = 450;
const HEIGHT = 450;
const state = {
app: {},
camera: {},
map_layer: {},
puppets_layer: {},
puppets: {},
map: {},
main: null,
playing: false,
history: [],
p_history: [],
turn: [],
control: {},
}
function selectMap(event) {
ws.send(window.location.hash.substr(1));
}
function listenWS_selectMap(event) {
const { opcode, message } = JSON.parse(event.data);
switch (opcode) {
case 'INCORRECT_MAP':
console.log('Wrong URL');
break;
case 'CORRECT_MAP':
console.log("We are in!")
setupGame();
break;
default:
console.log('Anomaly happened')
}
}
function setupGame() {
state.app = new PIXI.Application({
width: WIDTH,
height: HEIGHT,
antialias: true,
resolution: 1,
});
state.camera = new PIXI.Container();
state.map_layer = new PIXI.Container();
state.puppets_layer = new PIXI.Container();
state.app.stage.addChild(state.camera);
state.camera.addChild(state.map_layer);
state.camera.addChild(state.puppets_layer);
document.getElementById('scene').appendChild(state.app.view);
document.getElementById('move_left').onclick = () => {
let x = state.puppets[state.main].position.x / SPACE - 1,
y = state.puppets[state.main].position.y / SPACE;
askMoveTo(x, y);
newSelectedControl('move_left');
};
document.getElementById('move_right').onclick = () => {
let x = state.puppets[state.main].position.x / SPACE + 1,
y = state.puppets[state.main].position.y / SPACE;
askMoveTo(x, y);
newSelectedControl('move_right');
};
document.getElementById('move_up').onclick = () => {
let x = state.puppets[state.main].position.x / SPACE,
y = state.puppets[state.main].position.y / SPACE - 1;
askMoveTo(x, y);
newSelectedControl('move_up');
};
document.getElementById('move_down').onclick = () => {
let x = state.puppets[state.main].position.x / SPACE,
y = state.puppets[state.main].position.y / SPACE + 1;
askMoveTo(x, y);
newSelectedControl('move_down');
};
document.getElementById('attack_left').onclick = () => {
let x = state.puppets[state.main].position.x / SPACE - 1,
y = state.puppets[state.main].position.y / SPACE;
askAttackTo(x, y);
newSelectedControl('attack_left');
};
document.getElementById('attack_right').onclick = () => {
let x = state.puppets[state.main].position.x / SPACE + 1,
y = state.puppets[state.main].position.y / SPACE;
askAttackTo(x, y);
newSelectedControl('attack_right');
};
document.getElementById('attack_up').onclick = () => {
let x = state.puppets[state.main].position.x / SPACE,
y = state.puppets[state.main].position.y / SPACE - 1;
askAttackTo(x, y);
newSelectedControl('attack_up');
};
document.getElementById('attack_down').onclick = () => {
let x = state.puppets[state.main].position.x / SPACE,
y = state.puppets[state.main].position.y / SPACE + 1;
askAttackTo(x, y);
newSelectedControl('attack_down');
};
document.getElementById('defend_left').onclick = () => {
let x = state.puppets[state.main].position.x / SPACE - 1,
y = state.puppets[state.main].position.y / SPACE;
askDefendTo(x, y);
newSelectedControl('defend_left');
};
document.getElementById('defend_right').onclick = () => {
let x = state.puppets[state.main].position.x / SPACE + 1,
y = state.puppets[state.main].position.y / SPACE;
askDefendTo(x, y);
newSelectedControl('defend_right');
};
document.getElementById('defend_up').onclick = () => {
let x = state.puppets[state.main].position.x / SPACE,
y = state.puppets[state.main].position.y / SPACE - 1;
askDefendTo(x, y);
newSelectedControl('defend_up');
};
document.getElementById('defend_down').onclick = () => {
let x = state.puppets[state.main].position.x / SPACE,
y = state.puppets[state.main].position.y / SPACE + 1;
askDefendTo(x, y);
newSelectedControl('defend_down');
};
document.getElementById('surrender').onclick = () => {
ws.send(JSON.stringify({
opcode: 'SURRENDER',
arguments: {}
}));
newSelectedControl('surrender');
};
document.getElementById('wait').onclick = () => {
ws.send(JSON.stringify({
opcode: 'WAIT',
arguments: {}
}));
newSelectedControl('wait');
};
ws.onmessage = listenWS_playGame;
ws.send('ready to go, boss');
}
function askMoveTo(x, y) {
if (0 <= x && 0 <= y && x < state.map.width && y < state.map.height) {
ws.send(JSON.stringify({
opcode: "MOVE",
arguments: {
x: x,
y: y
}
}));
}
}
function askAttackTo(x, y) {
ws.send(JSON.stringify({
opcode: "ATTACK",
arguments: {
x: x,
y: y
}
}));
}
function askDefendTo(x, y) {
ws.send(JSON.stringify({
opcode: "DEFEND",
arguments: {
x: x,
y: y
}
}));
}
function drawArena(lines, rows) {
for (i = 0; i < lines; i++) {
const line = new PIXI.Graphics();
let color = 0xcc6600;
if (i % 2) {
color = 0xbb7711;
}
line.position.set(0, i * SPACE);
line.lineStyle(RADIUS, color)
.moveTo(0, 0)
.lineTo(SPACE * (rows - 1), 0);
state.map_layer.addChild(line);
}
for (i = 0; i < rows; i++) {
const line = new PIXI.Graphics();
let color = 0xcc6600;
if (i % 2) {
color = 0xbb7711;
}
line.position.set(i * SPACE, 0);
line.lineStyle(RADIUS, color)
.moveTo(0, 0)
.lineTo(0, SPACE * (lines - 1));
state.map_layer.addChild(line);
}
}
function addNewPuppet(pk, puppet) {
if (puppet.plays) {
const puppet_layer = new PIXI.Graphics();
puppet_layer.position.set(puppet.x * SPACE, puppet.y * SPACE);
puppet_layer.puppet_name = puppet.name;
puppet_layer.puppet_color = puppet.color;
puppet_layer.puppet_stamina = puppet.stamina;
puppet_layer.puppet_anger = puppet.anger;
state.puppets[pk] = puppet_layer;
state.puppets_layer.addChild(puppet_layer);
drawPuppet(pk, puppet.color);
if (state.main == pk) {
updateCamera();
updateHUD();
}
listPuppets();
}
}
function drawPuppet(pk, color) {
const layer = state.puppets[pk];
layer.beginFill(0xcecece);
layer.drawCircle(0, 0, RADIUS + 2);
layer.endFill();
layer.beginFill(color);
layer.drawCircle(0, 0, RADIUS);
layer.endFill();
}
function listPuppets() {
const elem = document.getElementById('players');
let txt = '',
cpt = 0;
Object.keys(state.puppets).filter(Boolean).forEach((pk) => {
if (state.puppets[pk]) {
cpt += 1;
txt +=
'
'
+ puppetName(pk)
+ '';
}
});
elem.innerHTML = '' + cpt + ' joueurs' + txt
}
function movePuppet(cmd) {
let pk = cmd.puppet,
x = cmd.x,
y = cmd.y;
if (state.puppets[pk]) {
state.puppets[pk].position.set(x * SPACE, y * SPACE);
if (state.main == pk) {
updateCamera();
}
}
}
function removePuppet(pk) {
state.puppets_layer.removeChild(state.puppets[pk]);
state.puppets[pk] = null;
listPuppets();
}
function updateHUD(duration) {
const main = state.puppets[state.main];
if (main) {
document.getElementById('stamina').style.width = main.puppet_stamina + '%';
document.getElementById('anger').style.width = main.puppet_anger + '%';
}
if (duration) {
document.getElementById('time').style.transition = '0s';
document.getElementById('time').style.width = '2%';
setTimeout(() => {
document.getElementById('time').style.transition = 'width ' + (duration - 50) + 'ms';
document.getElementById('time').style.width = '100%';
}, 50);
}
}
function updateCamera() {
if (state.main) {
const main = state.puppets[state.main];
let x = main.position.x,
y = main.position.y;
state.camera.position.set((WIDTH / 2) - x, (HEIGHT / 2) - y);
}
}
function listenWS_playGame(event) {
const { opcode, message } = JSON.parse(event.data);
console.log(opcode);
switch (opcode) {
case 'BEGIN_TURN':
state.history.push([]);
break;
case 'SELECT_PHASE':
if (state.playing) {
document.getElementById('lobby').style.display = 'none';
document.getElementById('control').style.display = 'block';
}
updateHUD(message.duration);
updateHistory();
break;
case 'PUPPET_CHOICES':
if (state.main == message.puppet) {
enableControl(message.up, message.right, message.down, message.left);
}
break;
case 'RESOLVE_PHASE':
disableControl();
document.getElementById('p_history').innerHTML = '';
break;
case 'INSTANCE_DIGEST':
let s = message.map.digest.space,
l = (message.map.digest.lines - 1) * s + 1,
r = (message.map.digest.rows - 1) * s + 1;
state.map.width = r;
state.map.height = l;
drawArena(l, r);
Object.keys(message.puppets).filter(Boolean).forEach((pk) => {
addNewPuppet(pk, message.puppets[pk]);
});
break;
case 'PUPPET_ENTERS':
addNewPuppet(message.puppet_key, message.digest);
if (message.puppet_key == state.main) {
document.getElementById('lobby').style.display = 'block';
const color_input = document.getElementById('color');
const name_input = document.getElementById('name');
color_input.value = '#' + message.digest.color.toString(16);
name_input.value = message.digest.name;
color_input.oninput = () => {
const new_color = parseColor(color_input.value);
ws.send(JSON.stringify({
opcode: "CHANGE_COLOR",
arguments: {
new_color: new_color
}
}));
};
name_input.oninput = () => {
const new_name = name_input.value;
ws.send(JSON.stringify({
opcode: "CHANGE_NAME",
arguments: {
new_name: new_name
}
}));
};
}
break;
case 'PUPPET_LEAVES':
removePuppet(message.puppet_key);
break;
case 'END_OF_GAME':
if (state.playing) {
addPersoEvent("Vous faites parti des gagnants")
document.getElementById('control').style.display = 'none';
document.getElementById('summary').style.display = 'none';
document.getElementById('history').style.display = 'block';
}
break;
case 'PUPPET_FALLS':
addEvent(puppetName(message.winner) + ' a fait tomber ' + puppetName(message.looser));
if (message.winner == state.main) {
addPersoEvent('Vous avez fait tomber ' + puppetName(message.looser));
} else if (message.looser == state.main) {
addPersoEvent(puppetName(message.winner) + ' vous a fait tomber');
document.getElementById('control').style.display = 'none';
document.getElementById('summary').style.display = 'none';
document.getElementById('history').style.display = 'block';
state.playing = false;
}
removePuppet(message.looser);
break;
case 'PUPPET_DISGRACE':
addEvent('Le public a réclamé la défaite de ' + puppetName(message.puppet));
if (message.puppet == state.main) {
addPersoEvent('Le public a réclamé votre défaite');
state.playing = false;
}
removePuppet(message.puppet);
break;
case 'PUPPET_SURRENDERS':
addEvent(puppetName(message.looser) + ' a abandonné');
if (message.looser == state.main) {
document.getElementById('control').style.display = 'none';
document.getElementById('summary').style.display = 'none';
document.getElementById('history').style.display = 'block';
addPersoEvent('Vous avez abandonné');
state.playing = false;
}
removePuppet(message.looser);
break;
case 'PUPPET_NAME':
state.puppets[message.puppet].puppet_name = message.name;
listPuppets();
break;
case 'PUPPET_COLOR':
state.puppets[message.puppet].puppet_color = message.color;
listPuppets();
drawPuppet(message.puppet, message.color);
break;
case 'ATTRIBUTE_PUPPET':
state.main = message.puppet_key;
state.playing = true;
break;
case 'PUPPET_WAITS':
break;
case 'PUPPET_MISS':
addEvent(puppetName(message.attacker) + ' a manqué sa cible');
if (message.attacker == state.main) {
addPersoEvent('Vous avez manqué votre cible');
}
break;
case 'PUPPET_ATTACKS':
let comp = '';
if (message.success) {
comp = ' et l’a blessé'
} else {
comp = ', sans succès'
}
addEvent(puppetName(message.attacker) + ' a attaqué ' + puppetName(message.target) + comp);
if (message.attacker == state.main && message.success) {
addPersoEvent('Vous avez attaqué ' + puppetName(message.target) + ' et êtes parvenu à le blesser');
} else if (message.attacker == state.main) {
addPersoEvent('Vous avez attaqué ' + puppetName(message.target) + ', sans succès');
} else if (message.target == state.main) {
addPersoEvent(puppetName(message.attacker) + ' vous a attaqué');
}
break;
case 'PUPPET_STAMINA':
state.puppets[message.puppet].puppet_stamina = message.stamina;
if (message.puppet == state.main) {
updateHUD();
}
break;
case 'PUPPET_ANGER':
state.puppets[message.puppet].puppet_anger = message.anger;
if (message.puppet == state.main) {
updateHUD();
}
break;
case 'PUPPET_MOVES':
/*
addEvent(puppetName(message.puppet) + ' s’est déplacé en ' + puppetPos(message.x, message.y));
if (message.puppet == state.main) {
addPersoEvent('Vous vous êtes déplacé en ' + puppetPos(message.x, message.y));
}
*/
movePuppet(message);
break;
default:
console.log("not yet implemented:");
console.log(opcode);
console.log(message);
}
}
ws = new WebSocket('ws://localhost:10000');
ws.onmessage = listenWS_selectMap;
ws.onopen = selectMap;
function parseColor(str) {
str = str.substr(1);
return parseInt("0x" + str, 16);
}
function puppetName(pk) {
if (state.puppets[pk]) {
return ''
+ state.puppets[pk].puppet_name
+ '';
} else {
return '???';
}
}
function puppetPos(x, y) {
return '(' + x + ', ' + y + ')';
}
function addEvent(str) {
if (state.history[state.history.length - 1]) {
state.history[state.history.length - 1].push(str);
}
}
function addPersoEvent(str) {
state.p_history.push(str);
}
function updateHistory() {
const hist = document.getElementById('history');
let txt = '';
state.history.forEach((turn_hist, turn) => {
if (0 < turn_hist.length) {
txt += ' Tour ' + (turn + 1).toString() + '
';
turn_hist.forEach((elem) => {
txt += '- ' + elem + '
';
});
txt += '
';
}
});
hist.innerHTML = txt;
txt = '';
state.p_history.forEach((elem) => {
txt += '- ' + elem + '
';
});
txt += '
';
document.getElementById('p_history').innerHTML = txt;
if (state.playing) {
state.p_history = [];
}
}
function disableControl() {
disable('move_left');
disable('move_right');
disable('move_up');
disable('move_down');
disable('attack_left');
disable('attack_right');
disable('attack_up');
disable('attack_down');
disable('wait');
disable('surrender');
}
function enableControl(up, right, down, left) {
document.getElementById('wait').disabled = false;
document.getElementById('surrender').disabled = false;
if (up == 1) {
document.getElementById('move_up').disabled = false;
} else if (up == 2) {
document.getElementById('attack_up').disabled = false;
document.getElementById('defend_up').disabled = false;
}
if (right == 1) {
document.getElementById('move_right').disabled = false;
} else if (right == 2) {
document.getElementById('attack_right').disabled = false;
document.getElementById('defend_right').disabled = false;
}
if (left == 1) {
document.getElementById('move_left').disabled = false;
} else if (left == 2) {
document.getElementById('attack_left').disabled = false;
document.getElementById('defend_left').disabled = false;
}
if (down == 1) {
document.getElementById('move_down').disabled = false;
} else if (down == 2) {
document.getElementById('attack_down').disabled = false;
document.getElementById('defend_down').disabled = false;
}
}
disableControl()
function newSelectedControl(cls) {
if (state.control) {
state.control.style.color = '';
state.control.style.fontWeight = '';
state.control.disabled = false;
}
state.control = document.getElementById(cls);
state.control.style.color = 'goldenrod';
state.control.disabled = true;
state.control.style.fontWeight = 'bold';
}
function disable(cls) {
let elem = document.getElementById(cls);
elem.style.fontWeight = '';
elem.style.color = '';
elem.disabled = true;
}