add Tournament creation and tournament game start
This commit is contained in:
@ -6,7 +6,7 @@
|
||||
# By: tomoron <tomoron@student.42.fr> +#+ +:+ +#+ #
|
||||
# +#+#+#+#+#+ +#+ #
|
||||
# Created: 2024/10/05 03:54:20 by tomoron #+# #+# #
|
||||
# Updated: 2024/10/10 19:25:56 by tomoron ### ########.fr #
|
||||
# Updated: 2024/10/13 21:24:19 by tomoron ### ########.fr #
|
||||
# #
|
||||
# **************************************************************************** #
|
||||
|
||||
@ -19,9 +19,10 @@ import asyncio
|
||||
import time
|
||||
|
||||
class Bot(Player):
|
||||
def __init__(self, game):
|
||||
def __init__(self, game=None, tournament=None):
|
||||
self.socket = DummySocket(game)
|
||||
self.game = game
|
||||
self.tournament = tournament
|
||||
self.ready = True
|
||||
self.pos = {"pos":0, "up": False}
|
||||
self.lastCalculated = {"pos":0, "up":False}
|
||||
@ -46,7 +47,7 @@ class Bot(Player):
|
||||
return(self.objective)
|
||||
self.lastCalculated = {"pos":pos, "up" : up}
|
||||
if(not center):
|
||||
offset = random.randint(-100, 100) / 100
|
||||
offset = random.randint(-99, 99) / 100
|
||||
if(offset == 0):
|
||||
offset = 0.1
|
||||
pos += offset * (GameSettings.playerLength / 2)
|
||||
@ -65,24 +66,37 @@ class Bot(Player):
|
||||
self.objective = self.genRandomBallDirection(0, 0, True)
|
||||
return
|
||||
self.objective = self.genRandomBallDirection(tempBall.pos[0], tempBall.up, False)
|
||||
|
||||
def isEnd(self):
|
||||
if(self.tournament != None):
|
||||
return(self.tournament.end)
|
||||
else:
|
||||
return(self.game.end)
|
||||
|
||||
async def updateLoop(self):
|
||||
while not self.game.end:
|
||||
await self.getExpectedPos()
|
||||
while not self.isEnd():
|
||||
if(self.game):
|
||||
await self.getExpectedPos()
|
||||
await asyncio.sleep(1)
|
||||
|
||||
async def goToObjectiveLoop(self):
|
||||
lastUpdate = time.time()
|
||||
while not self.game.end:
|
||||
while not self.isEnd():
|
||||
if(self.pos["pos"] != self.objective["pos"] or self.pos["up"] != self.objective["up"]):
|
||||
self.pos["up"] = self.objective["up"]
|
||||
|
||||
maxDistance = GameSettings.maxPlayerSpeed * (time.time() - lastUpdate)
|
||||
lastUpdate = time.time()
|
||||
print("maxDistance :", maxDistance)
|
||||
travel = self.objective["pos"] - self.pos["pos"]
|
||||
if(travel >= 0):
|
||||
travel = min(self.objective["pos"] - self.pos["pos"], GameSettings.maxPlayerSpeed)
|
||||
travel = min(self.objective["pos"] - self.pos["pos"], maxDistance)
|
||||
else:
|
||||
travel = max(self.objective["pos"] - self.pos["pos"], -GameSettings.maxPlayerSpeed)
|
||||
travel = max(self.objective["pos"] - self.pos["pos"], -maxDistance)
|
||||
print("travel :", travel)
|
||||
self.game.move(self.socket, self.pos["pos"] + travel, self.pos["up"])
|
||||
lastUpdate = time.time()
|
||||
await asyncio.sleep(1 / 20)
|
||||
|
||||
def setGame(self, game):
|
||||
self.game = game
|
||||
self.socket.game = game
|
||||
|
@ -6,7 +6,7 @@
|
||||
# By: edbernar <edbernar@student.42angouleme. +#+ +:+ +#+ #
|
||||
# +#+#+#+#+#+ +#+ #
|
||||
# Created: 2024/09/13 16:20:58 by tomoron #+# #+# #
|
||||
# Updated: 2024/10/10 19:24:02 by tomoron ### ########.fr #
|
||||
# Updated: 2024/10/13 21:50:58 by tomoron ### ########.fr #
|
||||
# #
|
||||
# **************************************************************************** #
|
||||
|
||||
@ -16,31 +16,36 @@ from .models import GameResults, User
|
||||
from .GameSettings import GameSettings
|
||||
from .Bot import Bot
|
||||
from .Ball import Ball
|
||||
from typing import Union
|
||||
import time
|
||||
import json
|
||||
import asyncio
|
||||
import random
|
||||
import math
|
||||
from multimethod import multimethod
|
||||
|
||||
class Game:
|
||||
waitingForPlayer = None
|
||||
|
||||
def __init__(self, socket, withBot, skinId = 0, goalId = 0, opponent = None):
|
||||
self.p1 = None
|
||||
self.p2 = None
|
||||
self.started = False
|
||||
self.end = False
|
||||
self.left = None
|
||||
self.winner = None
|
||||
self.gameStart = 0
|
||||
self.gameTime = 0
|
||||
self.withBot = withBot
|
||||
@multimethod
|
||||
def __init__(self, p1 , p2 , isTournament = False):
|
||||
self.initAttributes()
|
||||
if(isinstance(p1, Bot) and isinstance(p2, Bot)):
|
||||
self.winner=1
|
||||
self.pWinner=p1
|
||||
return
|
||||
elif(isinstance(p2,Bot)):
|
||||
p2,p1 = p1, p2
|
||||
self.withBot = isinstance(p1,Bot)
|
||||
self.isTournament = isTournament
|
||||
p1.setGame(self)
|
||||
p2.setGame(self)
|
||||
print("game created with ", p1.socket.username, "vs", p2.socket.username)
|
||||
|
||||
self.ball = Ball()
|
||||
self.speed = GameSettings.startSpeed
|
||||
self.score = [0, 0]
|
||||
self.obstacles = []
|
||||
self.lastWin = 2
|
||||
@multimethod
|
||||
def __init__(self, socket, withBot : bool, skinId = 0, goalId = 0 , opponent = None):
|
||||
self.initAttributes()
|
||||
self.withBot = withBot
|
||||
|
||||
self.opponentLock = opponent
|
||||
if(1 or withBot):
|
||||
@ -67,6 +72,24 @@ class Game:
|
||||
def __del__(self):
|
||||
print("game destroy")
|
||||
|
||||
def initAttributes(self):
|
||||
self.p1 = None
|
||||
self.p2 = None
|
||||
self.isTournament=False
|
||||
self.started = False
|
||||
self.end = False
|
||||
self.left = None
|
||||
self.winner = None
|
||||
self.pWinner = None
|
||||
self.gameStart = 0
|
||||
self.gameTime = 0
|
||||
|
||||
self.ball = Ball()
|
||||
self.speed = GameSettings.startSpeed
|
||||
self.score = [0, 0]
|
||||
self.obstacles = []
|
||||
self.lastWin = 2
|
||||
|
||||
def obstaclesInvLength(self):
|
||||
for x in self.obstacles:
|
||||
x["pos"]["z"] = -x["pos"]["z"]
|
||||
@ -100,7 +123,8 @@ class Game:
|
||||
try:
|
||||
if(self.p1 == None):
|
||||
print("game created, set as player 1")
|
||||
self.p1 = Player(socket, self)
|
||||
self.p1 = Player(socket)
|
||||
self.p1.setGame(self)
|
||||
self.p1.skin = skin
|
||||
self.p1.goal = goal
|
||||
else:
|
||||
@ -108,7 +132,8 @@ class Game:
|
||||
socket.sendError("You are not invited to this game", 9103)
|
||||
return
|
||||
print("joined game, set as player 2")
|
||||
self.p2 = Player(socket, self)
|
||||
self.p2 = Player(socket)
|
||||
self.p2.setGame(self)
|
||||
self.p2.skin = skin
|
||||
self.p2.goal = goal
|
||||
if(self.p2 != None and self.p1 != None):
|
||||
@ -138,14 +163,16 @@ class Game:
|
||||
self.p1.socket.sync_send({"type":"game","content":{"action":10,"won":winner==1, "opponentLeft":self.left == 2}})
|
||||
self.p2.socket.sync_send({"type":"game","content":{"action":10,"won":winner==2, "opponentLeft":self.left == 1}})
|
||||
self.winner = winner
|
||||
self.pWinner = self.p1 if winner == 1 else self.p2
|
||||
self.end = True
|
||||
|
||||
def leave(self, socket):
|
||||
socket.game = None
|
||||
if (socket == self.p1.socket):
|
||||
self.left = 1
|
||||
self.p1.setGame(None)
|
||||
else:
|
||||
self.left = 2
|
||||
self.p2.setGame(None)
|
||||
if(Game.waitingForPlayer == self):
|
||||
Game.waitingForPlayer = None
|
||||
if(self.p2 != None):
|
||||
@ -238,9 +265,9 @@ class Game:
|
||||
self.sendNewBallInfo()
|
||||
print("game end")
|
||||
if(self.p1.socket.game == self):
|
||||
self.p1.socket.game = None
|
||||
self.p1.setGame(None)
|
||||
if(self.p2.socket.game == self):
|
||||
self.p2.socket.game = None
|
||||
self.p2.setGame(None)
|
||||
if(not self.withBot):
|
||||
await self.saveResults()
|
||||
del self
|
||||
|
@ -6,7 +6,7 @@
|
||||
# By: tomoron <tomoron@student.42.fr> +#+ +:+ +#+ #
|
||||
# +#+#+#+#+#+ +#+ #
|
||||
# Created: 2024/10/06 16:33:56 by tomoron #+# #+# #
|
||||
# Updated: 2024/10/10 03:48:00 by tomoron ### ########.fr #
|
||||
# Updated: 2024/10/12 23:31:00 by tomoron ### ########.fr #
|
||||
# #
|
||||
# **************************************************************************** #
|
||||
|
||||
@ -38,20 +38,11 @@ class GameSettings:
|
||||
{ "type":1, "name":"J6", "pos":{"x": 1.5, "y": 0.2, "z": -mapLength / 4}, "isUp": False },
|
||||
{ "type":1, "name":"J7", "pos":{"x": 1.5, "y": 3.2, "z": -mapLength / 4}, "isUp": True }
|
||||
]
|
||||
skins = [
|
||||
{id: 0, 'color': 0xff53aa, 'texture': None},
|
||||
{id: 1, 'color': 0xaa24ea, 'texture': None},
|
||||
{id: 2, 'color': 0x2c9c49, 'texture': None},
|
||||
{id: 3, 'color': 0x101099, 'texture': None},
|
||||
{id: 4, 'color': None, 'texture': '/static/img/skin/1.jpg'},
|
||||
{id: 5, 'color': None, 'texture': '/static/img/skin/2.jpg'},
|
||||
{id: 6, 'color': None, 'texture': '/static/img/skin/3.jpg'},
|
||||
{id: 7, 'color': None, 'texture': '/static/img/skin/4.jpg'},
|
||||
]
|
||||
nbSkins = 8
|
||||
nbGoals = 4
|
||||
wallLength = 1
|
||||
wallWidth = 0.05
|
||||
bounceSpeedIncrease = 0.2
|
||||
maxScore = 5
|
||||
|
||||
maxPlayerSpeed = 0.4
|
||||
maxPlayerSpeed = 6
|
||||
|
@ -6,14 +6,13 @@
|
||||
# By: tomoron <tomoron@student.42.fr> +#+ +:+ +#+ #
|
||||
# +#+#+#+#+#+ +#+ #
|
||||
# Created: 2024/10/05 03:22:32 by tomoron #+# #+# #
|
||||
# Updated: 2024/10/10 03:52:40 by tomoron ### ########.fr #
|
||||
# Updated: 2024/10/13 21:24:16 by tomoron ### ########.fr #
|
||||
# #
|
||||
# **************************************************************************** #
|
||||
|
||||
class Player():
|
||||
def __init__(self, socket, game):
|
||||
def __init__(self, socket):
|
||||
self.socket = socket
|
||||
socket.game = game
|
||||
self.ready = False
|
||||
self.pos = {"pos":0, "up": False}
|
||||
self.skin = 0
|
||||
@ -21,3 +20,7 @@ class Player():
|
||||
|
||||
def __del__(self):
|
||||
print("player destroy")
|
||||
|
||||
def setGame(self, game):
|
||||
self.game = game
|
||||
self.socket.game = game
|
||||
|
@ -6,28 +6,29 @@
|
||||
# By: edbernar <edbernar@student.42angouleme. +#+ +:+ +#+ #
|
||||
# +#+#+#+#+#+ +#+ #
|
||||
# Created: 2024/10/04 17:17:07 by tomoron #+# #+# #
|
||||
# Updated: 2024/10/10 06:12:28 by tomoron ### ########.fr #
|
||||
# Updated: 2024/10/13 21:11:56 by tomoron ### ########.fr #
|
||||
# #
|
||||
# **************************************************************************** #
|
||||
|
||||
import string
|
||||
import asyncio
|
||||
from .Bot import Bot
|
||||
from .Player import Player
|
||||
from .utils import genString
|
||||
from .TournamentGame import TournamentGame
|
||||
|
||||
class Tournament:
|
||||
currentTournamentsLock = False
|
||||
currentTournaments = {}
|
||||
|
||||
playerLimit = 8
|
||||
def __init__(self, socket):
|
||||
levels = 3
|
||||
def __init__(self, socket, nbBot):
|
||||
self.messages = []
|
||||
self.players = []
|
||||
while(Tournament.currentTournamentsLock):
|
||||
continue;
|
||||
Tournament.currentTournamentsLock = True
|
||||
self.nbBot = nbBot
|
||||
self.end = False
|
||||
self.genCode()
|
||||
Tournament.currentTournaments[self.code] = self
|
||||
Tournament.currentTournamentsLock = False
|
||||
self.join(socket)
|
||||
|
||||
def genCode(self):
|
||||
@ -43,12 +44,12 @@ class Tournament:
|
||||
|
||||
def broadcast(self, content):
|
||||
for x in self.players:
|
||||
x.sync_send("tournament",content)
|
||||
x.socket.sync_send("tournament",content)
|
||||
|
||||
def sendAllInfo(self, socket):
|
||||
players = []
|
||||
for x in self.players:
|
||||
players.append({"id":x.id,"username":x.username, "pfp":x.pfp})
|
||||
players.append({"id":x.socket.id,"username":x.socket.username, "pfp":x.socket.pfp})
|
||||
socket.sync_send("tournament",{"action":5, "players":players, "messages" : self.messages})
|
||||
|
||||
def sendMessage(self, socket, message):
|
||||
@ -57,22 +58,56 @@ class Tournament:
|
||||
self.messages.pop(0)
|
||||
self.broadcast({"action":3, "username":socket.username, "message":message})
|
||||
|
||||
def playerFromSocket(self, socket):
|
||||
for x in range(len(self.players)):
|
||||
if(self.players[x].socket == socket):
|
||||
return(x)
|
||||
return(-1)
|
||||
|
||||
def leave(self, socket):
|
||||
if(socket not in self.players):
|
||||
index = self.playerFromSocket(socket)
|
||||
if(index == -1):
|
||||
return;
|
||||
index = self.players.index(socket)
|
||||
self.players.pop(index)
|
||||
socket.tournament = None
|
||||
self.broadcast({"action":2,"id":socket.id})
|
||||
|
||||
def join(self, socket):
|
||||
if(socket.tournament != None):
|
||||
def join(self, socket, isBot=False):
|
||||
if(not isBot and socket.tournament != None):
|
||||
socket.sendError("already in a tournament", 9036)
|
||||
return
|
||||
if(len(self.players) == Tournament.playerLimit):
|
||||
if(not isBot and len(self.players) == Tournament.playerLimit):
|
||||
socket.sync_send("tournament",{"action":0, "isFull":True})
|
||||
return
|
||||
if(isBot):
|
||||
player = Bot(None, self)
|
||||
socket = player.socket
|
||||
else:
|
||||
player = Player(socket)
|
||||
socket.tournament = self
|
||||
self.players.append(socket)
|
||||
socket.sync_send("tournament",{"action":0,"isFull":False, "isStarted":False,"exist":True, "code":self.code})
|
||||
self.players.append(player)
|
||||
socket.sync_send("tournament",{"action":0, "code":self.code})
|
||||
self.broadcast({"action":1, "id":socket.id, "username": socket.username,"pfp":socket.pfp})
|
||||
if(len(self.players) == Tournament.playerLimit):
|
||||
self.start()
|
||||
if(len(self.players) == Tournament.playerLimit - self.nbBot):
|
||||
for x in range(self.nbBot):
|
||||
self.join(None, True)
|
||||
|
||||
def createGames(self, players, level=1):
|
||||
left = None
|
||||
right = None
|
||||
if(level == Tournament.levels):
|
||||
try:
|
||||
right = players.pop(0)
|
||||
left = players.pop(0)
|
||||
except IndexError:
|
||||
pass
|
||||
else:
|
||||
right = self.createGames(players, level + 1)
|
||||
left = self.createGames(players, level + 1)
|
||||
return(TournamentGame(left, right))
|
||||
|
||||
def start(self):
|
||||
self.started = True
|
||||
self.createGames(self.players.copy())
|
||||
|
@ -0,0 +1,58 @@
|
||||
# **************************************************************************** #
|
||||
# #
|
||||
# ::: :::::::: #
|
||||
# TournamentGame.py :+: :+: :+: #
|
||||
# +:+ +:+ +:+ #
|
||||
# By: tomoron <marvin@42.fr> +#+ +:+ +#+ #
|
||||
# +#+#+#+#+#+ +#+ #
|
||||
# Created: 2024/10/12 22:49:00 by tomoron #+# #+# #
|
||||
# Updated: 2024/10/13 22:01:59 by tomoron ### ########.fr #
|
||||
# #
|
||||
# **************************************************************************** #
|
||||
import asyncio
|
||||
from .Game import Game
|
||||
|
||||
class TournamentGame:
|
||||
def __init__(self, left, right):
|
||||
self.game = None
|
||||
self.winner = None
|
||||
self.right = right
|
||||
self.left = left
|
||||
asyncio.create_task(self.loop())
|
||||
|
||||
def startGame(self):
|
||||
l = None
|
||||
r = None
|
||||
if(isinstance(self.left,TournamentGame)):
|
||||
self.game = Game(self.left.winner, self.right.winner, True)
|
||||
l = self.left.winner.socket
|
||||
r = self.right.winner.socket
|
||||
else:
|
||||
self.game = Game(self.left, self.right, True)
|
||||
l = self.left.socket
|
||||
r = self.right.socket
|
||||
l.sync_send("tournament", {
|
||||
"action":4,
|
||||
"id": r.id,
|
||||
"username":r.username
|
||||
})
|
||||
r.sync_send("tournament", {
|
||||
"action":4,
|
||||
"id": l.id,
|
||||
"username": l.username
|
||||
})
|
||||
|
||||
async def loop(self):
|
||||
while self.winner == None:
|
||||
if(self.game == None):
|
||||
if(isinstance(self.left, TournamentGame)):
|
||||
if(self.left.winner != None and self.right.winner != None):
|
||||
await asyncio.sleep(3)
|
||||
self.startGame()
|
||||
else:
|
||||
await asyncio.sleep(3)
|
||||
self.startGame()
|
||||
else:
|
||||
if(self.game.winner != None):
|
||||
self.winner = self.game.pWinner
|
||||
await asyncio.sleep(1)
|
@ -6,7 +6,7 @@
|
||||
# By: edbernar <edbernar@student.42angouleme. +#+ +:+ +#+ #
|
||||
# +#+#+#+#+#+ +#+ #
|
||||
# Created: 2024/09/11 17:07:08 by tomoron #+# #+# #
|
||||
# Updated: 2024/10/10 03:52:54 by tomoron ### ########.fr #
|
||||
# Updated: 2024/10/12 23:31:22 by tomoron ### ########.fr #
|
||||
# #
|
||||
# **************************************************************************** #
|
||||
|
||||
@ -22,7 +22,7 @@ async def start(socket, content):
|
||||
socket.sendError("Your opponent isn't online",9032)
|
||||
return;
|
||||
skinId = content.get("skinId", 0)
|
||||
if(skinId < 0 or skinId >= len(GameSettings.skins)):
|
||||
if(skinId < 0 or skinId >= GameSettings.nbSkins):
|
||||
socket.sendError("Skin id out of range", 9033)
|
||||
return;
|
||||
goalId = content.get("goalId",0)
|
||||
|
@ -6,7 +6,7 @@
|
||||
# By: tomoron <tomoron@student.42.fr> +#+ +:+ +#+ #
|
||||
# +#+#+#+#+#+ +#+ #
|
||||
# Created: 2024/10/04 17:16:02 by tomoron #+# #+# #
|
||||
# Updated: 2024/10/05 02:28:50 by tomoron ### ########.fr #
|
||||
# Updated: 2024/10/11 21:14:54 by tomoron ### ########.fr #
|
||||
# #
|
||||
# **************************************************************************** #
|
||||
|
||||
@ -19,4 +19,8 @@ async def tournamentStart(socket, content):
|
||||
else:
|
||||
socket.sync_send("tournament",{"action":0, "exist":False})
|
||||
else:
|
||||
Tournament(socket)
|
||||
nbBot = content.get("nbBot", 0)
|
||||
if(nbBot < 0 or nbBot > 7):
|
||||
socket.sendError("invalid number of bots", 9040)
|
||||
return;
|
||||
Tournament(socket, nbBot)
|
||||
|
@ -6,7 +6,7 @@
|
||||
# By: edbernar <edbernar@student.42angouleme. +#+ +:+ +#+ #
|
||||
# +#+#+#+#+#+ +#+ #
|
||||
# Created: 2024/09/09 14:31:30 by tomoron #+# #+# #
|
||||
# Updated: 2024/10/06 16:28:47 by tomoron ### ########.fr #
|
||||
# Updated: 2024/10/12 02:43:29 by tomoron ### ########.fr #
|
||||
# #
|
||||
# **************************************************************************** #
|
||||
|
||||
@ -137,9 +137,9 @@ class WebsocketHandler(AsyncWebsocketConsumer):
|
||||
uid = await self.session_get("id", 0)
|
||||
if(uid in self.onlinePlayers):
|
||||
del self.onlinePlayers[uid]
|
||||
if(self.game !=None):
|
||||
if(self.game != None):
|
||||
self.game.leave(self)
|
||||
if(self.tournament !=None):
|
||||
if(self.tournament != None):
|
||||
self.tournament.leave(self)
|
||||
|
||||
async def receive(self, text_data):
|
||||
@ -148,7 +148,8 @@ class WebsocketHandler(AsyncWebsocketConsumer):
|
||||
except json.JSONDecodeError:
|
||||
self.sendError("Invalid JSON", 9002)
|
||||
return
|
||||
try:
|
||||
#try:
|
||||
if(1):
|
||||
self.printDebug(jsonRequest, 0)
|
||||
if (jsonRequest["type"] in typeRequest):
|
||||
if (jsonRequest["type"] == "login" or jsonRequest["type"] == "create_account"):
|
||||
@ -159,8 +160,8 @@ class WebsocketHandler(AsyncWebsocketConsumer):
|
||||
await functionRequest[typeRequest.index(jsonRequest["type"])](self, jsonRequest["content"])
|
||||
else:
|
||||
self.sendError("Invalid type", 9004)
|
||||
except Exception as e:
|
||||
self.sendError("Invalid request", 9005, e)
|
||||
# except Exception as e:
|
||||
# self.sendError("Invalid request", 9005, e)
|
||||
|
||||
@multimethod
|
||||
def sync_send(self, reqType : str, content:dict):
|
||||
|
Reference in New Issue
Block a user