Python Forum
[PyGame] How to rotate images
Thread Rating:
  • 4 Vote(s) - 4 Average
  • 1
  • 2
  • 3
  • 4
  • 5
[PyGame] How to rotate images
#11
(Nov-06-2016, 05:40 PM)LavaCreeperKing Wrote: Hey I did some looking online about this but I wasn't able to figure out how to get it to work. How do you rotate an image? For example I want to create a program the displays an image that just rotates on the screen. How would I do that? And is it possible to rotate text? P.s. I am using pygame.

i have same problem and i was wondering how could i rotate image using mouse by right click or a key , but it not working for me so can u hellp me out with it

(Nov-06-2016, 06:42 PM)metulburr Wrote: When you rotate an image you need to make sure that you make an original of the image, and use that to rotate, otherwise it gets distorted if you keep rotating the image from a rotated image, etc. 

Whatever you rotate, whether it be an image or text, both are going to be a surface and rotated the same way. 

You are going to use pygame.transform.rotate

Here is an example of a surface rotated based on mouse position
import pygame as pg
import math

class Rotator:
    def __init__(self, screen_rect):
        self.orig_image = pg.Surface([10,100]).convert_alpha() #
        self.image = self.orig_image
        self.image.fill((255,255,255))
        self.rect = self.image.get_rect(center=screen_rect.center)
        self.angle = 0
        self.distance = 0
        self.angle_offset = 0

    def render(self, screen):
        screen.blit(self.image, self.rect)
        
    def get_angle(self):
        mouse = pg.mouse.get_pos()
        offset = (self.rect.centerx-mouse[0],self.rect.centery-mouse[1])
        self.angle = math.degrees(math.atan2(*offset)) - self.angle_offset
        old_center = self.rect.center
        self.image = pg.transform.rotate(self.orig_image, self.angle)
        self.rect = self.image.get_rect(center=old_center)
        self.distance = math.sqrt((offset[0] * offset[0]) + (offset[1] * offset[1]))
        
    def update(self):
        self.get_angle()
        self.display = 'angle:{:.2f} disatance:{:.2f}'.format(self.angle, self.distance)

if __name__ == '__main__':
    running = True
    pg.init()
    screen = pg.display.set_mode((600,400))
    screen_rect = screen.get_rect()
    rotator = Rotator(screen_rect)
    clock = pg.time.Clock()

    while running:
        screen.fill((0,0,0))
        for event in pg.event.get():
            if event.type == pg.QUIT:
                running = False
        rotator.update()
        rotator.render(screen)
        pg.display.set_caption(rotator.display)
        pg.display.update()
        clock.tick(60)
here the surface is just a generic rectangle, but you can plug in an image or text surface. The lines you would need to change to do that is
        #self.orig_image = pg.Surface([10,100]).convert_alpha() #
        self.orig_image = pg.image.load("your_image.png").convert()
        self.image = self.orig_image
        #self.image.fill((255,255,255))
where you load your image as the original instead and comment out the image fill

another example, a non-interactive example a constant turning object. Again you can plugin your image/text surface instead of a generic surface

import pygame as pg

screen = pg.display.set_mode((800,600))
screen_rect = screen.get_rect()
clock = pg.time.Clock()
done = False

class Rotator:
    def __init__(self, screen_rect):
        self.screen_rect = screen_rect
        self.master_image = pg.Surface([100,100]).convert_alpha()
        self.master_image.fill((255,0,0))
        self.image = self.master_image.copy()
        self.rect = self.image.get_rect(center=self.screen_rect.center)
        self.delay = 10
        self.timer = 0.0
        self.angle = 0

    def new_angle(self):
        self.angle += 1
        self.angle %= 360

    def rotate(self):
        self.new_angle()
        self.image = pg.transform.rotate(self.master_image, self.angle)
        self.rect = self.image.get_rect(center=self.screen_rect.center)

    def update(self):
        if pg.time.get_ticks()- self.timer > self.delay:
            self.timer = pg.time.get_ticks()
            self.rotate()

    def draw(self, surf):
        surf.blit(self.image, self.rect)

rotator = Rotator(screen_rect)

while not done:
    for event in pg.event.get():
        if event.type == pg.QUIT:
            done = True
    screen.fill((0,0,0))
    rotator.update()
    rotator.draw(screen)
    pg.display.update()

i was having same problem i hope i could contact u so u could help me out with my program
Reply
#12
What problem do you have that isn't explained already above?

