Python Forum
[PyGame] Rotating image issue
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
[PyGame] Rotating image issue
#1
Hello everyone! I'm a new pygame/python (wannabe) programmer, and I stepped into a problem.

I want to have a character displayed on the screen, being able to move in every direction. When I left-click on it, he is "selectionned"(yes I'm aware of the error). When selected, if I right-click somewhere else, it will move to that position, and stop once destination reached. Until there, no problem at all, everything is working as intended.

However, I want to add the possibility of my character rotating to the direction where it is going. While the rotation is working fine, the problem is -and as I saw through my internet research, a common one- that the image is actually being displaced. The reason for it, I know it very well: the "rect" cannot be circular, so the image is moving, to look like a square on its tip. As a square diagonal is bigger than its side, the image is moving to the bottom right of the screen, the worst being when you're at a 45° angle. Here is a gif to make it clearer:
[Image: 7GfVA.gif]
While i would like something like:
[Image: diqBY.gif]
Note that I don't mind the hitbox changing of size, but if possible I wouldn't be nitpicky.

I've seen many ways to correct it, however, all of them were really out of reach for me, even more as English is not my first language. I see that most people use "pygame.transform.rotate()", however my code is a heavily modified version of a game I previously made with a friend, and I have no idea how to adapt it. Here it is:

import pygame,random,math
from pygame.locals import *

class Hero(pygame.sprite.Sprite):
    
    def __init__(self, x, y,DIRECTION,upKeyPressed,downKeyPressed,leftKeyPressed,rightKeyPressed, leftMousePressed, rightMousePressed, oneKeyPressed, HP, game):
        pygame.sprite.Sprite.__init__(self)
        self.image = self.perso_rotated_surf = pygame.image.load("Sprites/Ant-rot.png").convert_alpha()
        self.step1 = pygame.image.load("Sprites/Ant-1.png").convert_alpha()
        self.step2 = pygame.image.load("Sprites/Ant-mid.png").convert_alpha()
        self.step3 = pygame.image.load("Sprites/Ant-3.png").convert_alpha()
        self.step4 = pygame.image.load("Sprites/Ant-mid.png").convert_alpha()
        self.rect = self.image.get_rect()
        self.step = [self.step1,self.step2,self.step3,self.step4]
        self.perso_angle = 0
        self.ticker = 0
        self.rect.x = x
        self.rect.y = y
        self.center = None
        self.DIRECTION = DIRECTION
        self.upKeyPressed = upKeyPressed
        self.downKeyPressed = downKeyPressed
        self.leftKeyPressed = leftKeyPressed
        self.rightKeyPressed = rightKeyPressed
        self.leftMousePressed = leftMousePressed
        self.rightMousePressed = rightMousePressed
        self.oneKeyPressed = oneKeyPressed
        self.RIGHT, self.LEFT, self.UP, self.DOWN = "right left up down".split()
        self.game = game
        self.current_frame = 0
        self.vitessex = 0
        self.accx = 0
        self.vitessey = 0
        self.accy = 0
        self.coordx = 1920/2
        self.coordy = 1080/2
        self.centerc = None
        self.perso_angle = 0
        self.selection = 0, 0
        self.selectionned = False
        self.xdest = 0
        self.ydest = 0
        self.angledeg = 0


    def centerPos(self):
        self.center = (self.rect.x + 56, self.rect.y + 75)
        self.centerc = (self.coordx, self.coordy)

    def update(self):

        xc, yc = self.center
        xd, yd = self.selection

        if self.leftMousePressed:
            xm, ym = self.selection
            if xm >= (xc - 56) and xm < (xc + 56) and ym >= (yc - 75) and ym < (yc + 75):
                self.selectionned = True
            else:
                self.selectionned = False

        if self.rightMousePressed:
            self.xdest = xd
            self.ydest = yd
            if (xd-xc) >= 0:
                if (yd-yc) == 0:
                    self.vitessey = 0
                    self.vitessex = -5
                if (yd-yc) > 0:
                    angled = (math.atan((xd-xc)/(yd-yc)))
                    self.angledeg = ((angled*180) / 3.1415) + 90 #1
                    if self.selectionned == True:
                        angle2 = (self.angledeg * 3.1415) / 180
                        self.vitessex = -5 * math.cos(angle2)
                        self.vitessey = 5 * math.sin(angle2)
                if (yd-yc) < 0:
                    angled = (math.atan((xd-xc)/(yd-yc)))
                    self.angledeg = ((angled*180) / 3.1415) + 270 #2
                    if self.selectionned == True:
                        angle2 = (self.angledeg * 3.1415) / 180
                        self.vitessex = -5 * math.cos(angle2)
                        self.vitessey = 5 * math.sin(angle2)
            if (xd-xc) < 0:
                if (yd-yc) == 0:
                    self.vitessey = 0
                    self.vitessex = 5
                if (yd-yc) > 0:
                    angled = (math.atan((xd-xc)/(yd-yc)))
                    self.angledeg = ((angled*180) / 3.1415) + 90 #3
                    if self.selectionned == True:
                        angle2 = (self.angledeg * 3.1415) / 180
                        self.vitessex = -5 * math.cos(angle2)
                        self.vitessey = 5 * math.sin(angle2)
                if (yd-yc) < 0:
                    angled = (math.atan((xd-xc)/(yd-yc)))
                    self.angledeg = ((angled*180) / 3.1415) + 270 #4
                    if self.selectionned == True:
                        angle2 = (self.angledeg * 3.1415) / 180
                        self.vitessex = -5 * math.cos(angle2)
                        self.vitessey = 5 * math.sin(angle2)

            if self.vitessey != 0 or self.vitessex != 0:            
                self.perso_angle = (self.angledeg + 90)
                self.perso_rotated_surf = pygame.transform.rotate(self.image, self.perso_angle)
                self.rect = self.perso_rotated_surf.get_rect(center=self.centerc)

        if xc >= (self.xdest - 10) and xc <= (self.xdest + 10) and yc >= (self.ydest - 10) and yc <= (self.ydest + 10):
            self.vitessex = 0
            self.vitessey = 0

        self.ticker += 1
        if self.ticker % 8 == 0:
            self.current_frame = (self.current_frame + 1) % 4

        self.vitessex += self.accx
        self.coordx += self.vitessex
        self.rect.x = self.coordx
        self.accx = 0

        if self.vitessey != 0 or self.vitessex != 0:
            self.image = self.step[self.current_frame]
            self.perso_rotated_surf = pygame.transform.rotate(self.image, self.perso_angle)

        self.vitessey += self.accy
        self.coordy += self.vitessey
        self.rect.y = self.coordy
        self.accy = 0


class Room(object):
    wall_list = None
    def __init__(self):
        self.bullet = pygame.sprite.Group()

class Room1(Room):
    def __init__(self):
        Room.__init__(self)
        self.background = pygame.image.load("room/room1.png").convert_alpha()
        mobs = []

class GameMain():
    done = False
    
    def __init__(self,width = 1920, height = 1080):
        pygame.mixer.pre_init(44100, -16, 2, 2048)
        pygame.init()

        self.arial_font = pygame.font.SysFont("arial", 30)
        self.width, self.height = width, height
        pygame.display.set_caption("Ants")
        self.screen = pygame.display.set_mode((self.width, self.height), pygame.FULLSCREEN)
        self.hero = Hero(100,200,"UP",False,False,False,False,False,False,False,20, self)
        self.all_sprite_list = pygame.sprite.Group()
        self.all_sprite_list.add(self.hero)
        self.rooms = [[Room1()]]
        self.clock = pygame.time.Clock()
        self.current_x = 0
        self.current_y = 0
        self.current_screen = "title"
        self.current_room = self.rooms[self.current_y][self.current_x]
        
    def main_loop(self):
        while not self.done:
            if self.current_screen == "game":
                    self.handle_events()
                    self.hero.centerPos()
                    self.draw()
                    self.all_sprite_list.update()
                    self.change_room()
                    self.current_room.bullet.update()
            elif self.current_screen == "title":
                self.handle_events_title()
                self.draw_title()
            self.clock.tick(60)
        
        pygame.quit()

    def handle_events_title(self):
        events = pygame.event.get()
        for event in events:
            if event.type == pygame.QUIT:
                self.done = True
            if event.type == KEYDOWN:
                if event.key == K_RETURN:
                    self.current_screen = "game"
                if event.key == K_F4 :
                    self.done = True

    def draw_title(self):
        self.screen.fill(Color("Black"))
        credit = pygame.image.load("background_menu.jpg")
        self.screen.blit(credit,(0,0))
        pygame.display.flip()

    def draw(self):
        self.screen.fill((255,255, 255))
        background = self.current_room.background
        self.screen.blit(background,(0,0))
        self.all_sprite_list.draw(self.screen)
        self.screen.blit(self.hero.perso_rotated_surf, self.hero.rect)            
        pygame.display.flip()

    def change_room(self):
        if self.hero.coordx > 1921 :
            self.hero.coordx = 0
            self.current_room = self.rooms[self.current_y][self.current_x]

        elif self.hero.coordx < 0 :
            self.hero.coordx = 1919
            self.current_room = self.rooms[self.current_y][self.current_x]

        elif self.hero.coordy < 0 :
            self.hero.coordy = 1079
            self.current_room = self.rooms[self.current_y][self.current_x]

        elif self.hero.coordy > 1080 :
            self.hero.coordy = 0
            self.current_room = self.rooms[self.current_y][self.current_x]

    def handle_events(self):
        events = pygame.event.get()
        for event in events:
            if event.type == pygame.QUIT:
                self.done = True
            elif event.type == KEYDOWN :
                if event.key == (K_LALT and K_F4):
                    self.done = True

            if event.type == MOUSEBUTTONDOWN :
                if pygame.mouse.get_pressed() == (1, 0, 0):
                    self.hero.leftMousePressed = True

                if pygame.mouse.get_pressed() == (0, 0, 1):
                    self.hero.rightMousePressed = True

            elif event.type == MOUSEMOTION :
                self.hero.selection = event.pos

            elif event.type == MOUSEBUTTONUP :
                if pygame.mouse.get_pressed() == (0, 0, 0):
                    self.hero.leftMousePressed = False

                if pygame.mouse.get_pressed() == (0, 0, 0):
                    self.hero.rightMousePressed = False

if __name__ == "__main__":
    game = GameMain()
    game.main_loop()
So if anyone has an idea how I could fix this, I would be really grateful. Thank you for reading!
Reply


Messages In This Thread
Rotating image issue - by Evoluxman - Oct-11-2019, 07:07 PM
RE: Rotating image issue - by metulburr - Oct-11-2019, 09:52 PM
RE: Rotating image issue - by Evoluxman - Oct-11-2019, 09:54 PM
RE: Rotating image issue - by metulburr - Oct-11-2019, 09:58 PM
RE: Rotating image issue - by Evoluxman - Oct-11-2019, 10:06 PM
RE: Rotating image issue - by Windspar - Oct-11-2019, 10:45 PM
RE: Rotating image issue - by Evoluxman - Oct-12-2019, 08:10 AM
RE: Rotating image issue - by Windspar - Oct-12-2019, 11:58 AM
RE: Rotating image issue - by Evoluxman - Oct-12-2019, 12:54 PM

Possibly Related Threads…
Thread Author Replies Views Last Post
  Rotating a rectangle CompleteNewb 19 12,982 Aug-28-2021, 03:23 PM
Last Post: CompleteNewb

Forum Jump:

User Panel Messages

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