中国DOS联盟论坛

中国DOS联盟

-- 联合DOS 推动DOS 发展DOS --

联盟域名:www.cn-dos.net  论坛域名:www.cn-dos.net/forum
DOS,代表着自由开放与发展,我们努力起来,学习FreeDOS和Linux的自由开放与GNU精神,共同创造和发展美好的自由与GNU GPL世界吧!

游客:  注册 | 登录 | 命令行 | 搜索 | 上传 | 帮助 »
作者:
标题: TC写的小动画效果 上一主题 | 下一主题
523066680
银牌会员

SuperCleaner


积分 2362
发帖 1133
注册 2008-2-2
状态 离线
『楼 主』:  TC写的小动画效果 [已使用 LLM 解释]

上传的文件里有3个效果:变幻Delta带影子的 变幻四面体 不同速度随机游动的点

我平常放dos启动盘里,进入dos的时候拿来做屏保啦哈哈。

#include <Conio.h>
#include <graphics.h>
#include <stdlib.h>
#define closegr closegraph
#define NDOT 4


typedef struct
{
int a,b,x,y;
} DotInf;


void initgr(void) /* BGI初始化 */
{
int gd = DETECT, gm = 0;
registerbgidriver(EGAVGA_driver);
initgraph(&gd, &gm, "");
}

void delta(DotInf dot,int c)
{
int i,j;
setcolor(c);
for (i=0;i<NDOT;i++)
for (j=i+1;j<NDOT;j++) line(dot.x,dot.y,dot.x,dot.y);
}

int main(void)
{
int i,j,whi=0;
DotInf snk,everdot;

initgr(); /* BGI初始化 */

for (i=0;i<NDOT;i++) {
snk.a=snk.b=snk.x=snk.y=200;
}
delta(snk,2);
randomize();
while (!kbhit())
{
if (whi<4) whi++; else whi=0;
for (i=0;i<600;i++) delay(10);

delta(everdot,0);
delta(snk,2);

for (i=0;i<NDOT;i++){
if ((snk.x==snk.a)&&(snk.y==snk.b)){
snk.a=rand()%600+1;
snk.b=rand()%400+20;
}
}
for (i=0;i<NDOT;i++){
everdot.x=snk.x;
everdot.y=snk.y;
if (whi>i) continue;
if (snk.x>snk.a)
snk.x--;
else if (snk.x<snk.a)
snk.x++;
else
{
if (snk.y>snk.b)
snk.y--;
else if (snk.y<snk.b)
snk.y++;
}
}


}

getch();
closegr(); /* 恢复TEXT屏幕模式 */
return 0;
}



Last edited by 523066680 on 2009-9-7 at 01:25
]
LLM 解释

这段代码是 2000 年代初期中文 DOS 编程爱好者常用的典型实现,基于 Borland Turbo C (TC) 的 BGI (Borland Graphics Interface) 图形库。

技术实现分析

  1. BGI 初始化机制: 代码中使用了 registerbgidriver(EGAVGA_driver)。在当年的 TC 环境下,BGI 驱动程序(如 EGAVGA.BGI)通常是作为独立文件存在的。如果程序运行时找不到该文件,图形初始化会失败。通过 registerbgidriver 函数,开发者可以将驱动程序静态链接到生成的可执行文件中,从而摆脱对外部 .BGI 文件的依赖,这在制作“单文件”屏保或实用工具时是标准做法。

  2. 动画逻辑与同步

    • 核心算法:程序定义了一个 DotInf 结构体来存储四个顶点(NDOT=4)的当前位置 (x, y) 和目标位置 (a, b)。通过 delta 函数绘制顶点间的连线,形成一个四面体(在此平面投影中为全连接图)。
    • 擦除机制:程序采用了“异或擦除”或“覆盖擦除”的简化版。它保存了上一帧的状态 everdot,并在绘制新一帧之前,用背景色(颜色 0)在旧位置重绘一次图形。这在当时的显示带宽下是避免全屏闪烁(Flicker)的常用技巧,因为全屏 cleardevice() 会导致严重的视觉闪烁。
    • 速度控制:代码中使用了 delay(10) 函数。需要注意的是,TC 中的 delay 函数在当时是基于硬件时钟周期的。在如今的模拟器(如 DOSBox)或现代高速 CPU 上,如果没有正确配置,这种循环延时可能会导致动画极快或极慢。

潜在的技术局限与误区

  1. 分步运动逻辑: 代码中的坐标更新逻辑存在一个常见的初学者偏差:

    if (snk[i].x > snk[i].a) snk[i].x--;
    else if (snk[i].x < snk[i].a) snk[i].x++;
    else {
        if (snk[i].y > snk[i].b) snk[i].y--;
        else if (snk[i].y < snk[i].b) snk[i].y++;
    }
    

    这种逻辑会导致点先在 X 轴移动,待 X 坐标对齐后再在 Y 轴移动,轨迹呈直角折线而非平滑的直线。在当时的动画编程中,标准的做法是使用 Bresenham 算法 的变体或浮点数步长来计算位移,以实现任意斜率的直线运动。

  2. 延迟函数的副作用: 外层循环 for (i=0; i<600; i++) delay(10); 产生了一个约 6 秒的长延迟(600 * 10ms),但在延迟期间并没有检测键盘输入 kbhit()。这意味着程序在每轮移动之间会有明显的停顿,且对用户按键的响应会有滞后感。这反映了早期单线程 DOS 程序在处理实时交互与逻辑循环时的典型局限。

  3. 坐标范围假设: 代码硬编码了 rand()%600+1rand()%400+20。这假设了显示模式为 VGA HiRes(640x480)。如果 BGI 环境被初始化为较早的 CGA 或低分辨率模式,这些坐标可能会超出绘图边界,导致 BGI 内部裁切或未定义行为。

环境兼容性提示

  • 编译环境:此类代码通常需要 Turbo C 2.0 或 Borland C++ 3.1 编译。
  • 图形驱动EGAVGA_driver 宏要求编译器能够找到对应的符号定义,通常在 graphics.h 中,并且在链接阶段需要开启图形库支持(Linker options -> Graphics library: ON)。
  • 现代运行:在 DOSBox 环境下,由于模拟了 18.2Hz 的标准时钟中断,delay 函数能相对准确地工作,但建议通过控制 CPU Cycles(如 cycles=3000)来还原当年实机的视觉速度。


附件 1: TCGRAPH.rar (2009-9-4 00:46, 59.37 KiB, 下载附件所需积分 1 点 ,下载次数: 132)


综合型编程论坛

我的作品索引
2009-9-4 00:43
查看资料  发送邮件  访问主页  发短消息  网志  OICQ (523066680)  编辑帖子  回复  引用回复
523066680
银牌会员

SuperCleaner


积分 2362
发帖 1133
注册 2008-2-2
状态 离线
『第 2 楼』:   使用 LLM 解释/回答一下

………………




综合型编程论坛

我的作品索引
2009-9-7 01:25
查看资料  发送邮件  访问主页  发短消息  网志  OICQ (523066680)  编辑帖子  回复  引用回复
justzero
新手上路




积分 8
发帖 3
注册 2009-9-5
来自 China
状态 离线
『第 3 楼』:  12 使用 LLM 解释/回答一下

不错!


2009-9-11 08:05
查看资料  发短消息  网志   编辑帖子  回复  引用回复
cike09
新手上路





积分 17
发帖 11
注册 2009-9-12
来自 宇宙·······禹州
状态 离线
『第 4 楼』:   使用 LLM 解释/回答一下

??????????????????


2009-9-12 05:35
查看资料  发送邮件  访问主页  发短消息  网志  OICQ (1144733571)  编辑帖子  回复  引用回复
523066680
银牌会员

