无法理解如何在 PyGame 中制作角色面部鼠标 [英] Can't understand how to make character face mouse in PyGame

查看:29
本文介绍了无法理解如何在 PyGame 中制作角色面部鼠标的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下是我目前所拥有的.目前,玩家会移动,而我现在要做的就是始终面对鼠标光标(想想 Hotline Miami 或其他自上而下的游戏).我使用了一些我在网上找到的涉及 atan2 的代码,但我几乎不明白它的作用(以某种方式找到玩家和鼠标之间的距离......)并且我的角色只是在屏幕外疯狂旋转,直到我得到内存不足"错误.任何帮助将不胜感激,我已经浏览了整个互联网,但找不到任何对我有帮助的东西.

Below is what I have so far. At the moment, the player moves, and all I want it to do now is face the mouse cursor at all times (think Hotline Miami or other top-down games). I've used some code involving atan2 that I found online, but I barely understand what it does (finds the distance between the player and mouse somehow...) and my character just spins wildly offscreen until I get an 'Out of memory' error. Any help would be much appreciated, I've looked all over the internet and can't find anything that helps me.

import pygame, sys, math
from pygame.locals import *

pygame.init()

#setup the window with a 720p resolution and a title
winX, winY = 1280, 720
display = pygame.display.set_mode((winX, winY))
winTitle = pygame.display.set_caption("Game name")

#Colours
cBlack = (0, 0, 0)

#setup the clock and FPS limit
FPS = 70
clock = pygame.time.Clock()

#sprite groups
allSprites = pygame.sprite.Group()

#background image
bg = pygame.image.load("bg.jpg")

class Player(pygame.sprite.Sprite):
    def __init__(self, speed):
        #import the __init__ from the Sprite class
        pygame.sprite.Sprite.__init__(self)
        #sets the objects speed to the speed argument
        self.speed = speed
        #set the soldiers image
        self.image = pygame.image.load("soldier_torso_DW.png")
        #get the rectangle of the image (used for movement later)
        self.rect = self.image.get_rect()
        #sets starting position
        self.rect.x, self.rect.y = winX/2, winY/2

    def checkPlayerMovement(self):
        """Check if user has pressed any movement buttons
            and sets the characters position accordingly."""
        pressed = pygame.key.get_pressed()
        if pressed[K_w]:
            self.rect.y -= self.speed
        if pressed[K_s]:
            self.rect.y += self.speed
        if pressed[K_a]:
            self.rect.x -= self.speed
        if pressed[K_d]:
            self.rect.x += self.speed

    def checkMouseMovement(self):
        """Check if user has moved the mouse and rotates the
            character accordingly."""
        mX, mY = pygame.mouse.get_pos()
        angleRad = math.atan2(mY, mX) - math.atan2(self.rect.y, self.rect.x)
        angleDeg = math.degrees(angleRad)
        print angleDeg
        self.image = pygame.transform.rotate(self.image, angleDeg)

    def update(self):
        """Performs all movement and drawing functions and shit
            for the object"""
        self.checkPlayerMovement()
        self.checkMouseMovement()
        #draw the image at the given coordinate
        display.blit(self.image, (self.rect.x, self.rect.y))

def updateAll():
    #fill the window with black
    display.blit(bg, (0, 0))
    #update all sprites
    allSprites.update()
    #keeps FPS at 60
    clock.tick(FPS)
    #updates the display
    pygame.display.flip()

#creates a player with a speed of 5
mainChar = Player(5)
#add the player character to main sprite group
allSprites.add(mainChar)

while True:
    for event in pygame.event.get():
        if event.type == QUIT:
            pygame.quit()
            sys.exit()
    updateAll()

推荐答案

(完全公开,我对pygame包不熟悉,但我用其他语言做过这种编程)

