【问题标题】:Pygame Making A Sprite Face The Mouse [duplicate]Pygame制作精灵面对鼠标[重复]
【发布时间】:2011-10-10 04:38:03
【问题描述】:

我是 Pygame 的新手,但在 Python 上还可以,我正在创建一个带有俯视图的僵尸射击游戏。
按下箭头键时,我设法使角色移动。但现在我需要让玩家面对鼠标/光标而不是一直点击屏幕。
有什么帮助吗?

【问题讨论】:

  • 所以你已经解决了让播放器面对鼠标点击位置的问题,所以你真正需要做的就是监听鼠标移动并以与你相同的方式更新播放器只需点击一下即可。所以要解决的问题是如何在pygame中监听鼠标移动

标签: python sprite pygame


【解决方案1】:
for event in pygame.event.get():
    if event.type == MOUSEMOTION:
        mousex, mousey = event.pos
        # build a vector between player position and mouse position
        moveVector = (mousex-playerx, mousey-playery)

        """
        compute the angle of moveVector from current vector that player is facing (faceVector).
        you should be keeping and updating this unit vector, with each mouse motion
        assume you have initial facing vector as (1,0) - facing East
        """

        # compute angle as in [1]

        # rotate the image to that angle and update faceVector

[1] - 如何找到两个向量之间的角度: http://www.euclideanspace.com/maths/algebra/vectors/angleBetween/index.htm

您的图像在以小角度旋转时可能会降低质量。 Pygame 文档页面中对此进行了讨论:http://pygame.org/docs/ref/transform.html#pygame.transform.rotate

【讨论】:

  • 如果event.type == pygame.MOUSEMOTION,你可以使用event.pos获取鼠标位置,而不是调用pygame.mouse.get_pos()
  • 它的工作,但 Pygames 'pygame.transform.rotate' 使用角度,所以我该怎么做?
  • @Firetryer:学习向量算术。 en.wikipedia.org/wiki/Dot_product#Properties
【解决方案2】:
import math

mouseX, mouseY = pygame.mouse.get_pos()
playerX, playerY = player.get_pos()

angle = math.atan2(playerX-mouseX, playerY-mouseY)

您可能不得不摆弄减法的顺序(即,它可能是 mousePosition-playerPosition)或 atan2 的 x 和 y 参数的顺序(即,您可能需要将 Y 差作为第一个参数传递而不是 X),但这取决于您的坐标系。

