这个效果没有使用缓存,可以根据这个思路,把将数据发给屏幕的部分替换成改成写进缓存的
这里用到的几条关键代码,一部分让AI助手进行了优化和添加注释
图标数组部分:
- /* 测试图标:32x32实心方块 */
- const unsigned char code IconsBlock[128]={
- 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
- 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
- 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
- 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
- };
-
-
- /* 图标0:'Finger1' */
- const unsigned char code Icon0[128] = {
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0xEF,0x01,0x01,0x01,0x02,0x1C,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0x80,0xC0,0x20,0x21,0x7F,0xC0,0x00,0x00,0x00,0xFE,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x3C,0xF6,0x82,0x82,0x87,0x7D,0x30,0x40,0x47,0x3C,0x38,0x24,0xC3,0x42,0x42,0x44,0x05,0x07,0x0C,0x08,0x90,0x60,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x1C,0x20,0x40,0x82,0x82,0x82,0x84,0xC0,0x4C,0x83,0x80,0x80,0x40,0x40,0x20,0x10,0x08,0x06,0x01,0x00,0x00,0x00,0x00,0x00,0x00,
- };
-
- /* 图标1:'Finger2' */
- const unsigned char code Icon1[128] = {
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x01,0x01,0x01,0x06,0xFC,0xE0,0x30,0x10,0x10,0x60,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xC0,0x60,0x20,0x20,0x7F,0xC0,0x00,0x00,0x00,0xFF,0xDF,0x00,0x00,0x00,0xE0,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x1E,0x73,0xC1,0x01,0x07,0x38,0xE0,0xC0,0x80,0x83,0x7E,0x71,0x89,0x09,0x09,0x09,0x08,0x08,0x0F,0x08,0x10,0xE0,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x0D,0x31,0x61,0x41,0x82,0x82,0x82,0x84,0x9C,0xC6,0x81,0x81,0x81,0xC0,0x60,0x30,0x18,0x0E,0x01,0x00,0x00,0x00,0x00,0x00,
- };
-
- /* 图标2:'Finger3' */
- const unsigned char code Icon2[128] = {
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0x30,0x10,0x20,0x60,0xC0,0xFE,0x01,0x01,0x01,0x03,0xFC,0x70,0x18,0x08,0x18,0x10,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x83,0x9E,0xF0,0x00,0x00,0x07,0xFF,0x80,0x00,0x00,0x00,0x7F,0x00,0x00,0x00,0xE0,0x3C,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x0C,0xF7,0x61,0x40,0x81,0x07,0x1C,0xE0,0x00,0x00,0x00,0x3C,0xE4,0xC2,0x42,0x42,0x62,0x03,0x04,0x04,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x18,0x60,0x41,0x81,0x81,0x81,0xC2,0x40,0x46,0xC1,0x80,0xC0,0x40,0x60,0x30,0x18,0x06,0x01,0x00,0x00,0x00,0x00,0x00,0x00,
- };
-
- /* 图标3:'Finger4' */
- const unsigned char code Icon3[128] = {
- 0x00,0x00,0x00,0x00,0x00,0x80,0x80,0x80,0xE0,0xB0,0x08,0x08,0x08,0x38,0xFE,0x83,0x01,0x01,0x03,0xFE,0x18,0x04,0x04,0x04,0x0C,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x0F,0x71,0x80,0x00,0x01,0x07,0x3E,0xF8,0x80,0x00,0x01,0x7F,0xE0,0x00,0x00,0x0F,0xF0,0x00,0x00,0x00,0xF0,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x06,0x38,0xE0,0x00,0x03,0x1F,0x98,0x88,0x08,0x05,0x04,0x84,0x7E,0x21,0x21,0x21,0x21,0x01,0x03,0xC6,0x3C,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x20,0x40,0x80,0x80,0x80,0xC1,0x43,0x43,0x41,0xC0,0xC0,0x40,0x60,0x30,0x18,0x06,0x01,0x00,0x00,0x00,0x00,0x00,
- };
-
- /* 图标4:'Finger5' */
- const unsigned char code Icon4[128] = {
- 0x00,0x00,0x00,0x00,0x00,0xF0,0x08,0x08,0x08,0x18,0x30,0xE0,0xFC,0x03,0x01,0x01,0x06,0xF8,0xF8,0x04,0x04,0x04,0x0C,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x10,0xF8,0x08,0x08,0x08,0x08,0x33,0xFC,0xE0,0x00,0x00,0x00,0x3F,0xC0,0x00,0x00,0x00,0x0F,0xFF,0x00,0x00,0x00,0xC0,0xFF,0xC0,0x40,0x20,0x20,0x20,0x40,0xC0,0x00,
- 0x00,0x00,0x07,0x0C,0x10,0x60,0x80,0x00,0x07,0x1E,0x10,0x88,0x88,0x8B,0x0C,0x04,0x04,0x84,0xC5,0x40,0x00,0x30,0x3F,0x0F,0x00,0x80,0x40,0x60,0x30,0x10,0x0F,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x38,0x60,0x40,0xC0,0x80,0x80,0xC1,0x41,0x5E,0xC7,0x81,0x80,0x80,0xC0,0x40,0x30,0x1E,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- };
-
- /*
- * 指针数组:每一项存放一个图标字模数组的首地址。
- * 用法:
- * ShowIcon(x, y0, IconsPtr[i]); // i = 0~4,即可显示第 i 个图标
- * 后期要更换图标时,只需把某个位置替换成新数组名(或新数组地址)即可,
- * 其它调用代码无需改动,实现"随时改变图标数组"。
- */
- const unsigned char code * const IconsPtr[5] = {
- Icon0, /* 索引 0:'Finger1' */
- Icon1, /* 索引 1:'Finger2' */
- Icon2, /* 索引 2:'Finger3' */
- Icon3, /* 索引 3:'Finger4' */
- Icon4 /* 索引 4:'Finger5' */
- };
复制代码
- #define IconsMaxNum 5 /* 图标总数(编号范围 0 ~ IconsMaxNum-1,即 0~4) */
复制代码
显示图标和擦除拖尾的两个函数
- /**************************************************************************
- * 函数名:ShowIcon
- * 功能 :在 OLED 指定位置显示一个 32x32 像素的图标,支持图标移出屏幕
- * 边缘时的自动裁剪(只画屏幕内可见部分),并对起始页号做越界保护。
- * 参数 :
- * x —— 图标左上角在屏幕上的 X 坐标(可为负,表示图标向左移出屏幕)
- * y0 —— 图标左上角所在的起始页号(一页 8 像素,图标共 4 页 = 32 像素高)
- * ICON —— 图标点阵数据首地址(存放在 code 区,每个图标固定 32*4=128 字节)
- * 返回 :无
- * 说明 :
- * 1. 图标固定尺寸为 32 列 x 32 像素(32 列,4 页)。
- * 2. 点阵数据按"页优先"排列:ICON[page*32 + 列号],即每页连续 32 字节。
- * 3. 本函数要求图标能在屏幕上完整放下 4 页,因此 y0 最大只能到 4
- * (4+4=8 页,恰好放在 128x64 屏的底部),y0>4 直接返回不显示。
- * 4. 依据 x 的位置分三种情况处理,算出实际可见宽度 IconWidth
- * 和源数据起始偏移 ColumnStart:
- * - x<0 :图标左半部分移出屏幕左侧,屏幕起点 x0 归 0,
- * 源数据跳过被遮挡的左边部分(从 ColumnStart 列开始取);
- * - x>96 :图标右半部分超出屏幕右侧(96+32=128),只画剩余宽度;
- * - 其余 :图标完整落在屏幕内,宽度为 32。
- * 5. x<-32 或 x>=128 时图标完全不可见,直接返回。
- * 6. 逐页(共 4 页)定位光标,把该页中可见的 IconWidth 列数据写入 OLED。
- **************************************************************************/
- void ShowIcon( int x, u8 y0, const u8 code *ICON )
- {
- u8 IconWidth, ColumnStart = 0, x0 = x; /* IconWidth:实际可见宽度; ColumnStart:源数据起始列偏移; x0:屏幕实际起始列 */
- u8 page, i;
-
- if( y0>4 ) return; /* 起始页越界保护:y0+4 超过 8 页会写出屏外,直接返回 */
-
- if( x<0 ) /* ==== 情况1:图标左侧移出屏幕 ==== */
- {
- if( x>-32 ) /* 图标还有部分可见(x 在 -31~-1 之间) */
- {
- IconWidth = 32+x; /* 可见宽度 = 32 - 移出宽度(|x|) */
- ColumnStart = 32-IconWidth; /* 源数据从被遮挡处开始取,跳过不可见的左边部分 */
- x0=0; /* 从屏幕第 0 列开始显示 */
- }
- else return; /* x<=-32,图标完全移出屏幕,不显示 */
- }
- else if( x>96 ) /* ==== 情况2:图标右侧超出屏幕(96=128-32) ==== */
- {
- if( x<128 ) /* 图标还有部分可见 */
- {
- IconWidth = 128-x; /* 可见宽度 = 屏幕右边界 128 - 起始列 x */
- }
- else return; /* x>=128,图标完全移出屏幕右侧,不显示 */
- }
- else /* ==== 情况3:图标完整位于屏幕内(0<=x<=96) ==== */
- {
- IconWidth = 32; /* 完整宽度 32 列 */
- }
-
- for( page=0; page<4; page++ ) /* 逐页绘制,图标高 4 页(32 像素) */
- {
- OLED_Set_Pos( x0, y0+page ); /* 定位到当前页的实际起始列 x0 */
- for( i=0; i<IconWidth; i++ ) /* 只写入可见的 IconWidth 列 */
- {
- OLED_WR_Byte( ICON[page*32+i+ColumnStart], OLED_DATA ); /* 取源点阵数据写 OLED */
- }
- }
- }
-
- /**************************************************************************
- * 函数名:OLED_ClearPages
- * 功能 :局部清屏。清除从起始页 pStart 到结束页 pEnd 之间的显示内容
- * (将指定页范围内的所有列数据全部写 0x00,即该页区域全黑)
- * 参数 :
- * pStart —— 起始页地址(页号)
- * pEnd —— 结束页地址(页号),需满足 pStart <= pEnd
- * 返回 :无
- * 说明 :
- * 1. OLED 屏按"页-列"组织,一页高 8 像素,横向共 128 列。
- * 2. 每清一页:先把光标定位到该页的第 0 列,再连续写 128 个
- * 0x00(数据模式 OLED_DATA),把该页整行 128 列的点阵清空。
- * 3. 遍历 pStart 至 pEnd 的所有页即可完成指定区域的清除。
- * 4. 若要全屏清屏,调用时令 pStart=0、pEnd=最大页号即可。
- **************************************************************************/
- void OLED_ClearPages( u8 pStart, u8 pEnd )
- {
- u8 pagenum, i;
-
- for( pagenum=pStart; pagenum<=pEnd; pagenum++ ) /* 逐页遍历:从起始页到结束页 */
- {
- OLED_Set_Pos( 0, pagenum ); /* 光标定位到当前页的第 0 列 */
- for( i=0; i<128; i++) /* 连续写满整页 128 列 */
- {
- OLED_WR_Byte( 0x00, OLED_DATA ); /* 写入数据 0x00,该列点阵全灭 */
- }
- }
- }
-
-
- /**************************************************************************
- * 函数名:ClearIconsSide
- * 功能 :清除 OLED 上某一列的显示内容(把该列 4 个页全部写 0x00)。
- * 主要用于滑动动画中清掉图标移动后留下的残影。
- * 参数 :
- * x —— 要清除的列坐标(0~127)
- * page —— 起始页号(该列从 page 页开始,连续清 4 页 = 32 像素高)
- * 返回 :无
- * 说明 :
- * 1. 先判断列坐标 x 是否在屏幕有效范围(0~127)内:
- * 越界则直接返回,避免向屏外地址写数据。
- * 2. 在有效范围内,对该列从 page 起连续 4 页各写一个 0x00:
- * - OLED_Set_Pos(x, page+i) 把光标定位到第 page+i 页、第 x 列;
- * - OLED_WR_Byte(0x00, OLED_DATA) 写入数据 0x00,清空该页该列
- * 8 个像素点。
- * 3. 连续清 4 页(i=0~3),正好覆盖一个 32 像素高的图标区域,
- * 因此本函数常与高 4 页的图标(如 32x32 图标)配合使用。
- **************************************************************************/
- void ClearIconsSide( int x, int page )
- {
- u8 i;
-
- if( x>=0 && x<128 ) /* 列坐标有效性判断:必须在 0~127 内 */
- {
- for( i=0; i<4; i++ ) /* 从起始页起,连续清除 4 页(共 32 像素高) */
- {
- OLED_Set_Pos( x, page+i ); /* 定位到第 page+i 页、第 x 列 */
- OLED_WR_Byte( 0x00, OLED_DATA ); /* 写入 0x00,清除该列当前页的点阵 */
- }
- }
- else return; /* x 越界(屏外),不操作直接返回 */
- }
复制代码
单向滑动的函数
- /**************************************************************************
- * 函数名:IconsSlideLeft
- * 功能 :以【整体向左滑动 43 列】的动画,把图标滚动切换,使【屏幕中间】
- * 最终停在编号为 IconNum 的图标上(终点 = ShowIconsCurrent(IconNum))。
- * 参数 :
- * IconNum —— 动画结束后停在屏幕中间的图标编号(int)
- * 返回 :无
- * 说明 :
- * 1. 可见三位置固定坐标:左 x=5、中 x=48、右 x=91,间距 43 列。
- * 起点布置为"中位置 = IconNum-1",整体左移 43 列后中位置落到 IconNum。
- * 2. 4 个槽位(含屏外第3槽 x=134)对应编号:IconNum-2 ~ IconNum+1,
- * 超出 0 ~ IconsMaxNum-1 的槽位不绘制(保持空白)。
- * 3. 每步:先 ClearIconsSide 清原图标最右列(画图列+33),再左移一列重画。
- * 4. 边界处理:
- * IconNum < 0 :钳位为 0,直接返回(不重画);
- * IconNum > IconsMaxNum-1 :钳位为 IconsMaxNum-1,直接返回(不重画);
- * IconNum == 0 :起点终点相同,直接返回(不重画)。
- * 正常菜单操作(每次增减1)时,上一帧画面即为本帧应显示画面,
- * 无需重画;首次调用请先 ShowIconsCurrent(IconNum) 初始化。
- * 5. 每步延时 delay_ms(10),共 43 步约 430ms。
- **************************************************************************/
- void IconsSlideLeft( int IconNum )
- {
- int x[4] = { 5, 48, 91, 134 }; /* 4 个槽位当前画图列坐标 */
- int c[4] = { 38, 81, 124, 167 }; /* 4 个槽位需清除列坐标(画图列+33) */
- int n = 43; /* 滑动总列数 */
- int k, idx;
-
- /* --- 越界钳位 --- */
- if( IconNum < 0 ) IconNum = 0;
- if( IconNum > IconsMaxNum - 1 ) IconNum = IconsMaxNum - 1;
-
- /* --- 边界值:起点终点相同,直接返回(不重画,避免空转) --- */
- if( IconNum == 0 )
- {
- return;
- }
-
- /* --- 逐列左滑:先清后画(自擦自画,终点精确落位) --- */
- while( n-- )
- {
- for( k=0; k<4; k++ )
- {
- ClearIconsSide( c[k], 0 ); /* 清本槽右侧残影列 */
- idx = IconNum + k - 2; /* 本槽图标编号 */
- if( idx >= 0 && idx < IconsMaxNum )
- {
- ShowIcon( x[k], 0, IconsPtr[ idx ] );
- }
- }
- for( k=0; k<4; k++ ) { x[k]--; c[k]--; }
- delay_ms( IconsSlideSpeed );
- }
- }
-
- /**************************************************************************
- * 函数名:IconsSlideRight
- * 功能 :以【整体向右滑动 43 列】的动画,把图标滚动切换,使【屏幕中间】
- * 最终停在编号为 IconNum 的图标上(终点 = ShowIconsCurrent(IconNum))。
- * 参数 :
- * IconNum —— 动画结束后停在屏幕中间的图标编号(int)
- * 返回 :无
- * 说明 :
- * 1. 可见三位置固定坐标:左 x=5、中 x=48、右 x=91,间距 43 列。
- * 起点布置为"中位置 = IconNum+1",整体右移 43 列后中位置落到 IconNum。
- * 2. 4 个槽位(含屏外第0槽 x=-38)对应编号:IconNum-1 ~ IconNum+2,
- * 超出 0 ~ IconsMaxNum-1 的槽位不绘制(保持空白)。
- * 3. 每步:先右移一列坐标,再 ClearIconsSide 清原图标最左列(新位置-1),
- * 然后在右移后的位置重画(自擦自画,终点精确落位)。
- * 4. 边界处理:
- * IconNum < 0 :钳位为 0,直接返回(不重画);
- * IconNum > IconsMaxNum-1 :钳位为 IconsMaxNum-1,直接返回(不重画);
- * IconNum == IconsMaxNum-1 :起点终点相同,直接返回(不重画)。
- * 5. 每步延时 delay_ms(10),共 43 步约 430ms。
- **************************************************************************/
- void IconsSlideRight( int IconNum )
- {
- int x[4] = { -38, 5, 48, 91 }; /* 4 个槽位当前画图列坐标(含屏外第0槽) */
- int c[4] = { -39, 4, 47, 90 }; /* 4 个槽位需清除列坐标(画图列-1) */
- int n = 43; /* 滑动总列数 */
- int k, idx;
-
- /* --- 越界钳位 --- */
- if( IconNum < 0 ) IconNum = 0;
- if( IconNum > IconsMaxNum - 1 ) IconNum = IconsMaxNum - 1;
-
- /* --- 边界值:起点终点相同,直接返回(不重画,避免空转) --- */
- if( IconNum == IconsMaxNum - 1 )
- {
- return;
- }
-
- /* --- 逐列右滑:先移后画(自擦自画,终点精确落位) --- */
- while( n-- )
- {
- for( k=0; k<4; k++ ) { x[k]++; c[k]++; } /* 先右移一列 */
- for( k=0; k<4; k++ )
- {
- ClearIconsSide( c[k], 0 ); /* 清本槽左侧残影列 */
- idx = IconNum + k - 1; /* 本槽图标编号 */
- if( idx >= 0 && idx < IconsMaxNum )
- {
- ShowIcon( x[k], 0, IconsPtr[ idx ] );
- }
- }
- delay_ms( IconsSlideSpeed );
- }
- }
复制代码
循环滑动的函数
- /**************************************************************************
- * 函数名:IconsSLoopLeft
- * 功能 :以【整体向左滑动 43 列】的循环滚动动画,把图标向左切换一格,
- * 使【屏幕中间】最终停在编号为 IconNum 的图标上,且 4 个槽位
- * 始终填满 5 个图标(取模循环),不存在空白。
- * 参数 :
- * IconNum —— 动画结束后停在屏幕中间的图标编号(0 ~ IconsMaxNum-1)。
- * 本函数为循环滚动,参数任意值均合法,不需要钳位。
- * 返回 :无
- * 说明 :
- * 1. 可见三位置固定坐标:左 x=5、中 x=48、右 x=91,间距 43 列;
- * 屏外第 4 槽 x=134,用于滑入。
- * 2. 起点布置(语义 A):4 槽编号 = IconNum-2、IconNum-1、IconNum、IconNum+1,
- * 全部对 IconsMaxNum 取模,保证 4 个槽始终有图标。
- * 整体左移 43 列后,槽0 的 IconNum-1 落到中位置,终点中位置 = IconNum。
- * 3. 每步:先逐一 ClearIconsSide 清各槽右侧残影列,再左移一列重画,
- * 自擦自画,终点精确落位,无缝循环。
- * 4. 循环取模公式(防负数):
- * idx = ((idx % IconsMaxNum) + IconsMaxNum) % IconsMaxNum;
- * 5. 每步延时 delay_ms( IconsSlideSpeed ),共 43 步。
- **************************************************************************/
- void IconsLoopLeft( int IconNum )
- {
- int x[4] = { 5, 48, 91, 134 }; /* 4 个槽位当前画图列坐标 */
- int c[4] = { 38, 81, 124, 167 }; /* 4 个槽位需清除列坐标(画图列+33) */
- int n = 43; /* 滑动总列数 */
- int k, idx;
-
- /* --- 逐列左滑:先清后画(自擦自画,终点精确落位) --- */
- while( n-- )
- {
- for( k=0; k<4; k++ )
- {
- ClearIconsSide( c[k], 0 ); /* 清本槽右侧残影列 */
- idx = IconNum + k - 2; /* 本槽图标编号(未取模) */
- idx = ((idx % IconsMaxNum) + IconsMaxNum) % IconsMaxNum; /* 循环取模到 0~4 */
- ShowIcon( x[k], 0, IconsPtr[ idx ] ); /* 恒有图标,直接画 */
- }
- for( k=0; k<4; k++ ) { x[k]--; c[k]--; } /* 4 槽整体左移一列 */
- delay_ms( IconsSlideSpeed );
- }
- }
-
-
- /**************************************************************************
- * 函数名:IconsSLoopRight
- * 功能 :以【整体向右滑动 43 列】的循环滚动动画,把图标向右切换一格,
- * 使【屏幕中间】最终停在编号为 IconNum 的图标上,且 4 个槽位
- * 始终填满 5 个图标(取模循环),不存在空白。
- * 参数 :
- * IconNum —— 动画结束后停在屏幕中间的图标编号(0 ~ IconsMaxNum-1)。
- * 本函数为循环滚动,参数任意值均合法,不需要钳位。
- * 返回 :无
- * 说明 :
- * 1. 可见三位置固定坐标:左 x=5、中 x=48、右 x=91,间距 43 列;
- * 屏外第 0 槽 x=-38,用于从左侧滑入。
- * 2. 起点布置(语义 A):4 槽编号 = IconNum-1、IconNum、IconNum+1、IconNum+2,
- * 全部对 IconsMaxNum 取模,保证 4 个槽始终有图标。
- * 整体右移 43 列后,槽1 的 IconNum-1 落到中位置,终点中位置 = IconNum。
- * 3. 每步:先把 4 槽坐标整体右移一列,再逐一 ClearIconsSide 清各槽左侧
- * 残影列,然后在右移后的位置重画,自擦自画,终点精确落位,无缝循环。
- * 4. 循环取模公式(防负数):
- * idx = ((idx % IconsMaxNum) + IconsMaxNum) % IconsMaxNum;
- * 5. 每步延时 delay_ms( IconsSlideSpeed ),共 43 步。
- **************************************************************************/
- void IconsLoopRight( int IconNum )
- {
- int x[4] = { -38, 5, 48, 91 }; /* 4 个槽位当前画图列坐标(含屏外第0槽) */
- int c[4] = { -39, 4, 47, 90 }; /* 4 个槽位需清除列坐标(画图列-1) */
- int n = 43; /* 滑动总列数 */
- int k, idx;
-
- /* --- 逐列右滑:先移后画(自擦自画,终点精确落位) --- */
- while( n-- )
- {
- for( k=0; k<4; k++ ) { x[k]++; c[k]++; } /* 先整体右移一列 */
- for( k=0; k<4; k++ )
- {
- ClearIconsSide( c[k], 0 ); /* 清本槽左侧残影列 */
- idx = IconNum + k - 1; /* 本槽图标编号(未取模) */
- idx = ((idx % IconsMaxNum) + IconsMaxNum) % IconsMaxNum; /* 循环取模到 0~4 */
- ShowIcon( x[k], 0, IconsPtr[ idx ] ); /* 恒有图标,直接画 */
- }
- delay_ms( IconsSlideSpeed );
- }
- }
复制代码
这几个滑动函数的参数,是移动之后停留在中间位置的图标的编号,调用的时候可以用一个变量来指定
- int MenuIndex = 0; /* 当前菜单编号 */
复制代码
单向滑动测试
- if( !P01 && MenuIndex < IconsMaxNum - 1 )
- {
- MenuIndex++;
- IconsSlideLeft( MenuIndex ); /* 菜单左滑 */
- ShowIconInfo( MenuIndex );
- }
- else if( !P00 && MenuIndex > 0 )
- {
- MenuIndex--;
- IconsSlideRight( MenuIndex ); /* 菜单右滑 */
- ShowIconInfo( MenuIndex );
- }
复制代码
循环滑动测试
- if( !P01 ) /* P01 按下:向左滚动,编号 +1(循环) */
- {
- MenuIndex = ( MenuIndex + 1 ) % IconsMaxNum; /* 加 1 取模,4->0 自动回绕 */
- IconsLoopLeft( MenuIndex ); /* 菜单左滑 */
- ShowIconInfo( MenuIndex ); /* 更新图标下方信息 */
- }
- else if( !P00 ) /* P00 按下:向右滚动,编号 -1(循环) */
- {
- MenuIndex = ( MenuIndex + IconsMaxNum - 1 ) % IconsMaxNum; /* 加 4 取模,0->4 自动回绕 */
- IconsLoopRight( MenuIndex ); /* 菜单右滑 */
- ShowIconInfo( MenuIndex ); /* 更新图标下方信息 */
- }
复制代码
初始化时预先把图标显示在指定位置上,还有显示文字的部分,跟你的思路相同就不放了
|