(Full disclosure, I'm not familiar with the pygame package, but I have done this sort of programming in other languages)

当您希望玩家确定它应该旋转多少来面对一个物体时,玩家应该将自己视为世界中心.然而,它的坐标并不总是(0,0).我们首先需要通过从玩家希望面对的对象中减去玩家的位置,将我们的坐标转换为以自我为中心的坐标.

When you want a player to determine how much it should rotate to face an object, the player should consider itself to be the world center. However, its coordinates are not always going to be (0,0). We first need to transform our coordinates into egocentric ones by subtracting the players' pos from the object it wishes to face.

接下来,您似乎只使用玩家的位置来计算旋转.除非玩家始终面向与从其当前位置到原点的向量方向相同的方向,否则这不是正确的计算.您必须包含其他信息来跟踪玩家的旋转,这通常是通过具有 (x, y) 分量的单位方向向量来完成的.

Next, it looks like you're only using the player's position to compute the rotation. Unless the player always faces a direction equivalent to the direction of a vector from its current position to the origin, this is not a correct calculation. You must include additional information to track the player's rotation, and this is often done through a unit direction vector with (x, y) components.

  1. 计算从物体位置到玩家位置的相对向量
    • 称这个向量为 Vrel
  • 现在的结果是您的玩家需要旋转的量,相对于自身

atan2() 函数

atan2 函数会给你一个 signed 从正 X 轴旋转.

因此,给定笛卡尔 XY 平面和位置 (x, y),如果您绘制从 (0, 0) 到 (x, y) 的向量,则 atan2(y, x) 将为您提供之间的角度向量 (1, 0) 和 (x, y).例如,如果您的 (x, y) 为 (0, 1)(沿 y 轴),那么 atan2(1, 0) 将为您提供 π/2 或 90°,如果您的 (x, y) 为沿着负 y 轴 (0, -1),然后 atan2(0, -1) 会给你 -π/2 或 -90°.

So, given the Cartesian X-Y plane and a position (x, y), if you drew a vector from (0, 0) to (x, y), then atan2(y, x) will give you the angle between the vector (1, 0) and (x, y). For example, if your (x, y) was (0, 1) (along the y axis), then atan2(1, 0) will give you π/2, or 90°, and if your (x, y) went along the negative y axis (0, -1), then atan2(0, -1) will give you -π/2, or -90°.

atan2 输出的正角总是逆时针旋转,负角是顺时针旋转.大多数计算器确实需要 atan2(y, x) 形式,但不是全部,所以要小心.在Python的数学库中是atan2(y, x)

A positive angle output from atan2 is always a counter-clockwise rotation, and a negative angle is a clockwise rotation. Most calculators do require the form atan2(y, x), but not all, so be careful. In Python's math library, it is atan2(y, x)

请原谅不按比例、糟糕的颜色选择、幼儿园质量的图片,并尽量专注于概念.

Forgive the not-to-scale, bad color choice, kindergarten quality pictures and try to focus on the concepts.

位置 (5, 5) 处的对象位于 (-3, -1) 位置的玩家.玩家面向方向 (-0.8, 0.6)

Object at position (5, 5) Player at position (-3, -1). Player facing direction (-0.8, 0.6)

  1. 相对向量是 (Objectx - Playerx, Objecty - Playery) = (5, 5) - (-3, -1) = (5 - -3, 5 - -1) = (5+3, 5+1) = (8, 6)
  1. Relative vector is (Objectx - Playerx, Objecty - Playery) = (5, 5) - (-3, -1) = (5 - -3, 5 - -1) = (5+3, 5+1) = (8, 6)

  1. atan2(Vrel) = atan2(6, 8) = 0.9272952180016122 rad

  1. atan2(Vrel) = atan2(6, 8) = 0.9272952180016122 rad

  • atan2(playerDiry, playerDirx) = atan2(-0.8, 0.6) = 2.498091544796509 rad
  • atan2(playerDiry, playerDirx) = atan2(-0.8, 0.6) = 2.498091544796509 rad



  • atan2(Vrel) - atan2(玩家) = 0.9272952180016122 - 2.498091544796509 = -1.5707963267948966 rad
  • atan2(Vrel) - atan2(player) = 0.9272952180016122 - 2.498091544796509 = -1.5707963267948966 rad

因此玩家必须围绕自己的中心旋转 -1.57 弧度(顺时针近 90 度)才能面向对象.

So the player must rotate -1.57 rad about its own center (nearly 90 degrees clockwise) to face the object.

这篇关于无法理解如何在 PyGame 中制作角色面部鼠标的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