bot can now calculate where the ball is going to hit it's side

This commit is contained in:
2024-10-08 10:51:22 +02:00
parent 5fb0870c95
commit 7401ea3c17
5 changed files with 115 additions and 58 deletions

View File

@ -6,7 +6,7 @@
# By: tomoron <tomoron@student.42.fr> +#+ +:+ +#+ # # By: tomoron <tomoron@student.42.fr> +#+ +:+ +#+ #
# +#+#+#+#+#+ +#+ # # +#+#+#+#+#+ +#+ #
# Created: 2024/10/06 03:24:10 by tomoron #+# #+# # # Created: 2024/10/06 03:24:10 by tomoron #+# #+# #
# Updated: 2024/10/06 17:22:46 by tomoron ### ########.fr # # Updated: 2024/10/08 10:00:22 by tomoron ### ########.fr #
# # # #
# **************************************************************************** # # **************************************************************************** #
@ -54,7 +54,7 @@ class Ball:
offset = pos1[1] - (slope * pos1[0]) offset = pos1[1] - (slope * pos1[0])
#salagadou la menchikabou la bibidi bobidi bou #salagadou la menchikabou la bibidi bobidi bou
a = 1 + (slope ** 2) a = 1 + (slope ** 2)
b = ((-jpos[0]) * 2) + (2 * (slope * (-jpos[1] + offset))) b = ((-jpos[0]) * 2) + (2 * (slope * (-jpos[1] + offset)))
c = (((-jpos[0]) ** 2) + (((-jpos[1]) + offset) ** 2)) - (GameSettings.jumperRadius ** 2) c = (((-jpos[0]) ** 2) + (((-jpos[1]) + offset) ** 2)) - (GameSettings.jumperRadius ** 2)
return(self.solve_quadratic(a, b ,c)) return(self.solve_quadratic(a, b ,c))
@ -65,28 +65,23 @@ class Ball:
pos2 = self.pos[0] +self.vel[0], self.pos[1] + self.vel[1] pos2 = self.pos[0] +self.vel[0], self.pos[1] + self.vel[1]
slope = 0 slope = 0
if(abs(pos1[1]) <= (GameSettings.wallWidth / 2) + GameSettings.ballRadius): if(abs(pos1[1]) <= (GameSettings.wallWidth / 2) + GameSettings.ballRadius):
print("inside")
return(None) return(None)
if(pos1[0] - pos2[0] == 0): if(pos1[0] - pos2[0] == 0):
slope=100 slope=100
else: else:
slope = (pos1[1] - pos2[1])/(pos1[0] - pos2[0]) slope = (pos1[1] - pos2[1])/(pos1[0] - pos2[0])
offset = pos1[1] - (slope * pos1[0]) offset = pos1[1] - (slope * pos1[0])
if(slope == 0): if(slope == 0):
return(None) return(None)
wallSide = (GameSettings.wallWidth / 2) + GameSettings.ballRadius wallSide = (GameSettings.wallWidth / 2) + GameSettings.ballRadius
if(pos1[1] < 0): if(pos1[1] < 0):
wallSide *= -1 wallSide *= -1
hitPos = (wallSide - offset) / slope hitPos = (wallSide - offset) / slope
print(f'{hitPos=}')
relPos = wpos - hitPos relPos = wpos - hitPos
print("relative position : ", relPos)
print("max colision : ", (GameSettings.wallLength / 2) + GameSettings.ballRadius)
if(abs(relPos) < (GameSettings.wallLength / 2) + GameSettings.ballRadius): if(abs(relPos) < (GameSettings.wallLength / 2) + GameSettings.ballRadius):
return(hitPos) return(hitPos)
print("not in wall 1")
return(None) return(None)
def check_collision_obstacles(self): def check_collision_obstacles(self):
@ -117,7 +112,7 @@ class Ball:
def getTimeUntilColision(self, limitNeg, limitPos, position, velocity): def getTimeUntilColision(self, limitNeg, limitPos, position, velocity):
if(not velocity): if(not velocity):
return(-1) return(-1)
limit = GameSettings.limits[limitNeg] if velocity < 0 else GameSettings.limits[limitPos] limit = GameSettings.limits[limitNeg] if velocity < 0 else GameSettings.limits[limitPos]
wallDistance = max(limit, position) - min(limit, position) wallDistance = max(limit, position) - min(limit, position)
colision_time = wallDistance / abs(velocity) colision_time = wallDistance / abs(velocity)
return(colision_time) return(colision_time)
@ -141,55 +136,60 @@ class Ball:
def twoPointsDistance(self, pos1, pos2): def twoPointsDistance(self, pos1, pos2):
return(math.sqrt(((pos2[0] - pos1[0]) ** 2) + ((pos2[1] - pos1[1]) ** 2))) return(math.sqrt(((pos2[0] - pos1[0]) ** 2) + ((pos2[1] - pos1[1]) ** 2)))
def checkJumpersDistance(self, ballPos, p1, p2): def checkJumpersDistance(self, ballPos, p1, p2, noMsg):
for i in range(0, len(self.obstacles)): for i in range(0, len(self.obstacles)):
if(self.obstacles[i]["type"] != 1): if(self.obstacles[i]["type"] != 1):
continue; continue
if(self.obstacles[i]["isUp"] != self.up): if(self.obstacles[i]["isUp"] != self.up):
continue continue
if(self.twoPointsDistance((self.obstacles[i]["pos"]["x"], self.obstacles[i]["pos"]["z"]), ballPos) < GameSettings.jumperRadius): if(self.twoPointsDistance((self.obstacles[i]["pos"]["x"], self.obstacles[i]["pos"]["z"]), ballPos) < GameSettings.jumperRadius):
p1.socket.sync_send({"type":"game", "content":{"action":8,"name":self.obstacles[i]["name"]}}) if(p1.socket != None and not noMsg):
p2.socket.sync_send({"type":"game", "content":{"action":8,"name":self.obstacles[i]["name"]}}) p1.socket.sync_send({"type":"game", "content":{"action":8,"name":self.obstacles[i]["name"]}})
if(p2.socket != None and not noMsg):
p2.socket.sync_send({"type":"game", "content":{"action":8,"name":self.obstacles[i]["name"]}})
self.up = not self.up self.up = not self.up
def checkWallsColision(self, ballPos): def checkWallsColision(self, ballPos):
for i in range(0, len(self.obstacles)): for i in range(0, len(self.obstacles)):
if(self.obstacles[i]["type"] != 2): if(self.obstacles[i]["type"] != 2):
continue; continue
if(self.obstacles[i]["isUp"] != self.up): if(self.obstacles[i]["isUp"] != self.up):
continue; continue
if(abs(ballPos[1]) <= (GameSettings.wallWidth / 2) + GameSettings.ballRadius): if(abs(ballPos[1]) <= (GameSettings.wallWidth / 2) + GameSettings.ballRadius + 0.001):
if(abs(self.obstacles[i]["pos"]["x"] - ballPos[0]) < (GameSettings.wallLength / 2) + GameSettings.ballRadius): if(abs(self.obstacles[i]["pos"]["x"] - ballPos[0]) < (GameSettings.wallLength / 2) + GameSettings.ballRadius):
return(True) return(True)
return(False) return(False)
def increaseSpeed(self): def increaseSpeed(self):
self.vel[0] += (GameSettings.bounceSpeedIncrease * (self.vel[0] / self.speed)) self.vel[0] += (GameSettings.bounceSpeedIncrease * (self.vel[0] / self.speed))
self.vel[1] += (GameSettings.bounceSpeedIncrease * (self.vel[1] / self.speed)) self.vel[1] += (GameSettings.bounceSpeedIncrease * (self.vel[1] / self.speed))
self.speed += GameSettings.bounceSpeedIncrease self.speed += GameSettings.bounceSpeedIncrease
async def update(self, delta, p1, p2): async def update(self, delta, p1, p2, p1Hit = False):
print("AAAAAAAAAAAAAAAAAAAAAAA update")
self.pos[0] += (delta * self.vel[0]) self.pos[0] += (delta * self.vel[0])
self.pos[1] += (delta * self.vel[1]) self.pos[1] += (delta * self.vel[1])
if(self.pos[1] <= GameSettings.limits["back"] or self.pos[1] >= GameSettings.limits["front"]): if(self.pos[1] <= GameSettings.limits["back"] + 0.001 or self.pos[1] >= GameSettings.limits["front"] - 0.001):
player = p2.pos if self.pos[1] < 0 else p1.pos player = p2.pos if self.pos[1] < 0 else p1.pos
if(self.pos[1] > 0 and p1Hit):
return(1)
playerDistance = self.getPlayerDistance(player, self.pos) playerDistance = self.getPlayerDistance(player, self.pos)
if(playerDistance >= -(GameSettings.playerLength / 2) and playerDistance <= GameSettings.playerLength / 2 and player["up"] == self.up): if(playerDistance >= -(GameSettings.playerLength / 2) and playerDistance <= GameSettings.playerLength / 2 and player["up"] == self.up):
self.vel[0] = -((self.speed * 0.80) * (playerDistance / (GameSettings.playerLength / 2))) self.vel[0] = -((self.speed * 0.80) * (playerDistance / (GameSettings.playerLength / 2)))
self.vel[1] = self.speed - abs(self.vel[0]) self.vel[1] = self.speed - abs(self.vel[0])
if(self.pos[1] > 0): if(self.pos[1] > 0):
self.vel[1] = -self.vel[1] self.vel[1] = -self.vel[1]
p1.socket.sync_send({"type":"game","content":{"action":4, "is_opponent": self.pos[1] < 0}}) if(p1.socket != None and not p1Hit):
p2.socket.sync_send({"type":"game","content":{"action":4, "is_opponent": self.pos[1] > 0}}) p1.socket.sync_send({"type":"game","content":{"action":4, "is_opponent": self.pos[1] < 0}})
else: if(p2.socket != None and not p1Hit):
p2.socket.sync_send({"type":"game","content":{"action":4, "is_opponent": self.pos[1] > 0}})
elif(not p1Hit):
return(1 if self.pos[1] < 0 else 2) return(1 if self.pos[1] < 0 else 2)
elif(self.pos[0] <= GameSettings.limits["left"] or self.pos[0] >= GameSettings.limits["right"]): else:
return(0)
elif(self.pos[0] <= GameSettings.limits["left"] + 0.001 or self.pos[0] >= GameSettings.limits["right"] - 0.001):
self.vel[0] = -self.vel[0] self.vel[0] = -self.vel[0]
elif(self.checkWallsColision(self.pos)): elif(self.checkWallsColision(self.pos)):
self.vel[1] = -self.vel[1] self.vel[1] = -self.vel[1]
self.checkJumpersDistance(self.pos, p1, p2) self.checkJumpersDistance(self.pos, p1, p2, p1Hit)
self.increaseSpeed() self.increaseSpeed()
return(0) return(0)
#AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAa

View File

@ -6,10 +6,51 @@
# By: tomoron <tomoron@student.42.fr> +#+ +:+ +#+ # # By: tomoron <tomoron@student.42.fr> +#+ +:+ +#+ #
# +#+#+#+#+#+ +#+ # # +#+#+#+#+#+ +#+ #
# Created: 2024/10/05 03:54:20 by tomoron #+# #+# # # Created: 2024/10/05 03:54:20 by tomoron #+# #+# #
# Updated: 2024/10/05 03:55:31 by tomoron ### ########.fr # # Updated: 2024/10/08 10:20:50 by tomoron ### ########.fr #
# # # #
# **************************************************************************** # # **************************************************************************** #
from .Ball import Ball
from .Player import Player
from .DummySocket import DummySocket
from .GameSettings import GameSettings
import asyncio
class Bot(Player): class Bot(Player):
def __init__(self): def __init__(self, game):
print("I am a bot boop boop beep boop") self.socket = DummySocket(game)
self.game = game
self.ready = True
self.pos = {"pos":0, "up": False}
self.skin = 0
asyncio.create_task(self.updateLoop())
print("I am a bot, boop boop beep boop")
def createTempBall(self):
res = Ball()
res.setObstacles(self.game.obstacles)
res.vel = self.game.ball.vel.copy()
res.pos = self.game.ball.pos.copy()
res.up = self.game.ball.up
res.speed = self.game.ball.speed
return(res)
async def getExpectedPos(self):
tempBall = self.createTempBall()
hit = 0
i = 0
while(not hit):
sleepTime = tempBall.getSleepTime()
hit = await tempBall.update(sleepTime, self, self.game.p2, True)
i += 1
if(i == 50):
print("too many bounces")
return;
print("p1 hit at :", tempBall.pos[0])
self.game.move(self.socket, tempBall.pos[0], tempBall.up)
async def updateLoop(self):
while not self.game.end:
pos = await self.getExpectedPos()
await asyncio.sleep(1)

