11.8 消除闪烁(2)(harib08h)
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)的更多相关文章
- Java中用双缓冲技术消除闪烁
在Java编写具有连贯变化的窗口程序时,通常的办法是在子类中覆盖父类的paint(Graphics)方法,在方法中使用GUI函数实现窗口重绘的过程.连贯变换的窗口会不断地调用update(Graphi ...
- Java swing JFrame用repaint出现闪烁的问题解决
这几天用swing写登录页面背景动图的时候发现一直会有闪烁(我的类是继承JFrame),就来搜原因后发现好像是因为repaint会调用update()方法中的清屏操作导致闪烁. 我当时看的是这个文章 ...
- angular的时间指令 以及防止闪烁问题
1.点击事件 <!doctype html><html lang="en"><head> <meta charset="UTF- ...
- Wtl之奇技淫巧篇:一、SDI如何居中显示视图
Wtl的sdi应用,视图默认铺满框架的客户区.视图通常用modeless对话框,所有的界面元素都拥挤在左上角,这明显很丑陋.我们尝试让视图居中显示,保持原始大小,这是个很典型的问题,看似简单,诸多细节 ...
- 《30天自制操作系统》11_day_学习笔记
harib08a: 鼠标的显示问题:我们可以看到,鼠标移到窗口最右侧之后就不能再移动了,而WIN中,鼠标是可以移动到最右边隐藏起来的.怎么办?把鼠标指针显示的范围扩宽就行!我们来修改一下HariMai ...
- 转:YUV RGB 常见视频格式解析
转: http://www.cnblogs.com/qinjunni/archive/2012/02/23/2364446.html YUV RGB 常见视频格式解析 I420是YUV格式的一种,而Y ...
- YUV格式具体解释
YUV是指亮度參量和色度參量分开表示的像素格式,而这样分开的优点就是不但能够避免相互干扰,还能够减少色度的採样率而不会对图像质量影响太大.YUV是一个比較笼统地说法,针对它的详细排列方式,能够分为非常 ...
- YUY格式
YUV格式有两大类:planar和packed. 对于planar的YUV格式,先连续存储所有像素点的Y,紧接着存储所有像素点的U,随后是所有像素点的V. 对于packed的YUV格式,每个像素点的Y ...
- 图像处理之基础---yuv420及其rgb,bayer, yuv, RGB的相互转换详解
YUV格式解析1(播放器——project2) 根据板卡api设计实现yuv420格式的视频播放器 打开*.mp4;*.264类型的文件,实现其播放. 使用的视频格式是YUV420格式 YUV格式 ...
- 模拟试题A
模拟试题A 一.单项选择题(2′*12=24′) 1.下面各种坐标变换中,会产生变换前后维度的改变的是( ) A)建模变换 B)观察变换 C)投影变换 D)视口变换 2.下列描述深度缓冲消隐算法的特点 ...
随机推荐
- 网络编程之 urllib 模块
首先urlib并不是一个很好用的方法,这里仅作简单介绍.一般我们用requests方法来代替urlib方法. 1. get请求 1 from urllib import request 2 url = ...
- Java根据经纬度计算两点之间的距离
public final class DistanceUtils { /** * 地球半径,单位 km */ private static final double EARTH_RADIUS = 63 ...
- 建议收藏| 学python的看过来,Python 史上最全第三方库收集
发现一个宝藏网站: GitHub 上有一个 Awesome - XXX 系列的资源整理,这个系列以"全"闻名,但凡是有一定知识度的领域.语言.框架等,都有自己的 awesome-x ...
- vue后台管理系统——商品管理模块
电商后台管理系统的功能--商品管理模块 商品管理概述 商品管理模块用于维护电商平台的商品信息,包括商品的类型.参数.图片.详情等信息. 通过商品管理模块可以实现商品的添加.修改.展示和删除等功能. 1 ...
- mysql之存储引擎-第二篇
什么是存储引擎? 数据库存储引擎是数据库底层软件组件,数据库管理系统使用数据引擎进行创建,查询,更新和删除数据操作.不同的存储引擎提供了不同的存储机制,索引技巧及特定功能. 存储引擎类型 InnoDB ...
- AX2012 快速清空整个log表数据
如果当一个log表的数据非常大的时又需要清理时,如果允许删除全部数据,在AX里,可以 将log表的TableType调整为[TempDB], 保存同步后再将TableType设置回[Regular]即 ...
- LeetCode刷题感想之滑动窗口
发现滑动窗口也是一种经典解题思路,这一篇简单聊一下滑动窗口. 通常在碰到求XX子数组,子字符串,连续XX等题眼,可以考试用滑动窗口的思路来解决问题. 窗口的类型有几种: 1. 固定长度的窗口. 2. ...
- MongoDB:内嵌文档查询匹配 查询集合中的文档
1.db.getCollection('Notification').find({ Title:{$regex:/班/}, "Message.TargetUrl":{$regex: ...
- 三、JMeter实战-快速上手JMeter
1.JMeter基本操作 线JMeter最基本的操作有三个步骤: 先添加一个线程组. 添加HTTP请求. 添加查看结果树. 1.1.添加线程组 在测试计划下新建一个线程组 1.2.添加HTTP请求 在 ...
- MySQL分库分表原理
转自https://www.jianshu.com/p/7aec260ca1a2 前言 在互联网还未崛起的时代,我们的传统应用都有这样一个特点:访问量.数据量都比较小,单库单表都完全可以支撑整个业务. ...