当前位置: 移动技术网 > IT编程>开发语言>.net > 练手WPF(四)——贪吃蛇小游戏的简易实现(下)

练手WPF(四)——贪吃蛇小游戏的简易实现(下)

2019年06月17日  | 移动技术网IT编程  | 我要评论

2017挑战者联盟第三季,北京青年政治学院分数线,纸牌屋第三季中文字幕

八、生成新的单节蛇身
我们这里先说说游戏小原理好了,游戏运行后,通过计时器事件不断生成新的单节蛇身类snakenode,添加到list中的0位置,原来的蛇头变成了第二节。该节新蛇头的坐标通过蛇头前进方向direct进行判断,即如果原蛇头往左运行,则新蛇头在原蛇头位置的左一格生成,其他方向以此类推。最后将该节添加到snakenodes列表中,并将相应图形添加到游戏区。

private void gennewsnakenode()
{
    snakenode snakenode = null;
    switch (direct)
    {
        case direction.up:
            snakenode = new snakenode(new point(snakenodes[snakehead]._pos.x,
                snakenodes[snakehead]._pos.y - 1));
            break;

        case direction.down:
            snakenode = new snakenode(new point(snakenodes[snakehead]._pos.x,
                snakenodes[snakehead]._pos.y + 1));
            break;

        case direction.left:
            snakenode = new snakenode(new point(snakenodes[snakehead]._pos.x - 1,
                snakenodes[snakehead]._pos.y));
            break;

        case direction.right:
            snakenode = new snakenode(new point(snakenodes[snakehead]._pos.x + 1,
                snakenodes[snakehead]._pos.y));
            break;
    }

    if (snakenode != null)
    {
        snakenodes.insert(0, snakenode);
        mycanvas.children.add(snakenodes[0]._rect);
    }
}

 

九、随机水果位置
注意该新位置不得与蛇身任何一节重叠,如果重叠则另外生成新位置,直到成功为止。

private point setfruittorandompos()
{
    bool flag = true;
    point pos = new point();
    while (flag)
    {
        flag = false;
        pos = new point(rnd.next(0, cellwidth), rnd.next(0, cellheight));
        foreach (var node in snakenodes)
        {
            if (pos.x == node._pos.x && pos.y == node._pos.y)
            {
                flag = true;
                break;
            }
        }
    }

    return pos;
}

 

十、碰撞检测(蛇头与水果)
因为只有蛇头会最先触碰到水果,所以只需判断蛇头坐标与水果坐标是否相同即可。如果撞到水果,则将水果随机生成新位置;如果没有碰到,则删除蛇尾一节(因为之后会通过计时器会生成新一节蛇头,这样就会保存蛇身长度,感觉位置前进了一格)。

private void checkcollision()
{
    if (snakenodes[snakehead]._pos.x == fruit._pos.x && snakenodes[snakehead]._pos.y == fruit._pos.y)
    {
        fruit.setpostion(setfruittorandompos());
    }
    else
    {
        if (mycanvas.children.contains(snakenodes[snakenodes.count - 1]._rect))
            mycanvas.children.remove(snakenodes[snakenodes.count - 1]._rect);

        snakenodes.removeat(snakenodes.count - 1);
    }
}

 

十一、判断是否游戏结束
很简单,看看蛇头是否触碰游戏区四边或蛇身的任何一节,如果是则返回true。
注意蛇身循环是从1开始的,如果从0开始你知道会出现什么情况。

        private bool isgameover()
        {
            if (snakenodes[snakehead]._pos.x == -1 || snakenodes[snakehead]._pos.x == cellwidth
                || snakenodes[snakehead]._pos.y == -1 || snakenodes[snakehead]._pos.y == cellheight)
            {
                return true;
            }

            foreach (var node in snakenodes)
            {
                if (node == snakenodes[snakehead])
                    continue;

                if (node._pos.x == snakenodes[snakehead]._pos.x && node._pos.y == snakenodes[snakehead]._pos.y)
                {
                    return true;
                }
            }

            return false;
        }

 

十三、删除游戏区的所有蛇身节
这个会在重新开始游戏时使用到:

private void removesnakenodeall()
{
    for (int i = 0; i < snakenodes.count; i++)
    {
        if (mycanvas.children.contains(snakenodes[i]._rect))
        {
            mycanvas.children.remove(snakenodes[i]._rect);
        }
    }
}

 

顺便再来一发删除游戏区的水果:

private void removefruit()
{
    if (fruit == null) 
    {
        return;
    }

    if (mycanvas.children.contains(fruit._ellipse))
    {
        mycanvas.children.remove(fruit._ellipse);
    }
}

 

十四、按键操作
通过方向键,设置direct值即可。

private void mycanvas_previewkeydown(object sender, keyeventargs e)
{
    switch (e.key)
    {
        case key.left:
            if (direct != direction.right)
            {
                direct = direction.left;
            }
            break;

        case key.right:
            if (direct != direction.left)
            {
                direct = direction.right;
            }
            break;

        case key.up:
            if (direct != direction.down)
            {
                direct = direction.up;
            }
            break;

        case key.down:
            if (direct != direction.up)
            {
                direct = direction.down;
            }
            break;

        case key.escape:
            application.current.shutdown();
            break;

        case key.space:
            if (currgamestate == gamestate.none)
                return;

            if (currgamestate == gamestate.pause)
            {
                currgamestate = gamestate.gameing;
                timer.start();
                menucontrol_pause.header = "暂停";
            }
            else if (currgamestate == gamestate.gameing)
            {
                currgamestate = gamestate.pause;
                timer.stop();
                menucontrol_pause.header = "继续";
            }
            break;
    }
}

 

十四、定义开始游戏方法
先删除界面中的蛇身和水果(保留底部暗格),随机位置生成水果和三节蛇身。

private void startgame()
{
    removesnakenodeall();
    removefruit();

    int startx = rnd.next(5, cellwidth - 6);
    int starty = rnd.next(5, cellheight - 6);
    direct = direction.right;

    fruit = new fruit(setfruittorandompos(), mycanvas);

    snakenodes = new list<snakenode>();
    snakenodes.add(new snakenode(new point(startx, starty)));
    gennewsnakenode();
    gennewsnakenode();
}

 

十五、开始游戏菜单

调用startgame()方法,并设定计时器开始。

private void menufile_newgame_click(object sender, routedeventargs e)
{
    startgame();
    timer.start();
    currgamestate = gamestate.gameing;
    menucontrol_pause.header = "暂停";
}

 

十六、暂停与继续
直接上代码,没有要说的了。

private void menucontrol_pause_click(object sender, routedeventargs e)
{
    if (currgamestate == gamestate.gameing)
    {
        currgamestate = gamestate.pause;
        timer.stop();
        menucontrol_pause.header = "继续";
    }
    else if (currgamestate == gamestate.pause)
    {
        currgamestate = gamestate.gameing;
        timer.start();
        menucontrol_pause.header = "暂停";
    }
}

 

十七、退出游戏

private void menufile_exit_click(object sender, routedeventargs e)
{
    application.current.shutdown();
}

 

十八、其他菜单功能
自己实现好了

private void menuhelp_about_click(object sender, routedeventargs e)
{
}

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网