SuperCleaner


积分 2362
发帖 1133
注册 2008-2-2
状态 离线
『第 5 楼』:   使用 LLM 解释/回答一下

楼上有怀疑就说,发问号很容易被当作恶意灌水并扣分的。




综合型编程论坛

我的作品索引
2009-9-12 05:41
查看资料  发送邮件  访问主页  发短消息  网志  OICQ (523066680)  编辑帖子  回复  引用回复
xugaohui
高级用户




积分 774
发帖 293
注册 2003-4-16
来自 湖北仙桃
状态 离线
『第 6 楼』:   使用 LLM 解释/回答一下

不能在移动鼠标时退出,不能驻留内存。




下载
09年7月7日 更新
感谢网友 囧HQY 提供空间
2009-9-13 01:02
查看资料  发送邮件  发短消息  网志   编辑帖子  回复  引用回复
523066680
银牌会员

SuperCleaner


积分 2362
发帖 1133
注册 2008-2-2
状态 离线
『第 7 楼』:   使用 LLM 解释/回答一下

学没多久,不会,多多指教啊~
什么是驻留内存




综合型编程论坛

我的作品索引
2009-9-14 06:19
查看资料  发送邮件  访问主页  发短消息  网志  OICQ (523066680)  编辑帖子  回复  引用回复
xiaoguizi007
新手上路





积分 8
发帖 4
注册 2010-4-6
状态 离线
『第 8 楼』:   使用 LLM 解释/回答一下

这么好,看看


2010-4-20 16:22
查看资料  发送邮件  发短消息  网志   编辑帖子  回复  引用回复
erontec
新手上路





积分 2
发帖 1
注册 2010-2-24
状态 离线
『第 9 楼』:   使用 LLM 解释/回答一下

这么好,看看


2010-4-20 22:35
查看资料  发送邮件  发短消息  网志   编辑帖子  回复  引用回复
demonstone
新手上路





积分 2
发帖 1
注册 2010-4-20
状态 离线
『第 10 楼』:  不错 使用 LLM 解释/回答一下

收下了!


2010-4-26 21:05
查看资料  发送邮件  发短消息  网志   编辑帖子  回复  引用回复
messen
新手上路





积分 17
发帖 8
注册 2010-1-3
状态 离线
『第 11 楼』:   使用 LLM 解释/回答一下

看看的哦 可惜了 不怎么会用


2010-5-5 18:21
查看资料  发送邮件  发短消息  网志   编辑帖子  回复  引用回复
atak
新手上路





积分 16
发帖 7
注册 2010-10-18
状态 离线
『第 12 楼』:   使用 LLM 解释/回答一下

做的不错


2010-10-25 11:47
查看资料  发送邮件  发短消息  网志   编辑帖子  回复  引用回复
1beyondworld
新手上路





积分 8
发帖 4
注册 2010-8-3
状态 离线
『第 13 楼』:   使用 LLM 解释/回答一下

不错的方法


2010-11-1 20:52
查看资料  发送邮件  发短消息  网志   编辑帖子  回复  引用回复
wds59211314
新手上路





积分 2
发帖 1
注册 2010-12-14
状态 离线
『第 14 楼』:   使用 LLM 解释/回答一下

下载来看看,还没看过呢…


2010-12-15 10:30
查看资料  发送邮件  发短消息  网志   编辑帖子  回复  引用回复
1051093860
初级用户





积分 21
发帖 11
注册 2014-1-18
状态 离线
『第 15 楼』:   使用 LLM 解释/回答一下

不错!


2015-6-18 21:21
查看资料  发送邮件  发短消息  网志   编辑帖子  回复  引用回复

请注意:您目前尚未注册或登录,请您注册登录以使用论坛的各项功能,例如发表和回复帖子等。


可打印版本 | 推荐给朋友 | 订阅主题 | 收藏主题



论坛跳转: