You need to get the bounding rectangle of the rotated rectangle and set the center of the rectangle by (x
, y
) (see also How do I rotate an image around its center using PyGame?):
while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
rotatedSail = pygame.transform.rotate(Sail, degrees)
rotatedSail_rect = rotatedSail.get_rect(center = (x, y))
DISPLAYSURF.fill(Blue)
DISPLAYSURF.blit(rotatedSail, rotatedSail_rect)
pygame.display.flip()
fpsClock.tick(FPS)
degrees += 1

To rotate the object around another point than the center point is much more complicate. A general solution is described in the answer to How can you rotate an image around an off center pivot in PyGame.
Complete Example:

import pygame, math, sys
from pygame.locals import *
Blue = (0,0,255)
Black = (0, 0, 0)
Green = (0,255,0)
White = (255,255,255)
pygame.init()
DISPLAYSURF = pygame.display.set_mode((400, 300))
pygame.display.set_caption('Sailing!')
FPS = 30
fpsClock = pygame.time.Clock()
Sail = pygame.Surface([100,10])
Sail.set_colorkey (Black)
Sail.fill(White)
degrees = 0
hyp = 100
x = 200
y = 150
def blitRotate(surf, image, pos, originPos, angle):
# calcaulate the axis aligned bounding box of the rotated image
w, h = image.get_size()
sin_a, cos_a = math.sin(math.radians(angle)), math.cos(math.radians(angle))
min_x, min_y = min([0, sin_a*h, cos_a*w, sin_a*h + cos_a*w]), max([0, sin_a*w, -cos_a*h, sin_a*w - cos_a*h])
# calculate the translation of the pivot
pivot = pygame.math.Vector2(originPos[0], -originPos[1])
pivot_rotate = pivot.rotate(angle)
pivot_move = pivot_rotate - pivot
# calculate the upper left origin of the rotated image
origin = (pos[0] - originPos[0] + min_x - pivot_move[0], pos[1] - originPos[1] - min_y + pivot_move[1])
# get a rotated image
rotated_image = pygame.transform.rotate(image, angle)
# rotate and blit the image
surf.blit(rotated_image, origin)
while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
DISPLAYSURF.fill(Blue)
blitRotate(DISPLAYSURF, Sail, (x, y), (0, 5), degrees)
pygame.display.flip()
fpsClock.tick(FPS)
degrees += 1
With this mechanism, a complete analog clock can be realized:

import pygame, datetime
pygame.init()
window = pygame.display.set_mode((400, 300))
clock = pygame.time.Clock()
hour = pygame.Surface((60, 10), pygame.SRCALPHA)
hour.fill((255, 255, 255))
minute = pygame.Surface((80, 6), pygame.SRCALPHA)
minute.fill((255, 255, 0))
second = pygame.Surface((100, 2), pygame.SRCALPHA)
second.fill((255, 0, 0))
def blitRotate(surf, image, origin, pivot, angle):
# offset from pivot to center
image_rect = image.get_rect(topleft = (origin[0] - pivot[0], origin[1]-pivot[1]))
offset_center_to_pivot = pygame.math.Vector2(origin) - image_rect.center
# roatated offset from pivot to center
rotated_offset = offset_center_to_pivot.rotate(-angle)
# roatetd image center
rotated_image_center = (origin[0] - rotated_offset.x, origin[1] - rotated_offset.y)
# get a rotated image
rotated_image = pygame.transform.rotate(image, angle)
rotated_image_rect = rotated_image.get_rect(center = rotated_image_center)
# rotate and blit the image
surf.blit(rotated_image, rotated_image_rect)
start_time = pygame.time.get_ticks()
run = True
while run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
now = datetime.datetime.now()
angle_hour = 90 - 360 * (now.hour + now.minute/60) / 12
angle_minute = 90 - 360 * now.minute / 60
angle_second = 90 - 360 * now.second / 60
center = window.get_rect().center
window.fill(0)
blitRotate(window, hour, center, (5, 5), angle_hour)
blitRotate(window, minute, center, (5, 4), angle_minute)
blitRotate(window, second, center, (5, 2), angle_second)
pygame.display.flip()
clock.tick(100)
pygame.quit()
exit()