关于“The Sea Night”的编写说明

Author: 北京 吕汝元 Date: 1996-10-11

        在程序为营造海之夜的神秘氛围和在不采用快速拷贝、异或操作等常规动画技术情况下实现星星眨眼等动画效果以及实现月亮的颜色渐变(动态)、海浪颜色层次推移(静态)等目的,其关键在于对颜色寄存器的操作。通过对256个颜色寄存器值部分循环,部分固定的技术而完成设计,比较巧妙地解决了问题。具体思路为:对月亮及星星所用颜色寄存器进行由深入浅、由浅入深的循环;海浪的不同层次所使用的寄存器值固定为渐变的蓝色。
        二、具体程序设计
        程序采用模块化设计,各子功能分别由子函数完成。主main()函数的开始调用SetMode()子函数将工作模式设置成13h。SetMode()子函数调用int 86()函数通过视频BIOS int 10的0号子功能设置工作模式,其中reg.h.al为模式号(reg为DOS.h头文件中定义的联合体),reg.h.ah为功能号。然后主函数调用Initp()函数给定义的颜色结构体数组Color(229个元素,因为只用到229个颜色寄存器)赋初值。为展示设置颜色的方便性。1~216号颜色寄存器设置了蓝、黄、绿三种色相,每种36个渐变层次。217~226号寄存器设置为海浪的蓝色渐变层次。0号设置为黑色。之后主函数调用Setp(),Setp()子函数通过视频BIOS调用初始号将用到的颜色寄存器,使之符合Initp()中Color中各元素的设计值。至此,工作模式设置及颜色寄存器的初始化均已完成。
        绘图工作的开始利用库函数random()函数在屏幕上方画300个星星,颜色用0~255中的颜色寄存器。其中Plot()函数为在指定X、Y位置以指定颜色绘一象素的函数。之后的工作为调用Dsin()函数分几个层次以不同的颜色、不同的增益、周期和相位画出正弦海浪,解决海浪的颜色层次及浪形的变化。程序还特意在各层浪之间留出空隙,露出黑底色充当阴影,以使浪产生立体感。
        最后“千呼万唤始出来”的是画月亮的部分。大“for”循环使月亮的中心在海平线上由左至右移动。里面并列的两个“for”循环分别完成月亮的升起和落下。同时升起时颜色亮度由暗变亮,落下时由亮变暗。这里有个技巧:为保证升到最高时达到同种色的最亮色调,落到消失时达到同种色的最暗色调,特意设了一个计数器i,使i==16时循环一次颜色寄存器值,保证再次升起和落下的过程恰好遍历36个颜色层次。本程序现在设计的循环步长在主频为33MHz的386芯片上运行时速度适中。若在486、586上运行可适当改变for循环步长(变小)和循环颜色寄存器时i的值(增大),以使运行时画面变化速度适中,改善视觉效果。程序还设置了三处键盘中断出口。
        三、进一步的设想:可将海浪的颜色在水平方向上也设置成由浅入深、由深入浅的变化。然后使画海浪所用的颜色寄存器独自形成小循环,使海浪在水平方向上有强烈的流动感,感兴趣的读者不妨一试。