1.snake_3_widget.h
#ifndef SNAKE_3_WIDGET_H
#define SNAKE_3_WIDGET_H
#include <QWidget>
#include<algorithm>
#include<QPainter>
#include<QBrush>
#include<QImage>
#include<QPaintEvent>
#include<QTimer>
#include<conio.h>
#include<QMediaPlaylist>
#include<QMediaPlayer>
#include<queue>
#include<QMessageBox>
#include<snake_mainmenu.h>
#include<his_TYPE.h>
#include<cmath>
QT_BEGIN_NAMESPACE
namespace Ui { class snake_3_Widget; }
QT_END_NAMESPACE
class snake_3_Widget : public QWidget
{
Q_OBJECT
public:
snake_3_Widget(QWidget *parent = nullptr,int dif = 1,std::priority_queue<his_type> = {});
~snake_3_Widget();
protected:
void keyPressEvent(QKeyEvent *event);
void paintEvent(QPaintEvent *event);
void addTop();
void addDown();
void addLeft();
void addRight();
void deletelast();
void addTop_2();
void addDown_2();
void addLeft_2();
void addRight_2();
void deletelast_2();
void addbean();
int eatBean();//0没吃 1蓝吃 2绿吃
bool rule();
int rule_2();
int dist(QRectF a,QRectF b); //返回以格子为的单位的距离
protected slots:
void timeout(); //判定
void timeout_1(); //蓝色速度
void timeout_2(); //绿色速度
void start_timeout(); //游戏开始缓冲2.5秒
void dif_3_timeout(); //每秒加速
private:
Ui::snake_3_Widget *ui;
QTimer *gametime,*game_startf,*game_dif_3,*game_1,*game_2;
QList<QRectF>snake_loc,snake_loc_2; //蛇每一节的坐标
int snake_dire=0; //蛇头方向:0上 1左 2下 3右
int snake_dire_2=0;
int nodeWidth = 100;
int nodeHeight = 100;
int snake_time=200,snake_1=200,snake_2=200; //初始速度0.2秒
QRectF * bean;
bool game_start=true;
bool first_start = false; //游戏首次开始
int pix_dl=1,pix_dl_2=1; //蛇头图片动态图,0、1为左朝向图片,2、3为右朝向图片
int pix_js=0,pix_js_2=0; //控制结算图片
bool dire_buffer,dire_buffer_2; //方向是否正在缓冲
int current_score; //当前分数
std::priority_queue<his_type> his_score; //历史记录
QMediaPlaylist * game_musiclist;
QMediaPlayer * game_music;
int difficulty=1; //难度
int max_length=7; //双人模式最长蛇长
};
#endif // SNAKE_3_WIDGET_H
2.snake_mainmenu.h
#ifndef SNAKE_MAINMENU_H
#define SNAKE_MAINMENU_H
#include <QWidget>
#include<QMediaPlaylist>
#include<QMediaPlayer>
#include<QPainter>
#include <snake_3_widget.h>
#include <QSoundEffect>
#include<QString>
#include<queue>
#include<QDateTime>
#include<his_TYPE.h>
#include<QDir>
enum INTERFACE{
MAIN,
HISTORY,
OPTION,
HELP
};
namespace Ui {
class snake_mainmenu;
}
class snake_mainmenu : public QWidget
{
Q_OBJECT
public:
explicit snake_mainmenu(QWidget *parent = nullptr,std::priority_queue<his_type>his_score={});
~snake_mainmenu();
protected:
void paintEvent(QPaintEvent *event);
private slots:
void on_quit_button_clicked();
void on_play_button_clicked();
void on_record_button_clicked();
void on_help_button_clicked();
void on_back_button_clicked();
void on_bgm_button_clicked();
void on_stopvoice_button_clicked();
void on_dif_1_button_clicked();
void on_dif_2_button_clicked();
void on_dif_3_button_clicked();
void on_save_button_clicked();
void on_clear_button_clicked();
void on_dif_4_button_clicked();
private:
Ui::snake_mainmenu *ui;
int current_interface; //当前界面:主菜单0 纪录1 模式难度2 帮助3
QMediaPlaylist * menu_musiclist;
QMediaPlayer * menu_music = new QMediaPlayer;
QSoundEffect *effect;
void interface(int);//对应界面
std::priority_queue<his_type> his;
int difficulty=1; //难度
void ReadtestFile(); //导入历史
bool h_his;/*用于判断是否可以保存*/
};
#endif // SNAKE_MAINMENU_H
3.his_TYPE.h
#ifndef HIS_TYPE_H
#define HIS_TYPE_H
#include<QTime>
struct his_type //历史记录结构体存历史记录完成时间和分数
{
int score;
int dif;
QTime Time ;
//按分数优先级排列
friend bool operator < (his_type h1,his_type h2)
{
return h1.score<h2.score;
}
};
#endif // HIS_TYPE_H
4.MyButton.h
#ifndef MYBUTTON_H
#define MYBUTTON_H
#include<QPushButton>
#include<QEvent>
#include<AudioThread.h>
#include<queue>
class MyButton :public QPushButton
{
Q_OBJECT;
public:
MyButton(QWidget *parent = 0);
~MyButton();
public:
void enterEvent(QEvent *e); //鼠标进入事件
void menu_soundeffect(int sound_index);//生成对应音效
private:
};
#endif // MYBUTTON_H
5.AudioThread.h
参考文章QSoundEffect独立声音播放线程 movetothread方式_ZLOZL的博客-CSDN博客_qt声音线程
#ifndef DLTHREAD_H
#define DLTHREAD_H
#include <QtCore>
#include <QObject>
#include <QSoundEffect>
#include <QThread>
#include<QTime>
enum VOICE_TYPE{
VOICE_POSITIVE,
VOICE_NEGATIVE,
VOICE_TEMPERATURE,
VOICE_TOOCLOSE,
VOICE_GOOCLOSE
};
class AudioThread : public QObject
{
Q_OBJECT
public:
AudioThread(QObject *parent = nullptr);
~AudioThread();
signals:
void doPlay();
void doStop();
public slots:
void play_strong(int type);
void play(int type);
private:
int voice_type;
QSoundEffect effect;
QThread thread;
};
#endif // DLTHREAD_H
6.snake_3_widget.cpp
#include "snake_3_widget.h"
#include "ui_snake_3_widget.h"
#include<QDebug>
#include<ctime>
using namespace std;
int cnt_g=0;
snake_3_Widget::snake_3_Widget(QWidget *parent,int dif,priority_queue<his_type> h)
: QWidget(parent)
, ui(new Ui::snake_3_Widget)
{
ui->setupUi(this);
this->setWindowTitle("");
gametime = new QTimer;
game_startf = new QTimer;
game_startf->start(2500);
current_score=0;
connect(gametime,SIGNAL(timeout()),this,SLOT(timeout()));
connect(game_startf,SIGNAL(timeout()),this,SLOT(start_timeout()));
setFixedSize(1600,900);
//传入难度
/*模式4:双人规则初始两条蛇长为2的蛇AB,
* AB碰头平局,若A碰到B某一节身体,就将B从该节身体开始全部消除(B碰到自己同理),谁的蛇长先归为0谁就输
* 初始蛇速都为200,每吃一块石头加一节蛇身,每加一节蛇身速度减20,蛇身最长为7,速度最慢为300
* 模式5:人机 寻路方式:每次选择相对距离更近的方向走
* 制定寻路相对距离规则:蛇头改变方向后的坐标到某点的坐标之间的距离乘上该点的权值
* 每个点的权值应该随着两蛇的位置和石头发生
*/
difficulty=dif;
if(difficulty==3)
{
snake_time=120;
game_dif_3 = new QTimer;
game_dif_3->start(1000);
connect(game_dif_3,SIGNAL(timeout()),this,SLOT(dif_3_timeout()));
}
//添加背景图片
if(difficulty<4)
{
QImage background = QImage(":/pic/prefix1/picture/bj1.png");
QBrush *brush = new QBrush(background.scaled(this->size()));
QPalette pa(this->palette());
pa.setBrush(QPalette::Window,*brush);
this->setPalette(pa);
}
else
{
QImage background = QImage(":/pic/prefix1/picture/bj2.jpg");
QBrush *brush = new QBrush(background.scaled(this->size()));
QPalette pa(this->palette());
pa.setBrush(QPalette::Window,*brush);
this->setPalette(pa);
}
qDebug()<<"60";
//初始化音乐
game_musiclist = new QMediaPlaylist;
game_musiclist->addMedia(QUrl("qrc:/voi/wavbgm/bgm_game_inToOppor.wav"));
game_musiclist->addMedia(QUrl("qrc:/voi/wavbgm/bgm_game_oppressive.wav"));
game_musiclist->addMedia(QUrl("qrc:/voi/wavbgm/bgm_game_inTofier.wav"));
game_musiclist->addMedia(QUrl("qrc:/voi/wavbgm/bgm_game_subfierce.wav"));
game_musiclist->addMedia(QUrl("qrc:/voi/wavbgm/bgm_game_fierce.wav"));
game_musiclist->addMedia(QUrl("qrc:/voi/wavbgm/bgm_game_fierce_happy.wav"));
game_musiclist->addMedia(QUrl("qrc:/voi/wavbgm/bgm_game_funny.wav"));
game_music = new QMediaPlayer;
game_music->setPlaylist(game_musiclist);
game_musiclist->setPlaybackMode(QMediaPlaylist::CurrentItemInLoop);
game_musiclist->setCurrentIndex(cnt_g++);
game_music ->play();
qDebug()<<"76";
//初始化蛇身
QRectF rect(300,600,nodeWidth,nodeHeight);
QRectF rect_2(600,400,nodeWidth,nodeHeight);
snake_loc.append(rect);
addTop();
if(difficulty!=4)addTop();
else{
snake_time=20;
game_1 = new QTimer;
game_2 = new QTimer ;
connect(game_1,SIGNAL(timeout()),this,SLOT(timeout_1()));
connect(game_2,SIGNAL(timeout()),this,SLOT(timeout_2()));
snake_loc_2.append(rect_2);
addTop_2();
}
//初始化豆子
addbean();
//设置分数显示
ui->score_num->setDigitCount(3);
ui->score_num->setDecMode();
ui->score_num->setStyleSheet("border: none");
ui->score_num->setSegmentStyle(QLCDNumber::Flat);
if(difficulty==4){
ui->score_num->hide();
}
//承接历史记录
his_score = h;
}
snake_3_Widget::~snake_3_Widget()
{
delete ui;
}
void snake_3_Widget::paintEvent(QPaintEvent *)
{
// qDebug()<<snake_time<<"%%";
QPixmap pix_yzlz1,pix_yzlz2,pix_yzly1,pix_yzly2,pix_ld,pix_ys,pix_yzlz3,pix_yzly3;
QPixmap pix_yzlz1_2,pix_yzlz2_2,pix_yzly1_2,pix_yzly2_2,pix_ld_2,pix_yzlz3_2,pix_yzly3_2;
pix_yzlz1.load(":/pic/prefix1/picture/yzlz1.png");//岩贼龙动作1
pix_yzlz2.load(":/pic/prefix1/picture/yzlz3.png");//岩贼龙动作2
pix_yzly1.load(":/pic/prefix1/picture/yzly2.png");//岩贼龙动作3
pix_yzly2.load(":/pic/prefix1/picture/yzly1.png");//岩贼龙动作4
pix_yzlz3.load(":/pic/prefix1/picture/yzlz4.png");//岩贼龙动作5
pix_yzly3.load(":/pic/prefix1/picture/yzly4.png");//岩贼龙动作6
pix_ld.load(":/pic/prefix1/picture/ld2.png"); //龙蛋
if(difficulty==4){
pix_yzlz1_2.load(":/pic/prefix1/picture/yzlz1_2.png");//岩贼龙动作1
pix_yzlz2_2.load(":/pic/prefix1/picture/yzlz3_2.png");//岩贼龙动作2
pix_yzly1_2.load(":/pic/prefix1/picture/yzly2_2.png");//岩贼龙动作3
pix_yzly2_2.load(":/pic/prefix1/picture/yzly1_2.png");//岩贼龙动作4
pix_yzlz3_2.load(":/pic/prefix1/picture/yzlz4_2.png");//岩贼龙动作5
pix_yzly3_2.load(":/pic/prefix1/picture/yzly4_2.png");//岩贼龙动作6
pix_ld_2.load(":/pic/prefix1/picture/ld2_2.png"); //龙蛋
}
// pix_bj.load(":/pic/prefix1/picture/bj1.png"); //背景
pix_ys.load(":/pic/prefix1/picture/ys.png"); //岩石
QPainter painter(this); //设置画笔
painter.setRenderHint(QPainter::Antialiasing,true); //抗锯齿
// painter.drawPixmap(0,0,1600,900,pix_bj); //插入背景图片
painter.drawPixmap(bean->x(),bean->y(),nodeWidth,nodeHeight,pix_ys);//画岩石
for(int i=1;i<snake_loc.length();i++)
{
painter.drawPixmap(snake_loc[i].x(),snake_loc[i].y(),nodeWidth,nodeHeight,pix_ld); //画龙蛋
}
if(difficulty==4)
{
for(int i=1;i<snake_loc_2.length();i++)
{
painter.drawPixmap(snake_loc_2[i].x(),snake_loc_2[i].y(),nodeWidth,nodeHeight,pix_ld_2); //画龙蛋
}
}
if(!pix_js) //画岩贼龙
{
switch ((int)pix_dl) {
case 0:
painter.drawPixmap(snake_loc[0].x(),snake_loc[0].y(),nodeWidth,nodeHeight,pix_yzlz2);
break;
case 1:
painter.drawPixmap(snake_loc[0].x(),snake_loc[0].y(),nodeWidth,nodeHeight,pix_yzlz1);
break;
case 2:
painter.drawPixmap(snake_loc[0].x(),snake_loc[0].y(),nodeWidth,nodeHeight,pix_yzly1);
break;
case 3:
painter.drawPixmap(snake_loc[0].x(),snake_loc[0].y(),nodeWidth,nodeHeight,pix_yzly2);
break;
}
}
else
{
if(pix_js==1)painter.drawPixmap(snake_loc[0].x(),snake_loc[0].y(),nodeWidth,nodeHeight,pix_yzlz3);
if(pix_js==2)painter.drawPixmap(snake_loc[0].x(),snake_loc[0].y(),nodeWidth,nodeHeight,pix_yzly3);
gametime->stop();
}
if(difficulty==4)
{
if(!pix_js_2) //画岩贼龙
{
switch ((int)pix_dl_2) {
case 0:
painter.drawPixmap(snake_loc_2[0].x(),snake_loc_2[0].y(),nodeWidth,nodeHeight,pix_yzlz2_2);
break;
case 1:
painter.drawPixmap(snake_loc_2[0].x(),snake_loc_2[0].y(),nodeWidth,nodeHeight,pix_yzlz1_2);
break;
case 2:
painter.drawPixmap(snake_loc_2[0].x(),snake_loc_2[0].y(),nodeWidth,nodeHeight,pix_yzly1_2);
break;
case 3:
painter.drawPixmap(snake_loc_2[0].x(),snake_loc_2[0].y(),nodeWidth,nodeHeight,pix_yzly2_2);
break;
}
}
else
{
if(pix_js_2==1)painter.drawPixmap(snake_loc_2[0].x(),snake_loc_2[0].y(),nodeWidth,nodeHeight,pix_yzlz3_2);
if(pix_js_2==2)painter.drawPixmap(snake_loc_2[0].x(),snake_loc_2[0].y(),nodeWidth,nodeHeight,pix_yzly3_2);
gametime->stop();
}
}
// painter.setPen(QPen(QColor(0, 160, 230), 2)); //画笔颜色尺寸
// painter.drawPoint(QPointF(400,400)); //绘制点
// painter.drawEllipse(QPointF(120, 60), 5, 5); //绘制椭圆
// painter.setClipRect(rect.adjusted(20,20,-20,-20));
// painter.drawLine(rect.topLeft(),rect.bottomRight()); //绘制线
}
void snake_3_Widget::keyPressEvent(QKeyEvent *event) //键盘事件
{
switch(event->key())
{
case Qt::Key_W: //W键
if(!dire_buffer&&snake_dire!=2)
snake_dire=0,dire_buffer=true;
break;
case Qt::Key_A: //A键
if(!dire_buffer&&snake_dire!=3)
snake_dire=1,dire_buffer=true;
break;
case Qt::Key_S: //S键
if(!dire_buffer&&snake_dire!=0)
snake_dire=2,dire_buffer=true;
break;
case Qt::Key_D: //D键
if(!dire_buffer&&snake_dire!=1)
snake_dire=3,dire_buffer=true;
break;
case Qt::Key_Up: //up键
if(difficulty==4&&!dire_buffer_2&&snake_dire_2!=2)
snake_dire_2=0,dire_buffer_2=true;
break;
case Qt::Key_Left: //left键
if(difficulty==4&&!dire_buffer_2&&snake_dire_2!=3)
snake_dire_2=1,dire_buffer_2=true;
break;
case Qt::Key_Down: //down键
if(difficulty==4&&!dire_buffer_2&&snake_dire_2!=0)
snake_dire_2=2,dire_buffer_2=true;
break;
case Qt::Key_Right: //right键
if(difficulty==4&&!dire_buffer_2&&snake_dire_2!=1)
snake_dire_2=3,dire_buffer_2=true;
break;
// case Qt::Key_E: //慢速
// if(snake_time>=400)break;
// else snake_time+=50;
// if(game_start==true)
// gametime->start(snake_time);
// break;
// case Qt::Key_Q: //加速
// if(snake_time==20)break;
// else snake_time-=10;
// if(game_start==true)
// gametime->start(snake_time);
// break;
case Qt::Key_J: //切换bgm
game_musiclist->setCurrentIndex(cnt_g++);
if(cnt_g==7)cnt_g=0;
// qDebug()<<game_musiclist->currentIndex()<<"**";
game_musiclist->setPlaybackMode(QMediaPlaylist::CurrentItemInLoop);
game_music ->play();
break;
case Qt::Key_P: //暂停
if(game_music->isMuted())game_music->setMuted(false);
else game_music->setMuted(true);
break;
case Qt::Key_Escape: //退出
this->close();
break;
case Qt::Key_Space: //开始/暂停
if(first_start)
{
if(!game_start)
{
game_start=true;
if(difficulty==3)game_dif_3->start(1000);
gametime->start(snake_time);
game_1->start(snake_1);
game_2->start(snake_2);
}
else
{
game_start=false;
gametime->stop();
game_1->stop();
game_2->stop();
if(difficulty==3)game_dif_3->stop();
}
}
break;
}
}
void snake_3_Widget::dif_3_timeout()
{
snake_time=max(snake_time-20,20);
gametime->start(snake_time);
}
void snake_3_Widget::start_timeout()
{
first_start=true;
if(difficulty==4)
{
game_1->start(snake_1);
game_2->start(snake_2);
}
gametime->start(snake_time);
game_startf->stop();
}
void snake_3_Widget::timeout_1()
{
switch (snake_dire)
{
case 0:
addTop();
if(pix_dl<=1)
{
if(pix_dl==1)pix_dl=0;
else pix_dl=1;
}
else
{
if(pix_dl==2)pix_dl=3;
else pix_dl=2;
}
break;
case 1:
addLeft();
if(pix_dl==1)pix_dl=0;
else pix_dl=1;
break;
case 2:
addDown();
if(pix_dl<=1)
{
if(pix_dl==1)pix_dl=0;
else pix_dl=1;
}
else
{
if(pix_dl==2)pix_dl=3;
else pix_dl=2;
}
break;
case 3:
addRight();
if(pix_dl==2)pix_dl=3;
else pix_dl=2;
break;
}
dire_buffer=false;//方向缓冲解除
if(eatBean()!=1)
{
deletelast();
}
}
void snake_3_Widget::timeout_2()
{
switch (snake_dire_2)
{
case 0:
addTop_2();
if(pix_dl_2<=1)
{
if(pix_dl_2==1)pix_dl_2=0;
else pix_dl_2=1;
}
else
{
if(pix_dl_2==2)pix_dl_2=3;
else pix_dl_2=2;
}
break;
case 1:
addLeft_2();
if(pix_dl_2==1)pix_dl_2=0;
else pix_dl_2=1;
break;
case 2:
addDown_2();
if(pix_dl_2<=1)
{
if(pix_dl_2==1)pix_dl_2=0;
else pix_dl_2=1;
}
else
{
if(pix_dl_2==2)pix_dl_2=3;
else pix_dl_2=2;
}
break;
case 3:
addRight_2();
if(pix_dl_2==2)pix_dl_2=3;
else pix_dl_2=2;
break;
}
dire_buffer_2=false;//方向缓冲解除
if(eatBean()!=2)
{
deletelast_2();
}
}
void snake_3_Widget::timeout()
{
if(difficulty<4)
{
if(!rule())
{
gametime->stop();
if(difficulty==3)game_dif_3->stop();
if(pix_dl<=1)pix_js=1;
else pix_js=2;
update();
QTime Time = QTime::currentTime();
his_score.push({current_score,difficulty,Time});
QString df = "你的得分是:"+QString::number(current_score);
QMessageBox::information(this,"游戏结束!",df);
this->close();
game_music->stop();
snake_mainmenu *m = new snake_mainmenu(nullptr,his_score);
m->show();
}
else
{
switch (snake_dire)
{
case 0:
addTop();
if(pix_dl<=1)
{
if(pix_dl==1)pix_dl=0;
else pix_dl=1;
}
else
{
if(pix_dl==2)pix_dl=3;
else pix_dl=2;
}
break;
case 1:
addLeft();
if(pix_dl==1)pix_dl=0;
else pix_dl=1;
break;
case 2:
addDown();
if(pix_dl<=1)
{
if(pix_dl==1)pix_dl=0;
else pix_dl=1;
}
else
{
if(pix_dl==2)pix_dl=3;
else pix_dl=2;
}
break;
case 3:
addRight();
if(pix_dl==2)pix_dl=3;
else pix_dl=2;
break;
}
dire_buffer=false;//方向缓冲解除
}
if(eatBean())
{
delete bean;
current_score++;
ui->score_num->display(current_score);
addbean();
}
else
{
deletelast();
}
update();
}
//判定双人规则
else
{
// qDebug()<<"绿色分数"<<current_score_2;
int r=rule_2();
if(r)
{
gametime->stop();
game_1->stop();
game_2->stop();
switch (r) {
case 1:
if(pix_dl_2<=1)pix_js_2=1;
else pix_js_2=2;
update();
QMessageBox::information(this,"游戏结束!","蓝色胜利!");
break;
case 2:
if(pix_dl<=1)pix_js=1;
else pix_js=2;
update();
QMessageBox::information(this,"游戏结束!","绿色胜利!");
break;
case 3:
QMessageBox::information(this,"游戏结束!","平局!");
break;
}
QTime Time = QTime::currentTime();
his_score.push({r,difficulty,Time});
this->close();
game_music->stop();
snake_mainmenu *m = new snake_mainmenu(nullptr,his_score);
m->show();
}
else
{
switch (eatBean()) {
case 0:
break;
case 1:
if(snake_loc.size()<=max_length)
{
delete bean;
addbean();
snake_1=min(snake_1+20,300);
game_1->start(snake_1);
}
break;
case 2:
if(snake_loc_2.size()<=max_length)
{
delete bean;
addbean();
snake_2=min(snake_2+20,300);
game_2->start(snake_2);
}
break;
}
//蓝色被吃
for(int i=1;i<snake_loc.size();i++)
{
if(snake_loc_2[0]==snake_loc[i]||snake_loc[0]==snake_loc[i])
{
while(snake_loc.size()>i)deletelast();
snake_1=200+(snake_loc.size()-2)*20;
game_1->start(snake_1);
}
}
//绿色被吃
for(int i=1;i<snake_loc_2.size();i++)
{
if(snake_loc[0]==snake_loc_2[i]||snake_loc_2[0]==snake_loc_2[i])
{
while(snake_loc_2.size()>i)deletelast_2();
snake_2=200+(snake_loc_2.size()-2)*20;
game_2->start(snake_2);
}
}
update();
}
}
}
void snake_3_Widget::addTop()
{
QPointF leftTop; //蛇头左上角坐标
QPointF rightBotom; //蛇头右下角坐标
if(snake_loc[0].y() - nodeHeight<0) //出界处理
{
leftTop = QPointF(snake_loc[0].x(),this->height()-nodeHeight);
rightBotom = QPointF(snake_loc[0].x()+nodeWidth,this->height());
}
else
{
leftTop = QPointF(snake_loc[0].x(),snake_loc[0].y()-nodeHeight);
rightBotom = snake_loc[0].topRight();
}
snake_loc.insert(0,QRectF(leftTop,rightBotom));
}
void snake_3_Widget::addDown()
{
QPointF leftTop; //蛇头左上角坐标
QPointF rightBotom; //蛇头右下角坐标
if(snake_loc[0].y() + nodeHeight>=this->height()) //出界处理
{
leftTop = QPointF(snake_loc[0].x(),0);
rightBotom = QPointF(snake_loc[0].x()+nodeWidth,nodeHeight);
}
else
{
rightBotom = QPointF(snake_loc[0].x()+nodeWidth,snake_loc[0].y()+2*nodeHeight);
leftTop = snake_loc[0].bottomLeft();
}
snake_loc.insert(0,QRectF(leftTop,rightBotom));
}
void snake_3_Widget::addLeft()
{
QPointF leftTop; //蛇头左上角坐标
QPointF rightBotom; //蛇头右下角坐标
if(snake_loc[0].x() - nodeHeight<0) //出界处理
{
leftTop = QPointF(this->width()-nodeWidth,snake_loc[0].y());
rightBotom = QPointF(this->width(),snake_loc[0].y()+nodeHeight);
}
else
{
leftTop = QPointF(snake_loc[0].x()-nodeWidth,snake_loc[0].y());
rightBotom = snake_loc[0].bottomLeft();
}
snake_loc.insert(0,QRectF(leftTop,rightBotom));
}
void snake_3_Widget::addRight()
{
QPointF leftTop; //蛇头左上角坐标
QPointF rightBotom; //蛇头右下角坐标
if(snake_loc[0].x() + nodeHeight>=this->width()) //出界处理
{
leftTop = QPointF(0,snake_loc[0].y());
rightBotom = QPointF(nodeWidth,snake_loc[0].y()+nodeWidth);
}
else
{
rightBotom = QPointF(snake_loc[0].x()+2*nodeWidth,snake_loc[0].y()+nodeHeight);
leftTop = snake_loc[0].topRight();
}
snake_loc.insert(0,QRectF(leftTop,rightBotom));
}
inline void snake_3_Widget::deletelast()
{
snake_loc.removeLast();
}
void snake_3_Widget::addTop_2()
{
QPointF leftTop; //蛇头左上角坐标
QPointF rightBotom; //蛇头右下角坐标
if(snake_loc_2[0].y() - nodeHeight<0) //出界处理
{
leftTop = QPointF(snake_loc_2[0].x(),this->height()-nodeHeight);
rightBotom = QPointF(snake_loc_2[0].x()+nodeWidth,this->height());
}
else
{
leftTop = QPointF(snake_loc_2[0].x(),snake_loc_2[0].y()-nodeHeight);
rightBotom = snake_loc_2[0].topRight();
}
snake_loc_2.insert(0,QRectF(leftTop,rightBotom));
}
void snake_3_Widget::addDown_2()
{
QPointF leftTop; //蛇头左上角坐标
QPointF rightBotom; //蛇头右下角坐标
if(snake_loc_2[0].y() + nodeHeight>=this->height()) //出界处理
{
leftTop = QPointF(snake_loc_2[0].x(),0);
rightBotom = QPointF(snake_loc_2[0].x()+nodeWidth,nodeHeight);
}
else
{
rightBotom = QPointF(snake_loc_2[0].x()+nodeWidth,snake_loc_2[0].y()+2*nodeHeight);
leftTop = snake_loc_2[0].bottomLeft();
}
snake_loc_2.insert(0,QRectF(leftTop,rightBotom));
}
void snake_3_Widget::addLeft_2()
{
QPointF leftTop; //蛇头左上角坐标
QPointF rightBotom; //蛇头右下角坐标
if(snake_loc_2[0].x() - nodeHeight<0) //出界处理
{
leftTop = QPointF(this->width()-nodeWidth,snake_loc_2[0].y());
rightBotom = QPointF(this->width(),snake_loc_2[0].y()+nodeHeight);
}
else
{
leftTop = QPointF(snake_loc_2[0].x()-nodeWidth,snake_loc_2[0].y());
rightBotom = snake_loc_2[0].bottomLeft();
}
snake_loc_2.insert(0,QRectF(leftTop,rightBotom));
}
void snake_3_Widget::addRight_2()
{
QPointF leftTop; //蛇头左上角坐标
QPointF rightBotom; //蛇头右下角坐标
if(snake_loc_2[0].x() + nodeHeight>=this->width()) //出界处理
{
leftTop = QPointF(0,snake_loc_2[0].y());
rightBotom = QPointF(nodeWidth,snake_loc_2[0].y()+nodeWidth);
}
else
{
rightBotom = QPointF(snake_loc_2[0].x()+2*nodeWidth,snake_loc_2[0].y()+nodeHeight);
leftTop = snake_loc_2[0].topRight();
}
snake_loc_2.insert(0,QRectF(leftTop,rightBotom));
}
inline void snake_3_Widget::deletelast_2()
{
snake_loc_2.removeLast();
}
void snake_3_Widget::addbean()
{
bean = new QRectF;
bool bean_valid; //是否非法
srand(time(NULL));
do{
bean_valid=false;
* bean=QRectF(rand()%(this->width()/100)*100,
rand()%(this->height()/100)*100,
nodeWidth,
nodeHeight
);
for(auto temp:snake_loc)
if(temp==*bean)
{
bean_valid=true;
break;
}
if(difficulty==4&&!bean_valid)
{
for(auto temp:snake_loc_2)
if(temp==*bean)
{
bean_valid=true;
break;
}
}
}while(bean_valid);
}
int snake_3_Widget::eatBean()
{
if(snake_loc[0]==* bean)
{
switch (difficulty) {
case 2:
snake_time=max(snake_time-20,50);
gametime->start(snake_time);
break;
case 3:
snake_time=max(snake_time+20,120);
gametime->start(snake_time);
break;
case 4:
break;
}
return 1;
}
else if(difficulty==4&&snake_loc_2[0]==* bean)
{
return 2;
}
else return 0;
}
bool snake_3_Widget::rule()
{
for(int i=1;i<snake_loc.length();i++)
if(snake_loc[0]==snake_loc[i])
{
return false;
}
return true;
}
int snake_3_Widget::rule_2() //1蓝赢 2绿赢 3平局 否则平局
{
if(snake_loc.size()==1||snake_loc_2.size()>max_length)return 2; //绿赢
if(snake_loc_2.size()==1||snake_loc.size()>max_length)return 1;
if(snake_loc[0]==snake_loc_2[0])return 3;
return 0;
}
int snake_3_Widget::dist(QRectF a,QRectF b)
{
return std::abs(a.x()-b.x())/nodeWidth+std::abs(a.y()-b.y())/nodeHeight;
}
7.snake_mainmenu.cpp
#include "snake_mainmenu.h"
#include "ui_snake_mainmenu.h"
#include<MyButton.h>
int cnt=0; //播放列表位置
snake_mainmenu::snake_mainmenu(QWidget *parent,std::priority_queue<his_type> h) :
QWidget(parent),
ui(new Ui::snake_mainmenu)
{
ui->setupUi(this);
setFixedSize(750,700);
this->setWindowTitle("贪吃蛇之怪物猎人");
ui->his_record_edit->setReadOnly(true);
ui->help_edit->setReadOnly(true);
//设置主界面
current_interface=0;
interface(current_interface);
//导入历史记录
if(h.empty())ReadtestFile(),h_his=false; //没有纪录(首次打开游戏)
else his = h,h_his=true; //存在历史纪录
//导入音乐
menu_musiclist = new QMediaPlaylist;
menu_musiclist->addMedia(QUrl("qrc:/voi/wavbgm/bgm_other_fierce.wav"));
menu_musiclist->addMedia(QUrl("qrc:/voi/wavbgm/bgm_other_grand.wav"));
menu_musiclist->addMedia(QUrl("qrc:/voi/wavbgm/bgm_other_kAndR.wav"));
menu_musiclist->addMedia(QUrl("qrc:/voi/wavbgm/bgm_other_kind.wav"));
menu_musiclist->addMedia(QUrl("qrc:/voi/wavbgm/bgm_other_kind2.wav"));
menu_musiclist->addMedia(QUrl("qrc:/voi/wavbgm/bgm_menu_start.wav"));
menu_musiclist->addMedia(QUrl("qrc:/voi/wavbgm/bgm_other_relieve.wav"));
menu_musiclist->addMedia(QUrl("qrc:/voi/wavbgm/bgm_otherORgame_inter.wav"));
menu_music->setPlaylist(menu_musiclist);
menu_musiclist->setPlaybackMode(QMediaPlaylist::CurrentItemInLoop);
menu_musiclist->setCurrentIndex(cnt++);
menu_music->play();
update();
}
snake_mainmenu::~snake_mainmenu()
{
delete ui;
}
void snake_mainmenu::interface(int t)
{
switch (t) {
case MAIN:
ui->menu_frame->show();
ui->logo_main->show();
ui->back_button->hide();
ui->model_frame->hide();
ui->his_record_edit->hide();
ui->help_edit->hide();
ui->save_button->hide();
ui->clear_button->hide();
break;
case HISTORY:
ui->his_record_edit->show();
ui->save_button->show();
ui->logo_main->hide();
ui->menu_frame->hide();
ui->model_frame->hide();
ui->back_button->show();
ui->help_edit->hide();
ui->clear_button->show();
break;
case OPTION:
ui->model_frame->show();
ui->back_button->show();
ui->menu_frame->hide();
ui->his_record_edit->hide();
ui->logo_main->hide();
ui->help_edit->hide();
ui->save_button->hide();
ui->clear_button->hide();
break;
case HELP:
ui->model_frame->hide();
ui->back_button->show();
ui->menu_frame->hide();
ui->his_record_edit->hide();
ui->logo_main->hide();
ui->help_edit->show();
ui->save_button->hide();
ui->clear_button->hide();
break;
}
}
void snake_mainmenu::on_quit_button_clicked()
{
this->close();
}
void snake_mainmenu::paintEvent(QPaintEvent *)
{
QPainter menu_painter(this);
QPixmap menu_main,menu_help,menu_model,menu_record;
menu_main.load(":/pic/prefix1/picture/mjl.jpg");
menu_model.load(":/pic/prefix1/picture/sl.jpg");
menu_help.load(":/pic/prefix1/picture/hl.jpg");
menu_record.load(":/pic/prefix1/picture/mhw.jpg");
menu_painter.setRenderHint(QPainter::Antialiasing,true); //抗锯齿
switch(current_interface){
case MAIN:
menu_painter.drawPixmap(0,0,750,700,menu_main);
break;
case HISTORY:
menu_painter.drawPixmap(0,0,750,700,menu_record);
break;
case OPTION:
menu_painter.drawPixmap(0,0,750,700,menu_model);
break;
case HELP:
menu_painter.drawPixmap(0,0,750,700,menu_help);
break;
}
}
void snake_mainmenu::on_play_button_clicked()
{
ui->play_button->menu_soundeffect(0);
current_interface=2;
interface(current_interface);
update();
}
void snake_mainmenu::on_record_button_clicked()
{
ui->record_button->menu_soundeffect(0);
current_interface=1;
interface(current_interface);
ui->his_record_edit->setText("历史最高纪录");
auto temp = his;
for(unsigned i=0;i<his.size();i++)
{
if(temp.top().dif<4)
{
QString diff;
switch (temp.top().dif) {
case 1:
diff="简单";
break;
case 2:
diff="普通";
break;
case 3:
diff="困难";
break;
}
ui->his_record_edit->append(temp.top().Time.toString()+"时在"+diff+"模式下得分"+QString::number(temp.top().score));
}
else
{
QString winner;
switch (temp.top().score) {
case 1:
winner = "蓝色胜出";
break;
case 2:
winner = "绿色胜出";
break;
case 3:
winner = "平局";
break;
}
ui->his_record_edit->append(temp.top().Time.toString()+"时在双人模式下"+winner);
}
temp.pop();
}
// qDebug()<<"历史记录长度"<<his.size();
update();
}
void snake_mainmenu::on_help_button_clicked()
{
ui->help_button->menu_soundeffect(0);
current_interface=3;
interface(current_interface);
update();
}
void snake_mainmenu::on_back_button_clicked()
{
ui->back_button->menu_soundeffect(2);
switch(current_interface){
case 0:
break;
case 1:
current_interface=0;
interface(current_interface);
break;
case 2:
current_interface=0;
interface(current_interface);
break;
case 3:
current_interface=0;
interface(current_interface);
break;
}
update();
}
void snake_mainmenu::on_bgm_button_clicked()
{
if(!menu_music->isMuted())
{
ui->bgm_button->menu_soundeffect(2);
menu_musiclist->setCurrentIndex(cnt++);
if(cnt==8)cnt=0;
qDebug()<<menu_musiclist->currentIndex();
menu_musiclist->setPlaybackMode(QMediaPlaylist::CurrentItemInLoop);
menu_music->play();
}
}
void snake_mainmenu::on_stopvoice_button_clicked()
{
ui->stopvoice_button->menu_soundeffect(2);
if(menu_music->isMuted())
{
menu_music->setMuted(false);
ui->stopvoice_button->setStyleSheet("qproperty-icon: url(:/pic/prefix1/picture/voice.png);"
"background:transparent;");
}
else
{
menu_music->setMuted(true);
ui->stopvoice_button->setStyleSheet("qproperty-icon: url(:/pic/prefix1/picture/stopvoice.png);"
"background:transparent;");
}
}
void snake_mainmenu::on_dif_1_button_clicked()
{
ui->dif_1_button->menu_soundeffect(1);
difficulty=1;
menu_music->stop();
this ->close();
snake_3_Widget * game = new snake_3_Widget(nullptr,difficulty,his);
game->show();
}
void snake_mainmenu::on_dif_2_button_clicked()
{
ui->dif_2_button->menu_soundeffect(1);
difficulty=2;
menu_music->stop();
this ->close();
snake_3_Widget * game = new snake_3_Widget(nullptr,difficulty,his);
game->show();
}
void snake_mainmenu::on_dif_3_button_clicked()
{
ui->dif_3_button->menu_soundeffect(1);
difficulty=3;
menu_music->stop();
this ->close();
snake_3_Widget * game = new snake_3_Widget(nullptr,difficulty,his);
game->show();
}
void snake_mainmenu::on_save_button_clicked()
{
ui->save_button->menu_soundeffect(4);
if(his.empty())
{
QMessageBox::information(this,"纪录","没有纪录!");
}
else if(h_his)
{
//保存为TXT文件
bool exist;
QString fileName;
QDir *folder = new QDir;
exist = folder->exists("D:/QT/QT_project/snake_3/his_record");//查看目录是否存在
if(!exist){//不存在就创建
bool ok = folder->mkdir("D:/QT/QT_project/snake_3/his_record");
if(ok){
qDebug()<<"创建成功!";//添加提示方便查看是否成功创建
}else{
QMessageBox::information(this,"纪录","保存失败");
}
}
fileName = tr("D:/QT/QT_project/snake_3/his_record/%1.txt").arg("data");
QFile f(fileName);
if(!f.open(QIODevice::ReadWrite | QIODevice::Append | QIODevice::Text))
{//追加写入 添加结束符\r\n
QMessageBox::information(this,"纪录","保存失败");
return ;
}
else
{
QTextStream out(&f);
auto temp = his;
for(unsigned i=0;i<his.size();i++)
{
out<<temp.top().Time.toString()<<endl<<temp.top().score<<endl<<temp.top().dif<<endl<<QObject::tr("go on")<<endl;
temp.pop();
}
QMessageBox::information(this,"纪录","已保存");
}
f.close();
}
}
void snake_mainmenu::ReadtestFile()
{
QFile file("D:/QT/QT_project/snake_3/his_record/data.txt"); //文件路径 也可以用相对路径
if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
{
qDebug()<<"Can't open the file!"<<endl;
return;
}
QTextStream in(&file); //文件流
QString line =in.readLine(); //读取一行
his_type cur_h;
int index=1;
while (!line.isNull())
{
if(index==4)
{
index=0;
his.push(cur_h);
}
else
{
switch (index) {
case 1:
cur_h.Time= QTime::fromString(line, "hh:mm:ss");
break;
case 2:
cur_h.score=line.toInt();
break;
case 3:
cur_h.dif=line.toInt();
break;
}
}
line = in.readLine();
index++;
}
// qDebug()<<his.top().Time;
}
void snake_mainmenu::on_clear_button_clicked()
{
ui->clear_button->menu_soundeffect(4);
if(!his.empty())
{
QMessageBox::StandardButton result=QMessageBox::question(this,"清除纪录","确定要清除当前纪录吗?");
if(result)
while (!his.empty()) his.pop();
ui->his_record_edit->setText("历史最高纪录");
}
else
{
QMessageBox::StandardButton result=QMessageBox::question(this,"清除历史纪录","确定要清除历史纪录吗?");
if(result)
{
QFile file("D:/QT/QT_project/snake_3/his_record/data.txt");
file.open(QFile::WriteOnly|QFile::Truncate);
file.close();
QMessageBox::information(this,"清除历史纪录","历史纪录已清除!");
}
}
}
void snake_mainmenu::on_dif_4_button_clicked()
{
ui->dif_4_button->menu_soundeffect(1);
difficulty=4;
menu_music->stop();
this ->close();
snake_3_Widget * game = new snake_3_Widget(nullptr,difficulty,his);
game->show();
}
8.MyButton.cpp
#include"MyButton.h"
#include<snake_mainmenu.h>
MyButton::MyButton(QWidget* parent) :QPushButton(parent)
{
}
MyButton::~MyButton()
{
}
void MyButton::enterEvent(QEvent *)
{
AudioThread * e = new AudioThread;
// e->setSource(QUrl::fromLocalFile("D:/QT/QT_project/snake_3/voice_1.0/menu/wavmenu/menu_mousechoosing.wav"));
e->play(3);
}
void MyButton::menu_soundeffect(int sound_index)//生成对应音效
{
AudioThread * e = new AudioThread;
// e->setSource(QUrl::fromLocalFile("D:/QT/QT_project/snake_3/voice_1.0/menu/wavmenu/"+sound_index));
e->play(sound_index);
}
//void MyButton::mousePressEvent(QMouseEvent *ev)
//{
// //代表鼠标左键按下
// if(ev->button()==Qt::LeftButton&&!effect->isPlaying())
// {
// effect->setSource(QUrl::fromLocalFile("D:/QT/QT_project/snake_3/voice_1.0/menu/wavmenu/menu_chosed.wav"));
// effect->setLoopCount(1); //循环次数
// effect->setVolume(0.95f); //音量 0~1之间
// effect->play();
// }
//}
9.AudioThread.cpp
参考文章QSoundEffect独立声音播放线程 movetothread方式_ZLOZL的博客-CSDN博客_qt声音线程
#include <AudioThread.h>
#include <QUrl>
AudioThread::AudioThread(QObject *parent) :
QObject(parent)
{
effect.moveToThread(&thread);
connect(this, SIGNAL(doPlay()), &effect, SLOT(play()));
connect(this, &AudioThread::doStop, &effect, &QSoundEffect::stop);
thread.start();
}
AudioThread::~AudioThread()
{
if(thread.isRunning())
{
thread.terminate();
}
}
void AudioThread::play_strong(int type)
{
if(effect.isPlaying())
{
emit this->doStop();
effect.stop();
}
voice_type = type;
QString fileName;
switch (voice_type)
{
case VOICE_POSITIVE:
{
fileName = "menu_model_chosed.wav";
}
break;
case VOICE_NEGATIVE:
{
fileName = "menu_gamestart.wav";
}
break;
case VOICE_TEMPERATURE:
{
fileName = "menu_chosed.wav";
}
break;
case VOICE_TOOCLOSE:
{
fileName = "menu_mousechoosing.wav";
}
break;
default:
{
return;
}
}
effect.setSource(QUrl("qrc:/voi/wavmenu/"+fileName));
effect.setLoopCount(1);
effect.setVolume(1.0f);
emit this->doPlay();
}
void AudioThread::play(int type)
{
if(effect.isPlaying())
{
return;
}
voice_type = type;
QString fileName;
switch (voice_type)
{
case VOICE_POSITIVE:
{
fileName = "menu_model_chosed.wav";
}
break;
case VOICE_NEGATIVE:
{
fileName = "menu_gamestart.wav";
}
break;
case VOICE_TEMPERATURE:
{
fileName = "menu_chosed.wav";
}
break;
case VOICE_TOOCLOSE:
{
fileName = "menu_mousechoosing.wav";
}
break;
case VOICE_GOOCLOSE:
{
fileName = "menu_choose.wav";
}
break;
default:
{
return;
}
}
effect.setSource(QUrl("qrc:/voi/wavmenu/"+fileName));
effect.setLoopCount(1);
effect.setVolume(1.0f);
emit this->doPlay();
}
main.cpp和.qrc和.ui文件略