新闻中心

Qt学习之路_13(简易俄罗斯方块)

Qt学习之路_13(简易俄罗斯方块)

#include "myview.h"#include "box.h"#include <QIcon>#include <QPropertyAnimation>#include <QGraphicsBlurEffect>#include <QTimer>#include <QPushButton>#include <QGraphicsProxyWidget>#include <QApplication>#include <QLabel>#include <QFileInfo>static const qreal INITSSPEED = 500;//游戏的学习初始化速度static const QString SOUNDPATH = "https://www.cnblogs.com/tornadomeet/archive/2012/09/22/sounds/";MyView::MyView(QWidget *parent) :    QGraphicsView(parent){     init_view();}void MyView::init_view() {     setRenderHint(QPainter::Antialiasing);//使用抗锯齿的方式渲染    setCacheMode(CacheBackground);//设置缓存背景
,这样可以加快渲染速度    setWindowTitle(tr("Teris游戏"));    setWindowIcon(QIcon(":/images/icon.png"));//设置标题处的简易图标    setMinimumSize(810, 510);  //2者设置成一样说明视图尺寸不能再更改    setMaximumSize(810, 510);    QGraphicsScene *scene = new QGraphicsScene;//新建场景指针    scene->setSceneRect(5, 5, 800, 500);//场景大小    scene->setBackgroundBrush(QPixmap(":/images/background.png"));    setScene(scene);//设置场景    //俄罗斯方块可移动区域外界的4条线,与外界预留3个像素是为了方便进行碰撞检测    top_line = scene->addLine(197, 47, 403, 47);    bottom_line = scene->addLine(197, 453, 403, 453);    left_line = scene->addLine(197, 47, 197, 453);    right_line = scene->addLine(403, 47, 403, 453);    //添加当前方块组    box_group = new BoxGroup;//通过新建BoxGroup对象间接达到调用box的2个类    connect(box_group, SIGNAL(need_new_box()), this, SLOT(clear_full_rows()));    connect(box_group, SIGNAL(game_finished()), this, SLOT(game_over()));    scene->addItem(box_group);    //添加提示方块组    next_box_group = new BoxGroup;    scene->addItem(next_box_group);    game_score = new QGraphicsTextItem(0, scene);//文本的父item为对应的场景    game_score->setFont(QFont("Times", 50, QFont::Bold));//为文本设置字体    game_score->setPos(450, 350);//分数在场景中出现的位置    game_level = new QGraphicsTextItem(0, scene);    game_level->setFont(QFont("Times", 50, QFont::Bold));    game_level->setPos(20, 150);    //开始游戏 //   start_game();    //初始状态时不显示游戏区域
,不显示游戏分数和游戏等级    top_line->hide();    bottom_line->hide();    left_line->hide();    right_line->hide();    game_score->hide();    game_level->hide();    //添加黑色遮罩    QWidget *mask = new QWidget;    mask->setAutoFillBackground(true);    mask->setPalette(QPalette(QColor(0,俄罗 0, 0, 50)));//alpha为不透明度    mask->resize(900, 600);    //addWidget()函数的返回值是QGraphicsProxyWidget,如果不添加相应的斯方头文件,则此处会报错    mask_widget = scene->addWidget(mask);    mask_widget->setPos(-50,学习 -50);    mask_widget->setZValue(1);//该层薄纱放在原图的上面,这里有点类似于opengl中的简易3维绘图    //选项面板    QWidget *option = new QWidget;    //将关闭按钮放在option上    QPushButton *option_close_button = new QPushButton(tr("关  闭"), option);//第2个参数为按钮所在的widget    //设置按钮的字体颜色是白色    QPalette palette;    palette.setColor(QPalette::ButtonText, Qt::black);//第一个参数调色版的role,这里指的俄罗是按钮字体颜色    option_close_button->setPalette(palette);    //设置关闭按钮的位置,和单击后的斯方响应    option_close_button->move(120, 300);    connect(option_close_button, SIGNAL(clicked()), option, SLOT(hide()));//单击后消失    option->setAutoFillBackground(true);    option->setPalette(QPalette(QColor(0, 0, 0, 180)));    option->resize(300, 400);    QGraphicsWidget *option_widget = scene->addWidget(option);    option_widget->setPos(250, 50);    option_widget->setZValue(3);    option_widget->hide();    //帮助面板    QWidget *help = new QWidget;    QPushButton *help_close_button = new QPushButton(tr("帮  助"), help);    help_close_button->setPalette(palette);    help_close_button->move(120, 300);    connect(help_close_button, SIGNAL(clicked()), help, SLOT(hide()));    help->setAutoFillBackground(true);    help->setPalette(QPalette(QColor(0, 0, 0, 180)));    help->resize(300, 400);    QGraphicsWidget *help_widget = scene->addWidget(help);    help_widget->setPos(250, 50);    help_widget->setZValue(3);    help_widget->hide();    //游戏欢迎文本    game_welcome_text = new QGraphicsTextItem(0, scene);//第一个参数为文本内容
,第二个参数为父item    game_welcome_text->setHtml(tr("<font color=green>Tetris游戏</font>"));    game_welcome_text->setFont(QFont("Times",学习 40, QFont::Bold));    game_welcome_text->setPos(300, 100);    game_welcome_text->setZValue(2);//放在第2层    //游戏暂停文本    game_pause_text = new QGraphicsTextItem(0, scene);//第一个参数为文本内容
,第二个参数为父item    game_pause_text->setHtml(tr("<font color=green>游戏暂停中!简易</font>"));    game_pause_text->setFont(QFont("Times",俄罗 40, QFont::Bold));    game_pause_text->setPos(300, 100);    game_pause_text->setZValue(2);//放在第2层    game_pause_text->hide();    //游戏结束文本    game_over_text = new QGraphicsTextItem(0, scene);//第一个参数为文本内容,第二个参数为父item    game_over_text->setHtml(tr("<font color=green>GAME OVER	!斯方</font>"));    game_over_text->setFont(QFont("Times",学习 40, QFont::Bold));    game_over_text->setPos(300, 100);    game_over_text->setZValue(2);//放在第2层    game_over_text->hide();    // 游戏中使用的按钮    QPushButton *button1 = new QPushButton(tr("开    始"));    QPushButton *button2 = new QPushButton(tr("选    项"));    QPushButton *button3 = new QPushButton(tr("帮    助"));    QPushButton *button4 = new QPushButton(tr("退    出"));    QPushButton *button5 = new QPushButton(tr("重新开始"));    QPushButton *button6 = new QPushButton(tr("暂    停"));    QPushButton *button7 = new QPushButton(tr("主 菜 单"));    QPushButton *button8 = new QPushButton(tr("返回游戏"));    QPushButton *button9 = new QPushButton(tr("结束游戏"));    connect(button1, SIGNAL(clicked()), this, SLOT(start_game()));    connect(button2, SIGNAL(clicked()), option, SLOT(show()));    connect(button3, SIGNAL(clicked()), help, SLOT(show()));    connect(button4, SIGNAL(clicked()), qApp, SLOT(quit()));//此处槽函数的接收对象为应用程序本身    connect(button5, SIGNAL(clicked()), this, SLOT(restart_game()));    connect(button6, SIGNAL(clicked()), this, SLOT(pause_game()));    connect(button7, SIGNAL(clicked()), this, SLOT(finish_game()));    connect(button8, SIGNAL(clicked()), this, SLOT(return_game()));//返回主菜单    connect(button9, SIGNAL(clicked()), this, SLOT(finish_game()));    start_button = scene->addWidget(button1);//restart_button并不是QPushbutton类型,而是简易QGraphicsItem类型,后面的类似    option_button = scene->addWidget(button2);    help_button = scene->addWidget(button3);    exit_button = scene->addWidget(button4);    restart_button = scene->addWidget(button5);    pause_button = scene->addWidget(button6);    show_menu_button = scene->addWidget(button7);    return_button = scene->addWidget(button8);    finish_button = scene->addWidget(button9);    //设置位置    start_button->setPos(370, 200);    option_button->setPos(370, 250);    help_button->setPos(370, 300);    exit_button->setPos(370, 350);    restart_button->setPos(600, 150);    pause_button->setPos(600, 200);    show_menu_button->setPos(600, 250);    return_button->setPos(370, 200);    finish_button->setPos(370, 250);    //将这些按钮都放在z方向的第二层    start_button->setZValue(2);    option_button->setZValue(2);    help_button->setZValue(2);    exit_button->setZValue(2);    restart_button->setZValue(2);    return_button->setZValue(2);    finish_button->setZValue(2);    //一部分按钮隐藏起来    restart_button->hide();    finish_button->hide();    pause_button->hide();    show_menu_button->hide();    return_button->hide();    //设置声音    background_music = new Phonon::MediaObject(this);//背景音乐对象    clearrow_sound = new Phonon::MediaObject(this);//消行声音对象    //AudioOutput是一个将数据送到音频输出的设备    Phonon::AudioOutput *audio1 = new Phonon::AudioOutput(Phonon::MusicCategory, this);    Phonon::AudioOutput *audio2 = new Phonon::AudioOutput(Phonon::MusicCategory, this);    Phonon::createPath(background_music, audio1);//    Phonon::createPath(clearrow_sound, audio2);//绑定音源和音频输出控件    Phonon::VolumeSlider *volume1 = new Phonon::VolumeSlider(audio1, option);//参数1为音频输出设备,参数2为对应的俄罗父widget    Phonon::VolumeSlider *volume2 = new Phonon::VolumeSlider(audio2, option);    QLabel *volume_label1 = new QLabel(tr("音乐声:"), option);    QLabel *volume_label2 = new QLabel(tr("音效声:"), option);    volume1->move(100, 100);    volume2->move(100, 200);    volume_label1->move(65, 105);    volume_label2->move(60, 205);    //音乐播放完后发射信号触发about_to_finish()槽函数    connect(background_music, SIGNAL(aboutToFinish()), this, SLOT(about_to_finish()));    // 因为播放完毕后会进入暂停状态	,再调用play()将无法进行播放,需要在播放完毕后使其进入停止状态    connect(clearrow_sound, SIGNAL(finished()), clearrow_sound, SLOT(stop()));    background_music->setCurrentSource(Phonon::MediaSource(SOUNDPATH + "background.mp3"));    clearrow_sound->setCurrentSource(Phonon::MediaSource(SOUNDPATH + "clearrow.mp3"));    background_music->play();//初始化的时候直接播放背景音乐}//开始游戏void MyView::start_game() {     game_welcome_text->hide();    start_button->hide();    option_button->hide();    help_button->hide();    exit_button->hide();    mask_widget->hide();    init_game();}//初始化游戏,为什么要分2个函数来写
?void MyView::init_game() {     box_group->create_box(QPointF(300, 70)); //创建方块组,在中间位置处出现    box_group->setFocus();//设置人机交互焦点,这样就可以使用键盘来控制它    box_group->startTimer(INITSSPEED);//启动定时器    game_speed = INITSSPEED;//游戏速度,暂停时需要用到    next_box_group->create_box(QPoint(500, 70));//创建提示方块组    scene()->setBackgroundBrush(QPixmap(":/images/background01.png"));    game_score->setHtml(tr("<font color = red >0</font>"));    game_level->setHtml(tr("<font color = white>第<br>一<br>幕</font>"));//br为换行    restart_button->show();    pause_button->show();    show_menu_button->show();    game_score->show();    game_level->show();    top_line->show();    bottom_line->show();    left_line->show();    right_line->show();    // 可能以前返回主菜单时隐藏了boxGroup    box_group->show();    //设置游戏开始的背景音乐    background_music->setCurrentSource(Phonon::MediaSource(SOUNDPATH + "background01.mp3"));    background_music->play();}void MyView::clear_full_rows() {     for(int y = 429; y > 50; y -= 20) {         //每隔20行取一个item出来
,括号里面的参数不能弄错
,否则没有方块消失的效果        QList<QGraphicsItem *> list = scene()->items(199, y, 202, 22, Qt::ContainsItemShape);//返回指定区域内所有可见的item        if(list.count() == 10) {    //如果一行已满,则销毁该行的所有小方块            foreach(QGraphicsItem *item, list) {                 OneBox *box = (OneBox *) item;          //      box->deleteLater();                /*采用动态效果消失方块行*/                QGraphicsBlurEffect *blur_effect = new QGraphicsBlurEffect;//创建模糊效果对象                box->setGraphicsEffect(blur_effect);//给每个小方块添加模糊设置                QPropertyAnimation *animation = new QPropertyAnimation(box, "scale");//添加动态效果	,尺寸变换效果                animation->setEasingCurve(QEasingCurve::OutBounce);//为动态效果设置缓冲取曲线,是用来插值的                animation->setDuration(250);//持续250毫秒                animation->setStartValue(4);//其实尺寸                animation->setEndValue(0.25);//结束尺寸                animation->start(QAbstractAnimation::DeleteWhenStopped);//动画结束后删除该类                connect(animation, SIGNAL(finished()), box, SLOT(deleteLater()));//动画结束完后才调用小方块销毁函数       //         clearrow_sound->play();            }            rows << y;//将满行的行号保存到rows中        }    }    //如果满行,则下移上面的方块    if(rows.count()>0) {         clearrow_sound->play();        QTimer::singleShot(400, this, SLOT(move_box()));//只执行一次定时器,等动态效果完后再下移上面的方块    //    clearrow_sound->play();    }    else {         //没有满行
,则新出现提示方块
,且提示方块出更新新的提示方块        box_group->create_box(QPointF(300, 70), next_box_group->getCurrentShape());        next_box_group->clear_box_group(true);        next_box_group->create_box(QPointF(500, 70));//    }}void MyView::move_box() {     for(int i = rows.count(); i > 0; --i) {         int row = rows.at(i-1);//取出满行的行号,从最上面的位置开始        //取出从区域上边界到当前满行之间所形成的矩形区域        foreach(QGraphicsItem *item, scene()->items(199, 49, 202, row-47, Qt::ContainsItemShape)) {             item->moveBy(0, 20);        }    }    //更新分数    update_score(rows.count());    //出现新的方块组    rows.clear();    box_group->create_box(QPointF(300, 70), next_box_group->getCurrentShape());    next_box_group->clear_box_group(true);    next_box_group->create_box(QPoint(500, 70));}void MyView::update_score(const int full_row_num) {     long score = full_row_num*10000000;//每消一行的一千万分,比较霸气    int current_score = game_score->toPlainText().toInt();    current_score += score;    game_score->setHtml(tr("<font color = red>%1</font>").arg(current_score));    if(current_score >= 100000000) {         game_level->setHtml(tr("<font color = white>第<br>二<br>幕</font>"));        scene()->setBackgroundBrush(QPixmap(":/images/background02.png"));        game_speed = 300;        box_group->stop_timer();//重新设置定时器参数        box_group->startTimer(game_speed);        if (QFileInfo(background_music->currentSource().fileName()).baseName() != "background02") {              background_music->setCurrentSource(Phonon::MediaSource(SOUNDPATH + "background02.mp3"));             background_music->play();        }    }}void MyView::game_over() {     pause_button->hide();    show_menu_button->hide();    mask_widget->show();    game_over_text->show();    restart_button->setPos(370, 200);    finish_button->show();}void MyView::restart_game(){     mask_widget->hide();    game_over_text->hide();    finish_button->hide();    restart_button->setPos(600, 150);    //销毁当前方块组和当前方块中的所有小方块    next_box_group->clear_box_group(true);    box_group->clear_box_group();    box_group->hide();    foreach(QGraphicsItem *item, scene()->items(199, 49, 202, 402,Qt::ContainsItemBoundingRect)) {         scene()->removeItem(item);        OneBox *box = (OneBox*)item;        box->deleteLater();    }    init_game();}void MyView::finish_game(){     game_over_text->hide();    finish_button->hide();    restart_button->setPos(600, 150);    restart_button->hide();    pause_button->hide();    show_menu_button->hide();    game_score->hide();    game_level->hide();    top_line->hide();    bottom_line->hide();    left_line->hide();    right_line->hide();    next_box_group->clear_box_group(true);    box_group->clear_box_group();    box_group->hide();    foreach(QGraphicsItem *item, scene()->items(199, 49, 202, 402,Qt::ContainsItemBoundingRect)) {         scene()->removeItem(item);        OneBox *box = (OneBox*)item;        box->deleteLater();    }    mask_widget->show();    game_welcome_text->show();    start_button->show();    option_button->show();    help_button->show();    exit_button->show();    scene()->setBackgroundBrush(QPixmap(":/images/background.png"));    //游戏结束时更该背景音乐    background_music->setCurrentSource(Phonon::MediaSource(SOUNDPATH + "background.mp3"));    background_music->play();}void MyView::pause_game(){     box_group->stop_timer();//中断游戏最主要的是停止方块下移的定时器工作    restart_button->hide();    pause_button->hide();    show_menu_button->hide();    mask_widget->show();    game_pause_text->show();    return_button->show();}void MyView::return_game(){     return_button->hide();    game_pause_text->hide();    mask_widget->hide();    restart_button->show();    pause_button->show();    show_menu_button->show();    box_group->startTimer(game_speed);}void MyView::about_to_finish(){     background_music->enqueue(background_music->currentSource());//设置后续的播放序列为当前的音频文件
,达到重复播放的目的}void MyView::keyPressEvent(QKeyEvent *event) {     if(pause_button->isVisible())//当屏幕中可以看到暂停按钮时
,代表游戏还在运行,这时候的焦点给下降中的方块组        box_group->setFocus();    else        box_group->clearFocus();//如果游戏暂停
,则方块组不能获得焦点    QGraphicsView::keyPressEvent(event);}

上一篇:《仙剑奇侠传6》激活授权运行安装等问题解决方法 下一篇:汽车音响中音喇叭3.5寸3寸环绕纯中音改装三分频喇叭频仪表台喇叭

Copyright © 2024 茂名市某某路桥科技培训学校 版权所有   网站地图