bot now has normal movements, fix colisions when ball is perfectly straight
This commit is contained in:
@ -6,7 +6,7 @@
|
||||
# By: tomoron <tomoron@student.42.fr> +#+ +:+ +#+ #
|
||||
# +#+#+#+#+#+ +#+ #
|
||||
# Created: 2024/10/06 03:24:10 by tomoron #+# #+# #
|
||||
# Updated: 2024/10/08 10:00:22 by tomoron ### ########.fr #
|
||||
# Updated: 2024/10/09 09:02:37 by tomoron ### ########.fr #
|
||||
# #
|
||||
# **************************************************************************** #
|
||||
|
||||
@ -27,7 +27,7 @@ class Ball:
|
||||
self.vel[1] = -self.vel[1]
|
||||
|
||||
def default(self):
|
||||
self.pos = [0, 0]
|
||||
self.pos = [-1, 1]
|
||||
self.up = False
|
||||
self.vel = [0, 0]
|
||||
self.speed = GameSettings.startSpeed
|
||||
@ -35,21 +35,12 @@ class Ball:
|
||||
def setObstacles(self, obstacles):
|
||||
self.obstacles = obstacles
|
||||
|
||||
def solve_quadratic(self, a, b, c):
|
||||
disc = (b ** 2) - (4 * a * c)
|
||||
if(disc < 0):
|
||||
return None
|
||||
res = (((-b) + math.sqrt(disc)) / ( 2 * a )) + (((-b) - math.sqrt(disc)) / ( 2 * a ))
|
||||
return(res / 2)
|
||||
|
||||
def check_jumper_colision(self, jumper):
|
||||
def jumperCollisionDistanceX(self, jumper):
|
||||
jpos = (jumper["pos"]["x"], jumper["pos"]["z"])
|
||||
pos1 = self.pos
|
||||
pos2 = self.pos[0] + self.vel[0], self.pos[1] + self.vel[1]
|
||||
slope = 0
|
||||
if(pos1[0] - pos2[0] == 0):
|
||||
slope=100
|
||||
else:
|
||||
slope = (pos1[1] - pos2[1])/(pos1[0] - pos2[0])
|
||||
offset = pos1[1] - (slope * pos1[0])
|
||||
|
||||
@ -57,18 +48,20 @@ class Ball:
|
||||
a = 1 + (slope ** 2)
|
||||
b = ((-jpos[0]) * 2) + (2 * (slope * (-jpos[1] + offset)))
|
||||
c = (((-jpos[0]) ** 2) + (((-jpos[1]) + offset) ** 2)) - (GameSettings.jumperRadius ** 2)
|
||||
return(self.solve_quadratic(a, b ,c))
|
||||
|
||||
def check_wall_colision(self, wall):
|
||||
disc = (b ** 2) - (4 * a * c)
|
||||
if(disc < 0):
|
||||
return None
|
||||
res = (((-b) + math.sqrt(disc)) / ( 2 * a )) + (((-b) - math.sqrt(disc)) / ( 2 * a ))
|
||||
return(res / 2)
|
||||
|
||||
def wallColisionDistanceX(self, wall):
|
||||
wpos = wall["pos"]["x"]
|
||||
pos1 = self.pos
|
||||
pos2 = self.pos[0] +self.vel[0], self.pos[1] + self.vel[1]
|
||||
slope = 0
|
||||
if(abs(pos1[1]) <= (GameSettings.wallWidth / 2) + GameSettings.ballRadius):
|
||||
return(None)
|
||||
if(pos1[0] - pos2[0] == 0):
|
||||
slope=100
|
||||
else:
|
||||
slope = (pos1[1] - pos2[1])/(pos1[0] - pos2[0])
|
||||
offset = pos1[1] - (slope * pos1[0])
|
||||
|
||||
@ -84,16 +77,16 @@ class Ball:
|
||||
return(hitPos)
|
||||
return(None)
|
||||
|
||||
def check_collision_obstacles(self):
|
||||
def colisionTimeX(self):
|
||||
min_time = -1
|
||||
for x in self.obstacles:
|
||||
if x["isUp"] != self.up:
|
||||
continue
|
||||
pos = None
|
||||
if x["type"] == 1:
|
||||
pos = self.check_jumper_colision(x)
|
||||
pos = self.jumperCollisionDistanceX(x)
|
||||
elif x["type"] == 2:
|
||||
pos = self.check_wall_colision(x)
|
||||
pos = self.wallColisionDistanceX(x)
|
||||
if(pos == None):
|
||||
continue
|
||||
dist = pos - self.pos[0]
|
||||
@ -103,13 +96,17 @@ class Ball:
|
||||
else:
|
||||
time = -1
|
||||
if(time > 0):
|
||||
if(min_time == -1):
|
||||
if(min_time < 0):
|
||||
min_time = time
|
||||
else:
|
||||
min_time = (min(min_time, time))
|
||||
return(min_time)
|
||||
|
||||
def getTimeUntilColision(self, limitNeg, limitPos, position, velocity):
|
||||
wallsTime = self.getTimeUntilWallColision("left","right", self.pos[0], self.vel[0])
|
||||
if(wallsTime < 0):
|
||||
return(min_time)
|
||||
return(min(min_time, wallsTime))
|
||||
|
||||
def getTimeUntilWallColision(self, limitNeg, limitPos, position, velocity):
|
||||
if(not velocity):
|
||||
return(-1)
|
||||
limit = GameSettings.limits[limitNeg] if velocity < 0 else GameSettings.limits[limitPos]
|
||||
@ -117,17 +114,64 @@ class Ball:
|
||||
colision_time = wallDistance / abs(velocity)
|
||||
return(colision_time)
|
||||
|
||||
def wallColisionDistanceY(self, wall):
|
||||
wallSide = (GameSettings.wallWidth / 2) + GameSettings.ballRadius
|
||||
if(self.pos[1] < 0):
|
||||
wallSide *= -1
|
||||
relPos = wall["pos"]["x"] - self.pos[0]
|
||||
if(abs(relPos) < (GameSettings.wallLength / 2) + GameSettings.ballRadius):
|
||||
return(wallSide)
|
||||
return(None)
|
||||
|
||||
def jumperColisionDistanceY(self, jumper):
|
||||
relPos = jumper["pos"]["x"] - self.pos[0]
|
||||
if(abs(relPos) <= GameSettings.jumperRadius):
|
||||
return(jumper["pos"]["z"])
|
||||
return(None)
|
||||
|
||||
|
||||
def colisionTimeY(self, checkObstacles):
|
||||
wallsTime = self.getTimeUntilWallColision("back","front", self.pos[1], self.vel[1])
|
||||
if(not checkObstacles):
|
||||
return(wallsTime)
|
||||
|
||||
min_time = -1
|
||||
for x in self.obstacles:
|
||||
if x["isUp"] != self.up:
|
||||
continue
|
||||
pos = None
|
||||
if x["type"] == 1:
|
||||
pos = self.jumperColisionDistanceY(x)
|
||||
elif x["type"] == 2:
|
||||
pos = self.wallColisionDistanceY(x)
|
||||
if(pos == None):
|
||||
continue
|
||||
dist = pos - self.pos[1]
|
||||
time = 0
|
||||
if(self.vel[1] != 0):
|
||||
time = dist / self.vel[1]
|
||||
else:
|
||||
time = -1
|
||||
if(time > 0):
|
||||
if(min_time < 0):
|
||||
min_time = time
|
||||
else:
|
||||
min_time = (min(min_time, time))
|
||||
if(min_time < 0):
|
||||
return(wallsTime)
|
||||
return(min(wallsTime,min_time))
|
||||
|
||||
def getSleepTime(self):
|
||||
time_x = self.getTimeUntilColision("left","right", self.pos[0], self.vel[0])
|
||||
time_z = self.getTimeUntilColision("back","front", self.pos[1], self.vel[1])
|
||||
time_objects = self.check_collision_obstacles()
|
||||
if(time_objects != -1):
|
||||
time_x = min(time_x, time_objects)
|
||||
if(time_x == -1):
|
||||
return(time_z)
|
||||
if(time_z == -1):
|
||||
return(time_x)
|
||||
return(min(time_x, time_z))
|
||||
try:
|
||||
timeX = self.colisionTimeX()
|
||||
except ZeroDivisionError:
|
||||
timeX = -1
|
||||
timeY = self.colisionTimeY(timeX < 0)
|
||||
if(timeX < 0):
|
||||
return(timeY)
|
||||
if(timeY < 0):
|
||||
return(timeX)
|
||||
return(min(timeX, timeY))
|
||||
|
||||
def getPlayerDistance(self, player, ballPos):
|
||||
playerPos = player["pos"]
|
||||
|
@ -6,7 +6,7 @@
|
||||
# By: tomoron <tomoron@student.42.fr> +#+ +:+ +#+ #
|
||||
# +#+#+#+#+#+ +#+ #
|
||||
# Created: 2024/10/05 03:54:20 by tomoron #+# #+# #
|
||||
# Updated: 2024/10/08 10:20:50 by tomoron ### ########.fr #
|
||||
# Updated: 2024/10/09 07:24:54 by tomoron ### ########.fr #
|
||||
# #
|
||||
# **************************************************************************** #
|
||||
|
||||
@ -15,6 +15,7 @@ from .Player import Player
|
||||
from .DummySocket import DummySocket
|
||||
from .GameSettings import GameSettings
|
||||
import asyncio
|
||||
import time
|
||||
|
||||
class Bot(Player):
|
||||
def __init__(self, game):
|
||||
@ -22,8 +23,10 @@ class Bot(Player):
|
||||
self.game = game
|
||||
self.ready = True
|
||||
self.pos = {"pos":0, "up": False}
|
||||
self.objective = {"pos":0, "up": False}
|
||||
self.skin = 0
|
||||
asyncio.create_task(self.updateLoop())
|
||||
#asyncio.create_task(self.updateLoop())
|
||||
#asyncio.create_task(self.goToObjectiveLoop())
|
||||
print("I am a bot, boop boop beep boop")
|
||||
|
||||
def createTempBall(self):
|
||||
@ -44,13 +47,26 @@ class Bot(Player):
|
||||
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)
|
||||
return
|
||||
self.objective = {"pos":tempBall.pos[0], "up":tempBall.up}
|
||||
|
||||
async def updateLoop(self):
|
||||
while not self.game.end:
|
||||
pos = await self.getExpectedPos()
|
||||
await self.getExpectedPos()
|
||||
await asyncio.sleep(1)
|
||||
|
||||
async def goToObjectiveLoop(self):
|
||||
lastUpdate = time.time()
|
||||
while not self.game.end:
|
||||
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()
|
||||
travel = self.objective["pos"] - self.pos["pos"]
|
||||
if(travel >= 0):
|
||||
travel = min(self.objective["pos"] - self.pos["pos"], GameSettings.maxPlayerSpeed)
|
||||
else:
|
||||
travel = max(self.objective["pos"] - self.pos["pos"], -GameSettings.maxPlayerSpeed)
|
||||
self.game.move(self.socket, self.pos["pos"] + travel, self.pos["up"])
|
||||
await asyncio.sleep(1 / 20)
|
||||
|
@ -6,7 +6,7 @@
|
||||
# By: tomoron <marvin@42.fr> +#+ +:+ +#+ #
|
||||
# +#+#+#+#+#+ +#+ #
|
||||
# Created: 2024/10/08 07:33:29 by tomoron #+# #+# #
|
||||
# Updated: 2024/10/08 08:25:06 by tomoron ### ########.fr #
|
||||
# Updated: 2024/10/09 07:03:46 by tomoron ### ########.fr #
|
||||
# #
|
||||
# **************************************************************************** #
|
||||
|
||||
@ -15,6 +15,7 @@ class DummySocket:
|
||||
self.id = 0
|
||||
self.username = "bot"
|
||||
self.game = game
|
||||
self.pfp = "/static/img/robot_pfp.jpg"
|
||||
|
||||
def sync_send(*args):
|
||||
pass
|
||||
|
@ -6,7 +6,7 @@
|
||||
# By: edbernar <edbernar@student.42angouleme. +#+ +:+ +#+ #
|
||||
# +#+#+#+#+#+ +#+ #
|
||||
# Created: 2024/09/13 16:20:58 by tomoron #+# #+# #
|
||||
# Updated: 2024/10/08 17:44:34 by edbernar ### ########.fr #
|
||||
# Updated: 2024/10/09 07:06:00 by tomoron ### ########.fr #
|
||||
# #
|
||||
# **************************************************************************** #
|
||||
|
||||
@ -42,7 +42,7 @@ class Game:
|
||||
self.lastWin = 2
|
||||
|
||||
self.opponentLock = opponent
|
||||
if(withBot):
|
||||
if(1 or withBot):
|
||||
self.p1 = Bot(self)
|
||||
self.join(socket, skinId)
|
||||
elif(opponent != None):
|
||||
@ -73,7 +73,7 @@ class Game:
|
||||
|
||||
def genObstacles(self):
|
||||
for x in GameSettings.wallsPos:
|
||||
if random.randint(1, 100) < 70:
|
||||
if random.randint(1, 100) < 100:
|
||||
self.obstacles.append(x)
|
||||
i = 0
|
||||
down = False
|
||||
|
@ -6,7 +6,7 @@
|
||||
# By: tomoron <tomoron@student.42.fr> +#+ +:+ +#+ #
|
||||
# +#+#+#+#+#+ +#+ #
|
||||
# Created: 2024/10/06 16:33:56 by tomoron #+# #+# #
|
||||
# Updated: 2024/10/06 16:34:24 by tomoron ### ########.fr #
|
||||
# Updated: 2024/10/09 07:03:19 by tomoron ### ########.fr #
|
||||
# #
|
||||
# **************************************************************************** #
|
||||
|
||||
@ -52,3 +52,5 @@ class GameSettings:
|
||||
wallWidth = 0.05
|
||||
bounceSpeedIncrease = 0.2
|
||||
maxScore = 5
|
||||
|
||||
maxPlayerSpeed = 0.4
|
||||
|
@ -6,7 +6,7 @@
|
||||
# By: tomoron <tomoron@student.42.fr> +#+ +:+ +#+ #
|
||||
# +#+#+#+#+#+ +#+ #
|
||||
# Created: 2024/09/09 16:10:26 by tomoron #+# #+# #
|
||||
# Updated: 2024/10/04 17:10:39 by tomoron ### ########.fr #
|
||||
# Updated: 2024/10/09 00:53:25 by tomoron ### ########.fr #
|
||||
# #
|
||||
# **************************************************************************** #
|
||||
|
||||
@ -24,6 +24,9 @@ from .gameActions.ping import ping
|
||||
# 1 : opponent : tell the client the name of the opponent
|
||||
# - id : 0 if it's a bot
|
||||
# - username
|
||||
# - skin : id of the skin
|
||||
# - opponentSkin : eddy is wierd
|
||||
# - selfSkin : eddy is wierd
|
||||
#
|
||||
# 2 : go : the game started
|
||||
#
|
||||
|
BIN
docker-compose/requirements/nginx/static/img/robot_pfp.jpg
Normal file
BIN
docker-compose/requirements/nginx/static/img/robot_pfp.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 816 KiB |
Reference in New Issue
Block a user