What have you tried?
Reply
#13
(Jan-02-2020, 08:47 PM)stuckbunny Wrote: i have same problem and i was wondering how could i rotate image using mouse by right click or a key
It would be the same. You would just restrict the current Rotator more by instead of moving directly to the mouse upon movement, by getting the position when the mouse is clicked and move it. ITs really just simple moving the self.get_angle() method to the event of a mouse click
import pygame as pg
import math
 
class Rotator:
    def __init__(self, screen_rect):
        self.orig_image = pg.Surface([10,100]).convert_alpha() #
        self.image = self.orig_image
        self.image.fill((255,255,255))
        self.rect = self.image.get_rect(center=screen_rect.center)
        self.angle = 0
        self.distance = 0
        self.angle_offset = 0
 
    def render(self, screen):
        screen.blit(self.image, self.rect)
         
    def get_angle(self):
        mouse = pg.mouse.get_pos()
        offset = (self.rect.centerx-mouse[0],self.rect.centery-mouse[1])
        self.angle = math.degrees(math.atan2(*offset)) - self.angle_offset
        old_center = self.rect.center
        self.image = pg.transform.rotate(self.orig_image, self.angle)
        self.rect = self.image.get_rect(center=old_center)
        self.distance = math.sqrt((offset[0] * offset[0]) + (offset[1] * offset[1]))
        
    def get_event(self):
        self.get_angle()
         
    def update(self):
        self.display = 'angle:{:.2f} disatance:{:.2f}'.format(self.angle, self.distance)
 
if __name__ == '__main__':
    running = True
    pg.init()
    screen = pg.display.set_mode((600,400))
    screen_rect = screen.get_rect()
    rotator = Rotator(screen_rect)
    clock = pg.time.Clock()
 
    while running:
        screen.fill((0,0,0))
        for event in pg.event.get():
            if event.type == pg.QUIT:
                running = False
            elif event.type == pg.MOUSEBUTTONDOWN:
                rotator.get_event()
        rotator.update()
        rotator.render(screen)
        pg.display.set_caption(rotator.display)
        pg.display.update()
        clock.tick(60)
and here when you move it by key, you are removing everything regarding offset as you no longer need trig, you are just rotating it manually
import pygame as pg
import math
  
class Rotator:
    def __init__(self, screen_rect):
        self.orig_image = pg.Surface([10,100]).convert_alpha() #
        self.image = self.orig_image
        self.image.fill((255,255,255))
        self.rect = self.image.get_rect(center=screen_rect.center)
        self.angle = 0
        self.distance = 0
        self.angle_offset = 0
  
    def render(self, screen):
        screen.blit(self.image, self.rect)
          
    def get_angle(self, direction):
        if direction:
            self.angle += 1
        else:
            self.angle -= 1
        old_center = self.rect.center
        self.image = pg.transform.rotate(self.orig_image, self.angle)
        self.rect = self.image.get_rect(center=old_center)
        self.distance = 0
         
    def get_event(self, direction):
        self.get_angle(direction)
          
    def update(self):
        self.display = 'angle:{:.2f} disatance:{:.2f}'.format(self.angle, self.distance)
  
if __name__ == '__main__':
    running = True
    pg.init()
    screen = pg.display.set_mode((600,400))
    screen_rect = screen.get_rect()
    rotator = Rotator(screen_rect)
    clock = pg.time.Clock()
  
    while running:
        screen.fill((0,0,0))
        for event in pg.event.get():
            if event.type == pg.QUIT:
                running = False
            elif event.type == pg.KEYDOWN:
                if event.key == pg.K_LEFT:
                    rotator.get_event(0)
                elif event.key == pg.K_RIGHT:
                    rotator.get_event(1)
        rotator.update()
        rotator.render(screen)
        pg.display.set_caption(rotator.display)
        pg.display.update()
        clock.tick(60)
IF you want to hold the keys down you would instead of using event, use pygame.key.get_pressed() to determine constantly if a key is still held down to keep moving

    keys = pg.key.get_pressed()
...
        if keys[pg.K_LEFT] or keys[pg.K_a]:
            #move(0, -1)
        if keys[pg.K_RIGHT] or keys[pg.K_d]:
            #move(0, 1)
Recommended Tutorials:
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  How do I use pygame.transform.rotate()? noodlespinbot 1 2,879 Mar-05-2020, 08:08 AM
Last Post: michael1789

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020