import io
with redirect(stdout=io.StringIO()):
import tdoc.pygame
setup_canvas()
import pygame
import math
import pathlib
from random import randint, choice
width, height = 600, 600
window = pygame.display.set_mode((width, height))
pygame.init()
async def refresh(color):
await animation_frame()
pygame.display.flip()
window.fill(color)
class Actor(pygame.sprite.Sprite):
def __init__(self, image_path, cx, cy):
super().__init__()
self.original_image = pygame.image.load(image_path).convert_alpha()
self.image = self.original_image.copy()
self.rect = self.image.get_rect(center=(cx, cy))
self.collision_margin = 0.05 # 5% de marge
self.angle = 0
@property
def collision_rect(self):
"""Crée le rect de collision à la volée basé sur le rect actuel"""
return self.rect.inflate(
-self.rect.width * self.collision_margin,
-self.rect.height * self.collision_margin
)
def draw(self):
global window
window.blit(self.image, self.rect)
def get_x(self):
return self.rect.centerx
def get_y(self):
return self.rect.centery
def move(self, dx, dy):
self.rect.move_ip(dx, dy)
def set_position(self, x, y):
self.rect.centerx = x
self.rect.centery = y
def collide(self, other_actor):
other_rect = getattr(other_actor, 'collision_rect', other_actor.rect)
return self.collision_rect.colliderect(other_rect)
def flip(self, horizontal=True, vertical=False):
self.image = pygame.transform.flip(self.image, horizontal, vertical)
self.rect = self.image.get_rect(center=self.rect.center)
def scale(self, factor):
new_size = (
int(self.original_image.get_width() * factor),
int(self.original_image.get_height() * factor)
)
self.image = pygame.transform.scale(self.original_image, new_size)
self.rect = self.image.get_rect(center=self.rect.center)
def kill(self):
self.image = pygame.Surface((0, 0))
self.original_image = pygame.Surface((0, 0))
self.rect = self.image.get_rect()
def set_angle(self, angle):
self.angle = angle
self.image = pygame.transform.rotate(self.original_image, angle)
class Text(pygame.sprite.Sprite):
def __init__(self, text, cx, cy, *args):
super().__init__()
self.font = pygame.font.Font(None, 36)
self.image = self.font.render(text, *args)
self.rect = self.image.get_rect()
self.rect.centerx, self.rect.centery = cx, cy
def draw(self):
global window
window.blit(self.image, self.rect)
def kill(self):
self.image = pygame.Surface((0,0))
self.rect = self.image.get_rect()
class Timer(pygame.time.Clock):
def __init__(self, time):
super().__init__()
self.time = time * 1000
self.started = False
def start(self):
self.started = True
self.start_time = animation_time()
self.end_time = self.start_time + self.time
def is_finished(self):
return animation_time() >= self.end_time
def __str__(self):
if not self.started:
return "Not started"
elif self.is_finished():
return "0.00s"
else:
return f"{(self.end_time - animation_time()) / 1000:.2f}s"
def get_pressed_keys():
pressed_list = []
keys = pygame.key.get_pressed()
# 1. La boucle pour les touches "standards" (lettres, chiffres)
# On itère sur les scancodes standards
for scancode in range(len(keys)):
if keys[scancode]:
try:
name = pygame.key.name(scancode).upper()
# On filtre un peu pour éviter d'avoir des trucs bizarres ou vides
if name and name != "UNKNOWN":
pressed_list.append(name)
except ValueError:
pass
# 2. Vérification MANUELLE des touches spéciales (Flèches, Ctrl, etc.)
# C'est nécessaire car elles échappent souvent à la boucle simple ci-dessus
if keys[pygame.K_UP]:
pressed_list.append("UP")
if keys[pygame.K_DOWN]:
pressed_list.append("DOWN")
if keys[pygame.K_LEFT]:
pressed_list.append("LEFT")
if keys[pygame.K_RIGHT]:
pressed_list.append("RIGHT")
# Tu peux aussi ajouter d'autres touches spéciales souvent manquées par la boucle :
if keys[pygame.K_LSHIFT] or keys[pygame.K_RSHIFT]:
pressed_list.append("SHIFT")
if keys[pygame.K_SPACE]:
# Parfois "SPACE" ressort comme " " (vide) dans le name(), donc utile de le forcer
if " " in pressed_list: pressed_list.remove(" ") # Nettoyage optionnel
if "SPACE" not in pressed_list: pressed_list.append("SPACE")
# 3. Souris (Ton code original)
mouse_buttons = pygame.mouse.get_pressed()
if mouse_buttons[0]: pressed_list.append("MOUSE_1")
if mouse_buttons[1]: pressed_list.append("MOUSE_2")
if mouse_buttons[2]: pressed_list.append("MOUSE_3")
return pressed_list
try:
await main()
finally:
pygame.quit()
async def main():
pygame.init()
pineapples = []
basket = Actor("basket.png", 300, 550)
game_over = False
score = 0
game_over_text = Text(f"Game over. Score: {score}", 300, 300, True, (10, 10, 10), (255, 90, 20))
while True:
await refresh((111, 255, 255))
for p in pineapples:
p.draw()
basket.draw()
actions = get_pressed_keys()
for action in actions:
if action == "QUIT":
running = False
elif action == "D":
basket.move(3, 0)
elif action == "A":
basket.move(-3, 0)
if game_over == False:
if randint(0, 100) == 0:
pineapple = Actor("orange.png", randint(0, width - 1), -100)
pineapples.append(pineapple)
for pineapple in pineapples:
pineapple.move(0, 3)
if pineapple.collide(basket):
score += 1
pineapple.kill()
pineapples.remove(pineapple)
if pineapple.rect.y > height:
game_over = True
else:
game_over_text.draw()
Pygame - Le jeu du dino#
async def main():
while True:
await refresh((247, 247, 247))
Solution
À copier/coller ci-dessus :
async def main():
# Création du T-Rex
dino = Actor("t-rex.png", 100, 470)
dino.scale(0.8)
# Variables de saut
est_au_sol = True
vitesse_verticale = 0
GRAVITE = 0.2
FORCE_SAUT = -9
SOL_Y = 470
# Liste des cactus
cactus_liste = []
# Timer pour l'apparition des cactus
timer_cactus = Timer(1.5)
timer_cactus.start()
# Variables de jeu
score = 0
gameover = False
vitesse_jeu = 2
# Textes
txt_score = Text("Score: 0", 500, 30, True, (83, 83, 83), (247, 247, 247))
txt_gameover = Text("GAME OVER - Appuyez sur R pour rejouer", 300, 250, True, (83, 83, 83), (247, 247, 247))
txt_start = Text("Appuyez sur SPACE pour commencer", 300, 300, True, (83, 83, 83), (247, 247, 247))
game_started = False
while True:
await refresh((247, 247, 247))
touches_pressées = get_pressed_keys()
# Écran de démarrage
if not game_started:
dino.draw()
txt_start.draw()
if "SPACE" in touches_pressées:
game_started = True
timer_cactus.start()
continue
# Logique du jeu
if not gameover:
# Gestion du saut
if "SPACE" in touches_pressées and est_au_sol:
vitesse_verticale = FORCE_SAUT
est_au_sol = False
# Application de la gravité
if not est_au_sol:
vitesse_verticale += GRAVITE
dino.move(0, vitesse_verticale)
# Vérifier si le dino retombe au sol
if dino.get_y() >= SOL_Y:
dino.set_position(100, SOL_Y)
est_au_sol = True
vitesse_verticale = 0
# Apparition des cactus
if timer_cactus.is_finished():
nouveau_cactus = Actor("cactus.png", 650, 470)
nouveau_cactus.scale(0.6)
cactus_liste.append(nouveau_cactus)
timer_cactus.start()
# Augmenter progressivement la vitesse
if score % 10 == 0 and score > 0:
vitesse_jeu += 0.5
# Déplacement et collision des cactus
for cactus in cactus_liste:
cactus.move(-vitesse_jeu, 0)
# Collision avec le dino
if dino.collide(cactus):
gameover = True
# Retirer les cactus hors écran et augmenter le score
if cactus.get_x() < -50:
cactus_liste.remove(cactus)
score += 1
txt_score = Text(f"Score: {score}", 500, 30, True, (83, 83, 83), (247, 247, 247))
# Dessiner la ligne de sol
else:
# Game Over - Possibilité de recommencer
if "R" in touches_pressées:
# Réinitialisation
dino.set_position(100, SOL_Y)
est_au_sol = True
vitesse_verticale = 0
cactus_liste = []
score = 0
gameover = False
vitesse_jeu = 5
timer_cactus.start()
txt_score = Text("Score: 0", 500, 30, True, (83, 83, 83), (247, 247, 247))
# Dessiner tous les éléments
dino.draw()
for cactus in cactus_liste:
cactus.draw()
txt_score.draw()
if gameover:
txt_gameover.draw()