【问题标题】:Sprite Is Not Rotating Towards The Player Properly How Do I Fix This? [duplicate]Sprite 没有正确地朝向玩家旋转我该如何解决这个问题? [复制]
【发布时间】:2020-06-23 19:10:30
【问题描述】:

我试图让我的精灵朝向玩家旋转,但旋转不合适。这是video of the behaviour

我不知道如何解决这个问题,

精灵类

  #-------------------------------- enemy shoots left and right

    shotsright = pygame.image.load("canss.png")
    class enemyshoot:
        def __init__(self,x,y,height,width,color):
            self.x = x
            self.y =y
            self.height = height
            self.width = width
            self.color = color
            self.rect = pygame.Rect(x,y,height,width)
            self.health = 10
            self.hitbox = (self.x + -20, self.y + 30, 31, 57)
           #-------------------------------------------------------
            # Make a Reference Copy of the bitmap for later rotation
            self.shootsright = pygame.image.load("canss.png")
            self.shootsright = pygame.transform.scale(self.shootsright,(self.shootsright.get_width()-150,self.shootsright.get_height()-150))            
            self.image    = self.shootsright
            self.rect     = self.image.get_rect()
            self.position = pygame.math.Vector2( (200, 180) )
            self.isLookingAtPlayer = False
        def draw(self):
            self.rect.topleft = (self.x,self.y)
            window.blit(self.image, self.rect)
            self.hits = (self.x + 20, self.y, 28,60)
            pygame.draw.rect(window, (255,0,0), (self.hitbox[0], self.hitbox[1] - 60, 100, 10)) # NEW
            pygame.draw.rect(window, (0,255,0), (self.hitbox[0], self.hitbox[1] - 60, 100 - (5 * (10 - self.health)), 10))
            self.hitbox = (self.x + 200, self.y + 200, 51, 65)
        def lookAt( self, coordinate ):
            # Rotate image to point in the new direction
            delta_vector  = coordinate - self.position
            radius, angle = delta_vector.as_polar()
            self.image    = pygame.transform.rotate(self.shootsright, -angle)
            # Re-set the bounding rectangle and position since 
            # the dimensions and centroid will have (probably) changed.
            current_pos      = self.rect.center
            self.rect        = self.image.get_rect()
            self.rect.center = current_pos
            


            
    black = (0,0,0)
    enemyshooting = []
    platformGroup = pygame.sprite.Group
    platformList = []
    level = ["                                                                                                                     p               p           p                         p                        p        ",
             "                                       ",
             "                             ",
             "                                      ",
             "                                  ",
             "                           ",
             "                                      ",
             "                                      ",
             "                                    ",
             "                                   ",
             "                    ",]
    for iy, row in enumerate(level):
        for ix, col in enumerate(row):
            if col == "p":
                new_platforms = enemyshoot(ix*10, iy*50, 10,10,(255,255,255))
                enemyshooting.append(new_platforms)

这是旋转部分


class enemyshoot:
     def __init__(self,x,y,height,width,color):
       # [................]
           #-------------------------------------------------------
            # Make a Reference Copy of the bitmap for later rotation
            self.shootsright = pygame.image.load("canss.png")
            self.shootsright = pygame.transform.scale(self.shootsright,(self.shootsright.get_width()-150,self.shootsright.get_height()-150))            
            self.image    = self.shootsright
            self.rect     = self.image.get_rect()
            self.position = pygame.math.Vector2( (200, 180) )      


        def lookAt( self, coordinate ):
            # Rotate image to point in the new direction
            delta_vector  = coordinate - pygame.math.Vector2(self.rect.center)
            radius, angle = delta_vector.as_polar()
            self.image    = pygame.transform.rotate(self.shootsright, -angle)
            # Re-set the bounding rectangle and position since 
            # the dimensions and centroid will have (probably) changed.
            current_pos      = self.rect.center
            self.rect        = self.image.get_rect()
            self.rect.center = current_pos



这是我调用LookAt 函数来面对玩家的地方:

      # so instead of this 
            for enemyshoot in enemyshooting:
                if not enemyshoot.isLookingAtPlayer:
                    enemyshoot.lookAt((playerman.x, playerman.y)) 

旋转不合适,我不知道如何解决它。我试图让炮口朝玩家旋转,因为这是子弹会从那里追加的地方。

【问题讨论】:

标签: python pygame sprite


【解决方案1】:

我同意@Rabbid76 在上述答案中所说的一切。

我怀疑您的部分问题可能是位图的“人类可读”部分未以位图的centroid 为中心。因此,当旋转时,它“扫过”弧线,而不是“围绕自身”旋转。 (保持中心坐标是保持围绕对象质心平滑旋转的重要步骤)。

考虑两个位图(右边的图像在左上角有一个大的 3/4 透明部分):

两者都围绕它们的质心旋转,但是由于第二张图像上的可见部分没有居中,所以它旋转得很奇怪。

因此,请确保您的实际位图居中。

参考代码:

import pygame
import random

# Window size
WINDOW_WIDTH    = 800
WINDOW_HEIGHT   = 400
WINDOW_SURFACE  = pygame.HWSURFACE|pygame.DOUBLEBUF|pygame.RESIZABLE

DARK_BLUE = (   3,   5,  54 )

