qml实现贪吃蛇--缩水版

来源:互联网 发布:音乐合并软件 编辑:程序博客网 时间:2024/03/29 12:37

贪吃蛇作为一款经典的手机游戏,曾经风靡全世界,这里简单说一说玩法。

用游戏把子上下左右控制蛇的方向,寻找吃的东西,每吃一口就能得到一定的积分,而且蛇的身子会越吃越长,身子越长玩的难度就越大,不能碰墙,不能咬到自己的身体,更不能咬自己的尾巴,等到了一定的分数,就能过关,然后继续玩下一关。

这里我将使用qml来实现一个简单的贪吃蛇游戏

这个游戏现阶段没有通关,蛇的身子不会越吃越长。

我们简单分析一下贪吃蛇这个游戏的主要的实体有哪些吧~

一个是游戏视窗,一个是蛇,一个是糖果。

蛇不能越出游戏视窗,不然视为游戏结束,糖果出现的地方只能在游戏视窗内。

好,先看看蛇这个实体怎么用qml来构造吧(现阶段的蛇其实只是个矩形,不能变长也不能弯曲)。

====================================

Snake.qml

import QtQuick 2.4Rectangle {    id:snake;    width: 20;    height: 20;    color:"red";    x: 0.5 * areaX;    y: 0.5 * areaY;    property real areaX:500;    property real areaY:500;    readonly property int step: 10;    readonly property int timeStep: 50;    signal out;    property int moveDirection:3; // 0,1,2,3,4 ; left ,right, up, down, death    focus:true;    Keys.onPressed: {        if(event.key == Qt.Key_Left) {            snake.moveDirection = 0;            snake.start();        }        if(event.key == Qt.Key_Right) {            snake.moveDirection = 1;            snake.start();        }        if(event.key == Qt.Key_Up) {            snake.moveDirection = 2;            snake.start();        }        if(event.key == Qt.Key_Down) {            snake.moveDirection = 3;            snake.start();        }        event.accepted = true;    }    NumberAnimation on x { duration: snake.timeStep; }    NumberAnimation on y { duration: snake.timeStep; }    function start(){        if(!time.running) {            time.running = true;            snake.x = 0.5 * areaX;            snake.y = 0.5 * areaY;            snake.color = "red";        }    }    function stop() { time.running = false; }    function move(){        switch(moveDirection)        {        case 0:         /*left */            snake.x -= snake.step;            break;        case 1:         /*right*/            snake.x += snake.step;            break;        case 2:         /*up*/            snake.y -= snake.step;            break;        case 3:         /*down*/            snake.y += snake.step;            break;        case 4:         /*death*/            snake.y = 0;            snake.x = 0;            break;        default:        /*death*/            snake.y = 0;            snake.x = 0;            break;        }        checkOut();    }    function checkOut(){        if(snake.x < 0 || snake.y < 0 || (snake.x+snake.width) > areaX  || (snake.y+snake.height) > areaY ) {            out();            return true;        } else {            return false;        }    }    Timer{        id:time;        interval:snake.timeStep;        repeat:true;        onTriggered : move();    }    onOut: {        snake.stop();        snake.moveDirection = 4;        snake.color = "black";    }}

Snake通过定时调用move()来进行移动,move()函数内判断moveDirection的数值来确定Snake的移动方向,每移动一次,使用checkOut()函数判断Snake是否移动出了游戏视窗(也就是撞墙)。当Snake撞墙后,发射out信号,使用out的信号处理函数来让snake颜色变黑,并且停止计时器。

我们再来看看Candy这个实体

======================

Candy.qml

import QtQuick 2.0Rectangle {    id:candy;    width: 20;    height: 20;    signal ate; // 被吃时发信号    x:Math.random() * 500;    y : Math.random() * 500;    color:Qt.rgba(Math.random(),Math.random(),Math.random(),1);    function newCandy(){        candy.x = Math.random() * 500;        candy.y = Math.random() * 500;        candy.color = Qt.rgba(Math.random(),Math.random(),Math.random(),1);        candy.opacity = 1;    }    NumberAnimation on x { duration: 50; }    NumberAnimation on y { duration: 50; }    onAte:candy.opacity = 0;}

当Candy被吃时(也就是和Snake发生碰撞)发出ate这个信号,然后将自己变成透明的。还有一个函数时newCandy(),他的作用是让Candy这个实体,以随机的颜色和位置出现在游戏视窗里,达到Candy被Snake吃之后,又产生新的糖果。

现在看看游戏主视窗吧

=============================

main.qml

import QtQuick 2.4Rectangle {    id:gameView;    width: 500;    height: 500;    property int score:0;    Text{        anchors.centerIn: parent;        text:"score: "+ gameView.score;    }    Snake{        id:snake;        areaX : 500;        areaY : 500;        onOut:{            gameView.score = 0;        }    }    Candy { id:candy; }    Timer{        id:time;        interval:10;        repeat:true;        running:true;        onTriggered: {            if(collide(snake,candy)) {                candy.ate(); // signal;                ++gameView.score;                candy.newCandy();            }        }    }    // to check two rectangles collided 碰撞    function collide(item1,item2) {        if( ((item1.y+item1.height) >= item2.y)                && (item1.y <=( item2.y+item2.height)) ) {            if( ((item1.x+item1.width) >= item2.x)                    && (item1.x <=( item2.x+item2.width)) ) {                return true;            }            return false;        }        return false;    }}

游戏主视窗里有个比较重要的碰撞检测函数(矩形碰撞检测,定时被调用),当snake和candy发生了碰撞,也就是snake吃了candy时就会让candy发送ate信号,同时计分加一,candy调用newCandy函数。

看看效果


1 0
原创粉丝点击