Pygame朝向鼠标指针向前进_Arrow类_射箭,坦克,海龟类雏形程序

如果用过Scratch,那么就会知道有一个叫朝向鼠标指针的命令。它能让角色朝着鼠标指针的方向。如果在Pygame中要让一个角色朝向鼠标指针,那么就必需“手动”地去旋转图形了。旋转的角度应该是它和x轴的夹角,我们把它叫angle。 这个夹角可以通过数学函数中的反正角函数求出。在Python对应了math.atan2这个函数。它要求有两个参数,一个是dy,一个是dx。dy就是两点之间的垂直距离,dx就是两点之间的水平距离。以下是求angle的示意图,虽然在接下来的例子中是以箭头的中心点为旋转中心的,但并不影响它示意原理,学过三角函数的都应该知道。

pygame计算夹角示意原理图_朝向鼠标指针向前进ARROW类

不过在Pygame中,y坐标轴是向下,所以计算dy的时候要取反。实时地把angle求出来了,那么就能旋转image了。以下是Arrow类的代码,读者可以把它应用到游戏中的很多地方。比如坦克发射炮弹 ,射箭游戏,甚至自制作一个海龟画图像块等等。代码如下所示:

"""
   朝向鼠标指针的Arrow类
"""
import math
import pygame
from pygame.locals import *

class Arrow(pygame.sprite.Sprite):
    def __init__(self,image,pos):
        """
          image:图形,pos:坐标
        """
        pygame.sprite.Sprite.__init__(self)
        self.rotate_center = pos         # 旋转中心
        self.rawimage = image            # 保留原始图形
        self.angle = 0                   # 和x轴的夹角
        self.rotate()                    # 旋转图形  

    def rotate(self):
        """根据和x轴的角度旋转图形"""
        self.image = pygame.transform.rotate(self.rawimage,self.angle)
        self.rect = self.image.get_rect(center=self.rotate_center)

    def update(self):
        """计算和鼠标指针的方向,更新image和rect"""
        p = pygame.mouse.get_pos()        # 获取鼠标指针坐标
        dy = self.rotate_center[1] -p[1]  # 和箭头的垂直距离
        dx = p[0] - self.rotate_center[0] # 和箭头的水平距离 
        degree = math.atan2(dy,dx)        # 计算夹角,代表方向
        self.angle = math.degrees(degree) # 转换为角度
        self.rotate()                     # 生成旋转后的image

在旋转的时候,要注意是对原始图像进行旋转。旋转后应该重新调整它的rect属性。上面定义的rotate函数就是对角色进行旋转的方法。update方法的用途是获取鼠标指针坐标,计算角度然后进行角色图像旋转的。箭头可以朝向它的方向前进,为了完成这个任务,编制作了forward方法。下面是这个方法的代码:

def forward(self,distance):
    """朝着它的方向前进一定的距离"""
    r = math.radians(self.angle)       # 转换成弧度值
    dx = distance * math.cos(r)        # 计算水平位移量
    dy = - distance * math.sin(r)      # 计算垂直位移量
    x = self.rotate_center[0] + dx     # 新的x坐标
    y = self.rotate_center[1] + dy     # 新的y坐标
    self.rotate_center = x,y           # 新的旋转中心
    self.rect.center = self.rotate_center
    
def backward(self,distance):
    """朝着它的反方向移动一定的距离"""
    self.forward(-distance)
    
fd = forward                          # 定义别名
bk = back = backward                  # 定义别名

当角色朝它的方向移动时,在水平和垂直方向的位移量是通过三角函数计算而来的。由于Python的y轴向下,所以在上面的代码中,当计算了dy时,对它进行了取反的运算。前进是相对于原来的坐标进行的位移量,所以最终的坐标还要加上原先的坐标。这在forward方法中都有体现。理解了上面的代码,我们自己编一个海龟类也就不在话下了。接下来代码是main函数。它新建了屏幕对象,实例化了一个箭头,叫做p。在while循环中,它会不断地朝向鼠标指针,并且当按上方向箭头时它会朝自己的方向移动。当按下方向箭头时它会反方向移动,以下是main函数的代码:

def main():
    """主要函数"""
    size = width,height = 480,360
    screen = pygame.display.set_mode(size)
    pygame.display.set_caption("面向鼠标指针旋转的箭头by lixingqiu")
    image = "arrow1-a.png"
    image = pygame.image.load(image).convert_alpha() # 转为每像素模式

    p = Arrow(image,(width//2,height//2))
    running = True
    while running:
        for event in pygame.event.get():
            if event.type == QUIT:running=False
            if event.type == KEYDOWN:
                if event.key == K_UP:   p.fd(10)
                if event.key == K_DOWN: p.bk(10)
                    
        screen.fill((255,255,255))
        p.update()
        screen.blit(p.image,p.rect)
        pygame.display.update()
    pygame.quit()

一个基本的游戏雏形就出来了,接下为就需要读者自己去完善了。这里只是把最核心的代码写出来用以抛砖引玉。