【讨论】:

    【解决方案3】:

    工作代码:

    import pygame, sys, math
    from pygame.locals import *
    
    
    #converte in base ai gradi le cordinate x,y
    #maxXY= surface MaxXY
    #gradoRot = grado di rotazione
    #distXY = spostamento in x,y lungo il vettore di cordinate locali dalle cordinate x,y
    
    #movement from one point to another
    def Move(t0,t1,psx,psy,speed):
        global mx
        global my
    
        speed = speed
    
        distance = [t0 - psx, t1 - psy]
        norm = math.sqrt(distance[0] ** 2 + distance[1] ** 2)
        direction = [distance[0] / norm, distance[1 ] / norm]
    
        bullet_vector = [direction[0] * speed, direction[1] * speed]
        return bullet_vector
    # Main Function
    if __name__ == '__main__':
        pygame.init()
        FPS = 30 # frames per second setting
        fpsClock = pygame.time.Clock()
        # set up the window
        DISPLAYSURF = pygame.display.set_mode((800, 600), 0, 32)
        alfhaSurface = DISPLAYSURF.convert_alpha() 
        pygame.display.set_caption('test')
        shipImg = pygame.image.load('ship.png')
        shipImgcpy=shipImg.copy()
        vetShip=pygame.math.Vector2(400,300)
        gradi = 0
        gradiRot=0
        mouseX=0
        mouseY=0
        SHIP_W=40
        SHIP_H=40
        vetMouse=pygame.math.Vector2(mouseX,mouseY)
        #main loop
        while True:
            DISPLAYSURF.fill((0,0,0)) 
            alfhaSurface.fill((0,0,0))
            for event in pygame.event.get():
                if event.type == QUIT:
                    pygame.quit()
                    sys.exit()  
                if event.type == MOUSEBUTTONDOWN:
                    mouseX, mouseY = pygame.mouse.get_pos()
                    vetMouse=pygame.math.Vector2(mouseX,mouseY)
    
                    gradiRot=**math.atan2(vetShip.x-vetMouse.x, vetShip.y-vetMouse.y)**
                    gradiRot=**math.degrees(gradiRot)**
                    pygame.display.set_caption(""+str(gradi) +"="+ str(gradiRot)+" "+ str(vetMouse.angle_to(vetShip)) ) 
            pygame.draw.line(alfhaSurface, (255,255,255), (vetShip.x+SHIP_W,vetShip.y+SHIP_H),(vetMouse.x,vetMouse.y),1)                      
            if gradi != int(gradiRot) :
                if gradiRot > gradi and gradi != gradiRot :
                    gradi=gradi+1
    
                if gradiRot < gradi and gradi != gradiRot :
                    gradi=gradi-1    
    
                shipImgcpy=pygame.transform.rotate(shipImg.copy(),gradi) 
    
            elif int(vetMouse.distance_to(vetShip)) >0:
                posNext=Move(mouseX,mouseY,vetShip.x+SHIP_W,vetShip.y+SHIP_H,1)                  
              vetShip=pygame.math.Vector2(vetShip.x+posNext[0],vetShip.y+posNext[1])
    
    
            alfhaSurface.blit(shipImgcpy, tuple(vetShip))
            DISPLAYSURF.blit(alfhaSurface,(0,0))
            pygame.display.update()
            fpsClock.tick(FPS)   
    

    【讨论】:

    • 我刚刚测试了船的鼻子图像看鼠标跟随,试试你自己
    【解决方案4】:
    _, angle = (pg.mouse.get_pos()-self.pos).as_polar()
    

    这条线首先计算一个到鼠标位置的向量(self.pos 必须是一个pygame.math.Vector2),.as_polar() 返回由径向距离和角度组成的向量的极坐标。最后用负角(因为pygame的y轴是翻转的)旋转精灵的图像,重新计算矩形。

    import pygame as pg
    
    
    class Player(pg.sprite.Sprite):
        def __init__(self, pos):
            super().__init__()
            self.image = pg.Surface((50, 30), pg.SRCALPHA)
            pg.draw.polygon(
                self.image,
                pg.Color('dodgerblue1'),
                ((1, 1), (49, 15), (1, 29)))
            self.orig_img = self.image
            self.rect = self.image.get_rect(center=pos)
            self.pos = pg.math.Vector2(pos)
            self.vel = pg.math.Vector2(0, 0)
    
        def update(self):
            self.rotate()
            self.pos += self.vel
            self.rect.center = self.pos
    
        def rotate(self):
            _, angle = (pg.mouse.get_pos()-self.pos).as_polar()
            self.image = pg.transform.rotozoom(self.orig_img, -angle, 1)
            self.rect = self.image.get_rect(center=self.rect.center)
    
    
    def main():
        screen = pg.display.set_mode((640, 480))
        clock = pg.time.Clock()
        all_sprites = pg.sprite.Group()
        all_sprites.add(Player((300, 200)))
    
        done = False
        while not done:
            for event in pg.event.get():
                if event.type == pg.QUIT:
                    done = True
    
            all_sprites.update()
            screen.fill((30, 30, 30))
            all_sprites.draw(screen)
    
            pg.display.flip()
            clock.tick(30)
    
    
    if __name__ == '__main__':
        pg.init()
        main()
        pg.quit()
    

    math.atan2 可以作为替代。

    def rotate(self):
        rel_x, rel_y = pg.mouse.get_pos() - self.pos
        angle = -math.degrees(math.atan2(rel_y, rel_x))
        self.image = pg.transform.rotozoom(self.orig_img, angle, 1)
        self.rect = self.image.get_rect(center=self.pos)
    

    【讨论】:

    • @Coder22 它对我来说可以正常工作,并且三角形会朝着鼠标旋转。究竟是什么不起作用?
    【解决方案5】:
    if event.type == MOUSEBUTTONDOWN:
        mouseX, mouseY = pygame.mouse.get_pos()
        vetMouse=pygame.math.Vector2(mouseX,mouseY)
        gradiRot=vetMouse.angle_to(vetShip)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-02-21
      • 2021-01-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-05-23
      • 1970-01-01
      相关资源
      最近更新 更多