Python不能做游戏?Pygame中的对象你了解吗?

Posted 易果啥笔

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python不能做游戏?Pygame中的对象你了解吗?相关的知识,希望对你有一定的参考价值。

        嗨喽~小伙伴们早上好,中午好,晚上好呀,        

        前面(点击跳转​​​​​​​)我们学习了第一个Pygame程序,接着,我们来了解Pygame中最为常用的几个对象。学完今天的内容,我们就可以开发一个稍微复杂一点的游戏了。

一. Surface 对象

        Surface对象表示的是一个矩形的2D图像,这个图像,实际上是由非常多的像素点组成的,比如一个(300px , 400px)的Surface对象,这个矩形2D图像300*400个像素点组成。可以通过调用Pygame的绘制函数,来对一个Surface对象的某些区域进行填充,从而达到修改整个2D图像的效果。需要注意的是,窗口的边框,标题栏,按钮并不属于Surface对象的一部分

        我们把通过pygame.display.set_mode() 函数返回的Surface对象,称为显示Surface对象,绘制到显示Surface对象上的任何内容,在调用pygame.display.update()函数后,都会显示到窗口上

        游戏制作中,经常要将几个不同的内容绘制到一个Surface对象中,在游戏的某一次循环里,调用pygame.display.update()函数后,这个Surface对象包含的所有内容都会绘制到屏幕上,这个Surface对象(会频繁更新)被显示到屏幕上的次数,称为帧数。一般而言,计算机的运行速度很快,游戏中一般采用每秒30(60,90)帧,即30(60,90)FPS,这叫作帧速率,简称帧率。此处30 FPS的含义是,1s内,游戏界面会被更新30次

二. Color对象

        颜色在游戏设计中是必不可少的一部分。在计算机显示器上,以光的颜色为基础,由于光有三原色-----绿,通过将这三种颜色按不同比例混合,可以形成任何其他的颜色。

        在Pygame中,我们使用三个整数的元组 (a,b,c) 来表示任何一种颜色,第一个整数a表示颜色中有多少红色,取值为0~255,同理,第二个整数对应绿色,第三个整数对应蓝色。如(0,0,255)表示蓝色,(0,255,0)表示绿色,(128,128,128)三色混合后会得到灰色

        Pygame中创建颜色主要有两种方式。一是利用3个0~255的整数组成的元组,二是利用pygame.Color对象

        我们用代码来演示一下:


import sys,pygame
from pygame.locals import *

#color      R    G    B

BLACK = (   0,   0,   0)
WHITE = ( 255, 255, 255)
BLUE  = pygame.Color(   0,   0, 255)  # 与前面的颜色创建方式效果相同
GREEN = pygame.Color(   0, 255,   0)

pygame.init()
DISPLAY_SURF = pygame.display.set_mode((400,300))
# 将整个显示Surface对象填充为白色
DISPLAY_SURF.fill(WHITE)
# 在Surface对象上,从左上角坐标(0,0)开始,绘制一个往右100px,往下100px的矩形2D区域并填充为黑色
pygame.draw.rect(DISPLAY_SURF, BLACK,(0,0,100,100))
# 在Surface对象上,从左上角坐标(100,0)开始,绘制一个往右100px,往下100px的矩形2D区域并填充为绿色
pygame.draw.rect(DISPLAY_SURF,GREEN,(100,0,100,100))

pygame.display.set_caption("Hello World~")

while True:
    for event in pygame.event.get():
        if event.type == QUIT:
            pygame.quit()
            sys.exit()
    # 将Surface对象更新到屏幕上显示
    pygame.display.update()

        运行结果:

  

        上面用到了一个绘制函数pygame.draw.rect(Surface,Color,(x,y,a,b)),它会在Surface对象上绘制一个矩形区域,第三个参数是一个四元元组,其前两个参数表明矩形区域左上角的坐标(pygame中的XOY坐标,以窗口左上角为原点(0,0),向右为x坐标,向下为y坐标),后两个参数表明矩形区域的大小,单位为像素px。

        此外,颜色除了各种颜色的混合比例之外,还有一个特征,那就是颜色的透明度。Pygame允许在颜色的三元元组基础之上加入第四个整数(alpha value,范围0~255),用于表示颜色的透明度。0表示完全透明,255表示完全不透明

        为了能够使用透明颜色来进行绘制,Pygame要求必须使用convert_alpha()方法来创建一个Surface对象。也就是说,能够使用透明颜色来进行绘制的Surface对象,必须用convert_alpha()方法创建。比如上面的代码,我们加上一句:

