bot now has normal movements, fix colisions when ball is perfectly straight

This commit is contained in:
2024-10-09 09:04:14 +02:00
parent 7be1d3ae9f
commit 2046ed4c9a
7 changed files with 114 additions and 48 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/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] self.vel[1] = -self.vel[1]
def default(self): def default(self):
self.pos = [0, 0] self.pos = [-1, 1]
self.up = False self.up = False
self.vel = [0, 0] self.vel = [0, 0]
self.speed = GameSettings.startSpeed self.speed = GameSettings.startSpeed
@ -35,21 +35,12 @@ class Ball:
def setObstacles(self, obstacles): def setObstacles(self, obstacles):
self.obstacles = 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"]) jpos = (jumper["pos"]["x"], jumper["pos"]["z"])
pos1 = self.pos pos1 = self.pos
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(pos1[0] - pos2[0] == 0):
slope=100
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])
@ -57,18 +48,20 @@ class Ball:
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))
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"] wpos = wall["pos"]["x"]
pos1 = self.pos pos1 = self.pos
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):
return(None) return(None)
if(pos1[0] - pos2[0] == 0):
slope=100
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])
@ -84,16 +77,16 @@ class Ball:
return(hitPos) return(hitPos)
return(None) return(None)
def check_collision_obstacles(self): def colisionTimeX(self):
min_time = -1 min_time = -1
for x in self.obstacles: for x in self.obstacles:
if x["isUp"] != self.up: if x["isUp"] != self.up:
continue continue
pos = None pos = None
if x["type"] == 1: if x["type"] == 1:
pos = self.check_jumper_colision(x) pos = self.jumperCollisionDistanceX(x)
elif x["type"] == 2: elif x["type"] == 2:
pos = self.check_wall_colision(x) pos = self.wallColisionDistanceX(x)
if(pos == None): if(pos == None):
continue continue
dist = pos - self.pos[0] dist = pos - self.pos[0]
@ -103,13 +96,17 @@ class Ball:
else: else:
time = -1 time = -1
if(time > 0): if(time > 0):
if(min_time == -1): if(min_time < 0):
min_time = time min_time = time
else: else:
min_time = (min(min_time, time)) 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): 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]
@ -117,17 +114,64 @@ class Ball:
colision_time = wallDistance / abs(velocity) colision_time = wallDistance / abs(velocity)
return(colision_time) 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): def getSleepTime(self):
time_x = self.getTimeUntilColision("left","right", self.pos[0], self.vel[0]) try:
time_z = self.getTimeUntilColision("back","front", self.pos[1], self.vel[1]) timeX = self.colisionTimeX()
time_objects = self.check_collision_obstacles() except ZeroDivisionError:
if(time_objects != -1): timeX = -1
time_x = min(time_x, time_objects) timeY = self.colisionTimeY(timeX < 0)
if(time_x == -1): if(timeX < 0):
return(time_z) return(timeY)
if(time_z == -1): if(timeY < 0):
return(time_x) return(timeX)
return(min(time_x, time_z)) return(min(timeX, timeY))
def getPlayerDistance(self, player, ballPos): def getPlayerDistance(self, player, ballPos):
playerPos = player["pos"] playerPos = player["pos"]

View File

@ -6,7 +6,7 @@
# 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/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 .DummySocket import DummySocket
from .GameSettings import GameSettings from .GameSettings import GameSettings
import asyncio import asyncio
import time
class Bot(Player): class Bot(Player):
def __init__(self, game): def __init__(self, game):
@ -22,8 +23,10 @@ class Bot(Player):
self.game = game self.game = game
self.ready = True self.ready = True
self.pos = {"pos":0, "up": False} self.pos = {"pos":0, "up": False}
self.objective = {"pos":0, "up": False}
self.skin = 0 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") print("I am a bot, boop boop beep boop")
def createTempBall(self): def createTempBall(self):
@ -44,13 +47,26 @@ class Bot(Player):
hit = await tempBall.update(sleepTime, self, self.game.p2, True) hit = await tempBall.update(sleepTime, self, self.game.p2, True)
i += 1 i += 1
if(i == 50): if(i == 50):
print("too many bounces") return
return; self.objective = {"pos":tempBall.pos[0], "up":tempBall.up}
print("p1 hit at :", tempBall.pos[0])
self.game.move(self.socket, tempBall.pos[0], tempBall.up)
async def updateLoop(self): async def updateLoop(self):
while not self.game.end: while not self.game.end:
pos = await self.getExpectedPos() await self.getExpectedPos()
await asyncio.sleep(1) 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)

View File

@ -6,7 +6,7 @@
# By: tomoron <marvin@42.fr> +#+ +:+ +#+ # # By: tomoron <marvin@42.fr> +#+ +:+ +#+ #
# +#+#+#+#+#+ +#+ # # +#+#+#+#+#+ +#+ #
# Created: 2024/10/08 07:33:29 by tomoron #+# #+# # # 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.id = 0
self.username = "bot" self.username = "bot"
self.game = game self.game = game
self.pfp = "/static/img/robot_pfp.jpg"
def sync_send(*args): def sync_send(*args):
pass 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/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.lastWin = 2
self.opponentLock = opponent self.opponentLock = opponent
if(withBot): if(1 or withBot):
self.p1 = Bot(self) self.p1 = Bot(self)
self.join(socket, skinId) self.join(socket, skinId)
elif(opponent != None): elif(opponent != None):
@ -73,7 +73,7 @@ class Game:
def genObstacles(self): def genObstacles(self):
for x in GameSettings.wallsPos: for x in GameSettings.wallsPos:
if random.randint(1, 100) < 70: if random.randint(1, 100) < 100:
self.obstacles.append(x) self.obstacles.append(x)
i = 0 i = 0
down = False down = False

View File

@ -6,7 +6,7 @@
# By: tomoron <tomoron@student.42.fr> +#+ +:+ +#+ # # By: tomoron <tomoron@student.42.fr> +#+ +:+ +#+ #
# +#+#+#+#+#+ +#+ # # +#+#+#+#+#+ +#+ #
# Created: 2024/10/06 16:33:56 by tomoron #+# #+# # # 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 wallWidth = 0.05
bounceSpeedIncrease = 0.2 bounceSpeedIncrease = 0.2
maxScore = 5 maxScore = 5
maxPlayerSpeed = 0.4

View File

@ -6,7 +6,7 @@
# By: tomoron <tomoron@student.42.fr> +#+ +:+ +#+ # # By: tomoron <tomoron@student.42.fr> +#+ +:+ +#+ #
# +#+#+#+#+#+ +#+ # # +#+#+#+#+#+ +#+ #
# Created: 2024/09/09 16:10:26 by tomoron #+# #+# # # 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 # 1 : opponent : tell the client the name of the opponent
# - id : 0 if it's a bot # - id : 0 if it's a bot
# - username # - username
# - skin : id of the skin
# - opponentSkin : eddy is wierd
# - selfSkin : eddy is wierd
# #
# 2 : go : the game started # 2 : go : the game started
# #

Binary file not shown.

After

Width:  |  Height:  |  Size: 816 KiB