Qt简单实现捕鱼达人

背景介绍

千炮捕鱼是一款经典童年游戏,现在在电玩城和手机上依然有它的影子,作为一款经典之作,我觉得有必要好好回味一下,恰逢大一暑假闲暇无事,又受到最近b站很多up主制作小游戏的启发,用qt简单实现千炮捕鱼。下方有图片资源和完整代码。

项目准备和框架

项目准备

我所要介绍的千炮捕鱼游戏使用的IDE是Qt Creator 4.11.1 (Community),附上Qt 官网,大家可自行去下载,下载安装等在此不在赘述,读者可以在网上找到很多教程。

框架

在这里插入图片描述

  1. 游戏开始

    开始界面

  2. 地图选择

    选择地图界面

  3. 游戏场景

    游戏场景

  4. 游戏结束
    游戏结束场景就是单纯的关闭窗口退出,简单粗暴!当然在此并不鼓励这种做法。

图片资源来源

项目中图片资源来自- 爱给网

总体思路

首先,我们实现一个主界面,给自己的按钮写一个类,它继承自Qt中Qpushbutton这个类,按钮可以下载纯色的矩形,再在中间填入文字,然后通过QPixmap类中的load方法加载图片,按钮就完成了。千炮捕鱼中许多对象都有相同的特点,不同种类的鱼都有不同的分数,血量等相同属性,往大的来说大炮,炮弹,渔网,鱼等也有相同属性,他们都应该有碰撞函数,都应该有绘制函数,我们把这些共有的属性写成一个基类,这个基类继承自QGraphicsItem这个类,然后炮弹,大炮,鱼,渔网等继承自我们的这个基类,这样省去了每次写一个类都要写碰撞函数和绘制函数的痛苦。最后,我们简单创造一个游戏场景即可。
基类与其他类的关系
在这里插入图片描述

实现

基类的实现

在游戏中,子弹,渔网,鱼等都有一些共有的方法,例如在此写的boundingRect和paint方法,在构造鱼,大炮等对象时可以通过向基类传参的方法构造对象。

#ifndef MYITEM_H
#define MYITEM_H
#include <QGraphicsItem>
#include <QRectF>
#include <QPainter>
class MyItem:public QGraphicsItem
{
public:
    MyItem(const QString & filename , QGraphicsScene *scence);
    //重写两个纯虚函数boundingRect 返回item大致区域paint来绘制item
    QRectF boundingRect () const;
    void paint(QPainter *painter,const QStyleOptionGraphicsItem *option,QWidget *widget);
    int type() const override;//判定碰撞物体的类型
private:
    QPixmap pixmap;
};
#endif // MYITEM_H
#include "myitem.h"
#include <QGraphicsItem>
#include <QGraphicsScene>
MyItem::MyItem(const QString & filename,QGraphicsScene * scence)
{
    pixmap.load(filename);
    scence->addItem(this);
}
int MyItem::type() const
{
    // Enable the use of qgraphicsitem_cast with this item.
    return Type;
}
QRectF MyItem::boundingRect () const
{
    return QRectF(-pixmap.width()/2,-pixmap.height(),pixmap.width(),pixmap.height());
}
void MyItem::paint(QPainter *painter,const QStyleOptionGraphicsItem *option,QWidget *widget)
{
    painter->drawPixmap(-pixmap.width()/2,-pixmap.height(),pixmap);
}
按钮
#ifndef MYBUTTON1_H
#define MYBUTTON1_H
#include <QWidget>
#include <QPushButton>
#include <QString>
class MyPushButton1 : public QPushButton
{
    Q_OBJECT
public:
    //explicit mybutton1(QWidget *parent = nullptr);
    //构造函数 参数一 默认显示图片 参数二 按下按键显示图片
    MyPushButton1(QString normalimg,QString pressimg);
    //成员属性
    QString normalimgpath;
    QString pressimgpath;
    //弹跳效果
    void sta1();//上跳
    void sta2();//下跳
signals:
};

