前言:
本文延續上一篇的設計,主要改良了使用觸控屏的方式來操控貪食蛇,並優化程式碼,按鈕以變色的方式來表達按下和放開,並提供原來官方的電阻屏校準程式,可隨時切換並在校準完後回到遊戲,繼續進行,程式碼部分也供小夥伴們參考
準備:
1. MM32F103 開發板
2. SPI LCD 箱內有附
3. MicroUSB
實作:
1. 延續上一篇的設計,並修改成觸控的方式,主要有以下變更
- 1. 取消原先三個外部中斷函式的功能
- 2. 新增KEY0可以啟用電阻屏校準程式的功能
- 3. 新增4個觸控按鈕
- 4. 按下和放開的顏色會不一樣,完成一次按和放的動作按鈕功能才會生效
复制代码
2. 統整所用到的函式庫
- 1. KEY - 修改成外部中斷
- 2. Dealy - 修改成往上計數
- 3. LCD - 刪除1963以外的初始化
- 4. LED - 無修改
- 5. 24CXX -無修改
- 6. IIC - 無修改
- 7. SPI - 無修改
- 8. TOUCH - 無修改
- 9. malloc - 無修改
复制代码
3. 接下來就是依照第一版為基礎,修改成以下程式碼
- #include "led.h"
- #include "delay.h"
- #include "sys.h"
- #include "uart.h"
- #include "lcd.h"
- #include "key.h"
- #include "spi.h"
- #include "malloc.h"
- #include "24cxx.h"
- #include "myiic.h"
- #include "touch.h"
- #include
- #define FIELD_ORIG_X 1
- #define FIELD_ORIG_Y 1
- #define FIELD_WIDTH 239
- #define FIELD_HEIGHT 239
- #define SNAKE_SHIFT 4
- #define SNAKE_SPACE 7
- #define SNAKE_LARGE 3
- #define EGG_LARGE 2
- #define DATA_LEN 5
- #define TX_SIZE DATA_LEN
- #define RX_SIZE TX_SIZE
- #define BTN_WIDTH 65
- #define BTN_HEIGHT 40
- #define BTN_SPACE 5
- #define BTN_ORIG_X 250
- #define BTN_ORIG_Y 60
- #define UP_BTN_ORIG_YS BTN_ORIG_Y //Start point
- #define UP_BTN_ORIG_YE BTN_ORIG_Y+BTN_HEIGHT //End point
- #define LEFT_BTN_ORIG_YS BTN_ORIG_Y+(BTN_HEIGHT+BTN_SPACE)
- #define LEFT_BTN_ORIG_YE BTN_ORIG_Y+(BTN_HEIGHT+BTN_SPACE)+BTN_HEIGHT
- #define RIGHT_BTN_ORIG_YS BTN_ORIG_Y+(BTN_HEIGHT+BTN_SPACE)*2
- #define RIGHT_BTN_ORIG_YE BTN_ORIG_Y+(BTN_HEIGHT+BTN_SPACE)*2+BTN_HEIGHT
- #define DOWN_BTN_ORIG_YS BTN_ORIG_Y+(BTN_HEIGHT+BTN_SPACE)*3
- #define DOWN_BTN_ORIG_YE BTN_ORIG_Y+(BTN_HEIGHT+BTN_SPACE)*3+BTN_HEIGHT
- enum
- {
- LEFT=0,
- RIGHT,
- UP,
- DOWN
- };
- s16 *snake_x;
- s16 *snake_y;
- u16 snake_len=3;
- u8 snake_dir=RIGHT;
- u16 snake_speed=100;
- s16 egg_x,egg_y;
- u16 score=0;
- u8 btn;
- unsigned char high[DATA_LEN];
- s8 pressed=-1;
-
- void draw_rectangle_fill(u16 x1, u16 y1, u16 x2, u16 y2, u16 color);
- void draw_circle_fill(u16 x0,u16 y0,u8 r,u16 color);
- void draw_snake(void);
- void check_btn(void);
- u32 int_pow(u8 m,u8 n);
- bool check_game(void);
- void change_array_size_t(void);
- void check_egg(void);
- void move_snake(void);
- bool save_high(void);
- void reload_game(void);
- void left_btn_color_normal(void);
- void right_btn_color_normal(void);
- void up_btn_color_normal(void);
- void down_btn_color_normal(void);
- void left_btn_color_pressed(void);
- void right_btn_color_pressed(void);
- void up_btn_color_pressed(void);
- void down_btn_color_pressed(void);
- void EXti0_IRQHandler(void)
- {
- if(EXTI_GetITStatus(EXTI_Line0) != RESET)
- {
- /*delay_ms(10);
- if(WK_UP)
- {
- btn=WKUP_PRES;
- }*/
- EXTI_ClearITPendingBit(EXTI_Line0);
- }
- }
- void EXTI9_5_IRQHandler(void)
- {
- if(EXTI_GetITStatus(EXTI_Line5) != RESET)
- {
- delay_ms(10);
- if(!KEY0)
- {
- //btn=KEY0_PRES;
- LCD_Clear(WHITE);//清屏
- TP_Adjust(); //屏幕校准
- TP_Save_Adjdata();
- reload_game();
- }
- EXTI_ClearITPendingBit(EXTI_Line5);
- }
- }
- void EXTI1_IRQHandler(void)
- {
- if(EXTI_GetITStatus(EXTI_Line1) != RESET)
- {
- /* delay_ms(10);
- if(!KEY1)
- {
- btn=KEY1_PRES;
- }*/
-
- EXTI_ClearITPendingBit(EXTI_Line1);
- }
- }
- void draw_rectangle_fill(u16 x1, u16 y1, u16 x2, u16 y2, u16 color)
- {
- POINT_COLOR=color;
- LCD_DrawLine(x1,y1,x2,y1);
- LCD_DrawLine(x1,y1,x1,y2);
- LCD_DrawLine(x1,y2,x2,y2);
- LCD_DrawLine(x2,y1,x2,y2);
- LCD_Fill(x1,y1,x2,y2,color);
- }
- void draw_circle_fill(u16 x0,u16 y0,u8 r,u16 color)
- {
- int a,b;
- int di;
- a=0;b=r;
- di=3-(r<<1); //判断下个点位置的标志
- POINT_COLOR=color;
- while(a<=b)
- {
- LCD_DrawPoint(x0+a,y0-b); //5
- LCD_DrawPoint(x0+b,y0-a); //0
- LCD_DrawPoint(x0+b,y0+a); //4
- LCD_DrawPoint(x0+a,y0+b); //6
- LCD_DrawPoint(x0-a,y0+b); //1
- LCD_DrawPoint(x0-b,y0+a);
- LCD_DrawPoint(x0-a,y0-b); //2
- LCD_DrawPoint(x0-b,y0-a); //7
- LCD_Fill(x0-a,y0-b,x0+a,y0+b,color);
- LCD_Fill(x0-b,y0-a,x0+b,y0+a,color);
- a++;
- //使用Bresenham算法画圆
- if(di<0)di +=4*a+6;
- else
- {
- di+=10+4*(a-b);
- b--;
- }
- }
- }
- void draw_snake(void)
- {
- draw_rectangle_fill(egg_x,egg_y,egg_x+EGG_LARGE,egg_y+EGG_LARGE,BLUE);
- draw_circle_fill(snake_x[0],snake_y[0],SNAKE_LARGE,BLACK);
- draw_circle_fill(snake_x[1],snake_y[1],SNAKE_LARGE,GRAY);
- draw_circle_fill(snake_x[snake_len],snake_y[snake_len],SNAKE_LARGE,WHITE);
- }
- void check_btn(void)
- {
-
- if(tp_dev.scan(0))
- {
- if(tp_dev.x[0]> BTN_ORIG_X && tp_dev.x[0]< BTN_ORIG_X+BTN_WIDTH )
- {
- if(tp_dev.y[0]> UP_BTN_ORIG_YS && tp_dev.y[0]< UP_BTN_ORIG_YE )
- {
- up_btn_color_pressed();
- pressed=UP;
- }
- else if (tp_dev.y[0]> LEFT_BTN_ORIG_YS && tp_dev.y[0]< LEFT_BTN_ORIG_YE )
- {
- left_btn_color_pressed();
- pressed=LEFT;
- }
- else if (tp_dev.y[0]> RIGHT_BTN_ORIG_YS && tp_dev.y[0]< RIGHT_BTN_ORIG_YE )
- {
- right_btn_color_pressed();
- pressed=RIGHT;
- }
- else if (tp_dev.y[0]> DOWN_BTN_ORIG_YS && tp_dev.y[0]< DOWN_BTN_ORIG_YE )
- {
- down_btn_color_pressed();
- pressed=DOWN;
- }
- }
- }
- else
- {
- if(pressed>=0)
- {
- switch (pressed)
- {
- case LEFT:
- {
- if(snake_dir == UP ||snake_dir == DOWN)
- snake_dir=LEFT;
- left_btn_color_normal();
- break;
- }
-
- case RIGHT:
- {
- if(snake_dir == UP ||snake_dir == DOWN)
- snake_dir=RIGHT;
- right_btn_color_normal();
- break;
- }
-
- case UP:
- {
- if(snake_dir == LEFT ||snake_dir == RIGHT)
- snake_dir=UP;
- up_btn_color_normal();
- break;
- }
-
- case DOWN:
- {
- if(snake_dir == LEFT ||snake_dir == RIGHT)
- snake_dir=DOWN;
- down_btn_color_normal();
- break;
- }
- }
- }
- pressed=-1;
- }
-
- /*switch (btn)
- {
- case KEY0_PRES:
- {
- if(snake_dir == RIGHT)
- snake_dir = UP;
- else if (snake_dir == LEFT)
- snake_dir = UP;
- else if (snake_dir == UP)
- snake_dir = RIGHT;
- else if (snake_dir == DOWN)
- snake_dir = RIGHT;
- break;
- }
- case KEY1_PRES:
- {
- if(snake_dir == RIGHT)
- snake_dir = DOWN;
- else if (snake_dir == LEFT)
- snake_dir = DOWN;
- else if (snake_dir == UP)
- snake_dir = LEFT;
- else if (snake_dir == DOWN)
- snake_dir = LEFT;
- break;
- }
- }*/
- }
- bool check_game(void)
- {
- u16 i;
- for(i=1;i< snake_len;i++)
- {
- if(snake_x[i]==snake_x[0] && snake_y[i]==snake_y[0])
- return true;
- }
- return false;
- }
- void change_array_size_t(void)
- {
- s16 *temp_x;
- s16 *temp_y;
-
- temp_x=myrealloc(snake_x,snake_len*sizeof(s16));
-
- if(snake_x!=temp_x)
- snake_x=temp_x;
-
- temp_y=myrealloc(snake_y,snake_len*sizeof(s16));
-
- if(snake_y!=temp_y)
- snake_y=temp_y;
-
- }
- void check_egg(void)
- {
- if( snake_x[0]==egg_x //D=0
- || snake_x[0]+1==egg_x //D=1
- || snake_x[0]==egg_x+1 //D=1
- || snake_x[0]+2==egg_x //D=2
- || snake_x[0]==egg_x+2 //D=2
- || snake_x[0]-1==egg_x+2 //D=3
- || snake_x[0]-2==egg_x+2 //D=4
- )
- {
- if( snake_y[0]==egg_y //D=0
- || snake_y[0]+1==egg_y //D=1
- || snake_y[0]==egg_y+1 //D=1
- || snake_y[0]+2==egg_y //D=2
- || snake_y[0]==egg_y+2 //D=2
- || snake_y[0]-1==egg_y+2 //D=3
- || snake_y[0]-2==egg_y+2 //D=4
- )
- {
- if(snake_speed>10)
- snake_speed--;
- snake_len++;
- score++;
-
- POINT_COLOR=BLACK;
- LCD_ShowxNum(250,5,score,DATA_LEN,24,0x80);
-
- change_array_size_t();
-
- draw_rectangle_fill(egg_x,egg_y,egg_x+EGG_LARGE,egg_y+EGG_LARGE,WHITE);
-
- srand(micros());
- egg_x=rand()%(FIELD_WIDTH-2*(EGG_LARGE+SNAKE_LARGE))+(EGG_LARGE+SNAKE_LARGE);// 5-233
- egg_y=rand()%(FIELD_HEIGHT-2*(EGG_LARGE+SNAKE_LARGE))+(EGG_LARGE+SNAKE_LARGE);
-
- }
- }
- }
- void move_snake(void)
- {
- s16 temp_x,temp_y;
- s16 orig_x,orig_y;
- u16 i;
- printf("x=%d,y=%drn",snake_x[0],snake_y[0]);
- check_btn();
- btn=NO_PRESS;
-
- switch (snake_dir)
- {
- case LEFT:
- {
- temp_x=snake_x[0]-SNAKE_SPACE;
- temp_y=snake_y[0];
- break;
- }
-
- case RIGHT:
- {
- temp_x=snake_x[0]+SNAKE_SPACE;
- temp_y=snake_y[0];
- break;
- }
-
- case UP:
- {
- temp_x=snake_x[0];
- temp_y=snake_y[0]-SNAKE_SPACE;
- break;
- }
-
- case DOWN:
- {
- temp_x=snake_x[0];
- temp_y=snake_y[0]+SNAKE_SPACE;
- break;
- }
- }
-
- if(temp_x>=(FIELD_WIDTH))
- temp_x-=(FIELD_WIDTH-FIELD_ORIG_X);
- else if (temp_x<=(FIELD_ORIG_X))
- temp_x+=(FIELD_WIDTH-FIELD_ORIG_X);
-
- if (temp_y>=(FIELD_HEIGHT))
- temp_y-=(FIELD_HEIGHT-FIELD_ORIG_Y);
- else if (temp_y<=(FIELD_ORIG_Y))
- temp_y+=(FIELD_HEIGHT-FIELD_ORIG_Y);
-
-
- for(i=0; i<=snake_len;i++)
- {
- orig_x=snake_x[i];
- orig_y=snake_y[i];
- snake_x[i]=temp_x;
- snake_y[i]=temp_y;
- temp_x=orig_x;
- temp_y=orig_y;
- }
- draw_snake();
- }
- u32 int_pow(u8 m,u8 n)
- {
- u32 result=1;
- while(n--)
- result*=m;
- return result;
- }
- bool save_high(void)
- {
- u8 temp,t;
- unsigned char buf[DATA_LEN];
- bool highest=false;
-
- if(atoi((char*)high)
- {
- highest=true;
- for(t=0;t<5;t++)
- {
- temp=(score/int_pow(10,4-t))%10;
- if (temp==0)
- {
- buf[t]='0';
- }
- else
- {
- buf[t]='0'+temp;
- }
- }
- SPIM_SectorErase(SPI1,0);
- delay_ms(100);
- printf("scores=%srn",buf);
- SPIM_PageProgram(SPI1,0,buf,TX_SIZE);
- delay_ms(100);
- }
- return highest;
- }
- void left_btn_color_normal(void)
- {
- POINT_COLOR=BROWN;
- LCD_DrawRectangle(BTN_ORIG_X,LEFT_BTN_ORIG_YS,BTN_ORIG_X+BTN_WIDTH,LEFT_BTN_ORIG_YE);
- LCD_ShowString(BTN_ORIG_X+10,LEFT_BTN_ORIG_YS+7,200,24,24,(u8 *)"LEFT");
- }
- void right_btn_color_normal(void)
- {
- POINT_COLOR=BROWN;
- LCD_DrawRectangle(BTN_ORIG_X,RIGHT_BTN_ORIG_YS,BTN_ORIG_X+BTN_WIDTH,RIGHT_BTN_ORIG_YE);
- LCD_ShowString(BTN_ORIG_X+3,RIGHT_BTN_ORIG_YS+7,200,24,24,(u8 *)"RIGHT");
- }
- void up_btn_color_normal(void)
- {
- POINT_COLOR=BROWN;
- LCD_DrawRectangle(BTN_ORIG_X,UP_BTN_ORIG_YS,BTN_ORIG_X+BTN_WIDTH,UP_BTN_ORIG_YE);
- LCD_ShowString(BTN_ORIG_X+22,UP_BTN_ORIG_YS+7,200,24,24,(u8 *)"UP");
- }
- void down_btn_color_normal(void)
- {
- POINT_COLOR=BROWN;
- LCD_DrawRectangle(BTN_ORIG_X,DOWN_BTN_ORIG_YS,BTN_ORIG_X+BTN_WIDTH,DOWN_BTN_ORIG_YE);
- LCD_ShowString(BTN_ORIG_X+10,DOWN_BTN_ORIG_YS+7,200,24,24,(u8 *)"DOWN");
- }
- void left_btn_color_pressed(void)
- {
- POINT_COLOR=CYAN;
- LCD_DrawRectangle(BTN_ORIG_X,LEFT_BTN_ORIG_YS,BTN_ORIG_X+BTN_WIDTH,LEFT_BTN_ORIG_YE);
- LCD_ShowString(BTN_ORIG_X+10,LEFT_BTN_ORIG_YS+7,200,24,24,(u8 *)"LEFT");
- }
- void right_btn_color_pressed(void)
- {
- POINT_COLOR=CYAN;
- LCD_DrawRectangle(BTN_ORIG_X,RIGHT_BTN_ORIG_YS,BTN_ORIG_X+BTN_WIDTH,RIGHT_BTN_ORIG_YE);
- LCD_ShowString(BTN_ORIG_X+3,RIGHT_BTN_ORIG_YS+7,200,24,24,(u8 *)"RIGHT");
- }
- void up_btn_color_pressed(void)
- {
- POINT_COLOR=CYAN;
- LCD_DrawRectangle(BTN_ORIG_X,UP_BTN_ORIG_YS,BTN_ORIG_X+BTN_WIDTH,UP_BTN_ORIG_YE);
- LCD_ShowString(BTN_ORIG_X+22,UP_BTN_ORIG_YS+7,200,24,24,(u8 *)"UP");
- }
- void down_btn_color_pressed(void)
- {
- POINT_COLOR=CYAN;
- LCD_DrawRectangle(BTN_ORIG_X,DOWN_BTN_ORIG_YS,BTN_ORIG_X+BTN_WIDTH,DOWN_BTN_ORIG_YE);
- LCD_ShowString(BTN_ORIG_X+10,DOWN_BTN_ORIG_YS+7,200,24,24,(u8 *)"DOWN");
- }
- void reload_game(void)
- {
- POINT_COLOR=RED;
- LCD_DrawRectangle(0,0,239,239);
-
- left_btn_color_normal();
- right_btn_color_normal();
- up_btn_color_normal();
- down_btn_color_normal();
-
- POINT_COLOR=BLACK;
- LCD_ShowxNum(250,5,score,DATA_LEN,24,0x80);
-
- POINT_COLOR=GRAY;
- LCD_ShowxNum(250,30,atoi((char*)high),DATA_LEN,24,0x80);
-
- }
- int main(void)
- {
- u16 i;
- snake_x=mymalloc(snake_len*sizeof(s16));
- snake_y=mymalloc(snake_len*sizeof(s16));
-
- NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
- delay_init(); //延时函数初始化
- NVIC_SetPriority(SysTick_IRQn,0);
-
- uart_init(9600); //串口初始化为9600
- LED_Init(); //初始化与LED连接的硬件接口
- LCD_Init();
- KEY_Init();
- SPIM_Init(SPI1,0x2);//SPI1频率设置为36M
-
- while(SPIM_ReadID(SPI1))
- {
- printf("S25FL008A Check Failed!rn");
- delay_ms(500);
- printf("Please Check! rn");
- delay_ms(500);
- LED0=!LED0;//DS0闪烁
- }
-
- tp_dev.init(); //触摸屏初始化
- delay_ms(1500);
-
- //LCD_Clear(WHITE);
-
- POINT_COLOR=RED;
- LCD_DrawRectangle(0,0,239,239);
-
- left_btn_color_normal();
- right_btn_color_normal();
- up_btn_color_normal();
- down_btn_color_normal();
-
- for(i=0;i
- {
- snake_x[i]=140+SNAKE_SHIFT-SNAKE_SPACE*i;
- snake_y[i]=140+SNAKE_SHIFT;
- }
-
- draw_circle_fill(snake_x[0],snake_y[0],SNAKE_LARGE,BLACK);
- for(i=1;i
- draw_circle_fill(snake_x[i],snake_y[i],SNAKE_LARGE,GRAY);
-
- egg_x=rand()%(FIELD_WIDTH-2*(EGG_LARGE+SNAKE_LARGE))+(EGG_LARGE+SNAKE_LARGE);// 5-233
- egg_y=rand()%(FIELD_HEIGHT-2*(EGG_LARGE+SNAKE_LARGE))+(EGG_LARGE+SNAKE_LARGE);
- draw_rectangle_fill(egg_x,egg_y,egg_x+EGG_LARGE,egg_y+EGG_LARGE,BLUE);
-
- POINT_COLOR=BLACK;
- LCD_ShowxNum(250,5,score,DATA_LEN,24,0x80);
-
- SPIM_PageRead(SPI1,0,(unsigned char*)high,RX_SIZE);
- delay_ms(100);
- printf("scores=%srn",high);
-
- POINT_COLOR=GRAY;
- LCD_ShowxNum(250,30,atoi((char*)high),DATA_LEN,24,0x80);
-
- while(1)
- {
- move_snake();
- if(check_game())
- break;
- check_egg();
-
- LED0=!LED0;
- delay_ms(snake_speed);
- }
- POINT_COLOR=GREEN;
- if(save_high())
- LCD_ShowString(20,100,200,24,24,(u8 *)"YOU GOT HIGH SCORES");
- LCD_ShowString(60,130,200,24,24,(u8 *)"GAME OVER");
- }
复制代码
按鈕方式採用改變顏色覆蓋的方式,來達到按鈕按下和放開的效果,以向左為例left_btn_color_normal()代表未按下,left_btn_color_pressed()代表按下,接著再交由check_btn()函式和旗標pressed變數來決定按下和放開之後所對應的按鈕位置,並依據原來的方向判定是否為有效的轉向
4. 依據上一篇的方法來進行編譯和燒寫
5. 以下是v2.0版本試玩畫面
Fig. 1 試玩畫面
Fig. 2 蛇蛇往左時,按下往上按鈕,同時按鈕也會變色
Fig. 3 放開時就會轉向,同時按鈕也會恢復未按下的顏色
6. 完成本篇設計和試用
V2.0版本,觸控式
|