View File

@ -0,0 +1,23 @@
# **************************************************************************** #
# #
# ::: :::::::: #
# DummySocket.py :+: :+: :+: #
# +:+ +:+ +:+ #
# By: tomoron <marvin@42.fr> +#+ +:+ +#+ #
# +#+#+#+#+#+ +#+ #
# Created: 2024/10/08 07:33:29 by tomoron #+# #+# #
# Updated: 2024/10/08 08:25:06 by tomoron ### ########.fr #
# #
# **************************************************************************** #
class DummySocket:
def __init__(self, game):
self.id = 0
self.username = "bot"
self.game = game
def sync_send(*args):
pass
def sendError(*args):
pass

View File

@ -6,7 +6,7 @@
# By: edbernar <edbernar@student.42angouleme. +#+ +:+ +#+ # # By: edbernar <edbernar@student.42angouleme. +#+ +:+ +#+ #
# +#+#+#+#+#+ +#+ # # +#+#+#+#+#+ +#+ #
# Created: 2024/09/13 16:20:58 by tomoron #+# #+# # # Created: 2024/09/13 16:20:58 by tomoron #+# #+# #
# Updated: 2024/10/06 17:40:23 by tomoron ### ########.fr # # Updated: 2024/10/08 10:50:47 by tomoron ### ########.fr #
# # # #
# **************************************************************************** # # **************************************************************************** #
@ -14,6 +14,7 @@ from asgiref.sync import sync_to_async
from .Player import Player from .Player import Player
from .models import GameResults, User from .models import GameResults, User
from .GameSettings import GameSettings from .GameSettings import GameSettings
from .Bot import Bot
from .Ball import Ball from .Ball import Ball
import time import time
import json import json
@ -22,12 +23,11 @@ import random
import math import math
class Game: class Game:
waitingForPlayerLock = False
waitingForPlayer = None waitingForPlayer = None
def __init__(self, socket, withBot, skinId = 0, opponent = None): def __init__(self, socket, withBot, skinId = 0, opponent = None):
self.p1 = None self.p1 = None
self.p2 = None self.p2 = None
self.started = False self.started = False
self.end = False self.end = False
self.left = None self.left = None
@ -43,10 +43,11 @@ class Game:
self.opponentLock = opponent self.opponentLock = opponent
if(withBot): if(withBot):
self.p1 = Bot(self)
self.join(socket, skinId) self.join(socket, skinId)
elif(opponent != None): elif(opponent != None):
if(opponent not in socket.onlinePlayers): if(opponent not in socket.onlinePlayers):
return; return
opponentGame = socket.onlinePlayers[opponent].game opponentGame = socket.onlinePlayers[opponent].game
if (opponentGame != None and opponentGame.opponentLock != None and opponentGame.opponentLock == socket.id): if (opponentGame != None and opponentGame.opponentLock != None and opponentGame.opponentLock == socket.id):
socket.onlinePlayers[opponent].game.join(socket, skinId) socket.onlinePlayers[opponent].game.join(socket, skinId)
@ -54,9 +55,6 @@ class Game:
self.join(socket, skinId) self.join(socket, skinId)
socket.onlinePlayers[opponent].sync_send({"type":"invitation","content":{"invitor":socket.id, "username":socket.username}}) socket.onlinePlayers[opponent].sync_send({"type":"invitation","content":{"invitor":socket.id, "username":socket.username}})
else: else:
while(Game.waitingForPlayerLock):
continue
Game.waitingForPlayerLock = True
if(Game.waitingForPlayer == None): if(Game.waitingForPlayer == None):
Game.waitingForPlayer = self Game.waitingForPlayer = self
socket.sync_send({"type":"game","content":{"action":0}}) socket.sync_send({"type":"game","content":{"action":0}})
@ -64,7 +62,6 @@ class Game:
else: else:
Game.waitingForPlayer.join(socket, skinId) Game.waitingForPlayer.join(socket, skinId)
Game.waitingForPlayer = None Game.waitingForPlayer = None
Game.waitingForPlayerLock = False
def __del__(self): def __del__(self):
print("game destroy") print("game destroy")
@ -107,7 +104,7 @@ class Game:
else: else:
if(self.opponentLock != None and self.opponentLock != socket.id): if(self.opponentLock != None and self.opponentLock != socket.id):
socket.sendError("You are not invited to this game", 9103) socket.sendError("You are not invited to this game", 9103)
return; return
print("joined game, set as player 2") print("joined game, set as player 2")
self.p2 = Player(socket, self) self.p2 = Player(socket, self)
self.p2.skin = skin self.p2.skin = skin
@ -139,20 +136,16 @@ class Game:
self.p2.socket.sync_send({"type":"game","content":{"action":10,"won":winner==2, "opponentLeft":self.left == 1}}) self.p2.socket.sync_send({"type":"game","content":{"action":10,"won":winner==2, "opponentLeft":self.left == 1}})
self.winner = winner self.winner = winner
self.end = True self.end = True
def leave(self, socket): def leave(self, socket):
socket.game = None socket.game = None
if (socket == self.p1.socket): if (socket == self.p1.socket):
self.left = 1 self.left = 1
else: else:
self.left = 2 self.left = 2
while(Game.waitingForPlayerLock):
time.sleeep(0.05)
Game.waitingForPlayerLock = True
if(Game.waitingForPlayer == self): if(Game.waitingForPlayer == self):
Game.waitingForPlayer = None; Game.waitingForPlayer = None
Game.waitingForPlayerLock = False if(self.p2 != None):
if(self.started):
self.endGame(1 if self.left == 2 else 2) self.endGame(1 if self.left == 2 else 2)
self.end=True self.end=True
@ -165,9 +158,9 @@ class Game:
opponent = self.p1.socket if socket != self.p1.socket else self.p2.socket opponent = self.p1.socket if socket != self.p1.socket else self.p2.socket
if(socket == self.p1.socket): if(socket == self.p1.socket):
self.p1.pos["pos"] = pos self.p1.pos["pos"] = pos
self.p1.pos["up"] = up; self.p1.pos["up"] = up
else: else:
self.p2.pos["pos"] = -pos; self.p2.pos["pos"] = -pos
self.p2.pos["up"] = up self.p2.pos["up"] = up
if(opponent != None): if(opponent != None):
opponent.sync_send({"type":"game","content":{"action":3, "pos":-pos, "up":up, "is_opponent":True}}) opponent.sync_send({"type":"game","content":{"action":3, "pos":-pos, "up":up, "is_opponent":True}})
@ -193,13 +186,13 @@ class Game:
if(self.score[0] < GameSettings.maxScore and self.score[1] < GameSettings.maxScore): if(self.score[0] < GameSettings.maxScore and self.score[1] < GameSettings.maxScore):
return(False) return(False)
print("someone won the game") print("someone won the game")
winner = 1 if self.score[0] == GameSettings.maxScore else 2 winner = 1 if self.score[0] == GameSettings.maxScore else 2
print("player", winner,"won the game") print("player", winner,"won the game")
self.endGame(winner) self.endGame(winner)
return(True) return(True)
async def scoreGoal(self, player): async def scoreGoal(self, player):
self.lastWin = player self.lastWin = player
print("a player suffured from a major skill issue") print("a player suffured from a major skill issue")
self.score[player-1] += 1 self.score[player-1] += 1
print("new score :", self.score) print("new score :", self.score)
@ -211,7 +204,7 @@ class Game:
self.prepareGame(True) self.prepareGame(True)
await asyncio.sleep(3) await asyncio.sleep(3)
self.prepareGame() self.prepareGame()
return; return
def prepareGame(self, stop = False): def prepareGame(self, stop = False):
self.speed = GameSettings.startSpeed self.speed = GameSettings.startSpeed
@ -247,7 +240,7 @@ class Game:
self.p2.socket.game = None self.p2.socket.game = None
await self.saveResults() await self.saveResults()
del self del self
@sync_to_async @sync_to_async
def saveResults(self): def saveResults(self):
try: try:

View File

@ -6,7 +6,7 @@
# By: tomoron <tomoron@student.42.fr> +#+ +:+ +#+ # # By: tomoron <tomoron@student.42.fr> +#+ +:+ +#+ #
# +#+#+#+#+#+ +#+ # # +#+#+#+#+#+ +#+ #
# Created: 2024/10/05 03:22:32 by tomoron #+# #+# # # Created: 2024/10/05 03:22:32 by tomoron #+# #+# #
# Updated: 2024/10/06 16:16:26 by tomoron ### ########.fr # # Updated: 2024/10/08 07:47:31 by tomoron ### ########.fr #
# # # #
# **************************************************************************** # # **************************************************************************** #