python和pygame,用Python和Pygame写游戏-从入门到精通(8)

是时候让我们的游戏活泼起来了。电脑游戏和桌面游戏的一个巨大差别,想来就是这个“动”。伟大的哲学家们告诉我们,“运动是绝对的,静止时相对的”,同样的在游戏中,只有活动起来,游戏才会拥有生命,否则和看连环画有什么差别呢?

这几章讲述的东西需要一些线性代数的知识,好吧有些夸张,如果你不明白,完全没关系,高中物理的知识就绝对足够了(或者说嫌多了)!

0fc3c6be963a2b94b4ee81b444104afe.png

现实生活中的物体,运动起来总是按照某种规律的(去问问牛顿就知道了),而游戏中,有些动作就可以非常的不靠谱,比如吃豆人,大嘴巴永远以恒定的速度前进,可以瞬间转身或停止,要知道,这可是逆天的行为……现在的游戏中,制作者总是尽量的把运动做的和现实贴近(尤其是赛车游戏等),一辆车的运动,可能是上百种力同时作用的结果。不过幸好,我们只要知道一些基础的东西,很多运动和力的计算,都有现成的代码供我们使用。

理解帧率

这是一个被说烂了的词,FPS(Frame Per Second)是游戏和硬件间较量的永恒话题,我也不想多插话了,相信玩游戏的朋友都知道。

只是记住几个常用的量:一般的电视画面是24FPS;30FPS基本可以给玩家提供流程的体验了;LCD的话,60FPS是常用的刷新率,所以你的游戏的帧率再高也就没什么意义了;而绝大多数地球人都无法分辨70FPS以上的画面了!

直线运动

我们先来看一下初中一开始就学习的直线运动,我们让一开始的程序中出现的那条鱼自己动起来~

Python

background_image_filename = 'sushiplate.jpg'

sprite_image_filename = 'fugu.png'

import pygame

from pygame.locals import *

from sys import exit

pygame.init()

screen = pygame.display.set_mode((640, 480), 0, 32)

background = pygame.image.load(background_image_filename).convert()

sprite = pygame.image.load(sprite_image_filename)

# sprite的起始x坐标

x = 0.

while True:

for event in pygame.event.get():

if event.type == QUIT:

exit()

screen.blit(background, (0,0))

screen.blit(sprite, (x, 100))

x+= 10. #如果你的机器性能太好以至于看不清,可以把这个数字改小一些

# 如果移动出屏幕了,就搬到开始位置继续

if x > 640.:

x = 0.

pygame.display.update()

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

background_image_filename='sushiplate.jpg'

sprite_image_filename='fugu.png'

importpygame

frompygame.localsimport*

fromsysimportexit

pygame.init()

screen=pygame.display.set_mode((640,480),0,32)

background=pygame.image.load(background_image_filename).convert()

sprite=pygame.image.load(sprite_image_filename)

# sprite的起始x坐标

x=0.

whileTrue:

foreventinpygame.event.get():

ifevent.type==QUIT:

exit()

screen.blit(background,(0,0))

screen.blit(sprite,(x,100))

x+=10.#如果你的机器性能太好以至于看不清,可以把这个数字改小一些

# 如果移动出屏幕了,就搬到开始位置继续

ifx>640.:

x=0.

pygame.display.update()

我想你应该需要调节一下“x += 10.”来让这条鱼游的自然一点,不过,这个动画的帧率是多少的?在这个情形下,动画很简单,所以应该会很快;而有些时候动画元素很多,速度就会慢下来。这可不是我们想看到的!

关于时间

有一个解决上述问题的方法,就是让我们的动画基于时间运作,我们需要知道上一个画面到现在经过了多少时间,然后我们才能决定是否开始绘制下一幅。pygame.time模块给我们提供了一个Clock的对象,使我们可以轻易做到这一些:

Python

clock = pygame.time.Clock()

time_passed = clock.tick()

time_passed = clock.tick(30)

1

2

3

clock=pygame.time.Clock()

time_passed=clock.tick()

time_passed=clock.tick(30)

第一行初始化了一个Clock对象;第二行的意识是返回一个上次调用的时间(以毫秒计);第三行非常有用,在每一个循环中加上它,那么给tick方法加上的参数就成为了游戏绘制的最大帧率,这样的话,游戏就不会用掉你所有的CPU资源了!但是这仅仅是“最大帧率”,并不能代表用户看到的就是这个数字,有些时候机器性能不足,或者动画太复杂,实际的帧率达不到这个值,我们需要一种更有效的手段来控制我们的动画效果。

为了使得在不同机器上有着一致的效果,我们其实是需要给定物体(我们把这个物体叫做精灵,Sprite)恒定的速度。这样的话,从起点到终点的时间点是一样的,最终的效果也就相同了,所差别的,只是流畅度。看下面的图试着理解一下~

514ecef2cb1843a5a7a892761d0bfae8.png

我们把上面的结论实际试用一下,假设让我们的小鱼儿每秒游动250像素,这样游动一个屏幕差不多需要2.56秒。我们就需要知道,从上一帧开始到现在,小鱼应该游动了多少像素,这个算法很简单,速度*时间就行了,也就是250 * time_passed_second。不过我们刚刚得到的time_passed是毫秒,不要忘了除以1000.0,当然我们也能假设小鱼每毫秒游动0.25像素,这样就可以直接乘了,不过这样的速度单位有些怪怪的……

Python

background_image_filename = 'sushiplate.jpg'

sprite_image_filename = 'fugu.png'

import pygame

from pygame.locals import *

from sys import exit

pygame.init()

screen = pygame.display.set_mode((640, 480), 0, 32)

background = pygame.image.load(background_image_filename).convert()

sprite = pygame.image.load(sprite_image_filename)

# Clock对象

clock = pygame.time.Clock()

x = 0.

# 速度(像素/秒)

speed = 250.

while True:

for event in pygame.event.get():

if event.type == QUIT:

exit()

screen.blit(background, (0,0))

screen.blit(sprite, (x, 100))

time_passed = clock.tick()

time_passed_seconds = time_passed / 1000.0

distance_moved = time_passed_seconds * speed

x += distance_moved

# 想一下,这里减去640和直接归零有何不同?

if x > 640.:

x -= 640.

pygame.display.update()

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

background_image_filename='sushiplate.jpg'

sprite_image_filename='fugu.png'

importpygame

frompygame.localsimport*

fromsysimportexit

pygame.init()

screen=pygame.display.set_mode((640,480),0,32)

background=pygame.image.load(background_image_filename).convert()

sprite=pygame.image.load(sprite_image_filename)

# Clock对象

clock=pygame.time.Clock()

x=0.

# 速度(像素/秒)

speed=250.

whileTrue:

foreventinpygame.event.get():

ifevent.type==QUIT:

exit()

screen.blit(background,(0,0))

screen.blit(sprite,(x,100))

time_passed=clock.tick()

time_passed_seconds=time_passed/1000.0

distance_moved=time_passed_seconds*speed

x+=distance_moved

# 想一下,这里减去640和直接归零有何不同?

ifx>640.:

x-=640.

pygame.display.update()

好了,这样不管你的机器是更深的蓝还是打开个记事本都要吼半天的淘汰机,人眼看起来,不同屏幕上的鱼的速度都是一致的了。请牢牢记住这个方法,在很多情况下,通过时间控制要比直接调节帧率好用的多。

斜线运动

下面有一个更有趣一些的程序,不再是单纯的直线运动,而是有点像屏保一样,碰到了壁会反弹。不过也并没有新的东西在里面,原理上来说,反弹只不过是把速度取反了而已~ 可以先试着自己写一个,然后与这个对照一下。

Python

background_image_filename = 'sushiplate.jpg'

sprite_image_filename = 'fugu.png'

import pygame

from pygame.locals import *

from sys import exit

pygame.init()

screen = pygame.display.set_mode((640, 480), 0, 32)

background = pygame.image.load(background_image_filename).convert()

sprite = pygame.image.load(sprite_image_filename).convert_alpha()

clock = pygame.time.Clock()

x, y = 100., 100.

speed_x, speed_y = 133., 170.

while True:

for event in pygame.event.get():

if event.type == QUIT:

exit()

screen.blit(background, (0,0))

screen.blit(sprite, (x, y))

time_passed = clock.tick(30)

time_passed_seconds = time_passed / 1000.0

x += speed_x * time_passed_seconds

y += speed_y * time_passed_seconds

# 到达边界则把速度反向

if x > 640 - sprite.get_width():

speed_x = -speed_x

x = 640 - sprite.get_width()

elif x < 0:

speed_x = -speed_x

x = 0.

if y > 480 - sprite.get_height():

speed_y = -speed_y

y = 480 - sprite.get_height()

elif y < 0:

speed_y = -speed_y

y = 0

pygame.display.update()

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

background_image_filename='sushiplate.jpg'

sprite_image_filename='fugu.png'

importpygame

frompygame.localsimport*

fromsysimportexit

pygame.init()

