2、天马行空

木鸿飞提前一个月来到了XT大学。

三年前,他是校园里可有可无的过客,三年后,他已经是学校的一员。三年前,他还来不及仔细欣赏校园的美景,三年后,他有足够的时间细细品味这优美的画卷。三年前,他对计算机只有惊鸿一瞥,三年后,他终于可以与计算机恋爱般亲密接触。

再次来到大学校园,木鸿飞不再来去匆匆,却是缓缓而行,贪婪的欣赏着周围的美景。穿过三道拱门组成的校门,景色依旧,庭院深深深几许,一条大路从校门向内延伸,直至眼光的尽头。道路两旁绿树成荫,从校门前行200米,是一个田径场,场内青草依依,微风吹过,绿色的草浪此起彼伏,仿佛在诉说校园里多么热闹,多么生机勃勃。

从最南边,到最北边,穿越校园就是穿越一个巨大而美丽的公园,在这里,上课将是一次次穿越花园的旅行!

旅行结束,到达北青楼,木鸿飞又见到了几年前熟悉的面孔,结实的高老师一个劲的感叹,“时间过得真快,小小木居然就读大学了!”。一如木鸿飞工作后感叹白云苍狗一般,记得刚刚参加工作时,看着同事的小孩在膝下嬉闹,十年弹指一挥间,如今却常常听同事诉说自己的小孩在大学中如何如何,唉,年轻真好!

得知弟弟提前到来,哥哥早有准备,他专门从系里借了一台486机器。三年过去了,486早已是昨日黄花,如今是586(奔腾)的时代,甚至传说中686也已经问世,所以暑假期间借一台淘汰的486到家里使用还是可以的,这样也省去了来回奔波上机的麻烦。

了解到木鸿飞高中开设了计算机课,还编写了俄罗斯方块,哥哥兴趣大增,要求木鸿飞演示一把。只是演示什么呢?俄罗斯方块程序在5寸磁盘中,但5寸磁盘早已全面被淘汰,数据取不出来。

“那就演示动画吧。”木鸿飞想了想,设计动画程序似乎是最方便的。

“哦,你还会动画!”哥哥吃惊的说道,然后马上出题:“设计一个从左边移动到右边的矩形。”

与俄罗斯方块相比,这个需求实在是太简单了,木鸿飞思索了一阵子,打开Qbasic,在发一点时间习惯后,写出了这段代码。

“我再编个天马飞翔的动画。”前面的热身显然达到了效果,木鸿飞主动请缨再战,编程瘾已经吊起,还可以show一次,何乐而不为。

但木鸿飞并不马上编程,而是拿出纸笔,用简笔画的方式勾勒出一匹大马,再在背上加上双翅,然后为每一根线条标上坐标,整个过程大约发费了两个小时。然后才进入Qbasic,开始输入代码,又过了一个多小时,一匹背生翅膀的天马从右到左飞过屏幕,屏幕黑黑的,时不时反射几丝亮光,就如同从宇宙深处掠过一般。

哥哥点点头,对这个作品赞不绝口:“很好,很好。先准备,再编程,比很多大学生强多了。现在有的学生连干什么都不知道就直接上机去了,真不明白他们要编什么。”

“无准备,不编程!”木鸿飞想起了设计俄罗斯方块时写满代码的笔记本,看来当初的做法是正确了。“我设计的马并不是简单的飞过屏幕怎么简单,你看,”木鸿飞再次运行程序,“在移动的过程中,翅膀上下翻动,马腿前后移动,而且整匹马也没有保持在同一个水平线上,而是忽上忽下,用来表示跑动中颠簸的效果。”

“你是如何实现上下颠簸的?”哥哥问道:“有没有为每个位置的马单独设计代码?”

“没有,我使用了一个函数来画马,马的左上角坐标是函数的参数,比如x是左上角的横坐标,y是左上角的纵坐标。函数中所有的画线过程均采用相对坐标,比如这条线从(x+1,y+10)开始画起,到(x+10, y+20)结束。无论在任何位置,都可以很方便的实现。”木鸿飞回答道。

“会使用函数,很好,很好!”哥哥继续点头:“你是如何实现动画的?”

“动画很简单,它由两个步骤组成:显示和擦除。显示就是直接画出马就可以了,而擦除吗,”木鸿飞洋洋得意起来,“其实就是在原地方用黑色再画一次,马就消失了,然后把左上角坐标移动到新的位置继续显示,马就前移了!不断的擦除和显示,就形成了动画的效果。我在俄罗斯方块中就是这么做的。”

“在原处用黑色画马实现动画。”哥哥若有所思,“你有没有考虑,还有什么方法可以实现动画呢?这些方法都有什么优缺点?比如目前你使用的方法实现动画有什不足?”

“多种方法?不足之处?”木鸿飞摇摇头,“我没有考虑过。”

“应该考虑,至少还有四种方法可以实现动画。”哥哥说道。

“还有四种,加上这一种不就是五种。我不知道。”顿了顿,木鸿飞补充道:“为什么要考虑这么多方法,反正可以实现了,不浪费吧。”

“在计算机中常常有多种方法可以实现同一件事情,也就是条条大路通罗马。真正的程序员需要综合各种情况,思索各种实现方法,并从中选择最适合的一种。”哥哥一本正经的说道,但木鸿飞显然不理解,一脸的不可置信。

“不信?”哥哥略一沉思,计从心来,“让我们演示一下。我在这个程序开头部分增加一个语句,设置屏幕背景为蓝色,咱们再看看效果。”

程序再次运行,蓝色的屏幕上,天马消失的无影无踪,取而代之的是,红线、黑线依次划过,留下一片漆黑的区域。

程序运行“异常”,木鸿飞大吃一惊,疑惑之情暴露无遗。不过这一切都在哥哥的预料之内。“实现动画的第一种方法,就是在原位置处以底色重画一次。记住是以底色重画一次,不是以黑色重画。”哥哥讲述“底色”和“黑色”时明显加重了语气。

“我明白了!”木鸿飞也是八面玲珑,一点就通,“我应该用蓝色重画天马!”说干就干,更改代码后,久违的天马终于再次行空,所不同的是上次是掠过宇宙星空,而本次则是划过蓝天。

“很好。”哥哥毫不吝啬对木鸿飞的赞誉,同时开始谆谆教导,“但是这种方法有个缺点,你发现了吗?”

“没有!”木鸿飞很直接。

“以底色重画天马来实现动画,这种方法的优点是简单,但缺点是,如果背景不是纯底色时,会破坏原来的背景。”见木鸿飞紧锁眉头,哥哥继续解释:“假设你的背景是由太阳、星星和地球的图案,当你用背景色——比如黑色——重画时,屏幕上留下的将是黑色的线条,原来的背影将被黑色取代。而随着动画的继续,最终天马飞过的地方将全成为黑色……

“就像刚刚以蓝色为背景时一样。”木鸿飞明白了,开始抢答。

“对!所以第二种动画方法就是以异或方式画图。”重音在“异或”上。

“疑惑?”木鸿飞只知疑惑,不识异或。

“异或是位运行,你还没有学习二进制,不过没关系,二进制很简单,你的数学也很好,应该马上能够理解。”哥哥开始现场教学。

不一会儿,木鸿飞理解了“异或”的特性:对同一背景,同一图形,使用“异或”方式显示两次,则背景复原,就如同从来没有显示一样。程序的更改也很简单:在开始处将输出方式设置为“异或”;“擦除”时也不再使用背景色而使用前景色——此处是红色——即可。为了使演示结果更具备说服力,木鸿飞还在移动前画了若干个几何图形充当背景。

程序开始运行,天马飞过星空后,星空背景一切依旧,成功!木鸿飞欢喜的手舞足蹈,不住的说:“这个方法好,这个方法好!简单!”

“使用异或方式是实现动画的一种方法,其优点是可以保护背景,但是缺点也显而易见。”哥哥继续爆料。

“它还有缺点?还显而易见?我怎么没有看到。”木鸿飞已经完全陷入惊奇当中。

“你别只顾高兴,平静的观察的话肯定可以发现。”哥哥叫停木鸿飞的兴奋。

“好。”木鸿飞深吸一口气,平静一下心情,然后看了看代码,好像还是没有什么特别,再运行程序,终于有了发现:“天马的颜色变了,程序使用了红色,但显示出来是紫红色!还有通过背景几何图形时,那些交叉的点颜色都变了!”

