Pygame学习笔记 4 —— 时间与运动

    还记得我们在之前的程序中如何让兔子动起来的吗,没错,使用event模块检测键盘事件,改变绘图的坐标,画面刷新后兔子就移动了。接下来我们细说如何精确控制时间和运动。
在这里插入图片描述
主要内容: pygame的时间模块、动画的速度、向量的引入



一、pygame的时间模块

  time模块是pygame用来监测时间流动的模块。由于不同的电脑CPU处理指令的速度不同,性能有差异,对于同一个pygame游戏的动画就会出现动画速度不一致的现象。因此,有必要使用time模块来控制速度。

time模块: 常用函数

  pygame.time模块有很多测量时间的函数,它们的返回值都是一个常数,代表流逝的时间。pygame的时间是以毫秒(millisecond)来计算的,pygame中含有一个常量TIMER_RESOLUTION标记了一毫秒的长度。

1、pygame.time.get_ticks
语法:get_ticks() -> milliseconds
说明:返回值代表了自pygame.init()被调用以来经过的时间。在pygame.init()被调用之前,返回值始终为0

2、pygame.time.wait
语法:wait(milliseconds) -> time
说明:程序暂停给定的毫秒数。该函数占用很少的CPU使劲按,精度略低于delay()函数。

3、pygame.time.delay
语法:delay(milliseconds) -> time
说明:程序暂停给定的毫秒数。它使用CPU来精确控制时间,精确度高。

4、pygame.time.Clock
语法:Clock) -> Clock
说明:该函数返回一个跟踪时间的对象,该对象有很多计算时间的函数。
帧率:FPS(frame per second),代表了游戏画面的刷新速度,一般60帧的刷新频率就可以让画面看起来光滑逼真,对更高的帧率人眼基本上察觉不到变化了。

Clock对象 :常用函数

1、tick
语法:tick(framerate=0) -> milliseconds
说明:可以说,这个函数是非常好用了。在每一次画面刷新时,这个函数都会被调用,它返回距离上一次被调用经过的时间。如果传入可选的参数framerate,如下面的例子,此时该函数会产生延迟使游戏刷新频率低于40。

clock = pygame.time.Clock()
while True:
	time_passed = clock.tick(40)
	...

2、tick_busy_loop
语法:tick_busy_loop(framerate=0) -> milliseconds
说明:使用同tick()一样,只不过这个函数牺牲更多CPU时间来换取精确度

3、get_fps
语法:get_fps() -> float
说明:利用最后10次调用的Clock.tick()的返回值的平均值计算帧率并返回。



二、动画的速度

  前面提到了动画的速度,如果不使用时间模块来控制,系统的程序在不同的机器上运行结果可能不一样。还记得我们在讨论键盘事件时做的动画吗,兔子?跑的特别快。这里,我们试试用time模块来控制速度:
  我们知道,位移(displacement) = 速度(velocity) * 时间(time),而对于pygame窗口来说,surface对象的移动是在不同坐标的绘制,我们只需要控制在相同时间里,坐标(x, y)的增量相同就可以啦。先看几行代码:

import pygame, sys
from pygame.locals import *

pygame.init()
pygame.display.set_caption("constant speed")
screen = pygame.display.set_mode((640,480), 0, 32)
rabbit = pygame.image.load("rabbit.png")

(x, y) = (0, 0)
speed = 100
clock = pygame.time.Clock()

while True:
	for event in pygame.event.get():
		if event.type == QUIT:
			pygame.quit()
			sys.exit()
	
	# 计算时间并转化为seconds
	time_passed = clock.tick(2)
	time_passed_seconds = time_passed / 1000
	
	x += time_passed_seconds * speed
	y += time_passed_seconds * speed
				
	screen.fill((200,200,255))
	screen.blit(rabbit, (x, y))
	
	pygame.display.update()

  上面的代码使用了Clock对象,坐标(x, y)的值由speed和时间控制,兔兔?每秒钟只移动100(speed = 100)个像素,下面是关键代码。
  刷新频率只是影响了运动的平滑程度,不影响移动的平均速度,比如我们把frame rate设为1,则隔1秒小兔子移动100px,而设置为2时,可以发现每0.5秒小兔子移动50px,结果一样,可以实践验证。

clock = pygame.time.Clock()
while True:
	time_passed = clock.tick(2)
	time_passed_seconds = time_passed / 1000
	x += time_passed_seconds * speed
	y += time_passed_seconds * speed



三、向量的引入

  数学对向量的定义是带方向的量,在pygame里面,向量只不过是一个元组,我们可以自己编写一个向量类,包含 获取模magnitude()、标准化normalize()以及各种重载运算符等方法。不过也利用现成的向量库可以使用,gameobjects库包含了Vector2、Vector3、Vector4等向量模块,下载一个gameobjects库,可以方便的在pygame中使用向量。

Vector2 —— 使用

step1:导入类

from gameobjects.vector2 import Vector2

step2:创建类对象

vector = Vector(3, 4)

step3:调用类方法

x = vector.get_x()
mag = vector.get_magnitude()
vector_normalized = vector.get_normalized()

Vector2 —— 主要函数

函数功能
Vector(x, y)构造函数,生成vector对象
get_x()返回向量的x分量
set_x()返回向量的x分量
get_length()返回向量的长度
normalise()将原向量标准化
get_normalise()返回单位化的向量,不修改原向量
运算符重载加、减、乘、(不)等于判断
from_points(p1, p2)返回从点p1到点p2的向量

Vector2 —— 应用

  下面,我们利用向量来实现兔子追胡萝卜的动画,代码如下:

import pygame, sys
from pygame.locals import *
from gameobjects.vector2 import Vector2

pygame.init()

pygame.display.set_caption("rabbit eat carrot")
screen = pygame.display.set_mode((640, 480), 0, 32)
rabbit = pygame.image.load("rabbit.png")
carrot = pygame.image.load("carrot.png")

speed = 100
direction = Vector2()
position = Vector2(300, 220)
clock = pygame.time.Clock()

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

	width = carrot.get_width()
	height = carrot.get_height()
	destination = (Vector2(*pygame.mouse.get_pos()) - 
		Vector2(width/2, height/2))
	vector_to_mouse = Vector2.from_points(position, destination).get_normalised()

	time_passed = clock.tick()
	time_passed_seconds = time_passed / 1000
	
	position.x += time_passed_seconds*speed*vector_to_mouse.x
	position.y += time_passed_seconds*speed*vector_to_mouse.y

	screen.fill((255, 255, 255))
	screen.blit(carrot, destination)
	screen.blit(rabbit, position)

	pygame.display.update()

  我们使用了clock和speed常量来控制兔子的移动速度,使用从兔子当前位置position到鼠标destination方向上的单位向量vector_to_mouse控制兔子的运动方向。兔兔吃胡萝卜的GIF如下 (●’◡’●)


第四篇pygame学习笔记完结 cheers! ?

附上:代码压缩包
提取码:j8th


参考博客:用Python和Pygame写游戏-从入门到精通
图标引用:Iconfont

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值