2
\$\begingroup\$

here is the code I use to rotate an image around its center:

class Square:
    def __init__(self) :
        self.x, self.y, self.angle = 50, 200, 0
        self.image = load('redrect.png')
        self.image360 = pygame.transform.rotate(self.image, self.angle)
        ...

    def blit(self):
        self.image360 = pygame.transform.rotate(self.image, self.angle)
        # I made a center() function to calculate the center of an image/rect 
        self.center360 = center(self.x, self.y, self.image360)
        MyScreen.blit(self.image360, self.center360)

mysquare = Square()

while 1:
    for e in events:
        if e.type == KEYDOWN:
            if e.key == K_r:
                mysquare.angle += 45

When I run the code and attempt to rotate the square, I notice that the rotation isn't smooth and isn't really around its center though I'm blitting the image360 attribute of the square in its center coordinates.

Btw if I just flip the image by 90°, it will seem to be perfectly rotating around its center.

Here is how I created my center() function :

def center(x, y, rect) :
    try:
        return (x + rect.get_width() / 2, y + rect.get_height() / 2)
    except AttributeError:
        return (x + rect.width / 2, y + rect.height / 2)

UPDATE :

Here is an example of what happens when I try to rotate the image (square case) :

square image

rectangular image case : (I modified the GIF as I realized I had made a wrong one before)

rect image

\$\endgroup\$
2
  • 1
    \$\begingroup\$ Isn't pygame's blits performed with a top-left origin? Meaning that your blit in the center is actually placing the top-left corner in what you think of as center? Where are you expecting the self.x and self.y coordinates to be? Hard to judge from the images but it sort of seems like the objects are moving by about half of what their size changes by, which would make sense considering the weird center transformation. \$\endgroup\$
    – Tyyppi_77
    Jul 26 at 11:04
  • \$\begingroup\$ @Tyyppi_77, ahh yeah the blits are performed at the top left, maybe using a rect object as the coordinates will solve the issue. \$\endgroup\$
    – Salem
    Jul 26 at 12:40
2
\$\begingroup\$

Finally I solved the issue and it was related to wrong image positioning as @Tyyppi_77 has mentionned in the comments.

The blit method of pygame.Surface turns out to blit a surface in the topleft corner if coordinates are passed to the 2nd parameter.

However, if we pass a Rect object, we would be able to position the image as we want.

Here is what the documentation says :

The dest argument can either be a pair of coordinates representing the position of the upper left corner of the blit or a Rect, where the upper left corner of the rectangle will be used as the position for the blit.

And fortunately, pygame.Surface objects have a get_rect() method using which we can obtain a Rect object that can be centered at a given position.

So what I did to solve the issue is getting and updating the rotated image's rect object while positioning it to the center not to the top left corner like this :

class Square:
    def __init__(self):
        self.x, self.y, self.angle = 50, 200, 0
        self.image = load('square.png')
    
    @property
    def center360(self):
        return center(self.x, self.y, self.image)

    @property
    def image360(self):
        return pygame.transform.rotate(self.image, self.angle)

    @property
    def rect360(self):
        return self.image360.get_rect(center=self.center360)

    def blit(self):
        MyScreen.blit(self.image360, self.rect360)
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.