【python游戏编程04--加载位图与常用的数学函数】

一、pygame中常用的数学函数

首先介绍两个角度和弧度转换的函数

math.degress()和math.radians()用法很简单,只要将数值传进去然后接受返回值就可以

math.cos(angle),math.sin(angle),这里的angle使用的是弧度表示的,因此需要先使用math.radians(),将角度换成弧度然后在传参

如果要获取当前时间,我们需要使用datetime模块

首先从datetime导入date和time

from datetime import datetime,date,time

使用datetime.body()函数可以获取当前的日期和事件

today = datetime.today()

print(today) 2019-03-29 17:42:55.960923

需要当前时间而不包含当前日期

time = datetime.today().time()
print(time)
17:46:47.602774

Time有很多属性,Time.hour Time.minute Time.second Time.micresecond

二、pygame中加载位图,绘制位图

通常,游戏游戏中需要大量的位图,pygame中自带了一些类和函数可以帮组我们轻松的实现

1、加载位图

在pygame中可以使用pygame.image.load()函数来加载位图

space= pygame.image.load("spqce.png").convert_alpha()

convert_alpha()方法会使用透明的方法绘制前景对象

2、绘制位图

surface对象有一个名为blit()的方法,它可以绘制位图

screen.blit(space,(0,0))

第一个参数;space 是加载完整的位图,第二个参数是绘制的起始坐

 完整的程序如下:

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

pygame.init()
screen = pygame.display.set_mode((800,600))
title = pygame.display.set_caption("星空")

#创建字体
font = pygame.font.Font(None,18)

#加载位图,convert_alpha:使前景对象透明
space = pygame.image.load("space.png").convert_alpha()

while True:
    for event in pygame.event.get():
        if event.type == QUIT:
            pygame.quit()
            sys.exit()
    #获得键盘上所有按键的状态
    keys = pygame.key.get_pressed()
    if keys[K_ESCAPE]:
        sys.exit()

    #绘制图位
    screen.blit(space,(0,0))

    pygame.display.update()

以上代码已经实现了星空背景图,下面的代码加载并绘制一个地球

#加载地球位图
planet2 = pygame.image.load("planet2.png").convert_alpha()
#获取地球位图的宽和高
width,height = planet2.get_size()
#在屏幕中间绘制地球
screen.blit(planet2,(400-width/2,300-height/2))

地球已经绘制完成以后,最后需要加载超人

#加载机器人
superman = pygame.image.load("military.png").convert_alpha()
#绘制机器人
screen.blit(superman,(30,30))

机器人图像太大,需要缩小一些

此时需要用到的模块:pygame.transform 这个模块可以满足我们的需求,这个模块包含了比如缩放,翻转等一些非常有用的函数

pygame.transform.scale()这是一个快速缩放函数,可以快速缩放一个图像,但是如果你试过以后就会发现他并不是那么理想,像素看起来很密集,有点奇怪

幸好它有一个名为pygame,transform,smoothscale()的变体,这个函数通过复杂的计算产生比较平滑的图像,当然他的运行好使大于快速缩放函数

