116 lines
4.7 KiB
Python
116 lines
4.7 KiB
Python
from __future__ import annotations
|
|
|
|
import pygame
|
|
import random
|
|
import math
|
|
from typing import Tuple, TYPE_CHECKING
|
|
from entity import Entity
|
|
from screen import Screen
|
|
|
|
if TYPE_CHECKING:
|
|
from player import Player
|
|
|
|
class Ball(Entity):
|
|
def __init__(self, screen_manager: Screen, player:Player, bot:Player):
|
|
self.player: Player = player
|
|
self.bot: Player = bot
|
|
|
|
self.size = 30
|
|
color_ball = (255, 200, 200, 255)
|
|
|
|
image:pygame.Surface = pygame.Surface((self.size, self.size), pygame.SRCALPHA)
|
|
pygame.draw.circle(image, color_ball, (round(self.size / 2), round(self.size / 2)), self.size / 2)
|
|
|
|
origin: Tuple[int, int] = (round(screen_manager.get_screen().get_size()[0] / 2) - round(self.size / 2), round(screen_manager.get_screen().get_size()[1] / 2) - round(self.size / 2))
|
|
|
|
super().__init__("Ball", origin, image, screen_manager)
|
|
|
|
self.speed: int = 25
|
|
self.friction.x = 1 # le vrai speed est la différence entre friction.x et speed
|
|
self.velocity.max = 10 ** 2 # Mettre au carré pour économiser des calcules plus tard (sur la normalisation du mouvement)
|
|
self.velocity.min = 2
|
|
|
|
self.collide: bool = False
|
|
|
|
def draw(self):
|
|
self.screen.blit(self.image, (self.pos.x, self.pos.y))
|
|
|
|
def speed_up(self):
|
|
self.velocity.x = self.velocity.x + .5 if (self.velocity.x > 0) else self.velocity.x - .5
|
|
self.velocity.y = self.velocity.y + .5 if (self.velocity.y > 0) else self.velocity.y - .5
|
|
|
|
def move(self, deltatime: float):
|
|
if (self.velocity.x == 0 and self.velocity.y == 0): # si la balle est a l'arret lui donner un mouvement aléatoire
|
|
self.velocity.x = random.randint(1, int(self.velocity.min))
|
|
self.velocity.y = random.randint(1, int(self.velocity.min))
|
|
|
|
|
|
norm: float = self.velocity.x ** 2 + self.velocity.y ** 2 # norme du vecteur mouvement
|
|
scale: float = 1
|
|
if (norm > self.velocity.max):
|
|
scale = math.sqrt(self.velocity.max / norm)
|
|
elif(norm < self.velocity.min):
|
|
scale = math.sqrt(self.velocity.min / norm)
|
|
|
|
self.velocity.x *= scale
|
|
self.velocity.y *= scale
|
|
|
|
# Réinitialise le flag de collision pour cette frame
|
|
self.collide = False
|
|
|
|
# Collision avec les murs gauche/droite
|
|
if (self.pos.x < 0 or (self.pos.x + self.size) > self.screen.get_size()[0]):
|
|
self.velocity.x = -self.velocity.x
|
|
|
|
# Récupère le centre et le rayon de la balle
|
|
ball_center_x = self.pos.x + self.size / 2
|
|
ball_center_y = self.pos.y + self.size / 2
|
|
ball_radius = self.size / 2
|
|
|
|
# Collision avec le joueur (raquette du bas)
|
|
player_left = self.player.pos.x
|
|
player_right = self.player.pos.x + self.player.size[0]
|
|
player_top = self.player.pos.y - self.player.size[1]
|
|
player_bottom = self.player.pos.y
|
|
|
|
# Vérifie si la balle entre en collision avec la raquette du joueur
|
|
if (ball_center_y + ball_radius >= player_top and
|
|
ball_center_y - ball_radius <= player_bottom and
|
|
ball_center_x + ball_radius >= player_left and
|
|
ball_center_x - ball_radius <= player_right):
|
|
|
|
# Vérifie que la balle vient de dessous (évite les faux positifs)
|
|
if self.velocity.y > 0:
|
|
self.velocity.y = -self.velocity.y
|
|
if not self.collide:
|
|
self.speed_up()
|
|
self.collide = True
|
|
|
|
# Collision avec le bot (raquette du haut)
|
|
elif (ball_center_y > 0): # Évite les collisions négatives
|
|
bot_left = self.bot.pos.x
|
|
bot_right = self.bot.pos.x + self.bot.size[0]
|
|
bot_top = self.bot.pos.y
|
|
bot_bottom = self.bot.pos.y + self.bot.size[1]
|
|
|
|
# Vérifie si la balle entre en collision avec la raquette du bot
|
|
if (ball_center_y + ball_radius >= bot_top and
|
|
ball_center_y - ball_radius <= bot_bottom and
|
|
ball_center_x + ball_radius >= bot_left and
|
|
ball_center_x - ball_radius <= bot_right):
|
|
|
|
# Vérifie que la balle vient de dessus (évite les faux positifs)
|
|
if self.velocity.y < 0:
|
|
self.velocity.y = -self.velocity.y
|
|
if not self.collide:
|
|
self.speed_up()
|
|
self.collide = True
|
|
|
|
self.pos.x += self.velocity.x * deltatime * 100
|
|
self.pos.y += self.velocity.y * deltatime * 100
|
|
|
|
def as_winner(self) -> int:
|
|
if (self.pos.y < 0): return 0 # Joueur a gagner
|
|
if (self.pos.y > self.screen.get_size()[1]): return 1 # Bot a gagner
|
|
|
|
return -1 |