QT-贪吃小游戏

QT-贪吃小游戏


一、演示效果

二、关键程序

c 复制代码
#include "Snake.h"
#include "Food.h"
#include "Stone.h"
#include "Mushroom.h"
#include "Ai.h"
#include "Game.h"
#include "Util.h"
#include "SnakeUnit.h"
#include <QGraphicsScene>
#include <QGraphicsRectItem>
#include <QTimer>
#include <QDebug>
#include <typeinfo.h>
#include <stdlib.h>
#include <QDesktopWidget>

extern Game *g;
QGraphicsScene *sc;
QTimer *timer;

Snake::Snake()
{

}

Snake::Snake(QGraphicsScene *s, QString nam, int l)
{
    sc = s;
    length = l;
    size = 6;
    alive = false;
    direction = "right";
    score = 1;
    count = 0;    
    speed = size+2;
    name = nam;
    type = "me";

    //snake body
    int startX = Util::screenWidth()/2;
    int startY = Util::screenHeight()/2;
    color = Util::randomSnakeColor();
    pic = ":/images/snakeUnit"+QString::number(color)+".png";
    for(int i=0; i<length; i++){
        SnakeUnit *e = new SnakeUnit(name, this);
        if(i==0){
            e->setPixmap(QPixmap(":/images/snakeUnit"+QString::number(color)+"Head.png"));
            e->setTransformOriginPoint(e->pixmap().width()/2, e->pixmap().height()/2);
        }
        else{           
             e->setPixmap(QPixmap(pic));
             e->setZValue(-100);            
        }
        e->setPos(startX-i*size, startY);
        s->addItem(e);
        body.append(e);       
    }
    body[0]->setRotation(90);

    //boundary
    boundary = new QGraphicsEllipseItem(0, 0, 100, 100);
    boundary->setPen(QPen(Qt::transparent));
    boundary->setZValue(-1);
    s->addItem(boundary);

    //snake name
    info = new QGraphicsTextItem();
    info->setFont(QFont("calibri", 9));
    info->setPlainText(name);
    info->setDefaultTextColor(Qt::white);
    info->setPos(startX+10, startY+10);
    s->addItem(info);

    //move timer
    timer = new QTimer();
    connect(timer, SIGNAL(timeout()), this, SLOT(move()));
    timer->start(100);
}

void Snake::move()
{

    if(g->snake->alive == true){

        //move snake
        for(int i = body.size()-1; i>=0; i--){

            //body
            if(i != 0){
                body[i]->setX(body[i-1]->x());
                body[i]->setY(body[i-1]->y());               
            }

            //head
            else{
                    //move according to direction
                    if(direction == "right"){
                        body[0]->setX(body[0]->x()+speed);
                    }

                    else if(direction == "left"){
                         body[0]->setX(body[0]->x()-speed);
                    }

                    else if(direction == "up"){
                        body[0]->setY(body[0]->y()-speed);
                    }

                    else if(direction == "down"){
                        body[0]->setY(body[0]->y()+speed);
                    }

                }

        }

        //move boundary
        boundary->setX(body[0]->x()-boundary->rect().width()/2);
        boundary->setY(body[0]->y()-boundary->rect().height()/2);

        //move snake name
        info->setX(body[0]->x()+10);
        info->setY(body[0]->y()+10);

        //acc according to ai type
        if(type == "normal"){
            //change direction randomly with low attack level
            changeRandomDirection(1);
        }

        else if(type == "chipku"){
             avoidThreat();

            //change direction randomly according to attack level
            changeRandomDirection(g->attackLevel);
        }

        else if(type == "courage"){
            //move away from threat if present
            avoidThreat();

            //change direction randomly with low attack level
            changeRandomDirection(1);
        }

        else if(type == "paytu"){

            avoidThreat();

            //eat nearby food
            QList<QGraphicsItem *> food_items = boundary->collidingItems();
            for(int i=0; i<food_items.size(); i++){
                if(typeid(*(food_items[i])) == typeid(Food) || (typeid(*(food_items[i])) == typeid(Mushroom))){
                    //if food has minimum life of 2 seconds
                    Food *f = (Food*)food_items[i];
                    if(f->life > 1){
                        QString d = Util::giveDirection(body[0]->x(), body[0]->y(), f->x(), f->y());
                        if(d != Util::oppositeDirection(direction)){
                            changeDirection(d);
                            qDebug()<<"Food";
                        }
                    }
                }
            }
        }

        //check collssion
        QList<QGraphicsItem *> colliding_items = body[0]->collidingItems();
        for(int i=0; i<colliding_items.size(); i++){

            //food
            if(typeid(*(colliding_items[i])) == typeid(Food)){

                body[0]->scene()->removeItem(colliding_items[i]);
                delete colliding_items[i];                
                count+=2;

                //update length at each 10 score
                if(count > 10){
                    score++;
                    count = 0;
                    g->updateScore();

                    //append one unit
                    SnakeUnit *e = new SnakeUnit(name, this);
                    e->setPixmap(QPixmap(pic));
                    e->setPos(-100,-100);
                    body[0]->scene()->addItem(e);
                    body.append(e);
                }
            }

            // Mushroom
            else if(typeid(*(colliding_items[i])) == typeid(Mushroom)){
                g->scene->removeItem(colliding_items[i]);
                delete colliding_items[i];
                count+=5;
                g->updateScore();
            }

            //stone
            else if(typeid(*(colliding_items[i])) == typeid(Stone)){               
                destroy();
                break;
            }

            //other snake
            else if(typeid(*(colliding_items[i])) == typeid(SnakeUnit) && ((SnakeUnit*)colliding_items[i])->parent != this){
                qDebug()<<"Collission " + name + " : " + ((SnakeUnit*)colliding_items[i])->name;
                destroy();
                break;
            }

        }

        //check screen-bounds
        if(body[0]->x() > sc->width()) body[0]->setX(0);
        else if(body[0]->x() < 0) body[0]->setX(sc->width());
        else if(body[0]->y() < 0) body[0]->setY(sc->height());
        else if(body[0]->y() > sc->height()) body[0]->setY(0);
     }
}

