Ce que vous allez apprendre

Ce chapitre explore deux concepts fondamentaux : le systeme de couleurs (RGB, HSV, transparence) et le systeme de coordonnees de Pygame. Vous apprendrez a generer des couleurs arc-en-ciel, a comprendre ou se trouve le point (0, 0), et a afficher une grille de debug pour mieux visualiser le positionnement des elements.

Le concept

Le systeme de coordonnees

En Pygame, le point (0, 0) se trouve dans le coin superieur gauche de la fenetre. L'axe X va vers la droite, l'axe Y va vers le bas. C'est l'inverse de ce que vous avez appris en mathematiques, ou Y monte vers le haut.

Pour une fenetre de 800x600 :

  • Le coin superieur gauche est (0, 0)
  • Le coin superieur droit est (799, 0)
  • Le coin inferieur gauche est (0, 599)
  • Le coin inferieur droit est (799, 599)

Les couleurs

Pygame supporte plusieurs facons de definir les couleurs :

  • RGB : tuple de 3 entiers (rouge, vert, bleu) de 0 a 255
  • RGBA : tuple de 4 entiers avec un canal alpha (transparence) de 0 (invisible) a 255 (opaque)
  • HSV : via pygame.Color, on peut definir teinte, saturation et valeur

Le modele HSV est particulierement utile pour generer des degradees : en faisant varier la teinte (Hue) de 0 a 360, on obtient un arc-en-ciel complet.

Etape par etape

1. Generer des couleurs arc-en-ciel

Notre fonction rainbow_color utilise le modele HSV de Pygame. On fait varier la teinte en fonction du numero de rangee pour obtenir un spectre de couleurs uniforme.

python
def rainbow_color(row, total_rows):
    """Generate a rainbow color based on row position."""
    hue = int(360 * row / total_rows)
    color = pygame.Color(0)
    color.hsva = (hue, 100, 100, 100)
    return (color.r, color.g, color.b)

pygame.Color est un objet puissant. Sa propriete hsva accepte un tuple (teinte, saturation, valeur, alpha). La teinte va de 0 a 360 (cercle chromatique), la saturation et la valeur de 0 a 100. On recupere ensuite les composantes r, g, b pour obtenir un tuple RGB classique.

2. Effet de damier sur les briques

Pour donner plus de relief visuel, on alterne la luminosite des briques en fonction de la parite de (row + col). C'est un effet de damier simple mais efficace.

python
for row in range(BRICK_ROWS):
    for col in range(BRICK_COLS):
        x = BRICK_OFFSET_X + col * (BRICK_WIDTH + BRICK_PADDING)
        y = BRICK_OFFSET_Y + row * (BRICK_HEIGHT + BRICK_PADDING)
        color = rainbow_color(row, BRICK_ROWS)
        # Alternate brightness for checkerboard effect
        if (row + col) % 2 == 0:
            color = tuple(min(255, c + 30) for c in color)
        pygame.draw.rect(screen, color, (x, y, BRICK_WIDTH, BRICK_HEIGHT))
        pygame.draw.rect(screen, (255, 255, 255),
                         (x, y, BRICK_WIDTH, BRICK_HEIGHT), 1)

Le deuxieme appel a draw.rect avec width=1 dessine un contour blanc fin autour de chaque brique, ce qui les separe visuellement.

3. Grille de coordonnees

Pour debugger le placement des elements, on ajoute une grille qui s'active avec la touche G. Elle trace des lignes tous les 50 pixels.

python
show_grid = False

# In the event loop:
if event.key == pygame.K_g:
    show_grid = not show_grid

# In the draw section:
if show_grid:
    for gx in range(0, SCREEN_WIDTH, 50):
        pygame.draw.line(screen, (50, 50, 70), (gx, 0), (gx, SCREEN_HEIGHT))
    for gy in range(0, SCREEN_HEIGHT, 50):
        pygame.draw.line(screen, (50, 50, 70), (0, gy), (SCREEN_WIDTH, gy))

4. Afficher les coordonnees de la souris

Pour mieux comprendre le systeme de coordonnees, on affiche en permanence la position de la souris. On utilise pygame.mouse.get_pos() et le rendu de texte (que nous verrons en detail au chapitre 8).

python
mouse_x, mouse_y = pygame.mouse.get_pos()
font = pygame.font.SysFont("monospace", 14)
coord_text = font.render(f"({mouse_x}, {mouse_y})", True, (150, 150, 150))
screen.blit(coord_text, (10, SCREEN_HEIGHT - 25))

Points cles a retenir

