Compare commits
6 Commits
2ee1a972d1
..
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 2aebe0fef1 | |||
| a0d25c9768 | |||
| 9d9c583598 | |||
| 75b16dd16f | |||
| a404dab474 | |||
| 7533c1191c |
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "",
|
||||
"version": "0.0.1",
|
||||
"version": "0.1.0",
|
||||
"author": "popkex",
|
||||
"icon": "",
|
||||
"entry": "src/main.py",
|
||||
|
||||
+49
-16
@@ -36,8 +36,8 @@ class Ball(Entity):
|
||||
self.screen.blit(self.image, (self.pos.x, self.pos.y))
|
||||
|
||||
def speed_up(self):
|
||||
self.velocity.x = self.velocity.x + .75 if (self.velocity.x > 0) else self.velocity.x - .25
|
||||
self.velocity.y = self.velocity.y + .75 if (self.velocity.y > 0) else self.velocity.y - .25
|
||||
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
|
||||
@@ -55,26 +55,59 @@ class Ball(Entity):
|
||||
self.velocity.x *= scale
|
||||
self.velocity.y *= scale
|
||||
|
||||
if (self.pos.x < 0 or (self.pos.x + round(self.size / 2)) > self.screen.get_size()[0]): self.velocity.x = -self.velocity.x # Collision avec le mur
|
||||
# Réinitialise le flag de collision pour cette frame
|
||||
self.collide = False
|
||||
|
||||
# collision avec le joueur
|
||||
if ((self.pos.y + self.size / 2) >= self.player.pos.y - self.player.size[1] and self.pos.y <= self.player.pos.y):
|
||||
if (self.pos.x + self.size >= self.player.pos.x and self.pos.x - self.size <= self.player.pos.x + self.player.size[0]):
|
||||
# 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()
|
||||
if not self.collide:
|
||||
self.speed_up()
|
||||
self.collide = True
|
||||
|
||||
# collision avec le bot
|
||||
elif (self.pos.y - round(self.size / 2) <= self.bot.pos.y and self.pos.y >= self.bot.pos.y + self.bot.size[1]):
|
||||
if (self.pos.x + self.size >= self.bot.pos.x and self.pos.x - self.size <= self.bot.pos.x + self.bot.size[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]
|
||||
|
||||
else: self.collide = False
|
||||
# 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 += round(self.velocity.x)
|
||||
self.pos.y += round(self.velocity.y)
|
||||
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
|
||||
|
||||
+2
-2
@@ -6,8 +6,8 @@ from screen import Screen
|
||||
|
||||
@dataclass
|
||||
class Pos:
|
||||
x: int
|
||||
y: int
|
||||
x: float
|
||||
y: float
|
||||
|
||||
@dataclass
|
||||
class Velocity:
|
||||
|
||||
+7
-10
@@ -5,25 +5,22 @@ from ball import Ball
|
||||
|
||||
class Game:
|
||||
def __init__(self):
|
||||
self.screen_manager = Screen()
|
||||
self.screen = self.screen_manager.get_screen()
|
||||
self.screen_manager: Screen = Screen()
|
||||
self.screen: pygame.Surface = self.screen_manager.get_screen()
|
||||
|
||||
self.clock: pygame.time.Clock = pygame.time.Clock()
|
||||
self.FPS_MAX: int = 60
|
||||
|
||||
self.running = True
|
||||
|
||||
self.player: Player = Player(self.screen_manager)
|
||||
self.bot: Player = Player(self.screen_manager, is_ai=True)
|
||||
self.ball: Ball = Ball(self.screen_manager, self.player, self.bot)
|
||||
self.restart()
|
||||
|
||||
self.my_font:pygame.font.Font = pygame.font.SysFont('Comic Sans MS', 30)
|
||||
|
||||
def restart(self):
|
||||
self.running = True
|
||||
self.difficulty = 2 # 0: facile, 1: normal, 2: difficile, change uniquement l'intelligence du bot
|
||||
|
||||
self.player: Player = Player(self.screen_manager)
|
||||
self.bot: Player = Player(self.screen_manager, is_ai=True)
|
||||
self.bot: Player = Player(self.screen_manager, difficulty=self.difficulty, is_ai=True)
|
||||
self.ball: Ball = Ball(self.screen_manager, self.player, self.bot)
|
||||
|
||||
def run(self):
|
||||
@@ -39,9 +36,9 @@ class Game:
|
||||
dt_ms: int = self.clock.tick(self.FPS_MAX)
|
||||
dt: float = dt_ms / 1000.0
|
||||
|
||||
self.player.move(dt, self.ball)
|
||||
self.player.move(dt, self.ball, self.player)
|
||||
self.ball.move(dt)
|
||||
self.bot.move(dt, self.ball)
|
||||
self.bot.move(dt, self.ball, self.player)
|
||||
self.player.draw()
|
||||
self.bot.draw()
|
||||
self.ball.draw()
|
||||
|
||||
+18
-2
@@ -1,13 +1,12 @@
|
||||
"""
|
||||
TODO
|
||||
- améliorer l'ia
|
||||
- rendre plus realiste les rebomd
|
||||
- faire un menu style arcade
|
||||
- rendre le jeu plus arcade
|
||||
- ajouter des sons style arcade
|
||||
- faire un highscore (avec la gestion de l'utilisateur et les saves)
|
||||
- faire le systeme de succes
|
||||
- mettre un easter egg
|
||||
- me crediter :)
|
||||
"""
|
||||
|
||||
import pygame
|
||||
@@ -31,3 +30,20 @@ while running:
|
||||
if game.run() == -1: running = False
|
||||
|
||||
pygame.quit()
|
||||
|
||||
|
||||
|
||||
# /\
|
||||
# p q
|
||||
# _\| \ / |/_
|
||||
# \// \\/
|
||||
# `| |`
|
||||
# | | ,/_
|
||||
# _\, | |//\
|
||||
# /\\| ;/
|
||||
# \; \
|
||||
# '. \
|
||||
# .-. \ |
|
||||
# ` '.__//
|
||||
# `"`
|
||||
# LIZARD GAMES
|
||||
+118
-26
@@ -9,16 +9,19 @@ if TYPE_CHECKING:
|
||||
from ball import Ball
|
||||
|
||||
class Player(Entity):
|
||||
def __init__(self, screen_manager: Screen, is_ai: bool = False):
|
||||
self.is_ai = is_ai
|
||||
|
||||
def __init__(self, screen_manager: Screen, difficulty:int = 0, is_ai: bool = False):
|
||||
self.size = (150, 10)
|
||||
color_player = (255, 255, 255, 255)
|
||||
|
||||
self.difficulty: int = difficulty
|
||||
self.is_ai = is_ai
|
||||
self.end_pos_is_calculate = False
|
||||
self.end_ballx: float = (screen_manager.get_screen().get_size()[0] / 2)
|
||||
|
||||
image:pygame.Surface = pygame.Surface(self.size)
|
||||
image.fill(color_player)
|
||||
|
||||
origin: Tuple[int, int] = (round(screen_manager.get_screen().get_size()[0] / 2) - round(self.size[0] / 2), 105) if is_ai else (round(screen_manager.get_screen().get_size()[0] / 2) - round(self.size[0] / 2), 675)
|
||||
origin: Tuple[int, int] = (round(screen_manager.get_screen().get_size()[0] / 2) - round(self.size[0] / 2), 45) if is_ai else (round(screen_manager.get_screen().get_size()[0] / 2) - round(self.size[0] / 2), 675)
|
||||
|
||||
super().__init__("Player", origin, image, screen_manager)
|
||||
|
||||
@@ -27,34 +30,18 @@ class Player(Entity):
|
||||
self.velocity.max = 10
|
||||
|
||||
def draw(self):
|
||||
self.screen.blit(self.image, (self.pos.x, self.pos.y))
|
||||
self.screen.blit(self.image, (round(self.pos.x), round(self.pos.y)))
|
||||
|
||||
def apply_friction(self, deltatime: float):
|
||||
if (self.velocity.x > 0): self.velocity.x -= self.friction.x * deltatime
|
||||
elif (self.velocity.x < 0): self.velocity.x += self.friction.x * deltatime
|
||||
|
||||
def move(self, deltatime: float, ball: Ball):
|
||||
if (self.is_ai):
|
||||
if (ball.pos.x < self.pos.x + self.size[0] / 2): self.velocity.x -= self.speed * deltatime
|
||||
elif (ball.pos.x > self.pos.x + self.size[0] / 2): self.velocity.x += self.speed * deltatime
|
||||
else:
|
||||
keys = pygame.key.get_pressed()
|
||||
|
||||
# if keys[pygame.K_z] or keys[pygame.K_UP]: self.velocity.y -= self.speed * deltatime
|
||||
# if keys[pygame.K_s] or keys[pygame.K_DOWN]: self.velocity.y += self.speed * deltatime
|
||||
if keys[pygame.K_q] or keys[pygame.K_LEFT]: self.velocity.x -= self.speed * deltatime
|
||||
if keys[pygame.K_d] or keys[pygame.K_RIGHT]: self.velocity.x += self.speed * deltatime
|
||||
|
||||
if (self.velocity.x > self.velocity.max): self.velocity.x = self.velocity.max
|
||||
elif (-self.velocity.x > self.velocity.max): self.velocity.x = -self.velocity.max
|
||||
# if (self.velocity.y > self.velocity.max): self.velocity.y = self.velocity.max
|
||||
# elif (-self.velocity.y > self.velocity.max): self.velocity.y = -self.velocity.max
|
||||
|
||||
def apply_move(self, deltatime:float):
|
||||
self.apply_friction(deltatime)
|
||||
|
||||
temps_pos: Tuple[int, int] = (
|
||||
self.pos.x + round(self.velocity.x),
|
||||
self.pos.y + round(self.velocity.y)
|
||||
temps_pos: Tuple[float, float] = (
|
||||
self.pos.x + self.velocity.x * deltatime * 100,
|
||||
self.pos.y + self.velocity.y * deltatime * 100
|
||||
)
|
||||
|
||||
# les collisions
|
||||
@@ -66,4 +53,109 @@ class Player(Entity):
|
||||
self.velocity.x = 0
|
||||
else:
|
||||
self.pos.x = temps_pos[0]
|
||||
self.pos.y = temps_pos[1]
|
||||
self.pos.y = temps_pos[1]
|
||||
|
||||
def _ball_center(self, ball_pos: Tuple[float, float], ball_size: float) -> Tuple[float, float]:
|
||||
return ball_pos[0] + ball_size / 2, ball_pos[1] + ball_size / 2
|
||||
|
||||
def _mirror_x_center(self, x_center: float, radius: float) -> float:
|
||||
min_x: float = radius
|
||||
max_x: float = self.screen.get_width() - radius
|
||||
span: float = max_x - min_x
|
||||
if span <= 0:
|
||||
return min_x
|
||||
|
||||
x_rel: float = x_center - min_x
|
||||
x_mod: float = x_rel % (2 * span)
|
||||
if x_mod <= span:
|
||||
return min_x + x_mod
|
||||
return max_x - (x_mod - span)
|
||||
|
||||
def predict_end_x(self, ball_pos:Tuple[float, float], ball_size:float, velocity_x:float, velocity_y:float, target_center_y:float) -> float:
|
||||
center_x, center_y = self._ball_center(ball_pos, ball_size)
|
||||
if velocity_y == 0:
|
||||
return self._mirror_x_center(center_x, ball_size / 2)
|
||||
|
||||
dt: float = (target_center_y - center_y) / velocity_y
|
||||
predicted_x: float = center_x + velocity_x * dt
|
||||
return self._mirror_x_center(predicted_x, ball_size / 2)
|
||||
|
||||
def determinate_endx(self, ball_pos:Tuple[float, float], ball_size:float, dist_boty:float, coef_dir:float, modify_end_ballx: bool = True) -> float:
|
||||
"""
|
||||
return le delta x de déplacement de la balle
|
||||
Determine ou se trouvera la balle en x quand elle sera au niveau du bot quand la balle monte vers le bot
|
||||
"""
|
||||
dtx: float = (dist_boty / coef_dir)
|
||||
if (modify_end_ballx): self.end_ballx = ball_pos[0] + dtx # déterminer ou la ball devrais arriver
|
||||
|
||||
if (self.end_ballx < 0): # Si la balle devrait collisionner avec le mur de gauche
|
||||
collisiony: float = ball_pos[1] + (coef_dir * (ball_pos[0] - (ball_size / 2))) # Calculer a quelle hauteur la balle va collisionner avec le mur
|
||||
dist_boty = (self.pos.y - self.size[1]) - (collisiony - (ball_size / 2))
|
||||
dtx = (dist_boty / -coef_dir)
|
||||
if (modify_end_ballx): self.end_ballx = ball_pos[0] + dtx # déterminer ou la ball devrais arriver
|
||||
return dtx
|
||||
elif (self.end_ballx > self.screen.get_width() + (ball_size / 2)): # Si la balle devrait collisionner avec le mur de droite
|
||||
collisiony: float = ball_pos[1] + (coef_dir * (self.screen.get_width() - (ball_pos[0] - (ball_size / 2)))) # Calculer a quelle hauteur la balle va collisionner avec le mur
|
||||
dtx = (dist_boty / -coef_dir)
|
||||
if (modify_end_ballx): self.end_ballx = ball_pos[0] + (dist_boty / -coef_dir) # déterminer ou la ball devrais arriver
|
||||
return dtx
|
||||
|
||||
return dtx
|
||||
|
||||
def ia_move(self, deltatime:float, ball:Ball, player:Player):
|
||||
"""
|
||||
- mode facile :
|
||||
le bot essaye juste de ce mettre ou se trouve la balle en temps reelle
|
||||
- mode normale :
|
||||
le bot anticipe ou se trouvera la balle quand elle sera a son niveau UNIQUEMENT quand elle vient vers lui
|
||||
- mode difficile :
|
||||
le bot anticipe ou se trouvera la balle quand elle sera a son niveau TOUT LE TEMPS
|
||||
"""
|
||||
|
||||
# IA en mode facile
|
||||
if (self.difficulty == 0):
|
||||
if (ball.pos.x < self.pos.x + self.size[0] / 2): self.velocity.x -= self.speed * deltatime
|
||||
elif (ball.pos.x > self.pos.x + self.size[0] / 2): self.velocity.x += self.speed * deltatime
|
||||
|
||||
# IA en mode normal && difficile
|
||||
if (self.difficulty > 0):
|
||||
if (ball.velocity.y < 0): # Si la balle va vers le bot (en gros, monte)
|
||||
target_center_y: float = self.pos.y + self.size[1] + (ball.size / 2)
|
||||
self.end_ballx = self.predict_end_x(ball_pos=(ball.pos.x, ball.pos.y), ball_size=ball.size, velocity_x=ball.velocity.x, velocity_y=ball.velocity.y, target_center_y=target_center_y)
|
||||
# else: self.end_ballx = round(self.screen.get_size()[0] / 2)
|
||||
|
||||
if (self.end_ballx < self.pos.x + self.size[0] / 2): self.velocity.x -= self.speed * deltatime
|
||||
elif (self.end_ballx > self.pos.x + self.size[0] / 2): self.velocity.x += self.speed * deltatime
|
||||
|
||||
if (self.difficulty == 2): # Le mode difficile
|
||||
if (ball.velocity.y > 0): # Quand la balle se dirige vers le joueur
|
||||
player_contact_center_y: float = player.pos.y - (ball.size / 2)
|
||||
impact_center_x: float = self.predict_end_x(ball_pos=(ball.pos.x, ball.pos.y), ball_size=ball.size, velocity_x=ball.velocity.x, velocity_y=ball.velocity.y, target_center_y=player_contact_center_y)
|
||||
|
||||
target_center_y: float = self.pos.y + self.size[1] + (ball.size / 2)
|
||||
impact_top_left: Tuple[float, float] = (impact_center_x - (ball.size / 2), player_contact_center_y - (ball.size / 2))
|
||||
self.end_ballx = self.predict_end_x(ball_pos=impact_top_left, ball_size=ball.size, velocity_x=ball.velocity.x, velocity_y=-ball.velocity.y, target_center_y=target_center_y)
|
||||
|
||||
self.apply_move(deltatime)
|
||||
|
||||
|
||||
def player_move(self, deltatime:float):
|
||||
keys = pygame.key.get_pressed()
|
||||
|
||||
# if keys[pygame.K_z] or keys[pygame.K_UP]: self.velocity.y -= self.speed * deltatime
|
||||
# if keys[pygame.K_s] or keys[pygame.K_DOWN]: self.velocity.y += self.speed * deltatime
|
||||
if keys[pygame.K_q] or keys[pygame.K_LEFT]: self.velocity.x -= self.speed * deltatime
|
||||
if keys[pygame.K_d] or keys[pygame.K_RIGHT]: self.velocity.x += self.speed * deltatime
|
||||
|
||||
if (self.velocity.x > self.velocity.max): self.velocity.x = self.velocity.max
|
||||
elif (-self.velocity.x > self.velocity.max): self.velocity.x = -self.velocity.max
|
||||
# if (self.velocity.y > self.velocity.max): self.velocity.y = self.velocity.max
|
||||
# elif (-self.velocity.y > self.velocity.max): self.velocity.y = -self.velocity.max
|
||||
|
||||
self.apply_move(deltatime)
|
||||
|
||||
def move(self, deltatime: float, ball: Ball, player:Player):
|
||||
if (self.is_ai):
|
||||
self.ia_move(deltatime, ball, player)
|
||||
else:
|
||||
self.player_move(deltatime)
|
||||
Reference in New Issue
Block a user