screen=pygame.display.set_mode((640,480),0,32)

background=pygame.image.load(background_image_filename).convert()

sprite=pygame.image.load(sprite_image_filename).convert_alpha()

clock=pygame.time.Clock()

x,y=100.,100.

speed_x,speed_y=133.,170.

whileTrue:

foreventinpygame.event.get():

ifevent.type==QUIT:

exit()

screen.blit(background,(0,0))

screen.blit(sprite,(x,y))

time_passed=clock.tick(30)

time_passed_seconds=time_passed/1000.0

x+=speed_x*time_passed_seconds

y+=speed_y*time_passed_seconds

# 到达边界则把速度反向

ifx>640-sprite.get_width():

speed_x=-speed_x

x=640-sprite.get_width()

elifx<0:

speed_x=-speed_x

x=0.

ify>480-sprite.get_height():

speed_y=-speed_y

y=480-sprite.get_height()

elify<0:

speed_y=-speed_y

y=0

pygame.display.update()

OK,这次的运动就说到这里。仔细一看的话,就会明白游戏中的所谓运动(尤其是2D游戏),不过是把一个物体的坐标改一下而已。不过总是不停的计算和修改x和y,有些麻烦不是么,下次我们引入向量,看看使用数学怎样可以帮我们减轻负担。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
PythonPygame游戏-从入门到精通 中文pdf版本 部分目录如下: 系统学习部分 用PythonPygame游戏-从入门到精通(1) Pygame的历史,安装Pygame,第一个Pygame脚本 用PythonPygame游戏-从入门到精通(2) 理解游戏中的事件 用PythonPygame游戏-从入门到精通(3) Pygmae的屏幕显示 用PythonPygame游戏-从入门到精通(4) 使用字体模块,Pygame 的错误处理 用PythonPygame游戏-从入门到精通(5) 像素和颜色 用PythonPygame游戏-从入门到精通(6) 使用图像,理解Surface 用PythonPygame游戏-从入门到精通(7) 绘制图形 用PythonPygame游戏-从入门到精通(8) 产生动画和控制帧率 用PythonPygame游戏-从入门到精通(9) 向量基础 用PythonPygame游戏-从入门到精通(10) 用户输入 用PythonPygame游戏-从入门到精通(11) 使用鼠标控制精灵。一个在鼠标旁不断游动的小鱼的例程。 用PythonPygame游戏-从入门到精通(12) 手柄操作,暂无 用PythonPygame游戏-从入门到精通(13) AI初探 用PythonPygame游戏-从入门到精通(14) 状态机 用PythonPygame游戏-从入门到精通(15) 开始AI编程 用PythonPygame游戏-从入门到精通(16) AI编程总结。一个蚂蚁采集食物,攻击蜘蛛的系统模拟例程。 用PythonPygame游戏-从入门到精通(17) 3D基础 用PythonPygame游戏-从入门到精通(18) 3D中的概念 用PythonPygame游戏-从入门到精通(19) 第一个 3D 程序(伪)。一个空间中的3D立方体的例程。 用PythonPygame游戏-从入门到精通(20) 声音原理 用PythonPygame游戏-从入门到精通(21) 使用声音,播放音效。一个重力模拟金属球碰撞的例程。 用PythonPygame游戏-从入门到精通(22) 播放长时间的背景音乐。一个建议播放器的例程。 额外提高部分 用PythonPygame游戏-从入门到精通(py2exe编) 使用py2exe将pygame脚本转换为exe可执行文件 用PythonPygame游戏-从入门到精通(Sprite篇) 介绍Pygame中不是必须但又很重要的Sprite模块,游戏中的角色实现,大多都要靠它。 实践部分 用PythonPygame游戏-从入门到精通(实战一:涂鸦画板1) 一个类似于Windows画图板的小玩意儿,精简了很多功能但是有更帅的笔刷。这一次主要是将笔刷的实现。 用PythonPygame游戏-从入门到精通(实战一:涂鸦画板2) 加上了按钮,我们的涂鸦画板可以用了! 用PythonPygame游戏-从入门到精通(实战二:恶搞俄罗斯方块1) 俄罗斯方块,却有不是普通的俄罗斯方块。 用PythonPygame游戏-从入门到精通(实战二:恶搞俄罗斯方块2) 代码构架 用PythonPygame游戏-从入门到精通(实战二:恶搞俄罗斯方块3) 实现说明 用PythonPygame游戏-从入门到精通(实战二:恶搞俄罗斯方块4) 完成,提供下载 用PythonPygame游戏-从入门到精通(实战三:植物大战僵尸1)

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值