05-数学运算解决飞船圆周运动

本文详细介绍了使用Pygame进行游戏开发时的位图加载、缩放和平滑缩放方法,以及如何通过点类简化代码。特别聚焦于飞船旋转的实现,包括角度预测、位图旋转和平移,确保飞船朝向正确位置。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

位图

space = pygame.image.load("space.png").convert_alpha()
planet = pygame.image.load("planet2.png").convert_alpha()
ship = pygame.image.load("freelance.png").convert_alpha()
  • 利用此函数可以加载位图,convert()可以将位图转换为程序窗口的本地颜色深度,以此作为一种优化.
    alpha为了使图像保持透明度.
  • 利用blit()可以绘制位图(bit block transfer的缩写),注意绘制的先后顺序,否则会使得图像被覆盖

位图缩放

  • 使用:ship.get_size()来获得图像的大小
  • pygame.transform.scale(ship, (width//2,height//2))缩放
  • pygame.transform.smoothscale(ship, (width//2, height//2))平滑缩放

点类

使用方便,减少代码冗余

class Point(object):
    def __init__(self, x, y):
        self.__x = x
        self.__y = y

    def getx(self):
        return self.__x

    def setx(self, x):
        self.__x = x
    x = property(getx, setx)

    def gety(self):
        return self.__y

    def sety(self, y):
        self.__y = y
    y = property(gety, sety)

    def __str__(self):
        return "{X:" + "{:.0f}".format(self.__x) + \
            ",Y:" + "{:.0f}".format(self.__y) + "}"

property属性: 可以接收四个参数,get,set,del和__doc__,详情请看 property属性

飞船旋转(难):

思路: 利用反正切函数进行角度的预测,根据当前点的坐标和上一次最近的坐标的差值,进行反正切计算,计算出的弧度转换为角度后再进行位图的旋转.

# 旋转飞船
    delta_x = pos.x - old_pos.x
    delta_y = pos.y - old_pos.y
    rangle = math.atan2(delta_y, delta_x)
    rangled = wrap_angle(-math.degrees(rangle))
    scratch_ship = pygame.transform.rotate(ship, rangled)

wrap函数是让角度和360°取模,这里的坑!就是负数和360°的取模运算,比如:-1%360 = 359!
而之所以要进行这一步运算,就是因为飞船的位图刚加载时脑袋是朝向东边的,而我们每次都要给他逆时针旋转一个角度(360°减去计算出来的arctan(y/x)角度),才能让飞船朝向正确的位置.


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



class Point(object):
    def __init__(self, x, y):
        self.__x = x
        self.__y = y

    def getx(self):
        return self.__x

    def setx(self, x):
        self.__x = x
    x = property(getx, setx)

    def gety(self):
        return self.__y

    def sety(self, y):
        self.__y = y
    y = property(gety, sety)

    def __str__(self):
        return "{X:" + "{:.0f}".format(self.__x) + \
            ",Y:" + "{:.0f}".format(self.__y) + "}"


#print_text function
def print_text(font, x, y, text, color=(255,255,255)):
    imgText = font.render(text, True, color)
    screen.blit(imgText, (x,y))


#wrap_angle function
def wrap_angle(angle):
    return angle % 360




pygame.init()
screen = pygame.display.set_mode((800, 600))
pygame.display.set_caption("spaceship")
space = pygame.image.load("space.png").convert_alpha()
planet = pygame.image.load("planet2.png").convert_alpha()
ship = pygame.image.load("freelance.png").convert_alpha()

width_ship, height_ship = ship.get_size()
ship = pygame.transform.smoothscale(ship, (width_ship//2, height_ship//2))
font = pygame.font.Font(None, 18)
pos = Point(0, 0)
old_pos = Point(0, 0)
radius = 250
angle = 0.0


while True:
    for event in pygame.event.get():
        if event.type == QUIT:
            sys.exit()
    keys = pygame.key.get_pressed()
    if keys[K_ESCAPE]:
        sys.exit()

    #绘制背景位图
    screen.blit(space, (0,0))
    # 绘制行星(注意绘制的先后顺序,否则无法显示)
    width, height = planet.get_size()
    screen.blit(planet, (400 - width / 2, 300 - height / 2))

    # 移动飞船
    angle = wrap_angle(angle + 0.1)
    pos.x = math.cos(math.radians(angle)) * radius
    pos.y = math.sin(math.radians(angle)) * radius
    # 旋转飞船
    delta_x = pos.x - old_pos.x
    delta_y = pos.y - old_pos.y
    rangle = math.atan2(delta_y, delta_x)
    rangled = wrap_angle(-math.degrees(rangle))
    scratch_ship = pygame.transform.rotate(ship, rangled)
    width_ship, height_ship = scratch_ship.get_size()
    x = 400+pos.x-width_ship//2
    y = 300+pos.y-height_ship//2
    # 绘制飞船
    screen.blit(scratch_ship, (x, y))
    print_text(font, 0, 0, "angle: " + "{:.0f}".format(angle))
    print_text(font, 0, 20, "rangled: " + "{:.2f}".format(rangled))
    print_text(font, 0, 40, "Position: " + str(pos))
    print_text(font, 0, 60, "Old Pos: " + str(old_pos))
    print("dx:{:.4f},dy:{:.4f},rangle:{:.4f},-degree{:.4f},rangled{:.4f}".format(delta_x,delta_y,rangle,-math.degrees(rangle),rangled))
    print("转换为角度:{:.4f}".format(180/math.pi*rangle))


    pygame.display.update()
    # time.sleep(0.025)
    old_pos.x = pos.x
    old_pos.y = pos.y

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值