/* ***********************************Copyright (c)******************************** * *------------------------------------------------------------------------------- * 文 件 名: snake.c * 文件描述: 贪吃蛇 * * 作 者: 吴玉灵,victorywyl@126.com * 创建日期: 2009-07-21 * * 编译环境: * 硬件环境: S3C2410a (32 bit ARM920T RISC core from Samsung) *------------------------------------------------------------------------------- * * *----------------------------------修改记录------------------------------------- * 修 改 人: None * 修改日期: None * 修改描述: None *------------------------------------------------------------------------------- ******************************************************************************** */ /* includes */ #include <vxWorks.h> #include <taskLib.h> #include <wdLib.h> #include <sysLib.h> #include <stdio.h> #include <stdlib.h> #include <msgQLib.h> #include <logLib.h> #include "../../headers/usrDataType.h" #include "../../headers/Keyboard.h" #include "../../headers/guiBasicDrv.h" /*MACROS*/ /*********************************** * Using flyleft take place LEFT * Using flyright take place RIGHT * Using "SEN" take place UP * Using "COPY" take place DOWN * Using "EXIT" take place ESC ************************************/ #define LEFT 51 #define RIGHT 34 #define UP 2 #define DOWN 4 #define ESC 9 #define COLOR_GRASS ((31>>1)<<6) #define COLOR_BLACK 0x0000 #define COLOR_WHITE 0xfffe #define COLOR_BLUE 0x003e #define N 200 /*GLOBAL Variables*/ int i,j,k,key=0; int score=0; /*得分*/ int task1,task2; /*食物的结构体*/ struct Food { int x; /*食物的横坐标*/ int y; /*食物的纵坐标*/ int yes; /*判断是否要出现食物的变量*/ }food; /*蛇的结构体*/ struct Snake { int x[N]; int y[N]; int node; /*蛇的节数*/ int direction; /*蛇移动方向*/ int life; /* 蛇的生命,0活着,1死亡*/ }snake; /* Functiond Forward Declarations 函数声明 */ void Init(void); /*初始化目标机键盘驱动以及显示器*/ void Close(void); /*关闭显示*/ void DrawK(void); /*游戏开始画面*/ void GameOver(void); /*游戏结束*/ void GamePlay(void); /*玩游戏具体过程*/ void move(void); void PrScore(void); /*打印玩家成绩*/ void keyhandle(void); /* 处理蛇的运动方向direction */ void generatefood(void); /*是否产生食物*/ extern void taskBeep(void); extern void Beep(int freq, int ticks); extern void GUI_init(void); extern void GUI_PutButton(int x0,int y0,int wide,int high,INT8U *name); extern void GUI_Botton(int x0,int y0,int wide,int high,INT8U *name,INT16U color); extern void LCD_PutPixel(int x,int y,INT16U color); /* Entry of the whole code 程序入口点*/ void entry_snake(void) { Init(); DrawK(); taskSpawn("tBeep",90, 0, 500, (FUNCPTR)taskBeep, 0,0,0,0,0,0,0,0,0,0); task1=taskSpawn("maintask",95, 0, 20000, (FUNCPTR)GamePlay,0,0,0,0,0,0,0,0,0,0); task2=taskSpawn("keytask",95, 0, 20000, (FUNCPTR)move,0,0,0,0,0,0,0,0,0,0); } /*Other Functions*/ void Init(void) { if(KeyInit()==ERROR) logMsg("keyboard initialization failed...",0,0,0,0,0,0); GUI_init(); LCD_TurnON(); Beep(2000,sysClkRateGet()*2); } void DrawK(void) { LCD_FillColor(COLOR_BLACK); /*set the background color*/ for(i=100;i<700;i+=10) /*draw the background wall*/ { GUI_PutButton(i,60,10,10,""); GUI_PutButton(i,500,10,10,""); } for(i=70;i<500;i+=10) { GUI_PutButton(100,i,10,10,""); GUI_PutButton(690,i,10,10,""); } food.yes=1; /*1表示需要出现新食物,0表示已经存在食物*/ snake.life=0; /*活着*/ snake.direction=DOWN; /*方向往右*/ snake.x[0]=200;snake.y[0]=100; /*蛇头*/ snake.x[1]=190;snake.y[1]=100; snake.node=2; generatefood(); } void generatefood(void) { if(food.yes==1) { food.x=rand()%400+100; food.y=rand()%350+80; while(food.x%10!=0) /*食物随机出现后必须让食物能够在整格内,这样才可以让蛇吃到*/ food.x++; while(food.y%10!=0) food.y++; for(j=food.x;j<(food.x)+10;j++) /*画出食物*/ for(k=food.y;k<(food.y)+10;k++) { LCD_PutPixel(j,k,COLOR_BLUE); } food.yes=0; /*画面上有食物了*/ } } void Close(void) { LCD_TurnOFF(); } void GameOver(void) { puts("GAME OVER..."); } void GamePlay(void) { while(1) { while(key==0) /*在没有按键的情况下,蛇自己移动身体*/ { generatefood(); for(i=snake.node-1;i>0;i--) /*蛇的每个环节往前移动,也就是贪吃蛇的关键算法*/ { snake.x[i]=snake.x[i-1]; snake.y[i]=snake.y[i-1]; } switch(snake.direction) { case RIGHT:snake.x[0]+=10;break; case LEFT: snake.x[0]-=10;break; case UP: snake.y[0]-=10;break; case DOWN: snake.y[0]+=10;break; } /*碰撞检测*/ for(i=3;i<snake.node;i++) /*从蛇的第四节开始判断是否撞到自己了,因为蛇头为两节,第三节不可能拐过来*/ { if(snake.x[i]==snake.x[0]&&snake.y[i]==snake.y[0]) { GameOver(); /*显示失败*/ snake.life=1; break; } } if(snake.x[0]<110||snake.x[0]>690||snake.y[0]<70||snake.y[0]>490)/*蛇是否撞到墙壁*/ { GameOver(); /*本次游戏结束*/ snake.life=1; /*蛇死*/ } if(snake.life==1) /*以上两种判断以后,如果蛇死就跳出内循环,重新开始*/ break; if(snake.x[0]==food.x&&snake.y[0]==food.y) /*吃到食物以后*/ { snake.x[snake.node]=-20;snake.y[snake.node]=-20; /*新的一节先放在看不见的位置,下次循环就取前一节的位置*/ snake.node++; /*蛇的身体长一节*/ food.yes=1; /*画面上需要出现新的食物*/ score+=10; PrScore(); /*输出新得分*/ } for(i=0;i<snake.node;i++) /*画出蛇*/ { GUI_PutButton(snake.x[i],snake.y[i],10,10,""); taskDelay(sysClkRateGet()/10); } for(j=snake.x[snake.node-1];j<(snake.x[snake.node-1]+10);j++) for(k=snake.y[snake.node-1];k<snake.y[snake.node-1]+10;k++) { LCD_PutPixel(j,k,COLOR_BLACK); } key=0; } /*endwhile(key==0)*/ if(snake.life==1) /*如果蛇死就跳出循环*/ break; } /*endwhile(1)*/ } void move(void) { while(1) { key=KeyGetValue(); taskSuspend(task1); keyhandle(); taskResume(task1); } } void keyhandle(void) { if(key==UP&&snake.direction!=DOWN) /*判断是否往相反的方向移动*/ snake.direction=UP; else if(key==RIGHT&&snake.direction!=LEFT) snake.direction=RIGHT; else if(key==LEFT&&snake.direction!=RIGHT) snake.direction=LEFT; else if(key==DOWN&&snake.direction!=UP) snake.direction=DOWN; } void PrScore(void) { logMsg(" your current score is %d/n",score,0,0,0,0,0); }