动画¶
通过在动画窗口上快速改变绘图(帧),我们可以制作动画。
时间控制¶
因为计算机能够以很快的速度画图,因此我们通常需要在两帧间停顿一些时间。
注意:在这节中使用的函数都无法在无窗口模式(Headless模式)中工作。
在Easy Graphics中,我们可以使用delay()函数来让程序暂停指定的毫秒(milliseconds或ms)数。
控制FPS¶
因为每次绘图的实际用时都有可能不一样,因此更好的控制每帧时长的方法是使用delay_fps()函数。
FPS是”frames per second”(每秒钟帧数)的缩写。delay_fps()会计算每一帧的实际绘制时长,将程序暂停对应的时长,以保证每帧的总时长一致。
渲染模式(Render Mode)¶
在EasyGraphics中有两种渲染模式
- 自动模式(RenderMode.AUTO):所有的在绘图窗口中的绘制都会导致窗口立即刷新。这是缺省工作模式,用于普通的绘图。
- 手动模式(RenderMode.Manual):绘制的内容不会立即刷新显示在绘图窗口中。要一直等到pause()/delay()/delay_fps()/get_mouse_msg()等时间控制和鼠标键盘函数被调用时,窗口才会刷新。这个模式用来加速动画帧的绘制。
在显示动画前,将渲染模式设置为手动是个好习惯。
可以使用set_render_mode()函数来设置渲染模式。
注意:如果你不是在绘图窗口中进行绘制,那么渲染模式没有任何效果。
背景处理¶
在动画中,我们经常需要某个物体在特定背景下移动。如果背景较为复杂,那么每帧都从头绘制一遍背景会严重影响绘制的速度。
在这种情况下,一般的处理方式是将背景预先单独绘制在一个图片上,要动的物体绘制在另一个图片上。通过对两张图片进行合成,来得到最终的结果。
下面的程序绘制了一辆在道路背景上移动的公共汽车。注意is_run()函数的使用。
from easygraphics import *
def main():
init_graph(800, 600)
set_render_mode(RenderMode.RENDER_MANUAL)
background = create_image(800, 600)
set_target(background)
set_background_color(Color.LIGHT_YELLOW)
set_fill_color(Color.RED)
draw_circle(150, 150, 50)
set_fill_color(Color.DARK_BLUE)
draw_rect(0, 400, 800, 600)
car = create_image(162, 150)
set_target(car)
set_composition_mode(CompositionMode.SOURCE)
set_background_color(Color.TRANSPARENT)
set_fill_color("white")
draw_polygon(0, 0, 0, 60, 160, 60, 160, 40, 125, 20, 110, 0)
set_fill_color("darkgray")
draw_circle(35, 60, 20)
draw_circle(120, 60, 20)
set_fill_color("transparent")
draw_rect(10, 10, 40, 25)
draw_rect(50, 10, 80, 25)
set_target()
x = 0
while is_run():
x = (x + 2) % 750
draw_image(0, 0, background)
draw_image(x, 350, car)
delay_fps(100)
background.close()
car.close()
close_graph()
easy_run(main)
跳帧¶
有时,一帧的绘制可能会比较复杂,因此较慢,导致该帧无法在指定的帧时长内完成绘制。这会导致动画出现延迟。
delay_jfps()函数通过跳帧来保证动画的平稳。跳帧是指,如果某帧绘制的时长太长后续的帧就会被跳过不进行绘制(但是算成是已完成绘制的帧数),从而保证达到指定的FPS。
下面的例子展示了delay_jfps()的用法。注意我们用sleep()来模拟一个耗时的操作,以便观看跳帧的效果。
from easygraphics import *
import time
def main():
init_graph(640, 480)
set_color(Color.BLUE)
set_fill_color(Color.GREEN)
set_render_mode(RenderMode.RENDER_MANUAL)
x = 0
while is_run():
x = (x + 1) % 440
if delay_jfps(60, 0):
clear_device()
draw_ellipse(x + 100, 200, 100, 100)
time.sleep(0.5)
close_graph()
easy_run(main)