Merge pull request #38 from H4CK3R-01/player-movement

Player movement
This commit is contained in:
Florian Kaiser 2021-06-18 10:20:22 +02:00 committed by GitHub
commit 60adfc1e49
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 223 additions and 139 deletions

View File

@ -1,26 +1,35 @@
const Player = require('./Player');
const Hunter = require("./Hunter");
class Game {
constructor() {
this.players = [];
this.whosNext = 0;
this.currentPlayerIndex = 0;
this.started = false;
this.round = 0;
this.hunter = new Hunter();
}
finish_turn() {
let move_to_next_round = false;
// move on to next player; skip dead players
do {
this.whosNext++;
if (this.whosNext === this.players.length) {
this.whosNext = 0;
this.round++;
if (this.players.length === 0) break;
this.currentPlayerIndex++;
if (this.currentPlayerIndex >= this.players.length) {
this.currentPlayerIndex = 0;
move_to_next_round = true;
}
} while (!this.players[this.whosNext].isAlive);
} while (!this.players[this.currentPlayerIndex].isAlive); // skip dead players
this.finish_round();
}
finish_round() {
this.round++;
// kill players with hunter
if (this.round >= 5) {
this.hunter.move(1);
this.hunter.move_by(1);
this.hunter.hunt(this.players);
}
// check if all players are dead
@ -28,6 +37,32 @@ class Game {
// todo: end game (all players are dead)
}
}
add_player(name) {
this.players.push(new Player(name));
}
remove_player(name) {
let index = this.get_player_index(name);
if (index !== -1) {
this.players.splice(index, 1);
if (this.currentPlayerIndex >= index) this.currentPlayerIndex--;
}
if (this.currentPlayerIndex === index) this.finish_turn(); // if current player leaves: move on to next
}
current_player_is(name) {
return this.players[this.currentPlayerIndex].name === name;
}
get_player_index(name) {
return this.players.findIndex(player => player.name === name);
}
move_player(name, amount) {
let index = this.get_player_index(name);
this.players[index].move_by(amount);
}
}
module.exports = Game;

View File

