目前把事件机制终于做好了。所有的操作都封装到事件里面。这是头文件snake.h:
/* Keyboard definition */
#define ENTER 13
/* Macro for quick control */
#define NEWEVENT (EventLink)malloc(sizeof(event))
#define REGISTER(name,in) tempevent=NEWEVENT;\
tempevent->interval=in;\
tempevent->timer=0;\
tempevent->invoke=name;
/* The prototype of bool type */
typedef enum
{
true,
false
}bool;
/* The prototype of directions */
typedef enum
{
up,
right,
down,
left
}direction;
/* The prototype of a point of the snake */
typedef struct
{
int posx;
int posy;
direction dir; /* The current direction of this point */
}point;
/* The prototype of the snake */
typedef struct
{
point dots[MAXSNAKELEN];
}snake;
#ifndef __SNAKE
/* prevent multiple includes */
#define __SNAKE
/* The prototype of the event */
typedef struct
{
long interval;/* The interval of the event occurs */
long timer;
void (*invoke)(); /* The function pointer to the invoke action */
}event;
/* The prototype of the eventlist */
struct eventlist
{
event *eventnow;
struct eventlist *next;
};
typedef struct eventlist Node;
typedef Node *Link;
typedef event *EventLink;
int screenx=0;
int screeny=0;
void Init();
void EventHandler(Link);
void EventInsert(Link,EventLink);
Link EventCreater(Link);
void EventFree(Link);
void Kernel();
/******************************************************/
void Kernel()
{
}
void EventInsert(Link eventhead,EventLink newevent)
{
Link pointer;
Link newlist;
pointer=eventhead;
while(1)
{
if (pointer->next==NULL)
{
newlist=(Link)malloc(sizeof(Node));
newlist->eventnow=newevent;
newlist->next=NULL;
pointer->next=newlist;
break;
}
pointer=pointer->next;
}
}
Link EventCreater(Link eventhead)
{
Link newevent;
EventLink tempevent;
int i;
eventhead=(Link)malloc(sizeof(Node));
/* Create event list */
if (eventhead==NULL)
{
printf("Memory allocate Failure!!\n");
}
else
{
tempevent=(EventLink)malloc(sizeof(event));
tempevent->interval=1;
tempevent->timer=0;
tempevent->invoke=Kernel;
eventhead->eventnow=tempevent;
eventhead->next=NULL;
}
return eventhead;
}
void EventFree(Link eventhead)
{
Link pointer;
EventLink tempevent;
while(eventhead !=NULL)
{
pointer=eventhead;
eventhead=eventhead->next;
tempevent=eventhead->eventnow;
free(pointer);
free(tempevent);
}
}
#endif
这里面没有什么解释的。Link EventCreater(Link)就是建立一个链表存放所有的事件。void EventInsert(Link,EventLink)是一个添加事件的函数。void EventFree(Link)是最后释放链表的函数。
下面是主程序snake.c
#include
#include
#include
#include
#include
#include
#include
/* Standard macro for quick caculation */
#define SNAKEUP if (me.dots[i].posy==0)\
me.dots[i].posy=getmaxy();\
else\
me.dots[i].posy--;\
#define SNAKEDOWN if (me.dots[i].posy==getmaxy())\
me.dots[i].posy=0;\
else\
me.dots[i].posy++;\
#define SNAKERIGHT if (me.dots[i].posx==getmaxx())\
me.dots[i].posx=0;\
else\
me.dots[i].posx++;\
#define SNAKELEFT if (me.dots[i].posx==0)\
me.dots[i].posx=getmaxx();\
else\
me.dots[i].posx--;\
/* The definition of keyboard */
#define KBUP 72
#define KBDOWN 80
#define KBRIGHT 77
#define KBLEFT 75
snake me;
/* Registry Events */
void Controler(); /* The main keyboard controler */
void DrawSnake();
void Calculate();
/* Registry Method */
void RegisterEvents(Link);
int main(void)
{
Link head;
int gdriver=DETECT,gmode;
/* Init graphic mode */
initgraph(&gdriver,&gmode,"");
Init();
head=EventCreater(head);
RegisterEvents(head);
EventHandler(head);
EventFree(head);
closegraph();
clrscr();
return 0;
}
void Controler()
{
char controlchar;
if (kbhit())
{
controlchar=getch();
switch (controlchar)
{
case ENTER:exit(0);break;
case KBUP:me.dots[0].dir=up;break;
case KBDOWN:me.dots[0].dir=down;break;
case KBRIGHT:me.dots[0].dir=right;break;
case KBLEFT:me.dots[0].dir=left;break;
}
}
}
void Calculate()
{
int i,j;
for (i=0;i<>
{
if (i==0)
{
j=0;
}
else
{
j=i-1;
}
switch(me.dots[j].dir)
{
case up:SNAKEUP;break;
case down:SNAKEDOWN;break;
case right:SNAKERIGHT;break;
case left:SNAKELEFT;break;
}
me.dots[i].dir=me.dots[j].dir;
}
}
void Init()
{
int i,j;
int sx=DEFAULTSTARTX,sy=DEFAULTSTARTY;
randomize();
for (i=0;i<>
{
me.dots[i].posx=sx;
me.dots[i].posy=sy;
me.dots[i].dir=up;
sy++;
}
screenx=getmaxx();
screeny=getmaxy();
}
/* Draw snake */
void DrawSnake()
{
int i;
cleardevice();
for (i=0;i<>
{
putpixel(me.dots[i].posx,me.dots[i].posy,DEFAULTSNAKECOLOR);
}
}
void RegisterEvents(Link head)
{
EventLink tempevent;
REGISTER(Controler,1);
EventInsert(head,tempevent);
REGISTER(Calculate,1000);
EventInsert(head,tempevent);
REGISTER(DrawSnake,1000);
EventInsert(head,tempevent);
}
void EventHandler(Link eventhead)
{
int i;
Link pointer;
while(1)
{
delay(1);
pointer=eventhead;
while (pointer!=NULL)
{
pointer->eventnow->timer++;
if ((pointer->eventnow->timer)>=(pointer->eventnow->interval))
{
/* Invoke current event */
pointer->eventnow->invoke();
pointer->eventnow->timer=0;
}
pointer=pointer->next;
}
/*if(kbhit())
{
if (getch()==KBUP)
break;
}*/
}
}
解释:void RegisterEvents(Link)是想注册事件的函数。这个函数是对void EventInsert(Link,EventLink)的更高级的封装。void Controler()是控制键盘的函数。void DrawSnake()是控制绘制蛇的函数.void Calculate()是计算蛇当前位置的函数。
下一步的任务就是使蛇准确按照键盘的输入移动。目前的移动有问题。
没有评论:
发表评论