mirror of
https://github.com/AudebertAdrien/ft_transcendence.git
synced 2025-12-16 22:17:48 +01:00
added a BOT player, and some fixes in the game logic
This commit is contained in:
parent
63ee8bc75b
commit
e7797eac2c
2
makefile
2
makefile
@ -2,7 +2,7 @@ COMPOSE_FILE=docker-compose.yaml
|
|||||||
COMPOSE=docker compose -f $(COMPOSE_FILE)
|
COMPOSE=docker compose -f $(COMPOSE_FILE)
|
||||||
CONTAINER=$(c)
|
CONTAINER=$(c)
|
||||||
|
|
||||||
up:
|
up: down
|
||||||
sudo mkdir -p data/db
|
sudo mkdir -p data/db
|
||||||
$(COMPOSE) build
|
$(COMPOSE) build
|
||||||
$(COMPOSE) up $(CONTAINER)
|
$(COMPOSE) up $(CONTAINER)
|
||||||
|
|||||||
@ -9,9 +9,10 @@ class Game:
|
|||||||
self.game_id = game_id
|
self.game_id = game_id
|
||||||
self.player1 = player1
|
self.player1 = player1
|
||||||
self.player2 = player2
|
self.player2 = player2
|
||||||
|
self.botgame = player2 is None
|
||||||
self.game_state = {
|
self.game_state = {
|
||||||
'player1_name': player1.user.username,
|
'player1_name': player1.user.username,
|
||||||
'player2_name': player2.user.username,
|
'player2_name': player2.user.username if player2 else 'BOT',
|
||||||
'player1_position': 150,
|
'player1_position': 150,
|
||||||
'player2_position': 150,
|
'player2_position': 150,
|
||||||
'ball_position': {'x': 390, 'y': 190},
|
'ball_position': {'x': 390, 'y': 190},
|
||||||
@ -28,37 +29,49 @@ class Game:
|
|||||||
|
|
||||||
async def game_loop(self):
|
async def game_loop(self):
|
||||||
while True:
|
while True:
|
||||||
|
if self.botgame:
|
||||||
|
await self.update_bot_position()
|
||||||
self.update_game_state()
|
self.update_game_state()
|
||||||
await self.send_game_state()
|
await self.send_game_state()
|
||||||
await asyncio.sleep(1/60) # 60 FPS
|
await asyncio.sleep(1/60) # Around 60 FPS
|
||||||
|
|
||||||
|
# The amazing AI BOT player
|
||||||
|
async def update_bot_position(self):
|
||||||
|
target_y = self.game_state['ball_position']['y']
|
||||||
|
if self.game_state['player2_position'] < target_y < self.game_state['player2_position'] + 80:
|
||||||
|
pass
|
||||||
|
elif self.game_state['player2_position'] < target_y:
|
||||||
|
self.game_state['player2_position'] = min(self.game_state['player2_position'] + (5 * self.speed), 300)
|
||||||
|
elif self.game_state['player2_position'] + 80 > target_y:
|
||||||
|
self.game_state['player2_position'] = max(self.game_state['player2_position'] - (5 * self.speed), 0)
|
||||||
|
|
||||||
def update_game_state(self):
|
def update_game_state(self):
|
||||||
# Update ball position
|
# Update ball position
|
||||||
self.game_state['ball_position']['x'] += self.game_state['ball_velocity']['x']
|
self.game_state['ball_position']['x'] += self.game_state['ball_velocity']['x']
|
||||||
self.game_state['ball_position']['y'] += self.game_state['ball_velocity']['y']
|
self.game_state['ball_position']['y'] += self.game_state['ball_velocity']['y']
|
||||||
|
|
||||||
# Check for collisions with top and bottom walls
|
# Check for collisions with top and bottom walls
|
||||||
if self.game_state['ball_position']['y'] <= 10 or self.game_state['ball_position']['y'] >= 390:
|
if self.game_state['ball_position']['y'] <= 10 or self.game_state['ball_position']['y'] >= 390:
|
||||||
self.game_state['ball_velocity']['y'] *= -1
|
self.game_state['ball_velocity']['y'] *= -1
|
||||||
|
# Check for collisions with paddles
|
||||||
|
if self.game_state['ball_position']['x'] <= 20 and \
|
||||||
|
self.game_state['player1_position'] - 10 <= self.game_state['ball_position']['y'] <= self.game_state['player1_position'] + 90:
|
||||||
|
if self.game_state['ball_velocity']['x'] < 0:
|
||||||
|
self.game_state['ball_velocity']['x'] *= -1
|
||||||
|
self.update_ball_velocity()
|
||||||
|
elif self.game_state['ball_position']['x'] >= 760 and \
|
||||||
|
self.game_state['player2_position'] - 10 <= self.game_state['ball_position']['y'] <= self.game_state['player2_position'] + 90:
|
||||||
|
if self.game_state['ball_velocity']['x'] > 0:
|
||||||
|
self.game_state['ball_velocity']['x'] *= -1
|
||||||
|
self.update_ball_velocity()
|
||||||
# Check for scoring
|
# Check for scoring
|
||||||
if self.game_state['ball_position']['x'] <= 10:
|
if self.game_state['ball_position']['x'] <= 10:
|
||||||
self.game_state['player2_score'] += 1
|
self.game_state['player2_score'] += 1
|
||||||
self.reset_ball()
|
self.reset_ball()
|
||||||
elif self.game_state['ball_position']['x'] >= 790:
|
elif self.game_state['ball_position']['x'] >= 790:
|
||||||
self.game_state['player1_score'] += 1
|
self.game_state['player1_score'] += 1
|
||||||
|
print(f"*** Ball in position ({self.game_state['ball_position']['x']},{self.game_state['ball_position']['y']}) with a speed ratio of {self.speed}")
|
||||||
self.reset_ball()
|
self.reset_ball()
|
||||||
|
|
||||||
# Check for collisions with paddles
|
|
||||||
if self.game_state['ball_position']['x'] <= 20 and \
|
|
||||||
self.game_state['player1_position'] <= self.game_state['ball_position']['y'] <= self.game_state['player1_position'] + 80:
|
|
||||||
self.update_ball_velocity()
|
|
||||||
self.game_state['ball_velocity']['x'] *= -1
|
|
||||||
elif self.game_state['ball_position']['x'] >= 760 and \
|
|
||||||
self.game_state['player2_position'] <= self.game_state['ball_position']['y'] <= self.game_state['player2_position'] + 80:
|
|
||||||
self.update_ball_velocity()
|
|
||||||
self.game_state['ball_velocity']['x'] *= -1
|
|
||||||
|
|
||||||
def reset_ball(self):
|
def reset_ball(self):
|
||||||
self.game_state['ball_position'] = {'x': 390, 'y': 190}
|
self.game_state['ball_position'] = {'x': 390, 'y': 190}
|
||||||
self.game_state['ball_velocity'] = {'x': random.choice([-5, 5]), 'y': random.choice([-5, 5])}
|
self.game_state['ball_velocity'] = {'x': random.choice([-5, 5]), 'y': random.choice([-5, 5])}
|
||||||
@ -68,8 +81,6 @@ class Game:
|
|||||||
self.speed += 0.05
|
self.speed += 0.05
|
||||||
if self.speed > 2:
|
if self.speed > 2:
|
||||||
self.speed = 2
|
self.speed = 2
|
||||||
else:
|
|
||||||
print(f"Ball velocity: {self.speed}")
|
|
||||||
self.game_state['ball_velocity']['x'] *= self.speed
|
self.game_state['ball_velocity']['x'] *= self.speed
|
||||||
if self.game_state['ball_velocity']['x'] < -10:
|
if self.game_state['ball_velocity']['x'] < -10:
|
||||||
self.game_state['ball_velocity']['x'] = -10
|
self.game_state['ball_velocity']['x'] = -10
|
||||||
@ -87,7 +98,8 @@ class Game:
|
|||||||
'game_state': self.game_state
|
'game_state': self.game_state
|
||||||
})
|
})
|
||||||
await self.player1.send(message)
|
await self.player1.send(message)
|
||||||
await self.player2.send(message)
|
if not self.botgame:
|
||||||
|
await self.player2.send(message)
|
||||||
|
|
||||||
async def handle_key_press(self, player, key):
|
async def handle_key_press(self, player, key):
|
||||||
if player == self.player1:
|
if player == self.player1:
|
||||||
@ -99,7 +111,7 @@ class Game:
|
|||||||
self.game_state['player1_position'] += 25
|
self.game_state['player1_position'] += 25
|
||||||
if self.game_state['player1_position'] > 300:
|
if self.game_state['player1_position'] > 300:
|
||||||
self.game_state['player1_position'] = 300
|
self.game_state['player1_position'] = 300
|
||||||
elif player == self.player2:
|
elif not self.botgame and player == self.player2:
|
||||||
if key == 'arrowup':
|
if key == 'arrowup':
|
||||||
self.game_state['player2_position'] -= 25
|
self.game_state['player2_position'] -= 25
|
||||||
if self.game_state['player2_position'] < 0:
|
if self.game_state['player2_position'] < 0:
|
||||||
|
|||||||
@ -9,6 +9,8 @@ class MatchMaker:
|
|||||||
self.waiting_players = []
|
self.waiting_players = []
|
||||||
self.active_games = {}
|
self.active_games = {}
|
||||||
self.matching_task = None
|
self.matching_task = None
|
||||||
|
self.timer = 0
|
||||||
|
self.botgame = False
|
||||||
|
|
||||||
async def add_player(self, player):
|
async def add_player(self, player):
|
||||||
if player not in self.waiting_players:
|
if player not in self.waiting_players:
|
||||||
@ -27,10 +29,17 @@ class MatchMaker:
|
|||||||
player1 = self.waiting_players.pop(0)
|
player1 = self.waiting_players.pop(0)
|
||||||
player2 = self.waiting_players.pop(0)
|
player2 = self.waiting_players.pop(0)
|
||||||
print(f"MATCH FOUND: {player1.user.username} vs {player2.user.username}")
|
print(f"MATCH FOUND: {player1.user.username} vs {player2.user.username}")
|
||||||
game_id = await self.create_game(player1, player2)
|
await self.create_game(player1, player2)
|
||||||
else:
|
else:
|
||||||
# No players to match, wait for a short time before checking again
|
|
||||||
await asyncio.sleep(1)
|
await asyncio.sleep(1)
|
||||||
|
self.timer += 1
|
||||||
|
# Waiting for more than 30s -> BOT game
|
||||||
|
if self.timer >= 30:
|
||||||
|
player1 = self.waiting_players.pop(0)
|
||||||
|
print(f"MATCH FOUND: {player1.user.username} vs BOT")
|
||||||
|
self.botgame = True
|
||||||
|
self.timer = 0
|
||||||
|
await self.create_bot_game(player1)
|
||||||
|
|
||||||
async def create_game(self, player1, player2):
|
async def create_game(self, player1, player2):
|
||||||
game_id = len(self.active_games) + 1
|
game_id = len(self.active_games) + 1
|
||||||
@ -39,25 +48,45 @@ class MatchMaker:
|
|||||||
self.active_games[game_id] = new_game
|
self.active_games[game_id] = new_game
|
||||||
await self.notify_players(player1, player2, game_id)
|
await self.notify_players(player1, player2, game_id)
|
||||||
asyncio.create_task(new_game.start_game())
|
asyncio.create_task(new_game.start_game())
|
||||||
return game_id
|
|
||||||
|
async def create_bot_game(self, player1):
|
||||||
|
game_id = len(self.active_games) + 1
|
||||||
|
print(f"- Creating BOT game: {game_id}")
|
||||||
|
new_game = Game(game_id, player1, None)
|
||||||
|
self.active_games[game_id] = new_game
|
||||||
|
await self.notify_players(player1, None, game_id)
|
||||||
|
asyncio.create_task(new_game.start_game())
|
||||||
|
|
||||||
|
|
||||||
async def notify_players(self, player1, player2, game_id):
|
async def notify_players(self, player1, player2, game_id):
|
||||||
await player1.send(json.dumps({
|
if player2:
|
||||||
'type': 'game_start',
|
await player1.send(json.dumps({
|
||||||
'game_id': game_id,
|
'type': 'game_start',
|
||||||
'player1': player1.user.username,
|
'game_id': game_id,
|
||||||
'player2': player2.user.username
|
'player1': player1.user.username,
|
||||||
}))
|
'player2': player2.user.username
|
||||||
await player2.send(json.dumps({
|
}))
|
||||||
'type': 'game_start',
|
await player2.send(json.dumps({
|
||||||
'game_id': game_id,
|
'type': 'game_start',
|
||||||
'player1': player1.user.username,
|
'game_id': game_id,
|
||||||
'player2': player2.user.username
|
'player1': player1.user.username,
|
||||||
}))
|
'player2': player2.user.username
|
||||||
|
}))
|
||||||
|
else:
|
||||||
|
await player1.send(json.dumps({
|
||||||
|
'type': 'game_start',
|
||||||
|
'game_id': game_id,
|
||||||
|
'player1': player1.user.username,
|
||||||
|
'player2': 'BOT'
|
||||||
|
}))
|
||||||
|
|
||||||
async def handle_key_press(self, player, key):
|
async def handle_key_press(self, player, key):
|
||||||
for game in self.active_games.values():
|
for game in self.active_games.values():
|
||||||
if player in [game.player1, game.player2]:
|
if not self.botgame:
|
||||||
|
if player in [game.player1, game.player2]:
|
||||||
|
await game.handle_key_press(player, key)
|
||||||
|
break
|
||||||
|
else:
|
||||||
await game.handle_key_press(player, key)
|
await game.handle_key_press(player, key)
|
||||||
break
|
break
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user