#endif // MYBUTTON1_H
#include "mybutton1.h"
#include <QDebug>
#include <QSize>
#include <QPropertyAnimation>
MyPushButton1::MyPushButton1(QString normalimg,QString pressimg)
{
    this->normalimgpath = normalimg;
    this->pressimgpath = pressimg;

    QPixmap pix;
    bool ret = pix.load(normalimg);
    if(!ret){
        qDebug()<<"图片加载失败";
        return ;
    }
    //设置图片固定大小
    this->setFixedSize(pix.width(),pix.height());
    //设置不规则图片样式
    this->setStyleSheet("QPushButton{border:0px;}");
    //设置图标
    this->setIcon(pix);
    //设置图标大小
    this->setIconSize(QSize(pix.width(),pix.height()));
    show();
}

void MyPushButton1::sta1(){
    //动画效果
    QPropertyAnimation * animation = new QPropertyAnimation(this,"geometry");
    animation->setDuration(200);//时间间隔
    //起始位置
    animation->setStartValue(QRect(this->x(),this->y(),this->width(),this->height()));
    //结束位置
    animation->setEndValue(QRect(this->x(),this->y()+15,this->width(),this->height()));
    //设置弹跳曲线
    animation->setEasingCurve(QEasingCurve::OutBounce);
    //执行
    animation->start();
}

void MyPushButton1::sta2(){
    //动画效果
    QPropertyAnimation * animation = new QPropertyAnimation(this,"geometry");
    animation->setDuration(200);//时间间隔
    //起始位置
    animation->setStartValue(QRect(this->x(),this->y()+15,this->width(),this->height()));
    //结束位置
    animation->setEndValue(QRect(this->x(),this->y(),this->width(),this->height()));
    //设置弹跳曲线
    animation->setEasingCurve(QEasingCurve::OutBounce);
    //执行
    animation->start();
}
地图
#ifndef MAP_H
#define MAP_H

#include <QMainWindow>
#include "playwindow.h"
class map : public QMainWindow
{
    Q_OBJECT
public:
    explicit map(QWidget *parent = nullptr);
    //重写绘图事件
    void paintEvent(QPaintEvent *);
    //游戏场景对象指针
    playwindow *play = NULL;
signals:

};

#endif // MAP_H

#include "map.h"
#include "mybutton1.h"
#include "playwindow.h"
#include <QMenuBar>
#include <QPainter>
#include <QTimer>
map::map(QWidget *parent) : QMainWindow(parent)
{
    //设置固定大小
    this->setFixedSize(1500,1000);
    //设置图片
    this->setWindowIcon(QPixmap(":/background/image/mainwin.jpg"));
    this->setWindowTitle("捕鱼达人场景选择");

    //菜单栏等等
    QMenuBar * bar = new QMenuBar();
    setMenuBar(bar);
    QMenu * startme = bar->addMenu("开始");
    bar->addAction("帮助");
    QAction * quit = startme->addAction("退出");
    connect(quit,&QAction::triggered,[=] () {
        this->close();
    });

    //设置地图选择按钮
    MyPushButton1 * map1btn = new MyPushButton1(":/other/image/chosebtn.png","");
    map1btn->setParent(this);
    map1btn->move(160,900);
    //设置地图选择按钮
    MyPushButton1 * map2btn = new MyPushButton1(":/other/image/chosebtn2.png","");
    map2btn->setParent(this);
    map2btn->move(650,900);
    //设置地图选择按钮
    MyPushButton1 * map3btn = new MyPushButton1(":/other/image/chosebtn3.png","");
    map3btn->setParent(this);
    map3btn->move(1100,900);


    //按钮触发的事件
    connect(map1btn,&MyPushButton1::clicked,[=] () {
        //做特效
        map1btn->sta1();
        map1btn->sta2();
        //延时一下
        QTimer::singleShot(500,this,[=] () {
            //进入场景
            //隐藏自身
            this->hide();
            this->play = new playwindow(1);//传入地图代号
            play->show();
        });
    });
    //按钮触发的事件
    connect(map2btn,&MyPushButton1::clicked,[=] () {
        //做特效
        map2btn->sta1();
        map2btn->sta2();
        //延时一下
        QTimer::singleShot(500,this,[=] () {
            //进入场景
            //隐藏自身
            this->hide();
            this->play = new playwindow(2);//传入地图代号
            play->show();
        });
    });
    //按钮触发的事件
    connect(map3btn,&MyPushButton1::clicked,[=] () {
        //做特效
        map3btn->sta1();
        map3btn->sta2();
        //延时一下
        QTimer::singleShot(500,this,[=] () {
            //进入场景
            //隐藏自身
            this->hide();
            this->play = new playwindow(3);//传入地图代号
            play->show();

        });
    });
}
void map::paintEvent(QPaintEvent *){
    QPainter painter(this);
    QPixmap pix;
    pix.load(":/background/image/chosemap.jpg");
    painter.drawPixmap(0,0,this->width(),this->height(),pix);

    pix.load(":/other/image/dia.png");
    painter.drawPixmap(590,120,pix.width(),pix.height(),pix);

    pix.load(":/background/image/background1.jpg");
    painter.drawPixmap(50,200,400,600,pix);

    pix.load(":/background/image/background2.jpg");
    painter.drawPixmap(550,200,400,600,pix);

    pix.load(":/background/image/background3.jpg");
    painter.drawPixmap(1050,200,400,600,pix);
}