Alpha_Surface = DISPLAY_SURF.convert_alpha()

        上述代码表明可以Alpha_Surface对象上可以使用透明颜色绘制,而DISPLAY_SURF上不行。

三. Rect对象

        与颜色一样,Pygame提供两种方式创建一个矩形区域。

        一是利用四元元组(x,y,a,b) 

  • x :矩形区域左上角的x坐标
  • y :矩形区域左上角的y坐标
  • a :矩形区域的宽度(以像素为单位)
  • b :矩形区域的高度(以像素为单位)

        二是创建pygame.Rect对象,如:

rect = pygame.Rect(100,200,100,200) # 等同于 rect = (100,200,100,200)

        与颜色类似,上述“等同”的含义是,如果有一个针对矩形区域的函数参数的话,那么既可以传入一个四元元组,也可以传入一个pygame.Rect对象(底层实现是重载) 。

         pygame.Rect对象有许多属性,现将常用的列举如下:

Rect对象的属性
属性含义(返回值)
Rect.left矩形区域最左边的X坐标(int类型)
Rect.right矩形区域最右边的X坐标(int类型)
Rect.top矩形区域顶部的Y坐标(int类型)
Rect.bottom矩形区域底部的Y坐标(int类型)
Rect.centerx矩形区域中央的X坐标(int类型)
Rect.centery矩形区域中央的Y坐标(int类型)
Rect.width矩形区域的宽度(int类型)
Rect.height矩形区域的高度(int类型)
Rect.size矩形区域大小的元组:(width,height)
Rect.topleft元组(int类型):(top,left)
Rect.topright元组(int类型):(top,right)
Rect.bottomleft元组(int类型):(bottom,left)
Rect.bottomright元组(int类型):(bottom,right)
Rect.midleft元组(int类型):(left,centery)
Rect.midright元组(int类型):(right,centery)
Rect.midtop元组(int类型):(centerx,top)
Rect.midbottom元组(int类型):(centerx,bottom)

 四. 绘制函数

        有了前面知识的铺垫,我们就可以用Pygame提供的绘制函数来绘制我们想要绘制的图形了。

        先上代码,在代码中注释了每个绘制函数参数的具体含义


import pygame, sys
from pygame.locals import *

# 初始化pygame库
pygame.init()

# 创建窗口
DISPLAY_SURF = pygame.display.set_mode((400, 300), 0, 32)
pygame.display.set_caption('Drawing')

# 设置颜色
BLACK = (  0,   0,   0)
WHITE = (255, 255, 255)
RED   = (255,   0,   0)
GREEN = (  0, 255,   0)
BLUE  = (  0,   0, 255)

# 绘制图形

# 填充为白色
DISPLAY_SURF.fill(WHITE)


'''
    pygame.draw.polygon(Surface,Color,pointlist,thickness)
    在DISPLAY_SURF上,画一个多边形,
    第三个参数为多边形顶点坐标顺次构成的元组,
    最后的1(px)为多边形的粗细,忽略此参数或设为0,Pygame会视为用颜色填充此多边形
'''
pygame.draw.polygon(DISPLAY_SURF, GREEN, ((146, 0), (291, 106), (236, 277), (56, 277), (0, 106)),1)



'''
    pygame.draw.line(Surface,Color,start_point,end_point,thickness)
    在DISPLAY_SURF上,画一条线,
    (60,60),(120,60)分别为线的起始坐标,终点坐标,
    4(px)为线条粗细,单位为像素
'''
pygame.draw.line(DISPLAY_SURF, BLUE, (60, 60), (120, 60), 4)
pygame.draw.line(DISPLAY_SURF, BLUE, (120, 60), (60, 120), 1)
pygame.draw.line(DISPLAY_SURF, BLUE, (60, 120), (120, 120), 4)


'''
    pygame.draw.circle(Surface,Color,center_point,radius,thickness)
    在DISPLAY_SURF上,
    画一个圆,
    (300,50)为圆心的坐标,
    20(px)为圆的半径,
    0(px)指明圆的粗细,忽略此参数或者设为0,则Pygame默认将圆用颜色填充
    
'''
pygame.draw.circle(DISPLAY_SURF, BLUE, (300, 50), 20, 0)



'''
    pygame.draw.ellipse(Surface,Color,bounding_rectangle,thickness)
    画一个椭圆,由于一个矩形可以唯一的确定一个椭圆,
    故将其绑定一个Rect对象的矩形区域,
    1(px)为椭圆的粗细,忽略此参数或者设为0,则Pygame默认将椭圆用颜色填充
'''
pygame.draw.ellipse(DISPLAY_SURF, RED, (300, 200, 40, 80), 1)


