Hi, Andreas. The sprite speed of 5 pixels per tick creates a jarring
effect on the eye. This especially happens if the colors starkly
contrast. Try this to lower the pixel delta (difference) per rendered frame:
self.fps =180
self.ball.x_speed = random.choice([-1, 1]) *5 * (60.0 /self.fps)
self.ball.y_speed = random.randint(-5, 5) * (60.0 /self.fps)
For pong-like games and scrollers usually I like to keep my framerate at
least 150.
For light loads like pong the builtin clock does fine. For more
demanding games I use a custom clock. There also exist ways to improve
performance, but they are advanced topics and your game doesn't need them.
I often code my own performance watchdogs in the form of logging or a
HUD. If you want to study your overall performance in detail you can
play with cProfile. Here is an example for your game:
def main():
pong = Pong()
pong.start()
if __name__ =='__main__':
import cProfile
import pstats
profile_me =True if profile_me:
cProfile.runctx('main()', globals(), locals(), 'prof.dat')
p = pstats.Stats('prof.dat')
p.sort_stats('time').print_stats()
else:
main()
On 7/17/2018 11:53 AM, Andreas Zielke wrote:
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, 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()