add: tictactoe: timers on catchup

This commit is contained in:
Namonay 2024-05-14 16:46:16 +02:00
parent aa01405988
commit 995a808974
5 changed files with 50 additions and 25 deletions

View File

@ -1,4 +1,4 @@
import { client, lang } from "../../../index.js"; import { client, lang, navigateTo } from "../../../index.js";
import { AGame } from "../AGame.js"; import { AGame } from "../AGame.js";
@ -50,7 +50,7 @@ class TicTacToe
this.game.finished = false; this.game.finished = false;
if (this.turn) if (this.turn)
this.setOutline(4, false); this.setOutline(4, false);
this.printTimer(); this.printTimer(20);
break; break;
case 'game_move': case 'game_move':
@ -59,7 +59,7 @@ class TicTacToe
this.map[messageData.targetMorpion][messageData.targetCase] = (this.sign == "x") ? 1 : 0; this.map[messageData.targetMorpion][messageData.targetCase] = (this.sign == "x") ? 1 : 0;
this.printSign(messageData.targetMorpion, messageData.targetCase, (this.sign == "x") ? "o" : "x"); this.printSign(messageData.targetMorpion, messageData.targetCase, (this.sign == "x") ? "o" : "x");
this.setOutline(this.currentMorpion, false); this.setOutline(this.currentMorpion, false);
this.printTimer(); this.printTimer(20);
break; break;
case 'game_end': case 'game_end':
@ -68,6 +68,7 @@ class TicTacToe
this.printWin(messageData.winning_sign); this.printWin(messageData.winning_sign);
break; break;
case 'catchup': case 'catchup':
this.game.finished = messageData.finished
this.map = messageData.morpion; this.map = messageData.morpion;
for (let i = 0; i < 9; i++) for (let i = 0; i < 9; i++)
{ {
@ -81,6 +82,7 @@ class TicTacToe
this.currentMorpion = messageData.currentMorpion; this.currentMorpion = messageData.currentMorpion;
if (this.turn) if (this.turn)
this.setOutline(this.currentMorpion, false); this.setOutline(this.currentMorpion, false);
this.printTimer(Math.floor(messageData.timer));
} }
} }
@ -96,10 +98,15 @@ class TicTacToe
this.context.fillText((winning_sign == "o") ? lang.get("morpionWin") + "O" : lang.get("morpionWin") + "X", this.width / 2 - 85, this.height - this.gap / 2 + 10, 180); this.context.fillText((winning_sign == "o") ? lang.get("morpionWin") + "O" : lang.get("morpionWin") + "X", this.width / 2 - 85, this.height - this.gap / 2 + 10, 180);
} }
printTimer() printTimer(sec)
{ {
let sec = 20; let turn = this.turn;
let turn = this.turn
if (sec <= 0)
{
this.game.send(JSON.stringify({"timerIsDue" : this.sign}))
return;
}
if (this.turn) if (this.turn)
{ {
this.context.beginPath(); this.context.beginPath();
@ -115,10 +122,10 @@ class TicTacToe
this.context.fillStyle = "#1a1a1d"; this.context.fillStyle = "#1a1a1d";
this.context.fillRect(this.width / 2 - 40, 0, this.width / 2 + 40, this.gap - 10) this.context.fillRect(this.width / 2 - 40, 0, this.width / 2 + 40, this.gap - 10)
this.context.closePath(); this.context.closePath();
if (sec == 0 || turn != this.turn || this.game.finished) if (sec <= 0 || turn != this.turn || this.game.finished)
{ {
clearInterval(id); clearInterval(id);
if (sec == 0 && !this.turn && this.game.finished == false) if (sec <= 0 && this.game.finished == false)
this.game.send(JSON.stringify({"timerIsDue" : this.sign})) this.game.send(JSON.stringify({"timerIsDue" : this.sign}))
return; return;
} }
@ -175,7 +182,7 @@ class TicTacToe
{ {
morpion.setOutline(this.currentMorpion, true); morpion.setOutline(this.currentMorpion, true);
morpion.sendCase(targetMorpion, targetCase); morpion.sendCase(targetMorpion, targetCase);
morpion.printTimer() morpion.printTimer(20)
} }
else else
morpion.incorrectCase(); morpion.incorrectCase();
@ -221,7 +228,7 @@ class TicTacToe
this.context.strokeStyle = "red"; this.context.strokeStyle = "red";
targetX += this.rectsize / 2; targetX += this.rectsize / 2;
targetY += this.rectsize / 2; targetY += this.rectsize / 2;
this.context.arc(targetX, targetY, 15, 0, 2 * Math.PI); this.context.arc(targetX, targetY, this.rectsize / 2 - 7, 0, 2 * Math.PI);
this.context.stroke(); this.context.stroke();
this.context.closePath(); this.context.closePath();
} }

View File

@ -86,8 +86,7 @@ export default class extends AbstractView {
games.forEach(game => { games.forEach(game => {
if (game.finished === false) if (game.finished === false)
return return
if (this.profile.id === game.winner?.id)
if (this.profile.id === game.winner.id)
win++; win++;
else else
lose++; lose++;
@ -114,10 +113,16 @@ export default class extends AbstractView {
let game_item = document.createElement("div"); let game_item = document.createElement("div");
game_item.className = "game-item"; game_item.className = "game-item";
game_item.style.backgroundColor = "grey"; game_item.style.backgroundColor = "grey";
if (game.started) if (game.finished && game.winner == null)
game_item.style.backgroundColor = "yellow"; game_item.style.backgroundColor = "red";
if (game.finished) else if (game.finished)
game_item.style.backgroundColor = this.profile.id === game.winner.id ? "green" : "red"; game_item.style.backgroundColor = this.profile.id === game.winner.id ? "green" : "red";
else if (game.started)
game_item.style.backgroundColor = "yellow";
let gametype = document.createElement("b");
gametype.innerText = `${(game.game_type == "tictactoe") ? lang.get("ticTacToeTitle") : "Pong"}`;
game_item.appendChild(gametype);
game.players.forEach(player => { game.players.forEach(player => {
let player_score = document.createElement("a"); let player_score = document.createElement("a");
@ -128,7 +133,6 @@ export default class extends AbstractView {
game_item.appendChild(player_score); game_item.appendChild(player_score);
}); });
a.appendChild(game_item); a.appendChild(game_item);
game_list.appendChild(a); game_list.appendChild(a);
}); });

View File

@ -1,12 +1,12 @@
import AbstractView from "./abstracts/AbstractView.js";
import { lang } from "../index.js"; import { lang } from "../index.js";
import { TicTacToe } from "../api/game/tictactoe/TicTacToeGame.js" import { TicTacToe } from "../api/game/tictactoe/TicTacToeGame.js"
import AbstractAuthenticatedView from "./abstracts/AbstractAuthenticatedView.js";
export class TicTacToeOnlineView extends AbstractView import { navigateTo } from "../index.js"
export class TicTacToeOnlineView extends AbstractAuthenticatedView
{ {
constructor(params, titleKey) constructor(params, titleKey)
{ {
super(params, lang.get('ticTacToeTitle')); super(params, 'ticTacToeTitle');
this.params = params; this.params = params;
this.titleKey = titleKey; this.titleKey = titleKey;
this.game_id = params.id; this.game_id = params.id;

View File

@ -5,7 +5,9 @@ from channels.generic.websocket import WebsocketConsumer
from django.contrib.auth.models import User from django.contrib.auth.models import User
import json import json
import sys
from .objects.GameManager import GameManager from .objects.GameManager import GameManager
from .objects.tictactoe.TicTacToePlayer import TicTacToePlayer from .objects.tictactoe.TicTacToePlayer import TicTacToePlayer
@ -47,7 +49,7 @@ class TicTacToeWebSocket(WebsocketConsumer):
self.member.send(self.member.sign) self.member.send(self.member.sign)
if (self.game._everbody_is_here() and self.game.model.started == True and self.game.model.finished == False): # if an user disconnected and joined back if (self.game._everbody_is_here() and self.game.model.started == True and self.game.model.finished == False): # if an user disconnected and joined back
self.member.send("catchup", {"morpion" : self.game._map, "turn" : self.game.turn, "currentMorpion": self.member.currentMorpion}) self.member.send("catchup", {"morpion" : self.game._map, "turn" : self.game.turn, "currentMorpion": self.member.currentMorpion, "timer" : 20 - (time.time() - self.game.time), "finished" : self.game.model.finished})
return return
if (self.game._everbody_is_here() and self.game.model.started == False): # Launch the game if the two players are connected if (self.game._everbody_is_here() and self.game.model.started == False): # Launch the game if the two players are connected
@ -64,8 +66,10 @@ class TicTacToeWebSocket(WebsocketConsumer):
self.game.broadcast("game_move", data, [self.member]) self.game.broadcast("game_move", data, [self.member])
if (data.get("timerIsDue") is not None and self.game.time + 20 < time.time()): # Frontend asking if the timer is due if (data.get("timerIsDue") is not None and self.game.time + 20 < time.time()): # Frontend asking if the timer is due
self.winner = 'x' if self.game.turn == 'o' else 'o' self.winner = "x" if self.game.turn == "o" else "o"
self.game.model.finish(self.user) self.game.get_members()
self.game.model.finish(self.game.get_players_by_sign(self.winner).user)
self.game.broadcast("game_end", {"winning_sign": self.winner}) self.game.broadcast("game_end", {"winning_sign": self.winner})
if (self.game.checkWin() != False): # Check if after a move, the game is finished if (self.game.checkWin() != False): # Check if after a move, the game is finished
@ -77,6 +81,8 @@ class TicTacToeWebSocket(WebsocketConsumer):
def disconnect(self, event): def disconnect(self, event):
try: try:
self.member.socket = None self.member.socket = None
if (len(self.game.get_players_connected()) == 0):
self.game.model.finish(None)
except: except:
pass pass

View File

@ -8,13 +8,15 @@ from .TicTacToeSpectator import TicTacToeSpectator
import time import time
import sys
class TicTacToeGame(AGame): class TicTacToeGame(AGame):
def __init__(self, game_id: int, game_manager): def __init__(self, game_id: int, game_manager):
super().__init__("tictactoe", game_id, game_manager) super().__init__("tictactoe", game_id, game_manager)
players: list[int] = self.model.get_players() players = self.model.get_players()
self.players: list[TicTacToePlayer] = [TicTacToePlayer(player, None, self, ["x", "o"][i]) for i, player in enumerate(players)] self.players: list[TicTacToePlayer] = [TicTacToePlayer(player, None, self, ["x", "o"][i]) for i, player in enumerate(players)]
@ -29,6 +31,12 @@ class TicTacToeGame(AGame):
def _everbody_is_here(self): def _everbody_is_here(self):
return len(self.players) == len(self.get_players_connected()) return len(self.players) == len(self.get_players_connected())
def get_players_by_sign(self, sign):
for player in self.players:
if (player.sign == sign):
return player
return None
def _player_join(self, user_id: int, socket: WebsocketConsumer): def _player_join(self, user_id: int, socket: WebsocketConsumer):
player = self.get_player_by_user_id(user_id) player = self.get_player_by_user_id(user_id)