#ifndef FISH_H
#define FISH_H
#include "myitem.h"

class fish : public MyItem
{
public:
    fish(const QString & filename , QGraphicsScene *scence,int hp,int value,int maxhp,int fishindex);
    void advance(int phase);
    QRectF boundingRect () const;
    void paint(QPainter *painter,const QStyleOptionGraphicsItem *option,QWidget *widget);
    int hp;//鱼的血量,分数等等
    int value;
    int maxhp;//最大血量,当鱼跑出边框时,把鱼的血量恢复最大
    int fishindex;//不同编号代表不同的鱼
    enum { Type = 1 };
    int type() const override;
private:
    QPixmap pixmap;
};

#endif // FISH_H
#include "fish.h"
#include <QGraphicsItem>
#include <QGraphicsScene>

fish::fish(const QString & filename , QGraphicsScene *scence,int hp,int value,int maxhp,int fishindex):MyItem(filename,scence)
{
    this->hp = hp;
    this->value = value;
    this->maxhp = maxhp;
    this->pixmap = filename;
    this->fishindex = fishindex;
    scence->addItem(this);
}
QRectF fish::boundingRect () const
{
    return QRectF(-pixmap.width()/2,-pixmap.height(),pixmap.width(),pixmap.height());
}
void fish::advance(int phase){
    if(mapToScene(0,0).y()<=0||mapToScene(0,0).x() >= 1400){//跑出去就重设位置
        this->hp = this->maxhp;
        setPos(-120,qrand()%600);
    }
    int speed = qrand()%20;
    setPos(mapToScene(speed,-qrand()%3));
}

void fish::paint(QPainter *painter,const QStyleOptionGraphicsItem *option,QWidget *widget)
{
    char filename[50]="0";

    switch (this->fishindex) {
    case 1:
        static int i1=0;
        sprintf(filename,":/fish/image/fish5.%d.png",i1++%4+1);//魔鬼鱼
        pixmap.load(filename);
        painter->drawPixmap(-pixmap.width()/2,-pixmap.height(),pixmap);
        break;
    case 2:
        static int i2=0;
        sprintf(filename,":/fish/image/fish6.%d.png",i2++%5+1);//鲨鱼
        pixmap.load(filename);
        painter->drawPixmap(-pixmap.width()/2,-pixmap.height(),pixmap);
        break;
    case 3:
        static int i3=0;
        sprintf(filename,":/fish/image/fish7.%d.png",i3++%3+1);//黄金墨鱼
        pixmap.load(filename);
        painter->drawPixmap(-pixmap.width()/2,-pixmap.height(),pixmap);
        break;
    case 4:
        static int i4=0;
        sprintf(filename,":/fish/image/fish8.%d.png",i4++%4+1);//大白鲨
        pixmap.load(filename);
        painter->drawPixmap(-pixmap.width()/2,-pixmap.height(),pixmap);
        break;
    case 5:
        static int i5=0;
        sprintf(filename,":/fish/image/fish9.%d.png",i5++%2+1);//大金鱼
        pixmap.load(filename);
        painter->drawPixmap(-pixmap.width()/2,-pixmap.height(),pixmap);
        break;
    default:
        static int i6=0;
        sprintf(filename,":/fish/image/greenfish%d.png",i6++%6+1);//小绿鱼
        pixmap.load(filename);
        painter->drawPixmap(-pixmap.width()/2,-pixmap.height(),pixmap);
        break;
    }

}
int fish::type() const
{
    return Type;
}

