时钟"/>
C语言俄罗斯方块时钟
C语言俄罗斯方块时钟
这个小程序是因为在某宝上看见一款点阵屏俄罗斯方块时钟,感觉很有意思就想在自己的stm32f469开发板上抄袭一下,看看效果,大家想玩一玩的可以参考一下,核心代码在下面。
先看一下效果图
当时间改变,每个数字是由小的俄罗斯方块逐渐累加起来的,不是视频看不到效果。
下面是一些const数据用来定义俄罗斯方块基础形状及每个数字下落的方块序列
/* config grid */
#define GRID_SIZE 14
#define GRID_ROW_NUM (RK043FN48H_HEIGHT/GRID_SIZE-6)
#define GRID_COL_NUM (RK043FN48H_WIDTH/GRID_SIZE-1)/* config number and colon position */
#define NUMBER_COUNT 4
#define FIRST_NUMBER_OFFSET 1
#define SECOND_NUMBER_OFFSET 8
#define THIRD_NUMBER_OFFSET 18
#define FOURTH_NUMBER_OFFSET 25
#define COLON_OFFSET_X 15
#define COLON_OFFSET_Y 5uint16_t u16GridMap[GRID_ROW_NUM * GRID_COL_NUM];
uint8_t u8ClockNumber[NUMBER_COUNT+1] = {0, 0, 0, 0, 0};
stTetrisClockHandle stTetrisNumHandle[NUMBER_COUNT];
struct tm *p_tm;const uint32_t u32ColorRgb565Table[] =
{SCRLET ,CAMEL ,SUN_ORANGE ,LAWN_GREEN ,FOREST_GREEN ,MARINE_BLUE ,CHROME_YELLOW ,DARK_SLATE_BLUE ,CAYN_BLUE ,RUBY ,MIDIUM_TURQUOISE ,VERIDIAN ,LIGHT_LIME ,INDIAN_RED ,MAROON ,MISTY_ROSE ,LIGHT_CORAL ,HELIOTROPE ,
};const stNumSeqBase au8NumZeroTerisSeq[] =
{{18, 3}, {4, 1}, {9, 3}, {9, -1}, {5, 0}, {5, 4}, {5, 4}, {11, 0}, {0, 0}, {9, 0},{6, 2}, {19, 4}
};
const stNumSeqBase au8NumOneTerisSeq[] =
{{3, 4}, {17, 3}, {19, 4}, {17, 3}, {19, 4}
};
const stNumSeqBase au8NumTwoTerisSeq[] =
{{18, 3}, {14, 0}, {1, 1}, {2, 4}, {18, 3}, {14, 0}, {1, 1}, {2, 4}, {2, 2}, {0, 1}, {0, 0}
};
const stNumSeqBase au8NumThreeTerisSeq[] =
{{18, 3}, {14, 0}, {1, 1}, {0, 5}, {19, 3}, {14, 0}, {1, 1}, {2, 4}, {1, 1}, {12, 3}, {16, 0}
};
const stNumSeqBase au8NumFourTerisSeq[] =
{{2, 4}, {2, 4}, {2, 0}, {2, 0}, {18, 3}, {14, 0}, {1, 1}, {2, 4}, {2, 4}
};
const stNumSeqBase au8NumFiveTerisSeq[] =
{{2, 4, 8}, {2, 2, 8}, {0, 1}, {0, 0}, {1, 1}, {16, 0, 4}, {12, 3}, {2, 4}, {1, 1}, {12, 3},{16, 0}
};
const stNumSeqBase au8NumSixTerisSeq[] =
{{2, 4, 8}, {2, 2, 8}, {0, 1}, {0, 0}, {1, 1}, {16, 0}, {12, 3}, {2, 4}, {2, 0}, {1, 1},{12, 3},{16, 0}
};
const stNumSeqBase au8NumSevenTerisSeq[] =
{{18, 3}, {14, 0}, {1, 1}, {17, 3}, {0, 5}, {13, 3}, {2, 4}
};
const stNumSeqBase au8NumEightTerisSeq[] =
{{15, 4}, {1, 0}, {1, 1}, {7, 4}, {7, 0}, {16, 0}, {12, 1}, {9, 3}, {7, 0}, {12, 2}, {0, 5},{9, -1},{1, 1}
};
const stNumSeqBase au8NumNineTerisSeq[] =
{{10, 2}, {4, 0}, {5, 4}, {9, -1}, {12, 2}, {0, 5}, {5, 0}, {1, 1}, {2, 4}, {1, 2}, {1, 2}, {2, 0}
};const stNumSeqBase *stNumSeqArrayTable[] =
{au8NumZeroTerisSeq ,au8NumOneTerisSeq ,au8NumTwoTerisSeq ,au8NumThreeTerisSeq ,au8NumFourTerisSeq ,au8NumFiveTerisSeq ,au8NumSixTerisSeq ,au8NumSevenTerisSeq ,au8NumEightTerisSeq ,au8NumNineTerisSeq ,
};const uint16_t u16NumSeqArraySize[] =
{sizeof(au8NumZeroTerisSeq )/sizeof(stNumSeqBase),sizeof(au8NumOneTerisSeq )/sizeof(stNumSeqBase),sizeof(au8NumTwoTerisSeq )/sizeof(stNumSeqBase),sizeof(au8NumThreeTerisSeq)/sizeof(stNumSeqBase),sizeof(au8NumFourTerisSeq )/sizeof(stNumSeqBase),sizeof(au8NumFiveTerisSeq )/sizeof(stNumSeqBase),sizeof(au8NumSixTerisSeq )/sizeof(stNumSeqBase),sizeof(au8NumSevenTerisSeq)/sizeof(stNumSeqBase),sizeof(au8NumEightTerisSeq)/sizeof(stNumSeqBase),sizeof(au8NumNineTerisSeq )/sizeof(stNumSeqBase),
};//这个是俄罗斯方块在一个9x9像素点中的坐标
//就是这样(x,x)(x,x)(x,x)(x,x),每个坐标2bit, 组成一个16bit数据
const uint16_t u16BasicModelTable[20] = {/* #* #* #* #*/0xC840,/* 0 *//* # # # #*/0x3210,/* 1 *//* # #* # #*/0x5410,/* 2 *//* # #* # #*/0x5410,/* 3 *//* # #* # #*/0x6510,/* 4 *//* #* # #* #*/0x8541,/* 5 *//* # #* # #*/0x5421,/* 6 *//* #* # #* #*/0x9540,/* 7 *//* #* # # #*/0x6541,/* 8 *//* #* # #* #*/0x9651,/* 9 *//* # # #* #*/0x9654,/* 10 *//* #* # #* #*/0x9541,/* 11 *//* #* # # #*/0x6542,/* 12 *//* #* #* # #*/0xA951,/* 13 *//* # # #* #*/0x8654,/* 14 *//* # #* #* #*/0x9510,/* 15 *//* #* # # #*/0x6540,/* 16 *//* # #* #* #*/0x9521,/* 17 *//* # # #* #*/0xA654,/* 18 *//* #* #* # #*/0x9851, /* 19 */
};
下面是显示的main函数,10ms调用周期,可以自己改,把对应延时设置好就可以。
void tetris_main(void)
{static uint8_t u8LastSec = 0xff;static uint8_t u8LastDay = 0xff;static uint32_t u8AnimDelay = 0;stTetrisClockHandle *handle = NULL;uint32_t u32RandomColor = 0;int16_t xx, yy;uint8_t u8RandomNum = 0;uint8_t u8MinuteChange = TetrisClockUpdateTime(u8ClockNumber);if (u8MinuteChange) {/* clean screen and grid map */BSP_LCD_SetTextColor(LCD_COLOR_BLACK);BSP_LCD_FillRect(0, 0, RK043FN48H_WIDTH, 200);rt_memset(u16GridMap, 0, sizeof(u16GridMap));/* init handle */for (uint16_t i = 0; i < NUMBER_COUNT; i++) {handle = &stTetrisNumHandle[i];u8RandomNum = HAL_RNG_GetRandomNumber(&hrng);/* set clock number offset */(i == 0) && (handle->u16TerisXOffset = FIRST_NUMBER_OFFSET);(i == 1) && (handle->u16TerisXOffset = SECOND_NUMBER_OFFSET);(i == 2) && (handle->u16TerisXOffset = THIRD_NUMBER_OFFSET);(i == 3) && (handle->u16TerisXOffset = FOURTH_NUMBER_OFFSET);/* init paramter */handle->pNumSeq = stNumSeqArrayTable[u8ClockNumber[i]];handle->u8SeqIdx = u16NumSeqArraySize[u8ClockNumber[i]] - 1;handle->u32TerisColor = u32ColorRgb565Table[u8RandomNum % (sizeof(u32ColorRgb565Table)/sizeof(uint32_t))];handle->u16TerisMode = u16BasicModelTable[handle->pNumSeq[handle->u8SeqIdx].u8ModeIdx];handle->u16TerisX = handle->pNumSeq[handle->u8SeqIdx].u8DefX + handle->u16TerisXOffset;handle->u16TerisY = 0;handle->u8EndFlag = 0;}}/* delay 80 ms */if (++u8AnimDelay % 8 == 0) {/* draw clock number loop */for (uint16_t i = 0; i < NUMBER_COUNT; i++) {handle = &stTetrisNumHandle[i];/* update next tetris mode */if (handle->u8EndFlag) {if (handle->u8SeqIdx == 0)continue;u8RandomNum = HAL_RNG_GetRandomNumber(&hrng);handle->u8SeqIdx--;handle->u32TerisColor = u32ColorRgb565Table[u8RandomNum % (sizeof(u32ColorRgb565Table)/sizeof(uint32_t))];handle->u16TerisMode = u16BasicModelTable[handle->pNumSeq[handle->u8SeqIdx].u8ModeIdx];handle->u16TerisX = handle->pNumSeq[handle->u8SeqIdx].u8DefX + handle->u16TerisXOffset;handle->u16TerisY = 0;handle->u8EndFlag = 0;}/* clear last tetris base mode */for (uint16_t i = handle->u16TerisMode; xx = handle->u16TerisX + (i&0x3), yy = handle->u16TerisY + ((i>>2)&0x3), i; i >>= 4){u16GridMap[yy * GRID_COL_NUM + xx] = 0;DrawTetrisRect(xx, yy, GRID_SIZE, GRID_SIZE, LCD_COLOR_BLACK, LCD_COLOR_BLACK);}/* down */down(handle);/* draw new tetris base mode */for (uint16_t i = handle->u16TerisMode; xx = handle->u16TerisX + (i&0x3), yy = handle->u16TerisY + ((i>>2)&0x3), i; i >>= 4){u16GridMap[yy * GRID_COL_NUM + xx] = 1;DrawTetrisRect(xx, yy, GRID_SIZE, GRID_SIZE, handle->u32TerisColor, LCD_COLOR_BLACK);}}}/* flash colon */if (u8LastSec != u8ClockNumber[NUMBER_COUNT]) {/* get random color */u8RandomNum = HAL_RNG_GetRandomNumber(&hrng);u32RandomColor = u32ColorRgb565Table[u8RandomNum % (sizeof(u32ColorRgb565Table)/sizeof(uint32_t))];for (uint16_t i = u16BasicModelTable[2]; xx = COLON_OFFSET_X + (i&0x3), yy = COLON_OFFSET_Y + ((i>>2)&0x3), i; i >>= 4) {if (u8LastSec%2 == 0) {DrawTetrisRect(xx, yy, GRID_SIZE, GRID_SIZE, u32RandomColor, LCD_COLOR_BLACK);DrawTetrisRect(xx, yy+4, GRID_SIZE, GRID_SIZE, u32RandomColor, LCD_COLOR_BLACK);} else {DrawTetrisRect(xx, yy, GRID_SIZE, GRID_SIZE, LCD_COLOR_BLACK, LCD_COLOR_BLACK);DrawTetrisRect(xx, yy+4, GRID_SIZE, GRID_SIZE, LCD_COLOR_BLACK, LCD_COLOR_BLACK);}}u8LastSec = u8ClockNumber[NUMBER_COUNT];}/* update calendar */if (u8LastDay != p_tm->tm_mday) {/* show calendar */const char* str;str = solar_calendar(p_tm->tm_mon+1, p_tm->tm_mday, p_tm->tm_wday);show_str(170, 205, 200, 16, (uint8_t*)str, CH_FONT16);str = lunar_calendar(p_tm->tm_year+1900, p_tm->tm_mon+1, p_tm->tm_mday);show_str(170, 224, 440, 16, (uint8_t*)str, CH_FONT16);u8LastDay = p_tm->tm_mday;}
}
其他几个函数用来更新俄罗斯方块下落后的坐标,及获取时间还有画每个小方块的函数,
画图和获取时间的函数用到了其他接口,可以根据自己的工程修改。
static void DrawTetrisRect(uint16_t TetrisX, uint16_t TetrisY, uint16_t Width, uint16_t Height,uint32_t Fcolor, uint32_t Bcolor)
{BSP_LCD_SetTextColor(Fcolor);BSP_LCD_FillRect(TetrisX*(Width+1), TetrisY*(Height+1), Width, Height);if (Fcolor != Bcolor) {BSP_LCD_SetTextColor(LCD_COLOR_WHITE);BSP_LCD_DrawRect(TetrisX*(Width+1), TetrisY*(Height+1), Width-1, Height-1);}
}static uint8_t TetrisClockUpdateTime(uint8_t *data)
{static uint8_t u8LastMinute = 0xff;uint8_t u8MinuteChange = 0;rt_device_t rtc_dev = NULL;time_t time_stamp = 0;rtc_dev = rt_device_find("rtc");if (rtc_dev != NULL) {rt_device_control(rtc_dev, RT_DEVICE_CTRL_RTC_GET_TIME, &time_stamp);}p_tm = localtime(&time_stamp);//rt_kprintf("year %d day %d h:%d m:%d\n", p_tm->tm_year, p_tm->tm_mday, p_tm->tm_hour, p_tm->tm_min);data[0] = p_tm->tm_hour/10%10;data[1] = p_tm->tm_hour%10;data[2] = p_tm->tm_min/10%10;data[3] = p_tm->tm_min%10;data[4] = p_tm->tm_sec;if (u8LastMinute != p_tm->tm_min) {u8LastMinute = p_tm->tm_min;u8MinuteChange = 1;}return u8MinuteChange;
}
void down(stTetrisClockHandle *handle)
{int16_t xx, yy;handle->u16TerisY += 1;for (uint16_t i = handle->u16TerisMode; xx = handle->u16TerisX + (i&0x3), yy = handle->u16TerisY + ((i>>2)&0x3), i; i >>= 4){if (yy >= GRID_ROW_NUM-handle->pNumSeq[handle->u8SeqIdx].u8DefY|| u16GridMap[yy * GRID_COL_NUM + xx]) {/* crash bottom */handle->u16TerisY -= 1;handle->u8EndFlag = 1;}}
}
头文件
/** Copyright (c) 2006-2021, RT-Thread Development Team** SPDX-License-Identifier: Apache-2.0** Change Logs:* Date Author Notes* 2022-08-06 Administrator the first version*/
#ifndef APPLICATIONS_TETRIS_TETRIS_CLOCK_H_
#define APPLICATIONS_TETRIS_TETRIS_CLOCK_H_#include <stdint.h>
#include <stdlib.h>#include <rtthread.h>
#include "main.h"#define SCRLET 0xFF2400
#define CAMEL 0xA16B47
#define SUN_ORANGE 0xFF7300
#define LAWN_GREEN 0x7CFC00
#define FOREST_GREEN 0x228B22
#define MARINE_BLUE 0x00477D
#define CHROME_YELLOW 0xFFD700
#define DARK_SLATE_BLUE 0x483D8B
#define CAYN_BLUE 0x0DBF8C
#define RUBY 0xCC0080
#define MIDIUM_TURQUOISE 0x48D1CC
#define VERIDIAN 0x127436
#define LIGHT_LIME 0xCCFF00
#define INDIAN_RED 0xCD5C5C
#define MAROON 0x800000
#define MISTY_ROSE 0xFFE4E1
#define LIGHT_CORAL 0xF08080
#define HELIOTROPE 0x5000B8typedef struct{uint8_t u8ModeIdx;int8_t u8DefX;int8_t u8DefY;int8_t u8BottomOffset;
}stNumSeqBase;typedef struct{const stNumSeqBase *pNumSeq;uint16_t u16TerisMode;uint16_t u16TerisX;uint16_t u16TerisXOffset;uint16_t u16TerisY;uint32_t u32TerisColor;uint8_t u8SeqIdx;uint8_t u8EndFlag;
}stTetrisClockHandle;extern RNG_HandleTypeDef hrng;void tetris_main(void);#endif /* APPLICATIONS_TETRIS_TETRIS_CLOCK_H_ */
更多推荐
C语言俄罗斯方块时钟
发布评论