python - 如何让可移动图像跟随鼠标旋转

标签 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()

代码非常困惑,因为我真的不知道我在做什么,但到目前为止它是如何工作的 Youtube视频:https://www.youtube.com/watch?v=zShWAm4pSx8&feature=youtu.be

最佳答案

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

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),您需要将其缩放到所需的速度。现在,您需要将速度列表与矩形、额外位置列表和旋转图像一起放入表示项目符号对象的列表中。要更新矩形位置,您首先必须将速度添加到 pos,然后将 pos 分配给矩形中心(您必须这样做,因为矩形只能将整数作为 x 和 y 位置)。

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

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()

关于python - 如何让可移动图像跟随鼠标旋转,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46137397/

相关文章:

python - 将基于 pandas python 中重复列的数据集分组为列表

python - Django - 信号。简单的例子开始

python - 替换 pandas DataFrame 中的列值

python-2.7 - Pygame 会在显示器外用一个矩形 blit Sprite 吗

python - Pygame 显示仅在我退出时更新

python - 如何在pygame中制作波浪计时器

python - PysimpleGUI - 简单的动画

python - Scipy 和 Sklearn chi2 实现给出不同的结果

python - 如何在 Pygame 中分配和测试矩形的属性

python - 我一直在尝试对这个立方体进行纹理处理,它与图像一起纹理化,但方式不正确