class RotationSprite( pygame.sprite.Sprite ):
    def __init__( self, image, x, y, ):
        pygame.sprite.Sprite.__init__(self)
        self.original = image
        self.image    = image
        self.rect     = self.image.get_rect()
        self.rect.center = ( x, y )
        # for maintaining trajectory
        self.position    = pygame.math.Vector2( ( x, y ) )
        self.velocity    = pygame.math.Vector2( ( 0, 0 ) )

    def lookAt( self, co_ordinate ):
        # Rotate image to point in the new direction
        delta_vector  = co_ordinate - self.position
        radius, angle = delta_vector.as_polar()
        self.image    = pygame.transform.rotozoom( self.original, -angle, 1 )
        # Re-set the bounding rectagle
        current_pos      = self.rect.center
        self.rect        = self.image.get_rect()
        self.rect.center = current_pos



### initialisation
pygame.init()
pygame.mixer.init()
window = pygame.display.set_mode( ( WINDOW_WIDTH, WINDOW_HEIGHT ), WINDOW_SURFACE )
pygame.display.set_caption( "Rotation Example" )

### Missiles!
rotation_sprites = pygame.sprite.Group()
rotation_image1 = pygame.image.load( 'rot_offcentre_1.png' )
rotation_image2 = pygame.image.load( 'rot_offcentre_2.png' )
rotation_sprites.add( RotationSprite( rotation_image1, WINDOW_WIDTH//3, WINDOW_HEIGHT//2 ) )
rotation_sprites.add( RotationSprite( rotation_image2, 2*( WINDOW_WIDTH//3 ), WINDOW_HEIGHT//2 ) )


### Main Loop
clock = pygame.time.Clock()
done = False
while not done:

    # Handle user-input
    for event in pygame.event.get():
        if ( event.type == pygame.QUIT ):
            done = True
        elif ( event.type == pygame.MOUSEBUTTONUP ):
            # On mouse-click
            pass

    # Record mouse movements for positioning the paddle
    mouse_pos = pygame.mouse.get_pos()
    for m in rotation_sprites:
        m.lookAt( mouse_pos )
    rotation_sprites.update()

    # Update the window, but not more than 60 FPS
    window.fill( DARK_BLUE )
    rotation_sprites.draw( window )
    pygame.display.flip()

    # Clamp FPS
    clock.tick_busy_loop(60)

pygame.quit()

【讨论】:

  • 我已经试过了,我不确定你现在把它居中是什么意思我按照你展示的例子但是我仍然有旋转问题VIDEO它只会在玩家跳跃时稍微旋转@ 987654326@
【解决方案2】:

self.position 在构造函数中设置,但没有更新。使用self.rect.center 计算方向向量:

delta_vector = coordinate - pygame.math.Vector2(self.rect.center)

使用math.atan2 计算旋转角度:
(见How do I make my player rotate towards mouse position?

angle = (180 / math.pi) * math.atan2(-delta_vector.x, -delta_vector.y)

draw 中设置矩形位置很难旋转lookAt 中的精灵。请注意,旋转矩形的大小被放大。见How do I rotate an image around its center using Pygame?

我建议在lookAt 中设置查看位置并在draw 中计算旋转图像:

class enemyshoot:
    def __init__(self,x,y,height,width,color):
       # [...]

       self.look_at_pos = (x, y)

    def draw(self):
   
        self.rect = self.shootsright.get_rect(topleft = (self.x, self.y))

        dx = self.look_at_pos[0] - self.rect.centerx
        dy = self.look_at_pos[1] - self.rect.centery 
        angle = (180 / math.pi) * math.atan2(-dx, -dy)

        self.image = pygame.transform.rotate(self.shootsright, angle)
        self.rect  = self.image.get_rect(center = self.rect.center)

        window.blit(self.image, self.rect)
        self.hits = (self.x + 20, self.y, 28,60)
        pygame.draw.rect(window, (255,0,0), (self.hitbox[0], self.hitbox[1] - 60, 100, 10)) # NEW
        pygame.draw.rect(window, (0,255,0), (self.hitbox[0], self.hitbox[1] - 60, 100 - (5 * (10 - self.health)), 10))
        self.hitbox = (self.x + 200, self.y + 200, 51, 65)

    def lookAt(self, coordinate):
        self.look_at_pos = coordinate

【讨论】:

  • 我认为轮换变得更糟了vide
  • 所以我可以在敌人射击的底部给它一个更新定义,而不是说在敌人射击中为敌人射击:如果不是class* 我更新了线程而不是获取鼠标位置,我怎样才能让玩家的位置让它像那样移动?正确旋转? script
  • 我收到一个错误enemyshoot.lookAt((playerman.x, playerman.y)) TypeError: 'tuple' object is not callable 我没有发现我的enemyshoot class 有任何问题
  • @HabibIsmail 我的错。当然,属性和功能的名称必须不同。我改变了self.lookAt -> self.look_at_pos
  • `enemyshoot.lookAt((playerman.x, playerman.y)) TypeError: 'tuple' object is not callable` 再次出现同样的错误
猜你喜欢
  • 1970-01-01
  • 2021-04-30
  • 1970-01-01
  • 1970-01-01
  • 2020-10-06
  • 2020-03-25
  • 2020-02-14
相关资源
最近更新 更多