《从零开始PYTHON3》第十五讲

虽然看起来绘图和音乐并不相关,但是听过了上一讲的内容你一定知道,这是游戏编程中四个需要处理内容的两部分,这两部分必须同时、并行的处理,不能因为某一项计算的拖延,导致另外一方程序的停滞。要知道人对声音的断续和游戏的卡顿是很敏感的。

在Pygame中进行并行处理的主要手段,一是Pygame中的各种函数,大多是不等待工作完成,只要工作开始进行,就返回主程序,等待下一条命令,而任务会在看不到的后端继续执行,并不停止;另外则是各个并行的任务之间,会通过“消息事件”的方式跟主程序沟通,从而让主程序能够统一调度各项任务的进程。

这是复习上一讲的内容。

并行:指的是在硬件的帮助下,多个任务同时进行,互不影响,最终完成任务的过程。完成的时间取决于最慢的任务。这个硬件帮助,通常是指多核CPU、显卡计算配合CPU计算以及数据传输中的多通道。

串行:指的是完成一项工作,才进行另外一项工作,最后完成的时间是所有任务完成的总和。

游戏绘图

绘图模式

同我们前面学过的科学绘图和海龟绘图相比,游戏绘图在绘图的模式上有较大的区别。

传统程序绘图是顺序方式,每画一笔可以认为这一笔一直都在,直到程序退出或者擦除画面。你可以回忆一下我们在科学绘图和海龟绘图时候所学习的内容。

游戏绘图更类似拍照,一个个角色进入画面,摆好姿态,等待快门按下,这样完成一帧。随后会根据游戏逻辑和输入,调整画面,再拍摄下一张,这样至少达到每秒30帧,才能达成一个动画的效果。

从逻辑上讲,游戏绘图采用的方式似乎应当慢于传统方式。实际上因为这种方式能够得到CPU/显卡以及很多新技术的帮助。很多绘图任务发出后,实际上是进入显卡完成运算的,这时候CPU已经在处理其它内容。这样并行计算的方式,再加上显卡更善于处理图形、图像相关的工作。最终这种方式效率才会高很多。

我们前面讲的科学绘图和海龟绘图,新版本的实现有很多是使用游戏绘图的方式,通过并行的方式完成计算。但因为用户编程接口的兼容性,所以至少从我们编程时所感受到的方式上,还是串行处理的。

坐标系

科技绘图(matplotlib):采用数学坐标系,同显示设备无关,通常原点在屏幕中心。绘图包会自动调整数学坐标系跟窗口分辨率的比例(窗口分辨率是可以在程序中设置的,只是前面的学习中我们基本使用了默认的设置),从而让显示效果最优。

海龟绘图(turtle):原点在窗口中心,跟数学坐标系方向相同,坐标是同显示设备分辨率相关的,但绘图的操作通常是用几何的方式,所以不用太担心显示设备本身的分辨率。

游戏绘图(pygame):原点在窗口左上角,x轴坐标向右侧增大,y轴坐标向下增大,最大值为屏幕分辨率。还有一些更底层的游戏绘图引擎,比如OpenGL会使用统一的1.0*1.0坐标系,然后在不同设备上映射成不同的分辨率。我们本讲的课程采用Pygame所使用的坐标体系。

颜色

在计算机中常用的颜色分类有这么几种:

二值图:仅有黑白两色,比如字体库

灰度图:0-255,共256级灰度,比如黑白照片

伪彩色:0-255,共256种颜色,比如GIF动图、微信表情

真彩色:RGB红绿蓝三色图,每种颜色0-255,按二进制计算,也称为24位色

32位真彩色:RGBA四色,除了红绿蓝之外,A代表透明度,能表现更多的多种颜色互动、遮盖的效果

这些颜色格式Pygame都支持,但最新的游戏通常都已经采用32位真彩色的方式。

在游戏的显示过程中,如果不考虑透明度A的部分,所有颜色都是使用“三基色”来表达的,也就是红、绿、蓝,每个颜色分量可以的取值分为是0到255。0表示完全没有这个颜色,255表示这个颜色最强。当三个颜色都是0的时候显示为纯黑。当三个颜色都是255的时候,显示为纯白。

因为是三个颜色,所以通常的颜色都是使用三个值的“元组”的形式表达的。元组我们第九讲学过了。下面举一些例子,我们在程序中,预定义几个常用的颜色:

#黑色

BLACK =(0, 0, 0)

#白色

WHITE = (255, 255, 255)

#红色

RED = (255,0,0)

#绿色

GREEN =(0,255,0)

#蓝色

BLUE=(0, 0,255)

Pygame程序一般结构