superman = pygame.transform.smoothscale(superman,(width//2,height//2))

考虑让超人绕着地球旋转

import sys,pygame,math,random
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)

#定义一个warp_angle(angle)函数,返回0~360之间的角度
def warp_angle(angle):
    return angle % 360

'''
radius是半径
angle是角度默认值
pos代表图像坐标
'''
radius = 250
angle = 0.0
pos = Point(0,0)
old_pos = Point(0,0)

pygame.init()
screen = pygame.display.set_mode((800,600))
title = pygame.display.set_caption("星空")

#创建字体
font = pygame.font.Font(None,18)

#加载位图,convert_alpha:使前景对象透明
space = pygame.image.load("space.png").convert_alpha()
#加载地球位图
planet = pygame.image.load("planet2.png").convert_alpha()
#加载超人位图
superman = pygame.image.load("military.png").convert_alpha()

#获取超人位图的宽和高
width,height = superman.get_size()
#缩放机器人
superman = pygame.transform.smoothscale(superman,(width//2,height//2))

while True:
    for event in pygame.event.get():
        if event.type == QUIT:
            pygame.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))

    '''
    |-- warp_angle是返回0~360的角度,而此代码是360度逐次减0.5度,来控制机器人移动的速度
    |-- pos.x,pos.y:图像移动的正反坐标
    |-- math.sin:返回弧度的正弦值,数值在-1,1之间
    |-- math.cos:返回弧度的余弦值,数值在-1,1之间
    |-- math.radians:角度转换成弧度,返回的是一个数值
    '''
    angle = warp_angle(angle - 0.5)
    #print("====",angle)
    pos.x = math.sin(math.radians(angle))*radius
    pos.y = math.cos(math.radians(angle))*radius
    #获取机器人的宽和高
    width,height = superman.get_size()
    #绘制机器人,通过第二个参数的x,y轴移动来控制移动的正向还是反向
    screen.blit(superman,(350+pos.x-width//2,250+pos.y-height//2))

    pygame.display.update()

运行发现,超人可以绕着地球旋转,但是运动的比较僵硬,最好让自己也旋转起来,指向他移动的方向,以便让画面柔和一些

这里我们需要math.atan2()这个函数,它用于计算反正切函数,需要传递两个参数:delta_x,delta_y,

delta_x,delta_y表示两个坐标x,y之间的距离

工作流是这样的:先记录飞船的最近位置,然后使用当前位置和最近位置调用atan2函数,然后在给atan2函数的返回值加上180

我们还需要一个函数是pygame.trsnsform.rotate(),没错,它可以用来旋转位图,需要传两个参数:图像,图像旋转角度

import sys,pygame,math,random
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)

#定义一个warp_angle(angle)函数,返回0~360之间的角度
def warp_angle(angle):
    return angle % 360

'''
radius是半径
angle是角度默认值
pos代表图像坐标
'''
radius = 250
angle = 0.0
pos = Point(0,0)
old_pos = Point(0,0)

pygame.init()
screen = pygame.display.set_mode((800,600))
title = pygame.display.set_caption("星空")

#创建字体
font = pygame.font.Font(None,18)

#加载位图,convert_alpha:使前景对象透明
space = pygame.image.load("space.png").convert_alpha()
#加载地球位图
planet = pygame.image.load("planet2.png").convert_alpha()
#加载超人位图
superman = pygame.image.load("military.png").convert_alpha()

#获取超人位图的宽和高
width,height = superman.get_size()
#缩放机器人
superman = pygame.transform.smoothscale(superman,(width//2,height//2))

while True:
    for event in pygame.event.get():
        if event.type == QUIT:
            pygame.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))

    '''
    |-- warp_angle是返回0~360的角度,而此代码是360度逐次减0.5度,来控制机器人移动的速度
    |-- pos.x,pos.y:图像移动的正反坐标
    |-- math.sin:返回弧度的正弦值,数值在-1,1之间
    |-- math.cos:返回弧度的余弦值,数值在-1,1之间
    |-- math.radians:角度转换成弧度,返回的是一个数值
    '''
    angle = warp_angle(angle - 0.5)
    #print("====",angle)
    pos.x = math.sin(math.radians(angle))*radius
    pos.y = math.cos(math.radians(angle))*radius

    '''
    |-- 旋转飞船
    |-- delta_x,delta_y表示x,y轴之间的距离
    |-- math.atan2()表示返回给定的 X 及 Y 坐标值的反正切值
    |-- rangled表示图像旋转角度
    |-- math.degrees():将弧度转换成角度
    |-- pygame.transform.rotate():用来旋转位图,需要传入的两个参数:图像,角度
    '''
    delta_x = (pos.x - old_pos.x)
    delta_y = (pos.y - old_pos.y)
    rangle = math.atan2(delta_y,delta_x)
    rangled = warp_angle(-math.degrees(rangle))
    superman_rotate = pygame.transform.rotate(superman,rangled)

    #获取飞船的宽和高
    width,height = superman_rotate.get_size()
    #绘制飞船,通过第二个参数的x,y轴移动来控制移动的正向还是反向
    screen.blit(superman_rotate,(300+pos.x-width//2,250+pos.y-height//2))

    pygame.display.update()
原文地址:https://www.cnblogs.com/frankruby/p/10634935.html