嵌入式系統 Team2
- 1. 嵌入式專題-貪食蛇
組別:第2 組
組員:楊職銓(0010745)、王盛弘(0010841)、鄭孟原(0010834)
遊戲特色:
蛇在畫面中行進,碰到邊界會死亡(不可穿透),吃到藍色點點,蛇的身體會加長。另外,有選
單提供單人模式,以及雙人模式。以及死亡後的通知。
主要程式說明:
/***************************************************************************
Include files
***************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "app_platform_routing.h"
#include "platformplatform_board.h"
#include "joystickmodule_joystick.h"
#include "buzzermodule_buzzer.h"
#include "lcdmodule_gui.h"
#include "uartmodule_uart.h"
/***************************************************************************
Constant define
***************************************************************************/
#define TIMECONST 500;
- 2. /***************************************************************************
Function Prototype (External)
***************************************************************************/
/***************************************************************************
Function Prototype (Local)
***************************************************************************/
/***************************************************************************
Variable Define (External)
***************************************************************************/
/***************************************************************************
Variable Define (Global)
***************************************************************************/
int gameMode=0,mode=0;
int head[2],tail[2],point[20][3],pointcount=0;
int direction=2,length=5,t_direction=2,target[2];
int head_2[2],tail_2[2],point_2[20][3],pointcount_2=0;
int direction_2=2,length_2=5,t_direction_2=2;
int crossBoard_1=0,crossBoard_2=0,gameOver=0;
/***************************************************************************
Variable Define (Local)
***************************************************************************/
/***************************************************************************
* Purpose ....: Read value of the joystick then show to LCD.
* Input ....:
* @param ....: None.
* Output ....:
* @param ....: None
* @Return ....: None.
* Note ....: None
***************************************************************************/
static void app_display (void)
{
uint16_t gADCValue[4];
int i;
for (i=0; i < 4; i++) //取得joystick1,joystick2 座標(鄭孟原)
{
module_joystick_get_value(APP_ADC_JOYSTK1_X+i, &gADCValue[i]);
- 3. gADCValue[i]=gADCValue[i]>>8; //right shift 8 位
}
//snake_1's joystick
//判定joystick1 的方向(楊職銓、王盛弘、鄭孟原共同討論)
if(gADCValue[0]==0&&(direction==0||direction==1)) //Joy1 LEFT
{
direction=2; //2=向左
point[pointcount][0]=head[0]; //pointcount 為snake_1 的幾個轉折點
point[pointcount][1]=head[1]; // point[][0]放"x 座標"
point[pointcount][2]=direction; // point[][1]放"y 座標"
pointcount++; // point[][2]放"方向"
}
else if(gADCValue[0]==15&&(direction==0||direction==1)) //Joy1 RIGHT
{
direction=3; //3=向右
point[pointcount][0]=head[0];
point[pointcount][1]=head[1];
point[pointcount][2]=direction;
pointcount++;
}
else if(gADCValue[1]==0&&(direction==2||direction==3)) //Joy1 DOWN
{
direction=1; //1=向下
point[pointcount][0]=head[0];
point[pointcount][1]=head[1];
point[pointcount][2]=direction;
pointcount++;
}
else if(gADCValue[1]==15&&(direction==2||direction==3)) //Joy1 UP
{
direction=0; //0=向上
point[pointcount][0]=head[0];
point[pointcount][1]=head[1];
point[pointcount][2]=direction;
pointcount++;
}
if(gameMode==2)
{
//snake_2's joystick
//判定joystick2 的方向(楊職銓、王盛弘、鄭孟原共同討論)
- 4. if(gADCValue[2]==0&&(direction_2==0||direction_2==1)) //Joy2 LEFT
{
direction_2=2;
//pointcount_2=snake_2 的幾個轉折點
point_2[pointcount_2][0]=head_2[0]; //point_2[][0]放"x 座標"
point_2[pointcount_2][1]=head_2[1]; // point_2[][1]放"y 座標"
point_2[pointcount_2][2]=direction_2; // point_2[][2]放"方向"
pointcount_2++;
}
else if(gADCValue[2]==15&&(direction_2==0||direction_2==1))//Joy2 RIGHT
{
direction_2=3;
point_2[pointcount_2][0]=head_2[0];
point_2[pointcount_2][1]=head_2[1];
point_2[pointcount_2][2]=direction_2;
pointcount_2++;
}
else if(gADCValue[3]==0&&(direction_2==2||direction_2==3)) //Joy2 DOWN
{
direction_2=1;
point_2[pointcount_2][0]=head_2[0];
point_2[pointcount_2][1]=head_2[1];
point_2[pointcount_2][2]=direction_2;
pointcount_2++;
}
else if(gADCValue[3]==15&&(direction_2==2||direction_2==3)) //Joy2 UP
{
direction_2=0;
point_2[pointcount_2][0]=head_2[0];
point_2[pointcount_2][1]=head_2[1];
point_2[pointcount_2][2]=direction_2;
pointcount_2++;
}
}
//snake_1 tail block 畫出snake_1 尾巴(tail)的方塊
module_gui_draw_rect_fill_color (tail[0],tail[1],10,10,GUI_BLACK);
//snake_2 tail block 畫出snake_2 尾巴(tail_2)的方塊
if(gameMode==2){ module_gui_draw_rect_fill_color(tail_2[0],tail_2[1],10,10,GUI_
BLACK);}
- 5. //snake_1 頭(head)的座標移動,head[0]表示x 座標,head[1]表示y 座標
//(楊職銓、王盛弘共同討論)
switch(direction)
{
case 0:
head[1]-=10;
break;
case 1:
head[1]+=10;
break;
case 2:
head[0]-=10;
break;
case 3:
head[0]+=10;
break;
}
//crossBoard_1=0 表示snake_1 未超界,crossBoard_1=1 表示snake_1 超界
//(楊職銓)
if(head[0]<0) crossBoard_1=1;
if(head[0]>310) crossBoard_1=1;
if(head[1]<0) crossBoard_1=1;
if(head[1]>230) crossBoard_1=1;
//snake_2 頭(head_2)的座標移動,head_2[0]表示x 座標,head_2[1]表示y 座標
//(楊職銓、王盛弘共同討論)
if(gameMode==2)
{
switch(direction_2)
{
case 0:
head_2[1]-=10;
break;
case 1:
head_2[1]+=10;
break;
case 2:
head_2[0]-=10;
break;
case 3:
head_2[0]+=10;
- 6. break;
}
//crossBoard_2=0 表示snake_2 未超界,crossBoard_2=1 表示snake_2 超界
//(楊職銓)
if(head_2[0]<0) crossBoard_2=1;
if(head_2[0]>310) crossBoard_2=1;
if(head_2[1]<0) crossBoard_2=1;
if(head_2[1]>230) crossBoard_2=1;
}
//snake_1 suicide 自殺,自己撞到自己
//若snake_1 有n 個轉折點
//(楊職銓、王盛弘、鄭孟原共同討論)
for(int j=0;j<pointcount;j++)
{
if(j==0)
{
if(point[j][2]==0 || point[j][2]==1)
{
if((head[0]<=tail[0] && head[0]>=point[j][0]) ||
(head[0]>=tail[0] && head[0]<=point[j][0]))
{
if(head[1]==point[j][1])
gameOver=1;
}
if(gameMode==2)
{
if((head_2[0]<=tail[0] && head_2[0]>=point[j][0]) ||
(head_2[0]>=tail[0] && head_2[0]<=point[j][0]))
{
if(head_2[1]==point[j][1])
gameOver=2;
}
}
}
if(point[j][2]==2 || point[j][2]==3)
{
if((head[1]<=tail[1] && head[1]>=point[j][1]) ||
(head[1]>=tail[1] && head[1]<=point[j][1]))
{
if(head[0]==point[j][0])
gameOver=1;
- 7. }
if(gameMode==2)
{
if((head_2[1]<=tail[1] && head_2[1]>=point[j][1]) ||
(head_2[1]>=tail[1] && head_2[1]<=point[j][1]))
{
if(head_2[0]==point[j][0])
gameOver=2;
}
}
}
}else
{
if(point[j][2]==0 || point[j][2]==1)
{
if((head[0]<=point[j-1][0] && head[0]>=point[j][0]) ||
(head[0]>=point[j-1][0] && head[0]<=point[j][0]))
{
if(head[1]==point[j][1])
gameOver=1;
}
if(gameMode==2)
{
if((head_2[0]<=point[j-1][0] && head_2[0]>=point[j][0]) ||
(head_2[0]>=point[j-1][0] && head_2[0]<=point[j][0]))
{
if(head_2[1]==point[j][1])
gameOver=2;
}
}
}
if(point[j][2]==2 || point[j][2]==3)
{
if((head[1]<=point[j-1][1] && head[1]>=point[j][1]) ||
(head[1]>=point[j-1][1] && head[1]<=point[j][1]))
{
if(head[0]==point[j][0])
gameOver=1;
}
if(gameMode==2)
{
if((head_2[1]<=point[j-1][1] && head_2[1]>=point[j][1]) ||
- 8. (head_2[1]>=point[j-1][1] && head_2[1]<=point[j][1]))
{
if(head_2[0]==point[j][0])
gameOver=2;
}
}
}
}
}
//若snake_1 沒有轉折點,自己撞到自己
//(楊職銓、王盛弘、鄭孟原共同討論)
if(pointcount==0)
{
if(direction==0 || direction==1)
{
if((head_2[1]<=tail[1] && head_2[1]>=head[1]) ||
(head_2[1]>=tail[1] && head_2[1]<=head[1]))
{
if(head_2[0]==head[0])
gameOver=2;
}
}
if(direction==2 || direction==3)
{
if((head_2[0]<=tail[0] && head_2[0]>=head[0]) ||
(head_2[0]>=tail[0] && head_2[0]<=head[0]))
{
if(head_2[1]==head[1])
gameOver=2;
}
}
if(head[0]==tail[0] && head[1]==tail[1])
gameOver=1;
}
//snake_2 suicide 自殺,自己撞到自己
//若snake_2 有n 個轉折點
//(楊職銓、王盛弘、鄭孟原共同討論)
if(gameMode==2)
{
for(int j=0;j<pointcount_2;j++)
{
- 9. if(j==0)
{
if(point_2[j][2]==0 || point_2[j][2]==1)
{
if((head_2[0]<=tail_2[0] && head_2[0]>=point_2[j][0]) ||
(head_2[0]>=tail_2[0] && head_2[0]<=point_2[j][0]))
{
if(head_2[1]==point_2[j][1])
gameOver=2;
}
if((head[0]<=tail_2[0] && head[0]>=point_2[j][0]) ||
(head[0]>=tail_2[0] && head[0]<=point_2[j][0]))
{
if(head[1]==point_2[j][1])
gameOver=1;
}
}
if(point_2[j][2]==2 || point_2[j][2]==3)
{
if((head_2[1]<=tail_2[1] && head_2[1]>=point_2[j][1]) ||
(head_2[1]>=tail_2[1] && head_2[1]<=point_2[j][1]))
{
if(head_2[0]==point_2[j][0])
gameOver=2;
}
if((head[1]<=tail_2[1] && head[1]>=point_2[j][1]) ||
(head[1]>=tail_2[1] && head[1]<=point_2[j][1]))
{
if(head[0]==point_2[j][0])
gameOver=1;
}
}
}else
{
if(point_2[j][2]==0 || point_2[j][2]==1)
{
if((head_2[0]<=point_2[j-1][0] && head_2[0]>=point_2[j][0])
|| (head_2[0]>=point_2[j-1][0] && head_2[0]<=point_2[j][0]))
{
if(head_2[1]==point_2[j][1])
gameOver=2;
}
- 10. if((head[0]<=point_2[j-1][0] && head[0]>=point_2[j][0]) ||
(head[0]>=point_2[j-1][0] && head[0]<=point_2[j][0]))
{
if(head[1]==point_2[j][1])
gameOver=1;
}
}
if(point_2[j][2]==2 || point_2[j][2]==3)
{
if((head_2[1]<=point_2[j-1][1] && head_2[1]>=point_2[j][1])
|| (head_2[1]>=point_2[j-1][1] && head_2[1]<=point_2[j][1]))
{
if(head_2[0]==point_2[j][0])
gameOver=2;
}
if((head[1]<=point_2[j-1][1] && head[1]>=point_2[j][1]) ||
(head[1]>=point_2[j-1][1] && head[1]<=point_2[j][1]))
{
if(head[0]==point_2[j][0])
gameOver=1;
}
}
}
}
//若snake_2 沒有轉折點,自己撞到自己
//(楊職銓、王盛弘、鄭孟原共同討論)
if(pointcount_2==0)
{
if(direction_2==0 || direction_2==1)
{
if((head[1]<=tail_2[1] && head[1]>=head_2[1]) ||
(head[1]>=tail_2[1] && head[1]<=head_2[1]))
{
if(head[0]==head_2[0])
gameOver=1;
}
}
if(direction_2==2 || direction_2==3)
{
if((head[0]<=tail_2[0] && head[0]>=head_2[0]) ||
(head[0]>=tail_2[0] && head[0]<=head_2[0]))
{
- 11. if(head[1]==head_2[1])
gameOver=1;
}
}
if(head_2[0]==tail_2[0] && head_2[1]==tail_2[1])
gameOver=2;
}
}
//snake_1=========================================================
//判斷尾巴到轉折點,若到了要換方向
//(楊職銓、王盛弘、鄭孟原共同討論)
if(pointcount>0)
{
if(t_direction==0||t_direction==1)
{
if(tail[1]==point[0][1])
{
t_direction=point[0][2];
for(int n=0;n<pointcount;n++)
{
point[n][0]=point[n+1][0];
point[n][1]=point[n+1][1];
point[n][2]=point[n+1][2];
}
pointcount--;
}
}
if(t_direction==2||t_direction==3)
{
if(tail[0]==point[0][0])
{
t_direction=point[0][2];
for(int n=0;n<pointcount;n++)
{
point[n][0]=point[n+1][0];
point[n][1]=point[n+1][1];
point[n][2]=point[n+1][2];
}
pointcount--;
}
}
- 12. }
switch(t_direction)
{
case 0:
tail[1]-=10;
break;
case 1:
tail[1]+=10;
break;
case 2:
tail[0]-=10;
break;
case 3:
tail[0]+=10;
break;
}
if(tail[0]<0) tail[0]=310;
if(tail[0]>310) tail[0]=0;
if(tail[1]<0) tail[1]=230;
if(tail[1]>230) tail[1]=0;
if(head[0]==target[0]&&head[1]==target[1])
{
length++;
target[0]=(rand()%32)*10;
target[1]=(rand()%24)*10;
module_gui_draw_rect_fill_color(target[0],target[1],10,10,GUI_BLUE);
switch(t_direction)
{
case 0:
tail[1]+=10;
break;
case 1:
tail[1]-=10;
break;
case 2:
tail[0]+=10;
break;
case 3:
tail[0]-=10;
break;
}
if(tail[0]<0) tail[0]=310;
- 13. if(tail[0]>310) tail[0]=0;
if(tail[1]<0) tail[1]=230;
if(tail[1]>230) tail[1]=0;
module_gui_draw_rect_fill_color(tail[0],tail[1],10,10,GUI_WHITE);
}
//snake_1=========================================================
//snake_2=========================================================
//判斷尾巴到轉折點,若到了要換方向
//(楊職銓、王盛弘共同討論)
if(gameMode==2)
{
if(pointcount_2>0)
{
if(t_direction_2==0||t_direction_2==1)
{
if(tail_2[1]==point_2[0][1])
{
t_direction_2=point_2[0][2];
for(int n=0;n<pointcount_2;n++)
{
point_2[n][0]=point_2[n+1][0];
point_2[n][1]=point_2[n+1][1];
point_2[n][2]=point_2[n+1][2];
}
pointcount_2--;
}
}
if(t_direction_2==2||t_direction_2==3)
{
if(tail_2[0]==point_2[0][0])
{
t_direction_2=point_2[0][2];
for(int n=0;n<pointcount_2;n++)
{
point_2[n][0]=point_2[n+1][0];
point_2[n][1]=point_2[n+1][1];
point_2[n][2]=point_2[n+1][2];
}
pointcount_2--;
}
}
- 14. }
switch(t_direction_2)
{
case 0:
tail_2[1]-=10;
break;
case 1:
tail_2[1]+=10;
break;
case 2:
tail_2[0]-=10;
break;
case 3:
tail_2[0]+=10;
break;
}
if(tail_2[0]<0) tail_2[0]=310;
if(tail_2[0]>310) tail_2[0]=0;
if(tail_2[1]<0) tail_2[1]=230;
if(tail_2[1]>230) tail_2[1]=0;
if(head_2[0]==target[0]&&head_2[1]==target[1])
{
length_2++;
target[0]=(rand()%32)*10;
target[1]=(rand()%24)*10;
module_gui_draw_rect_fill_color (target[0], target[1], 10, 10,
GUI_BLUE);
switch(t_direction_2)
{
case 0:
tail_2[1]+=10;
break;
case 1:
tail_2[1]-=10;
break;
case 2:
tail_2[0]+=10;
break;
case 3:
tail_2[0]-=10;
break;
}
- 15. if(tail_2[0]<0) tail_2[0]=310;
if(tail_2[0]>310) tail_2[0]=0;
if(tail_2[1]<0) tail_2[1]=230;
if(tail_2[1]>230) tail_2[1]=0;
module_gui_draw_rect_fill_color (tail_2[0], tail_2[1], 10, 10,
GUI_GREEN);
}
}
//snake_2=========================================================
//cross board
if(crossBoard_1==1 && crossBoard_2==1) gameOver=3;
else if(crossBoard_1==1) gameOver=1;
else if(crossBoard_2==1) gameOver=2;
//snake_1 的畫圖,文字,顏色
module_gui_draw_rect_fill_color(target[0],target[1],10,10,GUI_BLUE);
module_gui_set_text_color(GUI_WHITE);
module_gui_text_printf_line (1,"P1 Length %d",length);
module_gui_draw_rect_fill_color (head[0], head[1], 10, 10, GUI_WHITE);
//snake_2 的畫圖,文字,顏色
if(gameMode==2)
{
module_gui_set_text_color (GUI_GREEN);
module_gui_text_printf_line (2,"P2 Length %d",length_2);
module_gui_draw_rect_fill_color (head_2[0], head_2[1], 10, 10,
GUI_GREEN);
}
}
//game lobby 遊戲進入畫面選單
//(楊職銓、王盛弘、鄭孟原共同討論)
static void game_lobby (void)
{
uint16_t gADCValue[4];
int i;
//取joystick 座標值
for (i=0; i < 4; i++)
{
- 16. module_joystick_get_value(APP_ADC_JOYSTK1_X+i, &gADCValue[i]);
gADCValue[i]=gADCValue[i]>>8;
}
//joystick1 選單,上下選擇與向右進入
//(王盛弘)
if(gADCValue[1]==0) //Joy1 DOWN
{
mode++;
if(mode>1) mode=0; //mode=0 表示第一個
}
else if(gADCValue[1]==15) //Joy1 UP
{
mode--;
if(mode<0) mode=1; //mode=2 表示第二個
}
else if(gADCValue[0]==15) //Joy1 RIGHT
{
gameMode=mode+1;
}
switch(mode)
{
case 0:
module_gui_text_printf_line (15," *Single");
module_gui_text_printf_line (18," Double");
break;
case 1:
module_gui_text_printf_line (15," Single");
module_gui_text_printf_line (18," *Double");
break;
}
}
/***************************************************************************
* Purpose ....: read value of the Joystick.
* Input ....:
* @param ....: None
* Output ....:
* @param ....: None
- 17. * @Return ....: None
* Note ....: None
***************************************************************************/
void main (void)
{
platform_board_init(SystemCoreClock);
module_gui_init();
module_gui_set_color(GUI_WHITE, GUI_BLACK);
module_joystick_init();
module_joystick_start();
//選單預設畫面
//(楊職銓)
module_gui_clear (GUI_RED);
module_font_scale_set(4);
module_gui_set_text_color (GUI_WHITE);
module_gui_text_printf_line (0,"Greedy");
module_gui_text_printf_line (4," Snakes");
module_font_scale_set(3);
module_gui_text_printf_line (15," *Single");
module_gui_text_printf_line (18," Double");
//game lobby 遊戲選單
while(1)
{
if(!gameMode)
{
game_lobby();
VK_DELAY_MS(200);
}else
{
break;
}
}
//clear background
module_gui_clear (GUI_BLACK);
module_font_scale_set(1);
//亂數產生食物方塊(藍色)
//(楊職銓)
- 18. srand(time(NULL));
target[0]=(rand()%32)*10;
target[1]=(rand()%24)*10;
module_gui_draw_rect_fill_color (target[0], target[1], 10, 10, GUI_BLUE);
module_gui_set_text_color (GUI_WHITE);
module_gui_text_printf_line (1,"P1 Length %d",length);
module_gui_set_text_color (GUI_GREEN);
//snake 1 initial position
head[0]=160;head[1]=120;
tail[0]=160+(length-1)*10;tail[1]=120;
module_gui_draw_rect_fill_color (head[0], head[1], 10, 10*length,
GUI_WHITE);
//snake 2 initial position
if(gameMode==2)
{
head_2[0]=160;head_2[1]=160;
tail_2[0]=160+(length_2-1)*10;tail_2[1]=160;
module_gui_draw_rect_fill_color (head_2[0], head_2[1], 10, 10*length_2,
GUI_GREEN);
module_gui_text_printf_line (2,"P2 Length %d",length_2);
}
//結束遊戲判斷
while (1)
{
if(!gameOver)
{
app_display();
VK_DELAY_MS(200-length*5-length_2*5);
}else
{
module_gui_set_text_color (GUI_WHITE);
if(gameOver==1)
{
module_font_scale_set(3);
module_gui_set_text_color (GUI_WHITE);
module_gui_text_printf_line (10,"Player 1 lose");
}
if(gameOver==2)
{
- 19. module_font_scale_set(3);
module_gui_set_text_color (GUI_GREEN);
module_gui_text_printf_line (10,"Player 2 lose");
}
if(gameOver==3)
{
module_font_scale_set(3);
module_gui_set_text_color (GUI_BLUE);
module_gui_text_printf_line (10," Ties");
}
}
}
}
工作分配:
已在上面程式碼中用顏色標示。
影片連結
http://www.youtube.com/watch?v=e-NROQvU2c4&feature=youtu.be
http://www.youtube.com/watch?v=wO5ge1-vmNQ&feature=youtu.be
參考資料
上課講義、網路。