PONG sur Raspberry Pi Pico

avec un afficheur OLED SSD1306 IC2 et 3 boutons

"""
Raspberry Pi Pico : Jeu PONG
Sur afficher screen SSD1306 I2C
Auteur : Daniel SAZERAT
Mars 2023
"""
 
from machine import Pin, I2C
from ssd1306 import SSD1306_I2C
 
# définition de l'afficheur
screen_width = 128
screen_height = 64
SCL = 9
SDA = 8
ADDR = 0x3C
 
# initialisation de la connexion I2C
i2c = I2C(0, scl=Pin(SCL), sda=Pin(SDA))
 
# initialisation de l'afficheur screen
screen = SSD1306_I2C(screen_width, screen_height, i2c, ADDR)
screen.fill(0)
 
# définition des boutons
left_button = Pin(4, mode=Pin.IN, pull=Pin.PULL_DOWN)
center_button = Pin(3, mode=Pin.IN, pull=Pin.PULL_DOWN)
right_button = Pin(2, mode=Pin.IN, pull=Pin.PULL_DOWN)
 
 
class Game:
    def __init__(self):
        self.active = True
        self.score = 0
        self.nb_balls = 3 # nombre de balles pour la partie
 
    def run(self):
        screen.fill(0)                
        paddle.move()   # gestion de la balle
        ball.move()     # gestion de la raquette
        self.display()  # affichage des infos
        screen.show()       
 
    def display(self):
        if self.active:
            screen.text(str(self.score), 5, 5)
            for counter in range(self.nb_balls):
                screen.text(".", 120-8*counter, 5)
 
    def gain(self):
        self.score += 1
 
    def end_round(self):
        self.nb_balls -= 1
        if self.nb_balls == 0:
            self.end_game()            
        else:
            ball.x_ball, ball.y_ball = 100, 0
 
    def end_game(self):                
        self.active = False
        screen.fill(0)
        screen.rect(5, 5 , 123, 59, 1)
        screen.text("GAME OVER", 30, 22)
        screen.text("SCORE : "+str(self.score), 30, 40)
        screen.show()
 
 
class Ball:
    def __init__(self, x_init, dir_init):
        self.width_ball, self.height_ball = 4, 4	# dimensions
        # position
        self.x_ball = 100 + x_init
        self.y_ball = 0
        # direction
        self.x_dir = dir_init
        self.y_dir = 1
 
    def move(self):
        self.x_ball += self.x_dir
        self.y_ball += self.y_dir
 
        # rebond à gauche
        if self.x_ball < 0:
            self.x_dir = 1
        # rebond à droite
        if self.x_ball > screen_width - self.width_ball :
            self.x_dir = -1
        # rebond en haut
        if self.y_ball < 0:
            self.y_dir = 1
        # rebond sur la raquette
        if self.y_ball > screen_height - 7 and self.y_dir == 1\
           and paddle.x_paddle -2 < self.x_ball < paddle.x_paddle + paddle.width_paddle:
            self.y_dir = -1
            game.gain()
 
        # sortie de la balle en bas de l'écran
        if self.y_ball > screen_height:
            game.end_round()
 
        # affiche la balle    
        self.display()
 
    def display(self):  # affiche la balle
        screen.fill_rect(self.x_ball, self.y_ball,
                       self.width_ball, self.height_ball, 1)
 
 
class Paddle:
    def __init__(self):
 
    # définition de la raquette
        self.width_paddle, self.height_paddle = 20, 2 	       # dim
        self.x_paddle = (screen_width - self.width_paddle)//2  # pos x
        self.y_paddle = screen_height - self.height_paddle     # pos y
        self.speed_paddle = 2				       # vitesse
 
        # affiche la raquette
        self.display()    
 
    def move(self):
        if left_button.value() == 1:	# appui sur le bouton gauche
            self.x_paddle = self.x_paddle - self.speed_paddle
 
            # limite le déplacement à gauche
            if self.x_paddle < 0:
                self.x_paddle = 0            
 
        elif right_button.value() == 1:	# appui sur le bouton droit
            self.x_paddle = self.x_paddle + self.speed_paddle
 
            # limite le déplacement à droite
            if self.x_paddle > screen_width - self.width_paddle:
                self.x_paddle = screen_width - self.width_paddle
 
        # affiche la raquette
        self.display()
 
    def display(self):  # affiche la raquette      
        screen.fill_rect(self.x_paddle, self.y_paddle,
                       self.width_paddle, self.height_paddle, 1)
 
 
if __name__ == '__main__':
 
    screen.fill(0)
    screen.rect(5, 5 , 123, 59, 1)
    screen.text("PONG", 50, 30)
    screen.show()
 
    while True:
        if center_button.value() == 1:
            game = Game()        
            paddle = Paddle()
            ball = Ball(0, 1)                
            while game.active:
                game.run()