pythonpygamepytmx

How to correctly display rotation object with pytmx?


After many research I didn't find the answer, when I'm trying to display object in pygame with pytmx, the result is fully broken, because x, y change with rotation. I've tried to use matrix rotation but for this, I need to know the original center. I don't know how to find it, because Tiled sends me, x, y after rotation...

So my goal is simply to display object tile in pygame with pytmx.

import numpy
import math

angle = math.radians(-117.57) #rotation get with tiled, set - for cancel rotation
center_x = 148 #how to get this ?
center_y = 747 #and this
x = 126.82 #get with tiled
y = 679.54 #get with tiled

id_rotation = [ [math.cos(angle), -math.sin(angle)],
                [math.sin(angle), math.cos(angle)] ]
R = numpy.matrix(id_rotation)

id_position = [ [x - center_x],
                [y - center_y] ]
B = numpy.matrix(id_position)

id_center = [ [center_x],
              [center_y] ]
C = numpy.matrix(id_center)

print(numpy.dot(R, B) + C) #return original position before rotation

If I only use pygame.transform.rotate:

if isinstance(layer, pytmx.TiledObjectGroup):
        for object in layer:
            if (object.image):
                assets_surface = pygame.Surface((object.width, object.height), pygame.SRCALPHA)
                assets_surface.blit(object.image, (0, 0))
                assets_surface_rotate = pygame.transform.rotate(assets_surface, -object.rotation)
                rdc.blit(assets_surface_rotate, (object.x, object.y))

I get this the wrong position x,y for tile object:

image of the error


Solution

  • Ok I have found the solution if someone needs :

    elif isinstance(layer, pytmx.TiledObjectGroup):
            for Object in layer:
                if (Object.image):
                    if Object.rotation != 0:
                        angle = math.radians(-Object.rotation)
                        center_x = Object.centerX
                        center_y = Object.centerY
                        Object_y = Object.y + Object.height
    
                        id_rotation = [ [math.cos(angle), -math.sin(angle)],
                                        [math.sin(angle), math.cos(angle)] ]
                        R = numpy.matrix(id_rotation)
    
                        id_position = [ [Object.x - center_x],
                                        [Object_y - center_y] ]
                        P = numpy.matrix(id_position)
    
                        id_center = [ [center_x],
                                    [center_y] ]
                        C = numpy.matrix(id_center)
    
                        position_without_rotation = numpy.dot(R, P) + C
    
                        no_rotation_x = position_without_rotation[0]
                        no_rotation_y = position_without_rotation[1] - Object.height #Repere Tiled pas le meme que Pygame
    
                        Object_surface = pygame.Surface((Object.image.get_rect()[2], Object.image.get_rect()[3]), pygame.SRCALPHA)
                        Object_surface.blit(Object.image, (0, 0))
                        Object_surface_scale = pygame.transform.scale(Object_surface, (round(Object.width), round(Object.height)))
                        Object_surface_rotate = pygame.transform.rotate(Object_surface_scale, -Object.rotation) #Pygame va en anti horaire
    
                        extra_x = (Object_surface_rotate.get_rect()[2] - Object.width) / 2
                        extra_y = (Object_surface_rotate.get_rect()[3] - Object.height) / 2
    
                        rdc.blit(Object_surface_rotate, (no_rotation_x - extra_x, no_rotation_y - extra_y))
                    else:
                        Object_surface = pygame.Surface((Object.image.get_rect()[2], Object.image.get_rect()[3]), pygame.SRCALPHA)
                        Object_surface.blit(Object.image, (0, 0))
                        Object_surface_scale = pygame.transform.scale(Object_surface, (round(Object.width), round(Object.height)))
    
                        rdc.blit(Object_surface_scale, (Object.x, Object.y))