@ -3,7 +3,7 @@ class Hunter {
this.position = 0;
}
move(amount) {
move_by(amount) {
this.position += amount;
}

View File

@ -1,13 +1,14 @@
class Player {
constructor(socketUsername) {
this.socketUsername = socketUsername;
constructor(name) {
this.name = name;
this.position = 0;
this.isAlive = true;
}
move(amount) {
move_by(amount) {
this.position += amount;
if (this.position === 15) {
//todo: move by 1 only on the last 3 fields
if (this.position >= 16) {
// todo: win
}
}

View File

@ -1,11 +0,0 @@
function isMobile() {
let mobileDeviceIndicator = 0;
if (/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)) {
mobileDeviceIndicator = 1;
}
/*
let hasTouchscreen = 'ontouchstart' in window;
alert(hasTouchscreen ? 'has touchscreen' : 'doesn\'t have touchscreen');
*/
}

View File

@ -1,4 +1,3 @@
const Player = require('./Player');
const Game = require('./Game');
const express = require('express');
@ -50,7 +49,7 @@ io.on('connection', socket => {
}
if (gameState[socket.room].players.length < 4 && !gameState[socket.room].started) {
gameState[socket.room].players.push(new Player(socket.username));
gameState[socket.room].add_player(socket.username);
addedUser = true;
socket.emit('login');
@ -60,7 +59,7 @@ io.on('connection', socket => {
generate_log_message(socket.room, socket.username, "JOINED", "");
} else {
// TODO
io.to(socket.id).emit('error', 'Game started already or room has two many members');
}
});
@ -78,23 +77,13 @@ io.on('connection', socket => {
socket.on('disconnect', function () {
if (gameState[socket.room] !== undefined && addedUser) {
socket.broadcast.to(socket.room).emit('user left', socket.username);
let index = -1;
for (let i = 0; i < gameState[socket.room].players.length; i++) {
if (gameState[socket.room].players[i].socketUsername === socket.username) {
index = i;
break;
}
}
gameState[socket.room].remove_player(socket.username);
if (index > -1) {
gameState[socket.room].players.splice(index, 1);
}
// TODO Close card if card is opened and active player left
socket.leave(socket.room);
if (gameState[socket.room].players.length === 0) {
delete gameState[socket.room];
}
if (gameState[socket.room].players.length === 0) delete gameState[socket.room];
}
generate_log_message(socket.room, socket.username, "LEFT", "");
@ -103,12 +92,7 @@ io.on('connection', socket => {
// Game
socket.on('roll dice', function () {
if (gameState[socket.room] !== undefined && addedUser) {
if(gameState[socket.room].players[gameState[socket.room].whosNext] === undefined) {
console.log(gameState[socket.room].players)
console.log(gameState[socket.room].whosNext)
}
if (gameState[socket.room].players[gameState[socket.room].whosNext].socketUsername === socket.username) {
if (gameState[socket.room].current_player_is(socket.username)) {
gameState[socket.room].started = true;
let sides = 3;
let randomNumber = Math.floor(Math.random() * sides) + 1;
@ -117,28 +101,40 @@ io.on('connection', socket => {
generate_log_message(socket.room, socket.username, "DICE", randomNumber);
} else {
// TODO
io.to(socket.id).emit('error', 'It\'s not your turn');
}
}
});
socket.on('get card', function (difficulty) {
if (gameState[socket.room] !== undefined && addedUser) {
if (gameState[socket.room].players[gameState[socket.room].whosNext].socketUsername === socket.username) {
if (gameState[socket.room].current_player_is(socket.username)) {
io.in(socket.room).emit('card', {'username': socket.username, 'card': getRandomCard(difficulty)});
generate_log_message(socket.room, socket.username, "CARD", difficulty);
} else {
// TODO
io.to(socket.id).emit('error', 'It\'s not your turn');
}
}
});
socket.on('card finished', function (difficulty, answerIsCorrect) {
if (gameState[socket.room] !== undefined && addedUser) {
if (answerIsCorrect) gameState[socket.room].players[gameState[socket.room].whosNext].move(difficulty);
if (answerIsCorrect) {
gameState[socket.room].move_player(socket.username, difficulty);
generate_log_message(socket.room, socket.username, "MOVE", difficulty);
}
io.in(socket.room).emit('card destroyed');
gameState[socket.room].finish_turn();
let index = gameState[socket.room].get_player_index(socket.username);
let next_player = gameState[socket.room].players[gameState[socket.room].currentPlayerIndex].name;
io.in(socket.room).emit('player moved', {
"next_player": next_player,
"player": index,
"position": gameState[socket.room].players[index].position
});
}
});
});
@ -161,6 +157,9 @@ function generate_log_message(room, user, type, message) {
case 'DICE':
color = '\x1b[34m';
break;
case 'MOVE':
color = '\x1b[30m';
break;
default:
color = '\x1b[0m';
}

View File

@ -1,3 +1,7 @@
#error {
color: red;
}
#login {
background: #212121;
height: 100%;

View File

@ -1,35 +0,0 @@
html {
width: 100%;
height: 100%;
font-family: Arial, sans-serif
}
body {
width: 100%;
height: 100%;
padding: 0;
margin: 0;
overflow: hidden;
}
main {
display: grid;
grid-template-rows: 80% 20%;
height: calc(100% - 3em - 10px);
}
.material-icon {
font-family: Material Icons, sans-serif !important;
font-weight: 400;
font-style: normal;
font-size: 24px;
line-height: 1;
letter-spacing: normal;
text-transform: none;
display: inline-block;
white-space: nowrap;
word-wrap: normal;
direction: ltr;
-webkit-font-feature-settings: "liga";
-webkit-font-smoothing: antialiased;
}

View File

@ -24,6 +24,7 @@
<main>
<div id="login">
<form>
<h2 id="error"></h2>
<label for="username">Benutzername: </label>
<input id="username" name="username" placeholder="Benutzername" type="text">

View File

@ -2,15 +2,29 @@ let socket;
let connected = false;
function start_chat() {
socket = io("/", {
closeOnBeforeunload: false
});
socket.on('login', function () {
connected = true;
document.getElementById('login').style.display = 'none';
document.getElementById('game').style.display = 'flex';
document.getElementById('chat').style.display = 'flex';
start_chat();
start_game();
resize();
addLogMessage("Welcome " + username + "!");
});
socket.on('error', function (data) {
if (data === 'Game started already or room has two many members') {
document.getElementById('login').style.display = 'flex';
document.getElementById('game').style.display = 'none';
document.getElementById('chat').style.display = 'none';
document.getElementById('error').innerText = data;
}
console.log(data);
});
socket.on('new message', function (data) {
addChatMessage(data);
});
@ -22,9 +36,6 @@ function start_chat() {
socket.on('user left', function (data) {
addLogMessage(data + ' left');
});
// Login
socket.emit('add user', {'username': username, 'room_name': room_name});
}
function sendMessage() {

View File

@ -14,38 +14,30 @@ let rolled_number = null;
let game = document.getElementById('game');
let app;
let border_card_stack = new PIXI.Graphics();
let my_turn;
let game_board_size = 2000;
let max_size = calculate_size();
let sprite_size = Math.floor(game_board_size / 11);
const rolled_number_style = new PIXI.TextStyle({
fontFamily: 'Arial',
fontSize: 140,
fontWeight: 'bold',
wordWrap: true,
wordWrapWidth: game_board_size * 0.5 - 20,
});
let rolled_number_text = new PIXI.Text("", rolled_number_style);
// fields
let sprites = [
new Sprite(9, 9),
new Sprite(9, 7),
new Sprite(9, 5),
new Sprite(9, 3),
new Sprite(9, 1),
new Sprite(7, 1),
new Sprite(5, 1),
new Sprite(3, 1),
new Sprite(1, 1),
new Sprite(1, 3),
new Sprite(1, 5),
new Sprite(1, 7),
new Sprite(1, 9),
new Sprite(3, 9),
new Sprite(9, 9), // lower right
new Sprite(7, 9),
new Sprite(5, 9),
new Sprite(7, 9)
new Sprite(3, 9),
new Sprite(1, 9), // upper right
new Sprite(1, 7),
new Sprite(1, 5),
new Sprite(1, 3),
new Sprite(1, 1), // upper left
new Sprite(3, 1),
new Sprite(5, 1),
new Sprite(7, 1),
new Sprite(9, 1), // lower left
new Sprite(9, 3),
new Sprite(9, 5),
new Sprite(9, 7)
];
function start_game() {
@ -66,19 +58,22 @@ function start_game() {
// White circles
let first_circle = generate_circle(new PIXI.Graphics(), 3, 9);
app.stage.addChild(first_circle);
let player_a = generate_circle(new PIXI.Graphics(), 9, 9, 'yellow', 1);
app.stage.addChild(player_a);
let second_circle = generate_circle(new PIXI.Graphics(), 5, 9);
app.stage.addChild(second_circle);
let player_b = generate_circle(new PIXI.Graphics(), 9, 9, 'blue', 2);
app.stage.addChild(player_b);
let third_circle = generate_circle(new PIXI.Graphics(), 7, 9);
app.stage.addChild(third_circle);
let player_c = generate_circle(new PIXI.Graphics(), 9, 9, 'green', 3);
app.stage.addChild(player_c);
let player_d = generate_circle(new PIXI.Graphics(), 9, 9, 'red', 4);
app.stage.addChild(player_d);
// Card stacks
let cards_1 = generate_card_stack(PIXI.Sprite.from('/img/card_stack.png'), 3, 3, function () {
if (!show_card && rolled_number === 1) {
if (diced && !show_card && rolled_number === 1) {
console.log("1");
socket.emit('get card', 1);
}
@ -86,7 +81,7 @@ function start_game() {
app.stage.addChild(cards_1);
let cards_2 = generate_card_stack(PIXI.Sprite.from('/img/card_stack.png'), 5, 3, function () {
if (!show_card && rolled_number === 2) {
if (diced && !show_card && rolled_number === 2) {
console.log("2");
socket.emit('get card', 2);
}
@ -94,7 +89,7 @@ function start_game() {
app.stage.addChild(cards_2);
let cards_3 = generate_card_stack(PIXI.Sprite.from('/img/card_stack.png'), 7, 3, function () {
if (!show_card && rolled_number === 3) {
if (diced && !show_card && rolled_number === 3) {
console.log("3");
socket.emit('get card', 3);
}
@ -131,6 +126,29 @@ function start_game() {
// logo.rotation -= Math.PI / 8;
app.stage.addChild(logo);
my_turn = new PIXI.Text("", new PIXI.TextStyle({
fontFamily: 'Arial',
fontSize: 70,
fontWeight: 'bold',
}));
my_turn.x = sprite_size * 3;
my_turn.y = sprite_size * 8;
app.stage.addChild(my_turn);
let rolled_number_text = new PIXI.Text("", new PIXI.TextStyle({
fontFamily: 'Arial',
fontSize: 140,
fontWeight: 'bold',
wordWrap: true,
wordWrapWidth: game_board_size * 0.5 - 20,
}));
rolled_number_text.x = sprite_size * 7 - sprite_size * 0.2 + dice.width / 2 - rolled_number_text.width / 2;
rolled_number_text.y = sprite_size * 6 - sprite_size * 0.2;
app.stage.addChild(rolled_number_text);
socket.on('dice', function (randomInt) {
rolled_number = randomInt;
diced = true;
@ -138,10 +156,7 @@ function start_game() {
border_card_stack.lineStyle(15, 0x862323, 1);
border_card_stack.drawRoundedRect(sprite_size * (1 + 2 * rolled_number) - sprite_size * 0.2, sprite_size * 3 - sprite_size * 0.2, sprite_size * 1.5, sprite_size * 3 * 0.72, 10);
rolled_number_text = new PIXI.Text(rolled_number, rolled_number_style);
rolled_number_text.x = sprite_size * 7 - sprite_size * 0.2 + dice.width / 2 - rolled_number_text.width / 2;
rolled_number_text.y = sprite_size * 6 - sprite_size * 0.2;
app.stage.addChild(rolled_number_text);
rolled_number_text.text = rolled_number;
});
socket.on('card', function (data) {
@ -158,10 +173,46 @@ function start_game() {
diced = false;
show_card = false;
card.destroyCard();
rolled_number_text.destroy();
rolled_number_text.text = "";
border_card_stack.clear();
});
socket.on('player moved', function (data) {
my_turn.text = "";
let player = data.player;
let position = data.position;
let next_player = data.next_player;
let x = sprites[position].coord_x;
let y = sprites[position].coord_y;
switch (player) {
case 0:
player_a.clear();
player_a = generate_circle(new PIXI.Graphics(), y, x, 'yellow', 1);
app.stage.addChild(player_a);
break;
case 1:
player_b.clear();
player_b = generate_circle(new PIXI.Graphics(), y, x, 'blue', 2);
app.stage.addChild(player_b);
break;
case 2:
player_c.clear();
player_c = generate_circle(new PIXI.Graphics(), y, x, 'green', 3);
app.stage.addChild(player_c);
break;
case 3:
player_d.clear();
player_d = generate_circle(new PIXI.Graphics(), y, x, 'red', 4);
app.stage.addChild(player_d);
break;
}
if (next_player === username) my_turn.text = "Your Turn";
});
resize();
}
@ -183,10 +234,36 @@ function generate_red_border(graphics) {
return graphics;
}
function generate_circle(graphics, x, y) {
function generate_circle(graphics, x, y, color, offset) {
graphics.lineStyle(0);
graphics.beginFill(0xffffff, 1);
graphics.drawCircle(sprite_size * x - sprite_size * 0.2 + sprite_size * 0.75, sprite_size * y - sprite_size * 0.2 + sprite_size * 0.75, sprite_size / 4);
switch (color) {
case 'yellow':
graphics.beginFill(0xFFDDA1, 1);
break;
case 'red':
graphics.beginFill(0xF47A93, 1);
break;
case 'green':
graphics.beginFill(0x6C9A8B, 1);
break;
case 'blue':
graphics.beginFill(0x4169E1, 1);
break;
}
switch (offset) {
case 1:
graphics.drawCircle(sprite_size * x - 65 - sprite_size * 0.2 + sprite_size * 0.75, sprite_size * y + 65 - sprite_size * 0.2 + sprite_size * 0.75, sprite_size / 4);
break; // upper left
case 2:
graphics.drawCircle(sprite_size * x + 65 - sprite_size * 0.2 + sprite_size * 0.75, sprite_size * y + 65 - sprite_size * 0.2 + sprite_size * 0.75, sprite_size / 4);
break; // upper right
case 3:
graphics.drawCircle(sprite_size * x - 65 - sprite_size * 0.2 + sprite_size * 0.75, sprite_size * y - 65 - sprite_size * 0.2 + sprite_size * 0.75, sprite_size / 4);
break; // lower left
case 4:
graphics.drawCircle(sprite_size * x + 65 - sprite_size * 0.2 + sprite_size * 0.75, sprite_size * y - 65 - sprite_size * 0.2 + sprite_size * 0.75, sprite_size / 4);
break; // lower right
}
graphics.endFill();
return graphics;
}

View File

@ -10,10 +10,12 @@ document.getElementById('ok').addEventListener('click', function () {
username = document.getElementById('username').value;
room_name = document.getElementById('room').value;
document.getElementById('login').style.display = 'none';
document.getElementById('game').style.display = 'flex';
document.getElementById('chat').style.display = 'flex';
socket = io("/", {
closeOnBeforeunload: false
});
start_chat();
start_game();
resize();
// Login
socket.emit('add user', {'username': username, 'room_name': room_name});
});