• 【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()
  • 相关阅读:
    记账本程序三
    记账本程序二
    记账本程序一
    <<人月神话>>笔记1
    库存管理系统
    Java实现数据库
    第九周作业
    四则运算总结
    java异常处理
    第十周学习进度报告
  • 原文地址:https://www.cnblogs.com/frankruby/p/10634935.html
Copyright © 2020-2023  润新知