[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

[pygame] Newbie performance question



Hi all,

I've dabbled with pygame and wrote a Pong-like game (code see below).

I've tried to follow the advice in the tips/tutorial section and also tried out the dirty-rect strategy described in 
https://www.pygame.org/docs/ref/sprite.html#comment_pygame_sprite_RenderUpdates

This did not seem to make any difference, so I reverted back to the original code.

The performance is still much less than I expecte - with a lot of stuttering on my (not so old) Windows PC, so I guess I must be making some silly mistake.

It would be very kind, if someone could give me a heads-up.

Cheers
Andreas

P.S. I'd be happy to supply additional information, if that would help.

-----------------------8< SNIP 8<-----------------------

import pygame
import random
import math


class MovingRectSprite(pygame.sprite.Sprite):
    def __init__(self, width, height, screen_width, screen_height, color, center_x=0, center_y=0):
        super().__init__()
        self.image = pygame.Surface((width, height)).convert()
        self.image.fill(color)
        self.rect = self.image.get_rect()
        self.rect.center = (center_x, center_y)
        self.screen_width = screen_width
        self.screen_height = screen_height
        self.x_speed = 0
        self.y_speed = 0

        
    def update(self):
        self.rect.x += self.x_speed
        self.rect.y += self.y_speed

        
        
class Paddle(MovingRectSprite):
    SPEED = 10
    
    def __init__(self, width, height, screen_width, screen_height, color, center_x, center_y):
        super().__init__(width, height, screen_width, screen_height, color, center_x, center_y)
        self.acceleration = 0
        self.go_up = False
        self.go_down = False
    
    
    def update(self):
        super().update()
        
        if self.rect.top < 0:
            self.rect.top = 0
            self.y_speed = 0            
        elif self.rect.bottom >= self.screen_height:
            self.rect.bottom = self.screen_height - 1
            self.y_speed = 0

            
    def key_down(self, is_up_key):
        if is_up_key:
            self.go_up = True
            self.y_speed = -self.SPEED
        else:
            self.go_down = True
            self.y_speed = self.SPEED

            
    def key_up(self, is_up_key):
        if is_up_key:
            self.go_up = False
            if self.go_down:
                self.y_speed = self.SPEED
            else:
                self.y_speed = 0
        else:
            self.go_down = False
            if self.go_up:
                self.y_speed = -self.SPEED
            else:
                self.y_speed = 0

    
            
class Pong(object):
    def __init__(self):
        pygame.init()
        self.fps = 60
        self.background = "" 0, 0)
        self.clock = pygame.time.Clock()
        self.running = False
        self.screen = pygame.display.set_mode((0, 0), pygame.FULLSCREEN | pygame.DOUBLEBUF)

        self.sprites = pygame.sprite.Group()

        paddle_width = self.screen.get_width() / 50
        paddle_height = self.screen.get_height() / 10
        self.paddles = pygame.sprite.Group()
        
        self.paddle_left = Paddle(paddle_width, paddle_height, self.screen.get_width(), self.screen.get_height(), (192, 0, 0), paddle_width / 2, self.screen.get_height() / 2)
        self.sprites.add(self.paddle_left)
        self.paddles.add(self.paddle_left)
        
        self.paddle_right = Paddle(paddle_width, paddle_height, self.screen.get_width(), self.screen.get_height(), (0, 0, 192), self.screen.get_width() - paddle_width / 2, self.screen.get_height() / 2)
        self.sprites.add(self.paddle_right)
        self.paddles.add(self.paddle_right)
        
        self.ball = MovingRectSprite(self.screen.get_width() / 100, self.screen.get_width() / 100, self.screen.get_width(), self.screen.get_height(), (255, 255, 0), self.screen.get_width() / 2, self.screen.get_height() / 2)
        self.sprites.add(self.ball)
        
        self.score_left = 0
        self.score_right = 0

        self.init_ball()
                

    def init_ball(self):
        self.ball.rect.center = (self.screen.get_width() / 2, self.screen.get_height() / 2)
        self.ball.x_speed = random.choice([-1, 1]) * 5
        self.ball.y_speed = random.randint(-5, 5)
        
        
    def on_key_up(self, event):
        if event.key in [pygame.K_s, pygame.K_x]:
            self.paddle_left.key_up(event.key == pygame.K_s)
        elif event.key in[pygame.K_UP, pygame.K_DOWN]:
            self.paddle_right.key_up(event.key == pygame.K_UP)
        
        
    def on_key_down(self, event):
        if event.key in [pygame.K_s, pygame.K_x]:
            self.paddle_left.key_down(event.key == pygame.K_s)
        elif event.key in[pygame.K_UP, pygame.K_DOWN]:
            self.paddle_right.key_down(event.key == pygame.K_UP)
        elif event.key == pygame.K_ESCAPE:
            self.running = False
        
        
    def start(self):
        self.running = True
        while self.running:
            self.clock.tick(self.fps)
            self.handle_events()
            self.update()
            self.draw()
        pygame.quit()
        
            
    def handle_events(self):
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                self.running = False
                break;
            elif event.type == pygame.KEYDOWN:
                self.on_key_down(event)
            elif event.type == pygame.KEYUP:
                self.on_key_up(event)

           
    def update(self):
        self.sprites.update()
        if self.ball.rect.right < 0:
            self.score_right += 1
            self.init_ball()
        elif self.ball.rect.left > self.screen.get_width():
            self.score_left += 1
            self.init_ball()
        elif self.ball.rect.top < 0 and self.ball.y_speed < 0:
            self.ball.y_speed *= -1;
        elif self.ball.rect.bottom > self.screen.get_height() and self.ball.y_speed > 0:
            self.ball.y_speed *= -1;

        paddles_hit = pygame.sprite.spritecollide(self.ball, self.paddles, False)
        if paddles_hit:
            paddle_hit = paddles_hit[0]
            if (paddle_hit == self.paddle_left and self.ball.x_speed < 0) or \
               (paddle_hit == self.paddle_right and self.ball.x_speed > 0):
                self.ball.x_speed *= -1.05
    
        if abs(self.ball.y_speed) < 2:
            self.ball.y_speed = math.copysign(2, self.ball.y_speed)


    def draw(self):
        self.screen.fill(self.background)
        self.sprites.draw(self.screen)
        pygame.display.flip()
        
                    
if __name__ == '__main__':
    pong = Pong()
    pong.start()