void Snake::destroy(){

    //remove yourself and turn into clouds
    for(int i=0; i<body.size(); i++){
        SnakeUnit *s = body[i];
        new Food(sc, 1, 1, s->x(), s->y());
        g->scene->removeItem(s); //remove body from scene
    }
     g->scene->removeItem(info); //remove info from scene
    alive = false;
    g->snakes.removeOne(this);
    Util::removeReservedName(this->name);
    Util::removeReservedColor(this->color);
     g->scene->removeItem(this->boundary);

    //delete ai from memory
    if(type == "ai"){        
        delete this;
    }

    //add new snake
    g->generateAi(1);
}

void Snake::changeDirection(QString dir){
    if(dir=="right" && direction != "left"){
        direction = "right";
        body[0]->setRotation(0);
        body[0]->setRotation(90);
    }
    else if(dir=="left" && direction != "right"){
        direction = "left";
        body[0]->setRotation(0);
        body[0]->setRotation(-90);
    }
    else if(dir=="up" && direction != "down"){
        direction = "up";
        body[0]->setRotation(0);
    }
    else if(dir=="down" && direction != "up"){
        direction = "down";
        body[0]->setRotation(0);
        body[0]->setRotation(180);
    }
}

void Snake::changeRandomDirection(int attackLevel){
    if(Util::random(0,10) % 2 == 0){

        //change direction
        int r = Util::random(0,3+attackLevel);

        if(r==0 && direction != "left"){
            changeDirection("right");
        }
        else if(r==1 && direction != "right"){
            changeDirection("left");
        }
        else if(r==2 && direction != "down"){
            changeDirection("up");
        }
        else if(r==3 && direction != "up"){
            changeDirection("down");
        }

        //move towards the player
        else if(r>3){
            QString d = Util::giveDirection(body[0]->x(), body[0]->y(), g->snake->body[0]->x(), g->snake->body[0]->y());
            if(direction != Util::oppositeDirection(d)) changeDirection(d);
        }
    }
}

void Snake::avoidThreat(){
    bool threat = false;
    int threatPointX, threatPointY;
    QList<QGraphicsItem *> boundary_items = boundary->collidingItems();
    for(int i=0; i<boundary_items.size(); i++){
        //if its other's boundary or body
        if(typeid(*(boundary_items[i])) == typeid(QGraphicsEllipseItem) || (typeid(*(boundary_items[i])) == typeid(SnakeUnit)) || (typeid(*(boundary_items[i])) == typeid(Stone))){
            threat = true;
            threatPointX = (boundary_items[i])->x();
            threatPointY = (boundary_items[i])->y();
        }
    }
    if(threat == true){
        QString d = Util::giveDirection(body[0]->x(), body[0]->y(), threatPointX, threatPointY);
        if(d != Util::oppositeDirection(direction)){
            changeDirection(Util::oppositeDirection(d));
            qDebug()<<"Threat kiled";
        }
    }
}

三、下载链接

https://download.csdn.net/download/u013083044/88758860

相关推荐
看山还是山,看水还是。8 分钟前
MySQL 管理
数据库·笔记·mysql·adb
fishmemory7sec15 分钟前
Koa2项目实战2(路由管理、项目结构优化)
数据库·mongodb·koa
momo小菜pa25 分钟前
【MySQL 09】表的内外连接
数据库·mysql
Манго нектар26 分钟前
JavaScript for循环语句
开发语言·前端·javascript
Jasonakeke33 分钟前
【重学 MySQL】四十九、阿里 MySQL 命名规范及 MySQL8 DDL 的原子化
数据库·mysql
程序猿小D35 分钟前
第二百六十九节 JPA教程 - JPA查询OrderBy两个属性示例
java·开发语言·数据库·windows·jpa
阿华的代码王国43 分钟前
【JavaEE】——文件IO的应用
开发语言·python
satan–01 小时前
R语言的下载、安装及环境配置(Rstudio&VSCode)
开发语言·windows·vscode·r语言
小宇成长录1 小时前
Mysql:数据库和表增删查改基本语句
数据库·mysql·数据库备份
电饭叔1 小时前
《python语言程序设计》2018版第8章19题几何Rectangle2D类(下)-头疼的几何和数学
开发语言·python