Pygame делает спрайт лицо мышью

Я новичок в Pygame, но вроде нормально на Python, я создаю игру-стрелялку по зомби с видом сверху.
Мне удалось заставить персонажа двигаться при нажатии клавиш со стрелками. Но теперь мне нужно, чтобы плеер смотрел ЛИЦОМ мыши / курсора, не нажимая все время на экран.
Есть помощь?


person Community    schedule 21.07.2011    source источник
comment
Итак, вы уже решили проблему, заставляющую игрока смотреть на место щелчка мыши, поэтому все, что вам действительно нужно сделать, это прислушиваться к движению мыши и обновлять проигрыватель так же, как при щелчке мышью. Итак, проблема, которую нужно решить, - это как слушать движения мыши в pygame?   -  person Dan D.    schedule 21.07.2011


Ответы (4)


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

person faraday    schedule 21.07.2011
comment
если event.type == pygame.MOUSEMOTION, вы можете просто использовать event.pos для получения позиции мыши, а не вызывать pygame.mouse.get_pos(). - person Dan D.; 21.07.2011
comment
Это работает, но Pygame.transform.rotate использует Angle, как мне это сделать? - person ; 21.07.2011
comment
@Firetryer: Изучите векторную арифметику. en.wikipedia.org/wiki/Dot_product#Properties - person JAB; 21.07.2011

import math

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

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

Возможно, вам придется поиграть с порядком вычитания (например, это может быть mousePosition-playerPosition) или порядком параметров x и y для atan2 (то есть вам может потребоваться передать разницу Y в качестве первого параметра, а не X), но это зависит от вашей системы координат.

person combatdave    schedule 21.07.2011

рабочий код:

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)   
person Manfre Manfre    schedule 07.07.2017
comment
Я только что проверил изображение носа корабля, посмотри мышкой и следуй, попробуй себя - person Manfre Manfre; 07.07.2017

_, angle = (pg.mouse.get_pos()-self.pos).as_polar()

В этой строке сначала вычисляется вектор положения мыши (self.pos должен быть pygame.math.Vector2) и _ 4_ возвращает полярные координаты вектора, которые состоят из радиального расстояния и угла. Наконец, используйте отрицательный угол (потому что ось y pygame перевернута), чтобы повернуть изображение спрайта и пересчитать прямоугольник.

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)
person skrx    schedule 07.07.2017
comment
@ Coder22 у меня работает правильно, и треугольник вращается в сторону мыши. Что именно не работает? - person skrx; 21.04.2018