贪吃蛇详解Windows编程(二)

终于可以让蛇动起来了,想想还有点小激动呢!哈哈,我们继续!

3.让蛇动起来

首先你得先创建一个定时器吧,然后我们先让蛇默认只往一个方向移动先,不要着急想着键盘控制那么快,只要一个方向能动,其它方向你还怕动不了?
代码片段如下:

#define SNAKESPEED 500 //初始化蛇的速度为500ms
#define TIMERID_1 1 //定时器ID

UINT uiSnakeSpeed = SNAKESPEED;//初始化蛇的速度为500ms
POINT ptDirectHead = {1,0};//蛇头的方向,初始化为向右
[其它代码]
//初始化蛇
VOID InitSnake()
{
    //先清空坐标
    vSnakePoint.clear();
    //给蛇坐标分配空间
    vSnakePoint.resize(SNAKEMAX);
    //游戏结束后再次初始化
    ucSnakeHead = 4;//初始化蛇头为4,实际上是vSnakePoint[3];
    ucSnakeTail = 0;//初始化蛇尾为0
    ucSnakekLen = 4;//初始化蛇身长度为4
    uiSnakeSpeed = SNAKESPEED;//初始化蛇的速度为200ms
    ptDirectHead = { 1,0 };//初始化蛇头方向
    //初始化每一节的蛇身坐标
    for (int i = 0;i < ucSnakekLen;i++)
    {
        vSnakePoint[i].x = i;
        vSnakePoint[i].y = 0;
    }
}
//获取蛇结点位置
//index是一个偏移蛇尾的偏移量
//很多人不懂&是什么意思,在C语言中是取地址的意思,在C++中还有一个用法就是引用传递,意思是,比如有个函数是int f(int &a);
//那么你就只需要传递一个普通变量进去就相当于C语言中传递的指针一样了,都可以改变实参。f(a);
POINT &GetSnakeNode(int index)
{
    //因为蛇的位置时刻改变,所以我们要用相对坐标来计算
    //自己画个图算算就理解了。
    int i = ucSnakeTail + index;//蛇身的长度
    //如果超过了蛇的最大长度则往返循环
    if (i>=SNAKEMAX)
    {
        i -= SNAKEMAX;
    }
    //返回某个坐标
    return vSnakePoint[i];
}
//让蛇动起来
//里面有很多自己写的小函数,现在就先知道它们有什么用处,先不用管它如何实现,后面会贴出来的
BOOL  SnakeMove()
{
    BOOL bRet = FALSE;
    do 
    {
        POINT ptNewNode = { 0 };//新的蛇头
        //前面是当前蛇头的x坐标,如果当前蛇头的方向是向右,那么x==1,所以蛇头向前移动一步,同理其它方向也是如此
        //然后两个相加就是移动后的蛇头新坐标
        ptNewNode.x = GetSnakeNode(ucSnakekLen-1).x + ptDirectHead.x;
        ptNewNode.y = GetSnakeNode(ucSnakekLen - 1).y + ptDirectHead.y;
        if (!IsStrikeWall(ptNewNode))//判断新的蛇头是否撞墙
             break;     
        if (!IsStrikeSelf(ptNewNode))//判断蛇是否撞到自己
              break;    
        if (IsEat(ptNewNode))//判断是否吃到食物
        {
            SetFood();//重新设置食物坐标
            uiScore += 10;//吃到一个食物加10分
            AddSnakeLen(ptNewNode);//增加蛇的长度
            break;
        }
        vSnakePoint[ucSnakeHead].x = ptNewNode.x;//蛇头移动
        vSnakePoint[ucSnakeHead++].y = ptNewNode.y;
        ucSnakeTail++;//整个蛇都移动了蛇尾肯定要移动是吧
        IsOverTake();//判断是否超出范围
        bRet = TRUE;
    } while (FALSE);
    return bRet;
}
[其他代码]
//在WM_CREATE消息中设置定时器
SetTimer(hWnd, TIMERID_1, uiSnakeSpeed, nullptr);//设置定时器

//定时器消息,处理蛇的移动和其它事件
case WM_TIMER:
     {  
            //移动蛇
            SnakeMove();
            //重新画蛇
            RECT rect = { 0 };
            SetRect(&rect, 0, 0, BOUNDSIZE + GAME_WIDE*SNAKESIZE,
                BOUNDSIZE + GAME_HEIGHT*SNAKESIZE);
            //这一步是必须的,必须让游戏区无效才能重画
            InvalidateRect(hWnd, &rect, TRUE);
        }

        break;


[其他代码]
在WM_DESTROY消息中关掉计时器
case WM_DESTROY:
    KillTimer(hWnd, TIMERID_1);

好了现在蛇已经可以往一个方向运动了。
效果如图:
贪吃蛇详解Windows编程(二)_第1张图片

接下来只要简单的加一个键盘消息就能控制蛇的方向了。

代码片段如下:

case WM_KEYDOWN://控制方向

        switch (wParam)
        {
        case VK_UP://x=0,y=1就是向下,所以当蛇头向上的时候不能向下走
            if (ptDirectHead.x != 0 && ptDirectHead.y != 1)
            {
                ptDirectHead.x = 0;
                ptDirectHead.y = -1;//向上y减小
            }
            break;
        case VK_DOWN:
            if (ptDirectHead.x != 0 && ptDirectHead.y != -1)
            {
                ptDirectHead.x = 0;
                ptDirectHead.y = 1;//向下y增大
            }
            break;
        case VK_LEFT:
            if (ptDirectHead.y != 0 && ptDirectHead.x != 1)
            {
                ptDirectHead.x = -1;//向左x减小
                ptDirectHead.y = 0;
            }
            break;
        case VK_RIGHT:
            if (ptDirectHead.y != 0 && ptDirectHead.x != -1)
            {
                ptDirectHead.x = 1;//向右x增大
                ptDirectHead.y = 0;
            }
            break;
        default:
            break;
        }

        break;

效果如图:


蛇的移动是难点,慢慢细细的用笔算算吧!

你可能感兴趣的:(编程,windows,移动)