大炮
#ifndef GUN_H
#define GUN_H
#include "myitem.h"

class Qgun:public MyItem
{
public:
    Qgun(const QString & filename , QGraphicsScene *scence,int power);
    void changegun(int gunindex);
    int netindex;
    int power;
//private:
    enum { Type = 3 };
    int type() const override;
    QPixmap pixmap;

};

#endif // GUN_H
#include "gun.h"
#include "myitem.h"

Qgun::Qgun(const QString & filename , QGraphicsScene *scence,int power):MyItem(filename,scence)//参数列表向基类传递参数
{
    this->power = power;
}

int Qgun::type() const
{
    return Type;
}
//void Qgun::changegun(int gunindex){
//    static int i = 0;



//}

子弹
#ifndef BUTTLE_H
#define BUTTLE_H
#include "myitem.h"
#include <QGraphicsScene>
#include "playwindow.h"
#include "gun.h"

class buttle : public MyItem
{
public:
    buttle(const QString & filename , QGraphicsScene *scence,qreal angle,playwindow*window,Qgun *gun);
    void paint(QPainter *painter,const QStyleOptionGraphicsItem *option,QWidget *widget);
    void advance(int phase);//重写advance函数进行移动

    void colliding();//碰撞之后执行
private:
    QGraphicsScene *scence;
    QPixmap pixmap;
    QString filename;
    playwindow*window;
    Qgun *gun;
};

#endif // BUTTLE_H
#include "buttle.h"
#include <QtGui>
#include <QGraphicsScene>
#include <QtDebug>
#include "net.h"
#include <QList>
#include <QGraphicsItem>
#include "fish.h"
#include "playwindow.h"
#include "gun.h"

buttle::buttle(const QString & filename ,QGraphicsScene *scence,qreal angle,playwindow*window , Qgun *gun):MyItem(filename,scence)
{
    this->gun = gun;
    this->window = window;
    this->filename = filename;
    this->scence = scence;
    qreal dx,dy;
    qreal rad;
    rad = angle*3.14/180;
    dx = 130*cos(rad);
    dy = 130*sin(rad);
    this->setPos(scence->width()/2+dx,scence->height()-dy);
    this->setRotation(90-angle);//设置角度
}
void buttle::paint(QPainter *painter,const QStyleOptionGraphicsItem *option,QWidget *widget)
{
    pixmap.load(filename);
    painter->drawPixmap(-pixmap.width()/2,-pixmap.height(),pixmap);
    if(this->collidingItems().count()>0){
        colliding();
    }
}
void buttle::advance(int phase){

    if(mapToScene(0,0).x() <= 0||mapToScene(0,0).x() > 1400||mapToScene(0,0).y() <= 0){
        delete  this;//超出边框自动释放
        //qDebug()<<mapToScene(0,0).x()<<mapToScene(0,0);
    }
    else{
        this->setPos(mapToScene(0,-22));
    }
}
void buttle::colliding(){//碰撞处理

    QString nett[5] = {":/pao/image/net2.png",":/pao/image/net4.png",":/pao/image/net.png",":/pao/image/netsss.png"};
    QString fin = nett[this->window->gunindex%4];
    net *mynet = new net(fin,this->scence,this->window,this->gun);
    mynet->setPos(mapToScene(0,0));
    delete this;
}

渔网
#ifndef NET_H
#define NET_H

#include "myitem.h"
#include "playwindow.h"
#include "gun.h"

class net: public MyItem
{
public:
    net(const QString & filename , QGraphicsScene *scence,playwindow *window,Qgun *gun);
    void advance(int phase);
    enum { Type = 2 };
    int type() const override;
    playwindow *window;
    Qgun *gun;
};

#endif // NET_H
#include "net.h"
#include "fish.h"
#include "playwindow.h"
#include <QDebug>

net::net(const QString & filename , QGraphicsScene *scence,playwindow *window,Qgun *gun):MyItem(filename,scence)
{
    this->window = window;
    this->gun = gun;
}
void net::advance(int phase){
    if(this->collidingItems().count()>0){

        QList <QGraphicsItem *> tem = this->collidingItems();
        foreach (QGraphicsItem *item, tem) {
            if(item->type() == fish::Type){
//重载了type函数,获取item的类型判断返回的QGraphicsItem *item每个节点是否都是鱼
//避免了返回的item是渔网类型而强制转换成鱼而报错终止程序的bug
// 2023/7/5
                //qDebug()<<"类型:"<<item->type();
                fish *fishs;
                fishs =(fish*)(item);
                     fishs->hp-=this->gun->power; //减少一点当前生命值
                     if(fishs->hp<=0)
                     {
                                       //鱼死亡,加分
                        this->window->score+=fishs->value;
                        fishs->setPos(-50-rand()%300,200+rand()%500);//鱼死亡就移到屏幕外
                        fishs->hp = fishs->maxhp;
                      }
            }
            else{
                //qDebug()<<"类型不对"<<item->type();
            }

        }
    }
    this->hide();
    delete this;
}
int net::type() const
{
    return Type;
}

其他
开始场景
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include "map.h"

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
    //重写绘图事件
    void paintEvent(QPaintEvent *);

    map *mymap = NULL;
private:
    Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "mybutton1.h"
#include "map.h"
#include <QPainter>
#include <QTimer>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    //设置固定大小
    this->setFixedSize(1500,1000);
    //设置图片
    this->setWindowIcon(QPixmap(":/background/image/mainwin.jpg"));

    this->setWindowTitle("捕鱼达人");
    //退出按钮
    connect(ui->exit,&QAction::triggered,[=] (){
        this->close();
    });
    //开始按钮
    MyPushButton1 * startbtn = new MyPushButton1(":/other/image/start.png","");
    startbtn->setParent(this);
    startbtn->move(this->width()*0.75,600);

    this->mymap = new map();
    //开始按钮触发的事件
    connect(startbtn,&MyPushButton1::clicked,[=] () {
        //做特效
        startbtn->sta1();
        startbtn->sta2();

        //延时一下
        QTimer::singleShot(500,this,[=] () {
            //进入场景选择
            //隐藏自身
            this->hide();
            mymap->show();
        });
    });

}
void MainWindow::paintEvent(QPaintEvent *){
    QPainter painter(this);
    QPixmap pix;
    pix.load(":/background/image/mainwin.jpg");
    painter.drawPixmap(0,0,this->width(),this->height(),pix);

}


MainWindow::~MainWindow()
{
    delete ui;
}



游戏场景
#ifndef PLAYWINDOW_H
#define PLAYWINDOW_H

#include <QMainWindow>
#include <QPainter>
#include <QGraphicsItem>
#include <QGraphicsView>
#include "gun.h"
#include "fish.h"
#include <QTimer>
#include <QTextEdit>

class playwindow : public QGraphicsView
{
    Q_OBJECT
public:
    //explicit playwindow(QWidget *parent = nullptr);
    playwindow(int level);
    ~playwindow();
    void resizeEvent(QResizeEvent * event);
    void mouseMoveEvent(QMouseEvent *event);//大炮追踪鼠标 用于大炮类
    void mousePressEvent(QMouseEvent *event);//鼠标按下事件 用于子弹类
    void checkgunindex(int gunindex);//切换大炮
    void updatescore();
    int levelnum;//记录关卡号
    int score = 50;//记录得分
    int fireornot = 0;//是否开火,开火就扣分当做消耗
    int gunindex;//记录炮的下标
    QTextEdit *showscore;//得分框显示

private:
    QGraphicsScene *scence;
    Qgun * gun;
    fish *fish1;
    fish *fish2;
    fish *fish3;
    fish *fish4;
    fish *fish5;
    fish *fish6;
    fish *fish7;
    fish *fish8;
    QTimer *timer;

signals:

};

#endif // PLAYWINDOW_H

#include "playwindow.h"
#include "myitem.h"
#include "gun.h"
#include <QMenuBar>
#include <QPainter>
#include <QTimer>
#include <QString>
#include <QGraphicsItem>
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QResizeEvent>
#include "fish.h"
#include "mybutton1.h"
#include <QTimer>
#include "buttle.h"
#include <QTextEdit>
playwindow::playwindow(int level){
    //设置固定大小
    this->setFixedSize(1500,1000);
    //设置图片
    this->setWindowIcon(QPixmap(":/background/image/mainwin.jpg"));
    this->levelnum = level;
    this->setWindowTitle("捕鱼达人");
    //设置背景图片
    this->setAutoFillBackground(true);
    QString a[5] = {"",":/background/image/background1.jpg",":/background/image/background2.jpg",":/background/image/background3.jpg"};
    QString fin = a[this->levelnum];
    this->setBackgroundBrush(QBrush(QPixmap(fin)));
    setViewportUpdateMode(QGraphicsView::FullViewportUpdate);
    //创建分数显示框
    this->showscore=new QTextEdit(this);
    this->showscore->setReadOnly(true);//只读,可以复制
    this->showscore->setFixedSize(170,50);
    this->showscore->setFontPointSize(20);
    this->showscore->move(1350,0);

    //坐标系统不同
    scence = new QGraphicsScene;
    //scence->setSceneRect(-this->width()/2,-this->height()/2,this->width(),this->height());
    scence->setSceneRect(0,0,this->width()-5,this->height()-5);
    this->setScene(scence);

    //大炮
    gun = new Qgun(":/pao/image/pao4.png",scence,1);
    this->gunindex = 0;
    gun->setPos(this->width()/2,this->height()-10);//设置位置
    scence->addItem(gun);

    //加减按钮
    MyPushButton1 * up = new MyPushButton1(":/pao/image/btnup.png","");
    up->setParent(this);
    up->move(this->width()*0.5+35,this->height()-50);
    connect(up,&QPushButton::clicked,[=] ()
    {
        delete gun;
        this->gunindex += 1;
        if(this->gunindex  >= 4)
            this->gunindex=0;
        this->checkgunindex(this->gunindex);
    });

    MyPushButton1 * down = new MyPushButton1(":/pao/image/btndown.png","");
    down->setParent(this);
    down->move(this->width()*0.5-95,this->height()-50);
    connect(down,&QPushButton::clicked,[=] ()
    {
        delete gun;
        this->gunindex -= 1;
        if(this->gunindex < 0)
            this->gunindex = 3;
        this->checkgunindex(this->gunindex);
    });

    this->setMouseTracking(true);//设置鼠标追踪

    fish1 = new fish(":/fish/image/fish5.1.png",scence,8,10,8,1);//魅魔鱼
    fish1->setPos(-120,10);
//    scence->addItem(fish1);
    fish2 = new fish(":/fish/image/fish6.1.png",scence,30,45,30,2);//鲨鱼
    fish2->setPos(-80,30);
//    scence->addItem(fish2);
    fish3 = new fish(":/fish/image/fish8.1.png",scence,4,15,4,3);//墨鱼
    fish3->setPos(-110,15);
//    scence->addItem(fish3);
    fish8 = new fish(":/fish/image/greenfish1.png",scence,6,25,6,4);//大白鲨
    fish8->setPos(-65,5);
    fish4 = new fish(":/fish/image/fish9.1.png",scence,90,120,90,5);//黄金鱼
    fish4->setPos(-99,11);
//    scence->addItem(fish4);
    fish5 = new fish(":/fish/image/greenfish1.png",scence,6,25,6,6);//小绿鱼
    fish5->setPos(-70,10);
    fish6 = new fish(":/fish/image/greenfish1.png",scence,6,25,6,6);//小绿鱼
    fish6->setPos(-75,44);
    fish7 = new fish(":/fish/image/greenfish1.png",scence,6,25,6,6);//小绿鱼
    fish7->setPos(-88,35);


    timer = new QTimer();
    connect(timer,SIGNAL(timeout()),scence,SLOT(advance()));
    connect(timer,&QTimer::timeout,this,&playwindow::updatescore);
    timer->start(50);


}

void playwindow::resizeEvent(QResizeEvent * event){
    QString a[5] = {"",":/background/image/background1.jpg",":/background/image/background2.jpg",":/background/image/background3.jpg"};
    QString fin = a[this->levelnum];
    this->setBackgroundBrush(QBrush(QPixmap(fin).scaled(event->size(),Qt::IgnoreAspectRatio,Qt::SmoothTransformation)));
}

void playwindow::mouseMoveEvent(QMouseEvent *event){
    QPoint p;
    p = event->pos();//获取鼠标的点
    QLine line(this->width()/2,this->height(),p.x(),p.y());//鼠标位置和大炮之间画一条线
    QLineF linef(line);//变成浮点数
    gun->setRotation(90-linef.angle());//获取角度,旋转大炮
}

void playwindow::mousePressEvent(QMouseEvent *event){

    QString dan[5] = {":/pao/image/dan3.png",":/pao/image/dan4.png",":/pao/image/dan1.png",":/pao/image/dan2.png"};
    QString fin = dan[this->gunindex%4];//不同子弹类型

    QPoint p = event->pos();
    QLineF linef(this->width()/2,this->height(),p.x(),p.y());
    //子弹射出位置应该是炮口,在一个弧线上
    buttle *mybuttle = new buttle(fin,scence,linef.angle(),this,this->gun);
    this->fireornot += 1;
//    mybuttle->setPos(this->width()/2,this->height());
//    mybuttle->setRotation(90-linef.angle());//转移到构造函数了
}

void playwindow::updatescore(){
    if(this->fireornot == 1){
        this->fireornot = 0;
        this->score -= this->gun->power;
    }
    if(this->score <= 0)this->close();
    QString str = "得分:";
    QString strscore = QString::number(this->score);
    str.append(strscore);
    //强制类型转换之后添加
    //str.sprintf("得分:%d",score);
    //强烈建议别使用这种方法qwq
    this->showscore->setText(str);
}
void playwindow::checkgunindex(int gunindex){
    QString gunn[5] = {":/pao/image/pao4.png",":/pao/image/pao3.png",":/pao/image/pao5.png",":/pao/image/pao10.jpg"};
    QString fin = gunn[this->gunindex%4];
    switch (gunindex%4) {
    case 0:
        gun = new Qgun(fin,scence,1);
        gun->setPos(this->width()/2,this->height()-10);//设置位置
        scence->addItem(gun);
        break;
    case 1:
        gun = new Qgun(fin,scence,2);
        gun->setPos(this->width()/2,this->height()-10);//设置位置
        scence->addItem(gun);
        break;
    case 2:
        gun = new Qgun(fin,scence,5);
        gun->setPos(this->width()/2,this->height()-10);//设置位置
        scence->addItem(gun);
        break;
    default:
        gun = new Qgun(fin,scence,10);
        gun->setPos(this->width()/2,this->height()-10);//设置位置
        scence->addItem(gun);
        break;
    }

}
playwindow::~playwindow(){
}

问题

1.此小游戏仍然有bug没有解决,因为发射的炮弹碰到的鱼后出现渔网,他们继承同一个基类,所以渔网也是有碰撞面积的,导致如果使用连点器发射一连串渔网时第一颗子弹碰到鱼之后爆炸产生渔网,后面的子弹碰到第一颗子弹的渔网也会爆炸,可以缩短渔网的出现时间解决,但是应该有更优解,但我没调试出来。
2.由于图片资源太少导致鱼的动画卡顿,游动姿势奇怪,影响感官,有待改进。

心得体会

暑假的任务被搁置到现在,难以克服的惰性,趁着这个中秋国庆假期完成了这篇粗糙的总结,悔恨多过欣喜,到了大二进入Java的学习,c++的学习也要搁置了,但是语言只是工具,思想是互通的,通过学习c++,qt对程序有了更多的认识,在学起Java市也不免看见c++的影子,这个小游戏虽然略显的粗糙,但我从中学到很多,找buy和解决bug的能力得以提升。“躬身入局,挺膺负责,方有成事之可冀。”与各位共勉。

附上Gitee地址

https://gitee.com/kirinofans/fish_-game.git

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值