'''
    pygame.draw.rect(Surface,Color,rectangle_tuple,thickness)
    画一个矩形,
    (200, 150, 100, 50)表示矩形左上角坐标为(200,150),宽度100px,高度50px
'''
pygame.draw.rect(DISPLAY_SURF, RED, (200, 150, 100, 50))

# run the game loop
while True:
    for event in pygame.event.get():
        if event.type == QUIT:
            pygame.quit()
            sys.exit()
    pygame.display.update()

         运行结果:

        代码中对每个绘制函数都有详细的注释,此处就不再赘述了。 

四. 制作动画 && pygame.time.Clock 对象

         动画是一个游戏的灵魂,如何产生一幅动的画面呢?

        前面聊过,while循环里如果设置帧率为30FPS,则屏幕上的画面会每秒更新30次,也就是说,Pygame会将Surface对象以每秒30次的速度不断重新绘制到屏幕上。

        这样,如果在每次绘制到屏幕之前,对Surface对象上的内容做略微修改,这样不就产生“动的”画面了吗?

        现在的问题是,我们如何控制Surface对象以每秒30次的速度绘制到屏幕上呢?

        这个不用我们考虑,Pygame提供了一个专门用于控制帧率的类 pygame.time.Clock。由于计算机运行速度极快,容易导致游戏速度过快,玩家的体验不太好,因而这个对象可以确保游戏以某一个最大的帧率运行,但有时,如果是大型游戏,代码量过多,以至于无法正常运行,来频繁的绘制到屏幕上,会使得帧率下降。

        Clock对象的用法:首先,创建Clock对象:

fpsClock = pygame.time.Clock()

        Clock对象会在游戏的每一次循环上都设置一个小小的暂停,确保游戏不会运行得太快。

        每次循坏的最后,调用pygame.display.update()方法将Surface对象绘制到屏幕上之后,应调用Clock对象的 tick() 方法:

# run the game loop
while True:
    for event in pygame.event.get():
        if event.type == QUIT:
            pygame.quit()
            sys.exit()
    pygame.display.update()
    # 调用tick(),传入30FPS
    fpsClock.tick(FPS)

        这样会使得,游戏以最大帧率30FPS运行。 

        借invpy官网的一段代码,我们演示一个简单的“猫移动”的动画,我们需要一张“猫”的图片:

        代码如下:


import pygame, sys
from pygame.locals import *

pygame.init()

# 帧率设置为30FPS
FPS = 30

# 创建Clock对象
fpsClock = pygame.time.Clock()

# 创建窗口
DISPLAY_SURF = pygame.display.set_mode((400, 300))
pygame.display.set_caption('Animation')

WHITE = (255, 255, 255)
# 加载图片
catImg = pygame.image.load('cat.png')
CAT_X = 10
CAT_Y = 10

# 设置猫初始往右移动
direction = 'right'

while True:  # main game loop

    DISPLAY_SURF.fill(WHITE)

    # 简单地方向控制
    if direction == 'right':
        CAT_X += 5
        if CAT_X == 280:
            direction = 'down'
    elif direction == 'down':
        CAT_Y += 5
        if CAT_Y == 220:
            direction = 'left'
    elif direction == 'left':
        CAT_X -= 5
        if CAT_X == 10:
            direction = 'up'
    elif direction == 'up':
        CAT_Y -= 5
        if CAT_Y == 10:
            direction = 'right'

    # 利用blit()方法将图片复制到Surface对象中
    # 图片的左上角位于(CAT_X, CAT_Y)
    DISPLAY_SURF.blit(catImg, (CAT_X, CAT_Y))

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

    # 将Surface对象绘制到屏幕上
    pygame.display.update()
    # 设置帧率:30FPS
    fpsClock.tick(FPS)

        运行结果:

        到这,Pygame的基础知识就介绍完了,内容也许比较多,小伙伴们多多理解和实践。下一章,我们开始动手做一个稍微复杂一点的游戏:

        Python不能做游戏?游戏实战之-----《ink spill》​​​​​​​

        最后,喜欢的小伙伴们点个赞鼓励支持一下吧~

       

       

以上是关于Python不能做游戏?Pygame中的对象你了解吗?的主要内容,如果未能解决你的问题,请参考以下文章

用pygame,做一个小小小小小........游戏

用python写游戏,pyqt与pygame可以交互吗?

一分钟带你了解Pygame

手把手教你使用Python写贪吃蛇游戏(pygame)

一篇文章带你了解Python中的游戏开发模块pyglet

一篇文章带你了解Python中的游戏开发模块pyglet