“对,异或方式显示容易更改颜色。”说着,哥哥拿起笔,在纸上演示:“你看,本来输出红色,红色代码是0100,而背景是蓝色,蓝色代码是0001,这两种颜色异或后是0101,正好是紫红色。”

“哦,我明白了。”木鸿飞恍然大悟,“有没有什么方法既可以保留背景,又不更改显示的颜色呢。”

“你能这么想就对了!程序就是在一次次改进中前行。不过其他的方法设计起来就比较麻烦了。比如背景保存法:在显示前,先把图形所涉及区域的背景保存下来。擦除时,就把保存的背景再显示出来。”考虑到木鸿飞还没有学习相关函数,哥哥亲自操刀,对程序进行了一些修改,于是天马终于以自己本来的颜色飞跃星空了。

“哥哥,这个方式设计起来好像比较麻烦,加了好多代码。”木鸿飞已经初步具备了分析设计方法的思维了。

“的确比较麻烦,而且保存背景也是需要内存的。当然,可以采用背景刷新的方法解决这个问题,。”哥哥又提出一种方法。

“背景刷新法,难道每次都重新刷新,也就是全面画一次背景图像。”木鸿飞自动忽略不懂的“内存”,主动思考新方法。

“没错,每次擦除时,都把重新画一次背景,这样做即能擦除原图形,又能复原背景,一举两得,而且实现起来相当简单。不过每次重画背景时都特别费时,每动一步,就看到屏幕闪烁一次,给人一种卡机的感觉。”哥哥详细的分析。

“有解决方案吗?”木鸿飞知道哥哥必有下文。

“有,可以采用多页面显示法。一个屏幕就是一个页面,我们调用各种画图函数,一般都是直接画在屏幕页面上,比如你调用line函数,屏幕上马上就会显示一条线。但是也可以不马上显示,比如准备一张白纸,所有的画图函数都画在白纸上,当然白纸藏起来不显示到屏幕上的,上面画的图形你都看不到,直到画图完毕,再把白纸的内容显示到屏幕上。这种白纸就是页面,我们可以在显示一个页面的同时,画另一个页面,画好后显示另一个页面而同时画前一个页面,如此循环。”哥哥说道。

“原理我懂,就像放电影一样,一秒钟24张图片,一页一页的显示出来,在显示第一页的同时设计下一页。但是为什么要这么做,直接在屏幕上显示不是很好吗?”木鸿飞不解的问。

“你还没有正式学习计算机,有些情况可能还不太了解。”哥哥解释道:“有时候直接在屏幕上画图速度会比较慢。今天的例子简单,所以看不出来。但是有一些复杂的图形程序,生成全部的图形需要比较长的时间,如果直接在屏幕上显示的话,就会像慢动作一样很明显的看到这个过程,比如先画一个三角形,再画一个矩形等等。而实际上,用户只在乎最后的结果,所以就需要把这些缓慢的实现步骤掩藏起来。”

 “我明白了。实现动画有背景色重画法、异或法、背景保存法、背景刷新法和多页面显示法。”木鸿飞对今天的学习做了一个总结。

“当然,你也可以找到其他的方法。其实今天告诉你动画的这么多种实现方法,并不是教会你做动画,那还太早了点。目的只是告诉你,计算机程序的设计方法多种多样,每种方法都有自己的优缺点,都有自己适用范围。所以在设计程序时,一定要考虑各种方法,并从中选出最适合的来。不要以为这样很多余,也不要以为浪费了其他的设计方法,这个程序不适合,也许下一个程序刚好适合也不一定。有一句可能现在你还不能理解:算法没有好坏之分,只有适合和不适合的区别。”

木鸿飞度过了非常有意义的一天,他在展示自身计算机才能的同时也隐隐触及了计算机的博大精深,仅仅一个动画就牵涉若干的方法,而这还只是冰山一角。虽然不能立刻学会这些的知识,虽然不能马上消化这些的思想,但木鸿飞越发喜欢上计算机,今天他对计算机还只是懵懵懂懂,但是明天他一定能掌握计算机,因为木鸿飞就是为计算机而生。

 ps :动画演示程序,五角星飞跃地球,未使用图形加速,有点闪。https://blog.51cto.com/p_w_upload/201010/653596_1287643414.rar

 

上一篇   目录  下一篇