- 已编辑
本教程旨在使用lcd屏幕显示一个运动的球,然后用板子将球反弹回去,每次反弹之后得分加一。在得分为一定值之后球的运动速度会加快。
算法实现
首先是画出板子,之后就可以利用五向开关移动板子,并把之前的板子给抹去。以下是实现的代码。
void moveboard()
{
uint8_t getkey =0;
lcd_fill(board.x, 229, board.x+60,239, WHITE);
getkey=Basic_Key_Handle();
switch(getkey)
{
case right:
board.x+=15;
break;
case left:
board.x-=15;
break;
default:
break;
}
if(board.x<=0)
{
if(getkey==1)
{
board.x=0;
}
}
if(board.x>=180)
{
if(getkey==2)
{
board.x=180;
}
}
lcd_fill(board.x, 229, board.x+60,239, BLACK);
Delay_Ms(250);
}
之后就是画出求并使其移动。为了实现这个功能,我首先使用随机函数创造圆心的坐标,之后用函数lcd_draw_circle画圆并用函数在圆内填充颜色。之后就是在每个时间点内将圆移动后打印出来,并将原来的圆删去。为了防止球的运动轨迹是在两点之间来回移动,我让球在x轴和y轴上移动的距离不相同。我用以下代码来实现。
void creatball()
{
ball.x=((RNG_GetRandomNumber()%200)+20);
ball.y=((RNG_GetRandomNumber()%160)+10);
lcd_draw_circle(ball.x,ball.y ,5);
fill_circle();
}
之后是如果圆在飞出屏幕后需要反弹回来。而且必须要保证球落到下面的时候不会因为速度过快导致球直接飞出屏幕而没有被板子接到的情况。所以我选择了以边界减去圆心的距离小于半径就会触发反弹,并且如果球的x点坐标在板子的x轴范围内,那么球就会反弹回去。并且如果获得了5分,球的速度就会变得更快。这里我用 ball.sp=10+5*(ball.sc/3);这个函数来实现。
void moveball()
{
lcd_fill(0,0,239,229,WHITE);
if(ball.d==0)
{
ball.x+=ball.sp+5;
ball.y+=ball.sp;
}
if(ball.d==1)
{
ball.x+=ball.sp+5;
ball.y-=ball.sp;
}
if(ball.d==2)
{
ball.x-=ball.sp-5;
ball.y+=ball.sp;
}
if(ball.d==3)
{
ball.x-=ball.sp-5;
ball.y-=ball.sp;
}
if(229-ball.y<=5)
{
if((ball.x-5<=board.x+60)&&(ball.x+5>=board.x))
{
if(ball.d==0)
ball.d=1;
if(ball.d==2)
ball.d=3;
ball.sc++;
}
else
ball.f=0;
}
if(ball.y<=5)
{
if(ball.d==1)
ball.d=0;
if(ball.d==3)
ball.d=2;
}
if(ball.x<=5)
{
if(ball.d==2)
ball.d=0;
if(ball.d==3)
ball.d=1;
}
if(ball.x>=234)
{
if(ball.d==0)
ball.d=2;
if(ball.d==1)
ball.d=3;
}
lcd_draw_circle(ball.x,ball.y ,5);
fill_circle();
}
之后我开始写main函数。首先我先初始化函数,然后我将来一些需要设置的数据设置好。之后在球结束之后我设置在屏幕上显示得分和gameover。
int main(void)
{
SystemCoreClockUpdate();
Delay_Init();
USART_Printf_Init(115200);
printf("SystemClk:%d\r\n",SystemCoreClock);
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_RNG, ENABLE);
RNG_Cmd(ENABLE);
lcd_init();
lcd_fill(0,0,250,250,WHITE);
lcd_set_color(WHITE, RED);
ball.sc=0;
ball.d=2;
ball.f=1;
creatball();
creatboard();
while(ball.f)
{
moveboard();
moveball();
ball.sp=10+5*(ball.sc/3);
}
lcd_fill(0,0,250,250,WHITE);
lcd_set_color(WHITE, BLACK);
lcd_show_string(50, 120, 32, "GAME OVER");
lcd_show_string(50, 152, 32, "SCORE=%d",ball.sc);
while(1)
{
}
}
```
## 实验代码
```c
#include "debug.h"
#include "lcd.h"
#include "ch32v30x_rng.h"
#define left 1
#define right 2
struct Board
{
int x;
}board;
struct Ball
{
int x,y,sp,sc,d,f;
}ball;
/*******************************************************************************
* Function Name : Basic_Key_Handle
* Description : Basic Key Handle
* Input : None
* Return : 0 = no key press
* key = key press down value
*******************************************************************************/
void GPIO_INIT()
{
GPIO_InitTypeDef GPIO_InitTypdefStruct;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOD|RCC_APB2Periph_GPIOE,ENABLE);
GPIO_InitTypdefStruct.GPIO_Pin = GPIO_Pin_3;
GPIO_InitTypdefStruct.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitTypdefStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOE, &GPIO_InitTypdefStruct);
GPIO_InitTypdefStruct.GPIO_Pin = GPIO_Pin_6;
GPIO_InitTypdefStruct.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitTypdefStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOD, &GPIO_InitTypdefStruct);
}
/*********************************************************************
设置按键
*/
uint8_t Basic_Key_Handle( void )
{
uint8_t keyval = 0;
if( ! GPIO_ReadInputDataBit( GPIOE, GPIO_Pin_3 ) )
{
Delay_Ms(10);
if( ! GPIO_ReadInputDataBit( GPIOE, GPIO_Pin_3 ) )
{
keyval = right;
}
}
else {
if( ! GPIO_ReadInputDataBit( GPIOD, GPIO_Pin_6 ) )
{
Delay_Ms(10);
if( ! GPIO_ReadInputDataBit( GPIOD, GPIO_Pin_6 ) )
{
keyval = left;
}
}
}
return keyval;
}
void fill_circle()
{
int x,y,r=5;
for(x=0;x<244;x++)
{
for(y=0;y<244;y++)
{
if((ball.x-x)*(ball.x-x)+(ball.y-y)*(ball.y-y)<=r*r)
{
lcd_draw_point_color(x, y, RED);
}
}
}
}
/*********************************************************************
*/
void creatboard()
{
board.x=90;
lcd_fill(board.x,229,board.x+60,239,BLACK);
}
void creatball()
{
ball.x=((RNG_GetRandomNumber()%200)+20);
ball.y=((RNG_GetRandomNumber()%160)+10);
lcd_draw_circle(ball.x,ball.y ,5);
fill_circle();
}
/*********************************************************************
*/
void moveboard()
{
uint8_t getkey =0;
lcd_fill(board.x, 229, board.x+60,239, WHITE);
getkey=Basic_Key_Handle();
switch(getkey)
{
case right:
board.x+=15;
break;
case left:
board.x-=15;
break;
default:
break;
}
if(board.x<=0)
{
if(getkey==1)
{
board.x=0;
}
}
if(board.x>=180)
{
if(getkey==2)
{
board.x=180;
}
}
lcd_fill(board.x, 229, board.x+60,239, BLACK);
Delay_Ms(250);
}
/*********************************************************************
*/
void moveball()
{
lcd_fill(0,0,239,229,WHITE);
if(ball.d==0)
{
ball.x+=ball.sp+5;
ball.y+=ball.sp;
}
if(ball.d==1)
{
ball.x+=ball.sp+5;
ball.y-=ball.sp;
}
if(ball.d==2)
{
ball.x-=ball.sp-5;
ball.y+=ball.sp;
}
if(ball.d==3)
{
ball.x-=ball.sp-5;
ball.y-=ball.sp;
}
if(229-ball.y<=5)
{
if((ball.x-5<=board.x+60)&&(ball.x+5>=board.x))
{
if(ball.d==0)
ball.d=1;
if(ball.d==2)
ball.d=3;
ball.sc++;
}
else
ball.f=0;
}
if(ball.y<=5)
{
if(ball.d==1)
ball.d=0;
if(ball.d==3)
ball.d=2;
}
if(ball.x<=5)
{
if(ball.d==2)
ball.d=0;
if(ball.d==3)
ball.d=1;
}
if(ball.x>=234)
{
if(ball.d==0)
ball.d=2;
if(ball.d==1)
ball.d=3;
}
lcd_draw_circle(ball.x,ball.y ,5);
fill_circle();
}
/*********************************************************************
* @fn main
*
* @brief Main program.
*
* @return none
*/
int main(void)
{
SystemCoreClockUpdate();
Delay_Init();
USART_Printf_Init(115200);
printf("SystemClk:%d\r\n",SystemCoreClock);
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_RNG, ENABLE);
RNG_Cmd(ENABLE);
lcd_init();
lcd_fill(0,0,250,250,WHITE);
lcd_set_color(WHITE, RED);
ball.sc=0;
ball.d=2;
ball.f=1;
creatball();
creatboard();
while(ball.f)
{
moveboard();
moveball();
ball.sp=10+5*(ball.sc/3);
}
lcd_fill(0,0,250,250,WHITE);
lcd_set_color(WHITE, BLACK);
lcd_show_string(50, 120, 32, "GAME OVER");
lcd_show_string(50, 152, 32, "SCORE=%d",ball.sc);
while(1)
{
}
}