ps:看书比较急,有错误的地方欢迎指正,不细致的地方我会持续的修改

11.8 消除闪烁(2)(harib08h)

11.7 消除闪烁(1)(harib08g)存在的问题: 鼠标放在计时器上会有 闪烁产生原因:会先绘制计时器,再绘制鼠标

书上的解决办法:

创造一个类VRAM,存储 图层号码,用于绘制。优点:似乎也可以同时解决点击问题。缺点:占内存,变复杂

另一种解决办法:

sheet_refresh进行改造,若指定图层上方有与指定图层相交的图层,则不再重绘 相交的区域

需考虑:1.如何判断其上有要显示的图层

struct SHEET *sheet_havehigher(struct SHEET *sht)//判断sht图层上是否有更高的图层
{
struct SHTCTL *ctl;
ctl=sht->ctl;
int i;
i=sht->height;
for (i ; i < MAX_SHEETS; i++) {
if (ctl->sheets0[i].flags == 1) {
return 1; //有
}
}
return 0;//无
}*/ void sheet_refresh(struct SHEET *sht, int bx0, int by0, int bx1, int by1)
{
if (sht->height >= 0) {
if(sheet_havehigher(sht)==0){/*这里!*/
sheet_refreshsub(sht->ctl, sht->vx0 + bx0, sht->vy0 + by0, sht->vx0 + bx1, sht->vy0 + by1, sht->height);
}else{/*这里!*/
sheet_refreshsub(sht->ctl, sht->vx0 + bx0, sht->vy0 + by0, sht->vx0 + bx1, sht->vy0 + by1, sht->height+1);
}
}
return;
}

上面的代码 sheet_havehigher用于判断指定图层上方有没有图层,sheet_refresh用于重绘

但上面的代码并没有解决闪烁问题,反而出现以下问题

数字不会变化,上方的数字也没有变化,只有鼠标滑过其上方才会重绘

上方代码的不足:

我们应该判断指定图层的上方指定区域内有没有比他更高的图层,且是此图层刷新后也需要刷新的,但这里却错误的判断了图层,即也许指定图层的绘制区域在中间,但比他图层高的鼠标在角落,二者并没有相交,也不会绘制指定区域。

结论:单纯利用图层高度无法判断,无法判断遮罩

疑问

在之前对sheet_refreshsub的优化中,似乎已经处理了重叠时的重新描画问题,为什么此处还是因为重绘高速计数器所在的层出现了问题

  • 以下对书上的解决办法进行说明

先对 bootpack.h和sheet.c进行修改,增加map (书P214)

  • sheet_refreshmap
void sheet_refreshmap(struct SHTCTL *ctl, int vx0, int vy0, int vx1, int vy1, int h0)
{
int h, bx, by, vx, vy, bx0, by0, bx1, by1;
unsigned char *buf, sid, *map = ctl->map;
struct SHEET *sht;
if (vx0 < 0) { vx0 = 0; }
if (vy0 < 0) { vy0 = 0; }
if (vx1 > ctl->xsize) { vx1 = ctl->xsize; }
if (vy1 > ctl->ysize) { vy1 = ctl->ysize; }
for (h = h0; h <= ctl->top; h++) {
sht = ctl->sheets[h];
sid = sht - ctl->sheets0; /* 将进行了减法的地址作为图层号码使用 */
buf = sht->buf;
bx0 = vx0 - sht->vx0;
by0 = vy0 - sht->vy0;
bx1 = vx1 - sht->vx0;
by1 = vy1 - sht->vy0;
if (bx0 < 0) { bx0 = 0; }
if (by0 < 0) { by0 = 0; }
if (bx1 > sht->bxsize) { bx1 = sht->bxsize; }
if (by1 > sht->bysize) { by1 = sht->bysize; }
for (by = by0; by < by1; by++) {
vy = sht->vy0 + by;
for (bx = bx0; bx < bx1; bx++) {
vx = sht->vx0 + bx;
if (buf[by * sht->bxsize + bx] != sht->col_inv) {
map[vy * ctl->xsize + vx] = sid;
}
}
}
}
return;
}