上一讲和本讲开始我们都已经讲过,Pygame的主要工作模式是并行处理,其结构同传统的串行程序就必然有一些差别。这个差别并不大,很类似我们学习互联网编程时候的框架模板,即使不够理解,照抄下来用就可以。下面就是一个一般的结构:

#此代码仅为架构示例,没有具体功能

#作者:Andrew

#引入扩展库

import pygame

width=1280

heigh=556

color=32

#pygame初始化

pygame.display.init()

#创建一个绘图平面,后面参数为设定的窗口分辨率及颜色

screen = pygame.display.set_mode((width, heigh), 0, color)

#声音系统初始化

pygame.mixer.init()

#1...其它自身初始化项目...

#是否要退出标志

requireQuit = False

#程序主循环,在有退出申请之前一直循环

while not requireQuit:

#2...自己的绘图部分...

#处理所有事件

for event in pygame.event.get():

#用户从窗口菜单选择退出

if event.type == pygame.QUIT:

requireQuit=True

break

#用户是否有按键?

elif event.type == pygame.KEYUP:

#为了可靠,只处理按键松开的动作

if event.key in [pygame.K_q,pygame.K_ESCAPE]:

#用户按了q键

requireQuit=True

break

#3...其它事件处理...

#4...其它程序逻辑...

#优雅的退出,释放各种资源

pygame.mixer.quit()

pygame.display.quit()

上面的代码中,并不包含任何功能,只是一个模板。通常没有特殊需求的程序,只要编写其中的#1/#2/#3/#4部分的程序就可以。

为了程序更便于理解和阅读,还可以对上面的结构进一步的优化,比如把需要继续编程的部分函数化。当然函数化的时候要考虑到变量作用域,避免增加不必要的麻烦。

常用绘图功能

我们介绍几个常用的绘图功能,然后就可以代入到上面的模板代码中来实验了。

一般的几何图形绘制功能,都汇总在pygame.draw包中,比如:

画圆:pygame.draw.circle

矩形:pygame.draw.rect

多边形:pygame.draw.polygon

画线:pygame.draw.line

画弧线:pygame.draw.arc

画矩形:pygame.draw.rect

正常情况下,pygame的显示是在一个窗口中显示的(也可以根据需要设置全屏),窗口可以设置一个标题来表示你当前做的工作,这个命令是:

#设置窗口标题

pygame.display.set_caption('Hello World!')

用于显示的窗口默认是没有颜色,也就是黑色,可以设置窗口的底色:

#用白色填充窗口,既是设置窗口底色,也是把窗口清空,重新绘制下一帧

#pygame绘图是像摄影师拍摄每一帧的照片,还记得吗?

screen.fill(WHITE)

还有一些函数的功能,可以参考help(pygame)。help也可以查看某一个具体的子包,比如:help(pygame.draw)。下面我们通过程序示例代码来看看刚才讲的这些功能:

#我们定义一个函数,来完成画面的绘制

#避免过多的语句挤入到主循环中影响程序的结构

def draw(screen):

#2...自己的绘图部分...

#用白色填充窗口

screen.fill(WHITE)

#画多边形

pygame.draw.polygon(screen, GREEN, ((146, 0), (291, 106), (236, 277), (56, 277), (0, 106)))

#画线

pygame.draw.line(screen, BLUE, (60, 60), (120, 60), 4)

pygame.draw.line(screen, BLUE, (120, 60), (60, 120))

pygame.draw.line(screen, BLUE, (60, 120), (120, 120), 4)

#画圆

pygame.draw.circle(screen, BLUE, (300, 50), 20, 0)

#椭圆

pygame.draw.ellipse(screen, RED, (300, 250, 40, 80), 1)

#矩形

pygame.draw.rect(screen, RED, (200, 150, 100, 50))

#使用直接操作图形缓存的方法在右下角画四个点

#这个功能比较底层,除非需要很专业的操作一般用不到

pixObj = pygame.PixelArray(screen)

pixObj[480][380] = BLACK

pixObj[482][382] = BLACK

pixObj[484][384] = BLACK

pixObj[486][386] = BLACK

pixObj[488][388] = BLACK

del pixObj

#显示在屏幕上

pygame.display.update()

上面代码只列出了自己定义的绘图部分,其它部分需要融合到框架模板中去。完整的代码可以参考code2.py源文件。

下面的图片是绘制的效果:

程序运行之后,可以按q键退出程序,也可以从菜单选择Quit来退出。

老话题,想掌握学习的知识,只能多练习。

请在上面程序的基础,调整各项参数,增加或者减少绘图的指令,自己练练。看看谁绘制的画面最好看。

挑战

我们已经掌握了基本的绘图知识。可惜游戏没有这么简单,至少游戏需要是以动画的方式为基础,玩起来才会感觉到真实。

我们早已经说过,现代的游戏开发已经是一个团队配合的产物。不管想达成什么样的动画,一般都需要有美工专业人员完成原画的设计制作,提供成素材,随后才能由程序人员来完成让画面动起来的工作。

我们这里已经从网上下载了几个素材:

上面包含两个动画元素的素材,上面部分是一只小地鼠,仔细观察这四副图片,他们的脚在不同的位置。四张图片代表动画中的4帧,连续起来,就会出现小地鼠在跑的样子。

下面的箭比较简单,只需要一帧,箭的图片出现在屏幕不同的位置上,感觉起来就是箭飞到了那个位置。

如果你还记得第一讲的演示,你应当能看出来这些素材出自游戏Bunny。

下面我们编程序,来实现小地鼠从屏幕右侧快速跑到屏幕左侧的动画,和羽箭从屏幕左侧飞到右侧的动画。

#使用pygame对图片处理的功能,载入图片到变量

arrow = pygame.image.load("bullet.png")

#地鼠因为包含四帧,我们使用列表格式

badguy = [pygame.image.load("badguy.png"),

pygame.image.load("badguy2.png"),

pygame.image.load("badguy3.png"),

pygame.image.load("badguy4.png")]

#动画动起来,需要一帧帧的变化,下面的变量用于指当前显示的第几帧

badguyIndex = 0

#定义x1/y1和x2/y2两组坐标,

#分别用于表示羽箭和小地鼠在屏幕上的位置

#坐标系还记得吧?左上角是0,y向下变大,x向右变大

x1=0 #羽箭从左侧飞到右侧,开始x坐标是0,表示在左侧

y1=heigh/3#y坐标,在窗口上面的1/3位置

x2=width #小地鼠一开始在屏幕右侧

y2=heigh/3*2

#定义一个函数,用于计算向左移动时候下一个位置的坐标

def moveLeft(x):

x -= dx

if x < 0:

x += width

return x

#定义一个函数,用于计算向右移动时候下一个位置的坐标

def moveRight(x):

return (x+dx) % width

#绘制的函数

def draw(screen):

screen.fill(WHITE) #白色填充窗口

screen.blit(arrow,(x1,y1)) #绘制羽箭

screen.blit(badguy[badguyIndex],(x2,y2)) #绘制地鼠

#显示在屏幕上

pygame.display.update()

...

#4...其它程序逻辑...

#移动元素坐标位置的工作,应当放到“其它程序逻辑”中

#这样的方式使得程序逻辑,特别是绘图的逻辑干净易读

x2 = moveLeft(x2)

x1 = moveRight(x1)

badguyIndex = (badguyIndex+1) % 4 #地鼠下次使用下一帧

上面代码依然去掉了同前面重复的部分,完整的代码请参考code3.py程序。现在运行一下看看吧:

截图无法展示动态,你一定要亲自动手来试试,才能看到效果。关键点:

屏幕绘制部分,根据坐标值,绘制指定的图片。

在程序逻辑运算的部分,计算下一帧画面的时候,小地鼠和羽箭在屏幕上的新位置。以及地鼠的动画图片下次绘制采用哪一帧图片。

练习时间

修改上面程序的参数,让地鼠的速度加快一倍,而箭的速度保持不变

上一讲中的mp3播放器,请实现在播放器播放的时候,显示一张歌曲的封面图片

本讲小结

本讲介绍了使用pygame绘制基本几何图形和绘制简单动画的方式

绘画、动画其实都不难,重要的是画面的设计,只要有了连续的图片,就可以用数组的方式来实现连续动画

对于一个规模越来越大的程序,想少出错、容易维护,就需要代码尽量规范、简洁、函数化

本课程至此就全部结束了。作为面对刚刚接触计算机软件编程的初学者课程,我们使用了15讲的篇幅,从Python的安装、命令行的互动计算开始,讲述了数学计算、程序逻辑控制、常用数据类型等基本Python编程的知识。接着又针对科技绘图、互联网编程、游戏编程等专业领域的应用做了讲解。时间所限,我们并没有能够特别深入对所有话题更进一步的学习。课程也没有对当前流行的面向对象编程做讲解,这些有待于学习者在对初级内容有了一段时间的熟悉和体验之后,继续深入学习。

希望各位同学能在当前学习的基础上,根据自己的爱好和自己的日常学习、生活需要。有选择的做进一步学习,让Python成为我们学习的好助手,生活的得力工具。

水平所限,课程内容难免疏漏、错误,敬请谅解并欢迎指正。

练习答案

请参考代码:mp3Player1.py

连载正文结束,所有程序源码及练习答案将会整理后在下一期提供下载。

python3从零开始学习_从零开始学习PYTHON3讲义(十五)让画面动起来相关推荐

  1. 零基础带你学习MySQL—unique 唯一(二十五)

    零基础带你学习MySQL-unique 唯一(二十五) unqiue 使用细节 如果没有指定 not null 则 unique 字段可以有多个 null 如果一个列(字段) 是 unique not ...

  2. 分类 迁移学习_迁移学习时间序列分类

    迁移学习时间序列分类 题目: Transfer learning for time series classification 作者: Hassan Ismail Fawaz, Germain For ...

  3. 元学习 迁移学习_元学习就是您所需要的

    元学习 迁移学习 Update: This post is part of a blog series on Meta-Learning that I'm working on. Check out ...

  4. 度量学习 流形学习_流形学习2

    度量学习 流形学习 潜图深度学习 (Deep learning with latent graphs) TL;DR: Graph neural networks exploit relational ...

  5. 训练深度学习_深度学习训练tricks整理1

    深度学习训练tricks整理1 环境:pytorch1.4.0 + Ubuntu16.04 参考: 数据增强策略(一)​mp.weixin.qq.com https://zhuanlan.zhihu. ...

  6. 保证为正数 深度学习_深度学习:让数学课堂学习真正发生

    在21世纪核心素养中,深度学习能力是公民必须具备的生活和工作能力,发展深度学习是当代学习科学的重要举措,是深度加工知识信息.提高学习效率的有效途径.深度学习也称深层学习,是美国学者Ference Ma ...

  7. 25 linux ndk 头文件_正点原子Linux第二十五章RTC实时时钟实验

    1)资料下载:点击资料即可下载 2)对正点原子Linux感兴趣的同学可以加群讨论:935446741 3)关注正点原子公众号,获取最新资料更新 第二十五章RTC实时时钟实验 实时时钟是很常用的一个外设 ...

  8. [转载]总结-七大人生工具_李晓瑞_廊坊师范提高班十五期_新浪博客

    高效能人士的好习惯,我们要多实践. 原文地址:总结-七大人生工具作者:李英杰-廊坊师院提高班十五期 一.SWOT分析法 Strengths:优势 Weaknesses:劣势 Opportunities ...

  9. [转载]为什么有人工作10年仍不是专家,有人2年就足够卓越了?_李晓瑞_廊坊师范提高班十五期_新浪博客...

    原文地址:为什么有人工作10年仍不是专家,有人2年就足够卓越了?作者:张铎-廊坊师院提高班十五期 如何成为一个领域的专家? 有人说主要靠经验,有人说靠天赋,但是大量的研究发现:不论是经验还是天赋,都不 ...

最新文章

  1. noip2018——题解总结
  2. “霸榜CLUE” ,刚刚发布的业界最大中文NLP预训练模型有多强?
  3. php数据库数据分割,使用PHP将分隔的值文件导入数据库时??,...
  4. Magnification API-Windows放大镜
  5. linux bzip2压缩文件,linux bzip2命令压缩或解压缩bzip2文件
  6. js中继承的几种方式
  7. PR转场 700+抖音视频转场素材包含PR调色预设和音效素材
  8. php递归还原,PHP递归调用的小技巧讲解-PHP递归返回值时出现的问题解...-PHP递归算法的详细示例分析_169IT.COM...
  9. 提速数字化转型,云徙科技批量建设数字中台
  10. 关于Allele(等位基因)的理解
  11. 如何使用unirest
  12. 账户信息不存在的问题
  13. word的xml文件中空白页和换页
  14. ffmpeg截取视频片段命令优化
  15. mysql group by个数_mysql 统计 group by 之后的 group 的个数
  16. 15.unsafe类的CAS是怎么保证原子性的?
  17. Dweb3.0的核心基础设施?NA(Nirvana)Chain加速开凿链上域名流量通道
  18. 卫星导航定位技术二:由星历参数求解卫星时空位置
  19. 垂直摄影——pix4d 4.4.10软件(附软件安装包)
  20. myrio与fpga编程_NI嵌入式创新应用开发平台myRIO介绍

热门文章

  1. 鸿蒙系统公布名单,鸿蒙系统首批升级名单公布_鸿蒙系统首批升级机型
  2. node.js打包环境部署CentOS7.4
  3. 2020成考C语言答案,2020年_优学院_C语言程序设计_章节答案
  4. python find函数 和index的区别_python list的index()和find()的实现
  5. 华为内部存储转sd卡_华为tit al00怎么将手机存储内容转移到sd卡
  6. tiny core linux ftp,tinycore 的基本搭建,开机时间只需要1-3秒
  7. STM32 HAL库 UART 串口读写功能笔记
  8. 部署knight项目
  9. HDU-2448 Mining Station on the Sea
  10. 征稿 | MIUA 2022 医学影像理解与分析会议