2

I'm trying to animate a ball getting thrown, and I want it to rotate an follow a smooth, parabolic path at the same time. However, I just can't seem to get pygame.transform.rotate() to cooperate.

Here's what I've tried so far:

import pygame
screen = pygame.display.set_mode((500, 500))
timer = pygame.time.Clock()
ball = pygame.sprite.Sprite()
ball.image = pygame.image.load("throwball.png")
ball.image = pygame.transform.scale(ball.image, (48,48))
ball.rect = ball.image.get_rect(topleft = (50,50))
ball.orig_image = ball.image
rotaterect = ball.rect

for i in range(60):
    #pygame.draw.rect(screen, Color(255,255,255), ball.rect)
    ball.image = pygame.transform.rotate(ball.orig_image, i*20)
    rotaterect.topleft = (5*i,((i-20)*(i-20) + 1)/5)
    ball.rect.center = rotaterect.center
    screen.blit(ball.image, ball.rect)
    pygame.display.update()
    timer.tick(60)
    for e in pygame.event.get():
        if e.type == pygame.QUIT:
            pygame.quit()
            sys.exit()
while 1:
    for e in pygame.event.get():
        if e.type == pygame.QUIT:
            pygame.quit()
            sys.exit()

Whenever I run the code, the ball moves in an irregular pattern. I made a second rect to try to keep the positioning under control, but the ball ends up forming a path like this: this

Obviously there's something wrong with the positioning on each frame, but I'm not sure why any of the frames would be out of place, since their location is determined by their center point.

Here's the ball image:

enter image description here

It's 16x16 (square), so I'm dumbfounded as to why the image isn't following a clean path.

Alex Foster
  • 114
  • 1
  • 9

1 Answers1

1

Note, a rotated image varies in size. See How do I rotate an image around its center using Pygame?.

Get the rectangle of the rotated image and set the center of the rectangle by the center of the helper rectangle rotaterect. This causes that the image is symmetrically aligned around the center.
You missed to update the ball.rect to the actual size of the rotated image:

ball.rect = ball.image.get_rect()
rotaterect.topleft = (5*i,((i-20)*(i-20) + 1)/5)
ball.rect.center = rotaterect.center

Example:

for i in range(60):
    ball.image = pygame.transform.rotate(ball.orig_image, i*20)
    ball.rect = ball.image.get_rect()
    rotaterect.topleft = (5*i,((i-20)*(i-20) + 1)/5)
    ball.rect.center = rotaterect.center
    screen.blit(ball.image, ball.rect)
    pygame.display.update()
Rabbid76
  • 202,892
  • 27
  • 131
  • 174
  • Huh. I figured that the center of the helper rect - `rotaterect` - would follow a smooth path, since it doesn't rotate and therefore shouldn't change in size. I guess my reasoning is off... why would that be? – Alex Foster May 24 '19 at 19:29
  • 1
    @AlexFoster Now I understand your solution. It would work, if you would update `ball.rect` to the actual image size: `ball.rect = ball.image.get_rect()`. I changes the answer. – Rabbid76 May 24 '19 at 19:35