作用:从下至上输入map,buf经过多次修改(覆盖),最终buf中的数据即为屏幕上所显示的图层的图层号

  • sheet_refreshsub
void sheet_refreshsub(struct SHTCTL *ctl, int vx0, int vy0, int vx1, int vy1, int h0, int h1)
{
int h, bx, by, vx, vy, bx0, by0, bx1, by1;
unsigned char *buf, *vram = ctl->vram, *map = ctl->map, sid;
struct SHEET *sht;
/* 如果refresh的范围超出了画面则修正 */
if (vx0 < 0) { vx0 = 0; }
if (vy0 < 0) { vy0 = 0; }
if (vx1 > ctl->xsize) { vx1 = ctl->xsize; }
if (vy1 > ctl->ysize) { vy1 = ctl->ysize; }
for (h = h0; h <= h1; h++) {
sht = ctl->sheets[h];
buf = sht->buf;
sid = sht - ctl->sheets0;
/* 利用vx0~vy1,对bx0~by1进行倒推 */
bx0 = vx0 - sht->vx0;
by0 = vy0 - sht->vy0;
bx1 = vx1 - sht->vx0;
by1 = vy1 - sht->vy0;
if (bx0 < 0) { bx0 = 0; }
if (by0 < 0) { by0 = 0; }
if (bx1 > sht->bxsize) { bx1 = sht->bxsize; }
if (by1 > sht->bysize) { by1 = sht->bysize; }
for (by = by0; by < by1; by++) {
vy = sht->vy0 + by;
for (bx = bx0; bx < bx1; bx++) {
vx = sht->vx0 + bx;
if (map[vy * ctl->xsize + vx] == sid) {
/* 如果该层的图层号码与map中的相同,则显示 */
vram[vy * ctl->xsize + vx] = buf[by * sht->bxsize + bx];
}
}
}
}
return;
}

sheet_refreshsub的作用:

根据map中的信息,来绘制

注意:形参有所优化,增加h1,因为有时不需要刷新到最上层,目前不理解在调用函数时是怎么确定h2的,另外,如书中所言,此时未考虑透明与不透明之间的转换

sheet_updown的优化也较为简单,看书P218即可

总结:

产生闪烁的原因,在第一次是因为刷新时会按顺序连指定图层的下方的图层也一起进行刷新,而在第二次是因为会刷新指定图层上方的也需刷新的图层(如鼠标),这样两次刷新会产生闪烁。第一次的解决方案,为缩小从下到上刷新的范围,即之刷新指定图层以上,但这并不能解决第二次的问题。由此产生第二次的解决方案,即书上的方案,另外存储屏幕上显示画面是由哪个图层提供的信息。这就好比,以前我们是用很多张大小不一的纸张叠起来,从一面来看画面,而现在变成了,用拼图(图层的一部分)拼出整个画面。从这个角度,我在上面的疑问中提到的“如何判断其上有要显示的图层”,其解决办法就是书中使用的map,那么还有其他方法吗?不增加map可以做到吗?或者不像map这样记录的过多?现在暂时想不到其他解决方案。

11.8 消除闪烁(2)(harib08h)的更多相关文章

  1. Java中用双缓冲技术消除闪烁

    在Java编写具有连贯变化的窗口程序时,通常的办法是在子类中覆盖父类的paint(Graphics)方法,在方法中使用GUI函数实现窗口重绘的过程.连贯变换的窗口会不断地调用update(Graphi ...

  2. Java swing JFrame用repaint出现闪烁的问题解决

    这几天用swing写登录页面背景动图的时候发现一直会有闪烁(我的类是继承JFrame),就来搜原因后发现好像是因为repaint会调用update()方法中的清屏操作导致闪烁. 我当时看的是这个文章 ...

  3. angular的时间指令 以及防止闪烁问题

    1.点击事件 <!doctype html><html lang="en"><head> <meta charset="UTF- ...

  4. Wtl之奇技淫巧篇:一、SDI如何居中显示视图

    Wtl的sdi应用,视图默认铺满框架的客户区.视图通常用modeless对话框,所有的界面元素都拥挤在左上角,这明显很丑陋.我们尝试让视图居中显示,保持原始大小,这是个很典型的问题,看似简单,诸多细节 ...

  5. 《30天自制操作系统》11_day_学习笔记

    harib08a: 鼠标的显示问题:我们可以看到,鼠标移到窗口最右侧之后就不能再移动了,而WIN中,鼠标是可以移动到最右边隐藏起来的.怎么办?把鼠标指针显示的范围扩宽就行!我们来修改一下HariMai ...

  6. 转:YUV RGB 常见视频格式解析

    转: http://www.cnblogs.com/qinjunni/archive/2012/02/23/2364446.html YUV RGB 常见视频格式解析 I420是YUV格式的一种,而Y ...

  7. YUV格式具体解释

    YUV是指亮度參量和色度參量分开表示的像素格式,而这样分开的优点就是不但能够避免相互干扰,还能够减少色度的採样率而不会对图像质量影响太大.YUV是一个比較笼统地说法,针对它的详细排列方式,能够分为非常 ...

  8. YUY格式

    YUV格式有两大类:planar和packed. 对于planar的YUV格式,先连续存储所有像素点的Y,紧接着存储所有像素点的U,随后是所有像素点的V. 对于packed的YUV格式,每个像素点的Y ...

  9. 图像处理之基础---yuv420及其rgb,bayer, yuv, RGB的相互转换详解

    YUV格式解析1(播放器——project2) 根据板卡api设计实现yuv420格式的视频播放器 打开*.mp4;*.264类型的文件,实现其播放. 使用的视频格式是YUV420格式   YUV格式 ...

  10. 模拟试题A

    模拟试题A 一.单项选择题(2′*12=24′) 1.下面各种坐标变换中,会产生变换前后维度的改变的是( ) A)建模变换 B)观察变换 C)投影变换 D)视口变换 2.下列描述深度缓冲消隐算法的特点 ...

随机推荐

  1. iOS 15 UI适配

    1. UINavigationBar 在iOS 15中,UINavigationBar默认为透明.在滑动时会有模糊效果.如果想要一直就是模糊效果,可以通过改变scrollEdgeAppearance属 ...

  2. 记录 windows RabbitMq 安装教程

    安装地址:https://www.rabbitmq.com/ RabbitMq 官网下载如下两个exe文件,otp_win64_22.0.exe 文件是rabbitmq的运行环境,必须安装!!! 傻子 ...

  3. net/http

    客户端 GET POST form表单 json body二进制流 上传文件 PUT DELETE HEAD 重定向 Client Request Response Cookie CookieJar ...

  4. 如何保证RabbitMQ的消息按照顺序执行???

    可以采用单线程的消费保证消息的顺序性.对消息进行编号,1,2,3,4--消费时按照编号的顺序去消费消息.这样就可以保证消息 按照一定顺序执行.

  5. 2.常用Dos命令

    #盘符切换 D:   C:#查看当前目录下的所有文件 dir#切换目录 cd change directory    #切换盘cd /d D:切换到D盘    #cd..返回上一级# 清理屏幕  CL ...

  6. 【python】绘图,颜色,线型

    颜色 最好用的:在网站上找到对应使用十六进制RGB/RGBA字符串表示颜色 可以看颜色及其对应色号名称:https://xkcd.com/color/rgb/ 参考:matplotlib指定绘图颜色的 ...

  7. windows elasticsearch 7.9.3安装

    1.JDK,我用的是OPEN JDK https://jdk.java.net/    通过CMD设定java环境变量设置    set java_home=C:\Program Files\java ...

  8. Java自增自减运算符

    3.1自增自减运算符 注意事项: ++和--既可以放在变量的后边,也可以放在变量的前边 单独实用的时候,++和--无论是放在变量的前边还是后边,结果是一样的 参与操作的时候,如果放在变量的后边,先拿变 ...

  9. 数组扩展(Java)

    Arrays类 基本介绍 数组的工具类java.util.Arrays 由于数组本身中没有什么方法可供我们调用,但API中提供了一个工具类Arrays供我们使用,从而可以对数据对象进行一些基本操作 查 ...

  10. java学习问题

    1.nacos Connection refused: connect 由于配置文件配置错误引起的.我的nacos是部署在另一台linux服务器的,yml具体配置如下: