如何使可移动图像旋转以跟随鼠标

时间:2017-09-10 04:48:08

标签: python pygame

标题是什么,我有一个我可以用W,S,A,D控制的图像。但我想让可移动的播放器图像旋转到面向鼠标的位置。这是相关代码:

import pygame
import random
import time
import math
import sys

pygame.init()

#The size of the game window
display_width = 1280
display_height = 800

#Colors available
black = (0, 0, 0) #colours defined by RGB,
white = (255, 255, 255)
red = (200, 0, 0)
green = (0, 150, 0)
bright_red = (255, 0, 0)
bright_green =(0, 255, 0)

#This code opens up the Game window
gameDisplay = pygame.display.set_mode((display_width, display_height))
pygame.display.set_caption("Blockslayer")
clock = pygame.time.Clock()
pygame.mouse.set_visible(True)

#player character info
slayerImg = pygame.image.load('squareslayer.png').convert_alpha()
slayerWidth = 84
slayerHeight = 84


#mouse info
mouse_c = pygame.image.load("crosshair.png ").convert_alpha()

def crosshair(mousex,mousey):
   mousex, mousey = pygame.mouse.get_pos()
   small_ch = pygame.transform.scale(mouse_c, (20, 20))
   gameDisplay.blit(small_ch, (mousex, mousey,))

   print(mousex,mousey)

#player character
def slayer(x,y,):
    #small_slayer = pygame.transform.scale(slayerImg, (120, 80,))
    pos = pygame.mouse.get_pos()
    angle = 360 - math.atan2(pos[1] - 84, pos[0] - 84) * 180 / math.pi
    rotimage = pygame.transform.rotate((slayerImg), angle,)
    rect = rotimage.get_rect(center=(x, y))
    gameDisplay.blit(rotimage, rect,)
    pygame.display.update()

#Game Logic
def block_game_loop():
    x = (display_width * 0.45)
    y = (display_height * 0.8)
    pos = pygame.mouse.get_pos()
    angle = 360 - math.atan2(pos[1] + x - 84, pos[0] + y - 84) * 180 / math.pi
    rotimage = pygame.transform.rotate((slayerImg), angle,)

    mousex, mousey = pygame.mouse.get_pos()


    #def blockguy(blockguyX, blockguyY, blockguyW, blockguyH, ):
    #blockguyX = random.randrange(0, 785)
    #blockguyY = random.randrange (0, 600)
    #blockguyW = 166
    #blockguyH = 110
    #blockguy_speed = 5


    #Event handler
    exit_game = False

    while not exit_game:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                quit()

        pressed = pygame.key.get_pressed()

        if pressed[pygame.K_s]: y += 7
        if pressed[pygame.K_w]: y -= 7
        if pressed[pygame.K_a]: x -= 7
        if pressed[pygame.K_d]: x += 7





        gameDisplay.fill(white)
        slayer(x, y,)

        #Boundaries
        if x > display_width:
            x = 1275

        if x < 0:
            x = 5

        if y > display_height:
            y = 795

        if y < 0:
            y = 5

        crosshair(mousex,mousey)
        #blockguy(blockguyX, blockguyY, blockguyW, blockguyH, )
        pygame.display.update()
        clock.tick(60)


block_game_loop()
pygame.quit()
quit()

代码非常混杂在一起,因为我真的不知道wtf我在做什么,但到目前为止这是怎么回事 Youtube视频:https://www.youtube.com/watch?v=zShWAm4pSx8&feature=youtu.be

2 个答案:

答案 0 :(得分:1)

看看这个rotate函数(阅读评论)。

import math
import pygame


pygame.init()

gray = (30, 30, 30)

display_width, display_height = (1280, 800)
gameDisplay = pygame.display.set_mode((display_width, display_height))

clock = pygame.time.Clock()

slayerImg = pygame.Surface((104, 84), pygame.SRCALPHA)
pygame.draw.polygon(slayerImg, (0, 120, 250), [(1, 1), (103, 42), (1, 83)])


def rotate(x, y, mouse_pos, image):
    # Calculate x and y distances to the mouse pos.
    run, rise = (mouse_pos[0]-x, mouse_pos[1]-y)
    # Pass the rise and run to atan2 (in this order)
    # and convert the angle to degrees.
    angle = math.degrees(math.atan2(rise, run))
    # Rotate the image (use the negative angle).
    rotimage = pygame.transform.rotate(image, -angle)
    rect = rotimage.get_rect(center=(x, y))
    return rotimage, rect


def block_game_loop():
    x = display_width * 0.45
    y = display_height * 0.8

    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                return

        pressed = pygame.key.get_pressed()
        if pressed[pygame.K_s]: y += 7
        if pressed[pygame.K_w]: y -= 7
        if pressed[pygame.K_a]: x -= 7
        if pressed[pygame.K_d]: x += 7

        mousex, mousey = pygame.mouse.get_pos()
        # Boundaries
        if x > display_width:
            x = 1275
        if x < 0:
            x = 5
        if y > display_height:
            y = 795
        if y < 0:
            y = 5

        gameDisplay.fill(gray)
        rotimage, rect = rotate(x, y, (mousex, mousey), slayerImg)
        gameDisplay.blit(rotimage, rect)

        pygame.display.update()
        clock.tick(60)


block_game_loop()
pygame.quit()

附录:这是一个示例,向您展示如何拍摄旋转的子弹。您需要一些基本的三角知识,因为您需要使用math.cosmath.sin来计算x和y速度。这将为您提供一个单位向量(长度为1),您需要缩放到所需的速度。现在,您需要将velocity列表与rect,一个额外的位置列表和旋转的图像放在一个表示子弹对象的列表中。要更新rect位置,首先必须将速度添加到pos,然后将pos分配给rect中心(你必须这样做,因为rects只能将int作为x和y位置)。

我建议使用pygame.math.Vector2和pygame sprite和sprite group而不是列表,正如您在链接的答案中看到的那样,因为这样可以更好地阅读。您仍然需要添加代码来删除项目符号,这也可以通过精灵和精灵组实现更简单。

import math
import pygame as pg
from pygame.math import Vector2


pg.init()
screen = pg.display.set_mode((640, 480))
FONT = pg.font.Font(None, 24)
BLACK = pg.Color('black')
BULLET_IMAGE = pg.Surface((20, 11), pg.SRCALPHA)
pg.draw.polygon(BULLET_IMAGE, pg.Color('grey11'), [(0, 0), (20, 5), (0, 11)])


def update_bullets(bullets):
    """Add the velocity to the pos then assign pos to the rect center."""
    for bullet_rect, pos, velocity, _ in bullets:
        pos[0] += velocity[0]
        pos[1] += velocity[1]
        bullet_rect.center = pos


def draw_bullets(bullets, screen):
    for bullet_rect, pos, _, image in bullets:
        screen.blit(image, bullet_rect)
        pg.draw.rect(screen, (200, 140, 0), bullet_rect, 1)


def main():
    clock = pg.time.Clock()
    # The cannon image and rect.
    cannon_img = pg.Surface((60, 22), pg.SRCALPHA)
    pg.draw.rect(cannon_img, pg.Color('grey19'), [0, 0, 35, 22])
    pg.draw.rect(cannon_img, pg.Color('grey19'), [35, 6, 35, 10])
    orig_cannon_img = cannon_img  # Store orig image to preserve quality.
    cannon = cannon_img.get_rect(center=(320, 240))
    angle = 0  # Angle of the cannon.

    # Add bullets to this list. Bullets will also be lists
    # consisting of a pygame.Rect, the velocity and the image.
    bullets = []
    bullet_speed = 5

    playing = True
    while playing:
        for event in pg.event.get():
            if event.type == pg.QUIT:
                playing = False
            elif event.type == pg.MOUSEBUTTONDOWN:
                # Left button fires a bullet from cannon center with
                # current angle. Add the bullet to the bullets list.
                if event.button == 1:
                    # Use cosine and sine to calculate the x and y
                    # velocity. Scale them by the desired speed.
                    velocity = (math.cos(math.radians(angle)) * bullet_speed,
                                math.sin(math.radians(angle)) * bullet_speed)
                    img = pg.transform.rotate(BULLET_IMAGE, -angle)
                    bullet_rect = img.get_rect(center=cannon.center)
                    # The extra pos list is needed because the pygame.Rect
                    # can only have ints as the x and y value. We still
                    # need the rect for collision detection.
                    pos = list(bullet_rect.center)
                    bullet = [bullet_rect, pos, velocity, img]
                    bullets.append(bullet)

        update_bullets(bullets)
        # Find angle to target (mouse pos).
        x, y = Vector2(pg.mouse.get_pos()) - cannon.center
        angle = math.degrees(math.atan2(y, x))
        # Rotate the cannon image.
        cannon_img = pg.transform.rotate(orig_cannon_img, -angle)
        cannon = cannon_img.get_rect(center=cannon.center)

        # Draw
        screen.fill(pg.Color('darkseagreen4'))
        draw_bullets(bullets, screen)
        screen.blit(cannon_img, cannon)
        txt = FONT.render('angle {:.1f}'.format(angle), True, BLACK)
        screen.blit(txt, (10, 10))
        pg.draw.line(
            screen, pg.Color(150, 60, 20),
            cannon.center, pg.mouse.get_pos(), 2)
        pg.display.update()

        clock.tick(30)


if __name__ == '__main__':
    main()
    pg.quit()

答案 1 :(得分:0)

这是大鱼,这是我针对该问题的代码:

import math
sprite = sprite_new("spr_plasma_blast")
targetx = 0
targety = 0
m = 0
time = 0
speed = 8
if time == 0:
  m = (targety - y)/(targetx - x)
  xSpeed = math.sqrt((speed*speed)/((m*m) + 1))
if targetx < x:
   xSpeed = -xSpeed

x = x + xSpeed
y = y + xSpeed*m

time = time + 1