Astuce : pygame.Color supporte aussi les noms de couleurs en anglais : pygame.Color("red"), pygame.Color("dodgerblue"). C'est pratique pour le prototypage rapide.

Piege courant : le canal alpha (RGBA) ne fonctionne pas directement avec pygame.draw sur la surface principale. Pour utiliser la transparence, il faut dessiner sur une surface intermediaire avec SRCALPHA, puis la copier sur l'ecran avec blit(). Nous verrons cela au chapitre 5.

Fonctions Pygame utilisees :

  • pygame.Color : objet couleur avec support RGB, RGBA, HSV
  • color.hsva : definir/lire la couleur en Hue-Saturation-Value
  • pygame.mouse.get_pos() : position actuelle du curseur
  • pygame.font.SysFont() : charger une police systeme
  • font.render() : convertir du texte en Surface

Code complet

python
"""Brick Breaker - Chapter 3: Colors and Coordinates"""
import pygame
import sys

pygame.init()

SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600
FPS = 60
BG_COLOR = (20, 20, 40)

PADDLE_WIDTH = 100
PADDLE_HEIGHT = 15
PADDLE_COLOR = (200, 200, 200)
paddle_x = SCREEN_WIDTH // 2 - PADDLE_WIDTH // 2
paddle_y = SCREEN_HEIGHT - 40

BALL_RADIUS = 8
BALL_COLOR = (255, 255, 255)
ball_x = SCREEN_WIDTH // 2
ball_y = SCREEN_HEIGHT // 2

BRICK_ROWS = 6
BRICK_COLS = 10
BRICK_WIDTH = 70
BRICK_HEIGHT = 20
BRICK_PADDING = 5
BRICK_OFFSET_X = 30
BRICK_OFFSET_Y = 50


def rainbow_color(row, total_rows):
    """Generate a rainbow color based on row position."""
    hue = int(360 * row / total_rows)
    color = pygame.Color(0)
    color.hsva = (hue, 100, 100, 100)
    return (color.r, color.g, color.b)


screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption("Brick Breaker - Chapter 3")
clock = pygame.time.Clock()
font = pygame.font.SysFont("monospace", 14)
show_grid = False

running = True
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_ESCAPE:
                running = False
            if event.key == pygame.K_g:
                show_grid = not show_grid

    mouse_x, mouse_y = pygame.mouse.get_pos()

    screen.fill(BG_COLOR)

    # Draw bricks with rainbow colors and slight alpha variation
    for row in range(BRICK_ROWS):
        for col in range(BRICK_COLS):
            x = BRICK_OFFSET_X + col * (BRICK_WIDTH + BRICK_PADDING)
            y = BRICK_OFFSET_Y + row * (BRICK_HEIGHT + BRICK_PADDING)
            color = rainbow_color(row, BRICK_ROWS)
            # Alternate brightness for checkerboard effect
            if (row + col) % 2 == 0:
                color = tuple(min(255, c + 30) for c in color)
            pygame.draw.rect(screen, color, (x, y, BRICK_WIDTH, BRICK_HEIGHT))
            pygame.draw.rect(screen, (255, 255, 255),
                             (x, y, BRICK_WIDTH, BRICK_HEIGHT), 1)

    # Draw paddle
    pygame.draw.rect(screen, PADDLE_COLOR,
                     (paddle_x, paddle_y, PADDLE_WIDTH, PADDLE_HEIGHT))

    # Draw ball
    pygame.draw.circle(screen, BALL_COLOR, (ball_x, ball_y), BALL_RADIUS)

    # Show grid overlay
    if show_grid:
        for gx in range(0, SCREEN_WIDTH, 50):
            pygame.draw.line(screen, (50, 50, 70),
                             (gx, 0), (gx, SCREEN_HEIGHT))
        for gy in range(0, SCREEN_HEIGHT, 50):
            pygame.draw.line(screen, (50, 50, 70),
                             (0, gy), (SCREEN_WIDTH, gy))

    # Show coordinates
    coord_text = font.render(f"({mouse_x}, {mouse_y})", True, (150, 150, 150))
    screen.blit(coord_text, (10, SCREEN_HEIGHT - 25))

    # Show instructions
    grid_text = font.render("[G] Toggle grid  [ESC] Quit", True, (100, 100, 100))
    screen.blit(grid_text, (SCREEN_WIDTH - 280, SCREEN_HEIGHT - 25))

    pygame.display.flip()
    clock.tick(FPS)

pygame.quit()
sys.exit()

Telechargement

Telecharger le code source de ce chapitre : brick-breaker-ch03.zip