Qt浅谈之四十九俄罗斯方块(代码来自网络)

一、简单介绍

      从网上下载了一个Qt实现的俄罗斯方块单机版的源代码。认为很有意思。故以博客形式记录下来。以便慢慢来研究。在centos6.6下编译执行(注意程序执行须要读取pro文件夹的配置文件,若把编译文件夹选择在pro外的话执行会报错):


二、具体解释

1、部分代码

(1)main.cpp

#include <QApplication>
#include <QTextCodec>
#include <QCursor>

#include "TetrixWidget.h"

int main( int argc, char **argv )
{

    QApplication a( argc, argv );

    QTextCodec::setCodecForTr(QTextCodec::codecForName("UTF-8"));
    QTextCodec::setCodecForLocale(QTextCodec::codecForName("UTF-8"));
    QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8"));
    //则更换图标
    QCursor myCursor( QPixmap( GLOBAL_CURSOR_IMAGE ) ) ;
    QApplication::setOverrideCursor( myCursor ) ;
    //这个是由于要使用Phonon这里要设置一个名字。可能是考虑到版权相关的问题吧,不然会有一个警告
    //并无其他实际意义
    a.setApplicationName("MyTetrix Game");

    TetrixWidget widget ;
    widget.show();

    return a.exec();
}
(2)TetrixWidget.h
#ifndef TETRIXWIDGET_H
#define TETRIXWIDGET_H


#include <QDesktopWidget>
#include <QApplication>
#include <QWidget>
#include <QGraphicsView>
#include <QSettings>
#include <QStringList>
#include <QImage>
#include <QPoint>
#include <QKeyEvent>


#include "GameGraphicsScene.h"
#include "GameBackGroundItem.h"
#include "GameLogoImageItem.h"
#include "GameButtonItem.h"
#include "GameArrowItem.h"
#include "GameMovBackGrouItem.h"
#include "GameIntroductionItem.h"
#include "GameOptionItem.h"
#include "GameHighWinItem.h"

#include "GameGameSound.h"

#include "globaldefines.h"

/**************************************************************************
 *                        常量                                            *
 **************************************************************************/


/**************************************************************************
 *                          宏定义                                         *
 **************************************************************************/


/**************************************************************************
 *                            数据类型                                     *
 **************************************************************************/


/**************************************************************************
 *                             类声明                                      *
 **************************************************************************/

class TetrixWidget : public QWidget
{
    Q_OBJECT
signals:
    //发送信号给ArrowItem。改变其坐标到坐标索引的index
    void moveArrowat( int index ) ;

    //这个是遮蔽箭头item上面的箭头的信号
    //这个信号放在这个类里是由于,button弹出的Item会通过按Esc来返回,这样就不能再发信号还原
    //其状态
    void coverOnArowItemSignal( bool state ) ;

    /**********************这个是当游戏被停用时的发送的信号********************/
    //这个是当游戏被停用时的发送的信号
    //就是当鼠标点击电脑桌面其他位置时。就是我们寻常所说的整个游戏软件失去焦点时。发送这个信号
    void gameDeactivateSignal() ;
public:
    TetrixWidget(QWidget *parent=0) ;
    ~TetrixWidget() ;

private:
    QGraphicsView *gameView ;
    GameGraphicsScene *gameScene ;

    void setTetrixWigAttribute() ;          //设置TetrixWidget类的属性

    void initGameSceneAndView() ;           //初始化游戏的场景与视图


    QSettings *configIni ;        //这个是用于读取配置文件指针
    //这是定义的一个表。用来存储图片名字与图片的指针
    //这个作为一个大的容器,所以图片都放在里面。便于之后用
    NameAndImageHash  nameImageHash ;

    //依据组名及每组相应的图片数目的A值来读取配置文件。而且载入图片文件。
    void initAndLoadImage( QString groupname, QString A_valueString ) ;

    void loadAllImageFile() ;      //载入全部的图片

    //这个坐标ponit用于取图片上某个坐标点的色素作为透明色,默觉得QPoint( 0,0 )
    QImage *getTransImage( QImage *image , QPoint ponit = QPoint( 0,0 ) ) ;

    /*
    这个是处理全部的粉红色背景的图片,使仅仅编程透明色背景
    */
    void dealPinkBackGroundImage( QString groupname, QString A_valueString ) ;

    /*
    这个是由于当第三层出现时,用户按下Esc键,要回到第二层游戏首页。
    所以在这里用这个hash表来记录
    */
    NumAndPointerHash numPointer ;
    /*
    这个是用来记录当前在第二层上面的Item。通过这个序号在NumAndPointerHash
    中查找Item相应的指针。默觉得-1
    */
    int nowIndex ;
    /*
    这里是由于,这个设置的图片太小。要把以下的開始与退出button给隐藏掉。
    不然用户移动鼠标会误点到
    */
    void setSomeItemVisible( bool visible ) ;
    //从配置文件里读出所要的音量的值
    inline int getVolumeValueFromFile( QString groupname ,QString A_valueString ) ;
    //从配置文件里读取是否要设置全屏
    inline bool getFullScreenValueFromFile( QString groupname ,QString A_valueString ) ;


    /****************************最底层的Item******************************/
    GameLogoImageItem *logoImageItem ;
    void addGameLogoImageItem( ) ;           //加入GameLogoImageItem到场景去

    GameBackGroundItem *backGroundItem ;
    //这是定义的一个表,用来存储图片名字与图片的坐标
    //部分图片的坐标不须要写在配置文件。由于其默认坐标一直都是(0,0)
    NameAndPointHash namePointHash ;
    //依据组名及每组相应的图片数目的A值来读取配置文件。而且记录到namePointHash中去。
    void initNameAndPointHash( QString groupname ,QString A_valueString ) ;

    /****************************第二层的Item******************************/
    GameButtonItem *dianwoButton ;            //点我的广告button
    GameButtonItem *moregameButton ;          //很多其他的游戏button
    GameButtonItem *startgameButton ;         //開始游戏button
    GameButtonItem *instrgameButton ;         //游戏介绍button
    GameButtonItem *gameoptionButton ;        //游戏选项button
    GameButtonItem *gamehihgscButton ;        //游戏排行榜button
    GameButtonItem *exitgameButton ;          //退出游戏button
    GameArrowItem  *arrowItem ;               //箭头Item
    /*
    加入全部的第二层的Item,通过一个接口把全部的第二层的Item全部放进来。方便管理
    */
    void addAllSecondLayerItem() ;
    //分开进行加入这样不至于让一个函数变的非常长
    void addDianWoButton() ;       //加入点我button
    void addMoreGameButton() ;     //加入很多其他的游戏button
    void addStartGameButton() ;    //加入開始游戏button
    void addInstrGameButton() ;    //加入游戏介绍button
    void addGameOptionButton() ;   //加入游戏选项button
    void addGameHihgscButton() ;   //加入游戏排行榜button
    void addExitGameButton() ;     //加入退出游戏button
    void addArrowItem() ;          //加入箭头Item
    /****************************第三层的Item******************************/

    GameMovBackGrouItem *movBacGrouItem ;    //动态背景图片
    GameIntroductionItem *introduItem ;      //游戏介绍Item
    GameOptionItem *optionItem ;             //游戏选项Item
    GameHighWinItem *highWinItem ;           //游戏排行榜Item

    /**************************游戏的背景音乐与音效的处理*************************/
    GameGameSound *gameSound ;      //游戏的背景音乐与音效
    void initGameGameSound() ;      //初始化游戏的背景音乐与音效

private slots:
    void addGameBackGroundItem( ) ;         //加入GameBackGroundItem到场景去

    void mouseOnStartgameButton( ) ;        //光标在開始游戏button
    void mouseOnInstrgameButton( ) ;        //光标在游戏介绍button
    void mouseOnGameOptionButton( ) ;       //光标在游戏选项button
    void mouseOnGameHihgscButton( ) ;       //光标在游戏排行榜button
    void mouseOnExitgameButton( ) ;         //光标在退出游戏button

    void clickOnStartgameButton( ) ;        //单击開始游戏button
    void clickOnInstrgameButton( ) ;        //单击游戏介绍button
    void clickOnGameOptionButton( ) ;       //单击游戏选项button
    void clickOnGameHihgscButton( ) ;       //单击游戏排行榜button
    void clickOnExitgameButton( ) ;         //单击退出游戏button

    /*
    这个是依据当前箭头序号来确定进入到哪个Item的槽函数
    */
    void clickOnButton( int index ) ;

    /*
    用户按Esc键返回到第二层。返回游戏首页的信号的槽函数
    */
    void backToSecondLaySlot( int index ) ;
    //这个是前景Item的退回到游戏首页的button的槽函数
    void backToGameHomeSlot() ;
protected:
    //事件过滤器
    bool eventFilter ( QObject * watched, QEvent * event ) ;
    void	resizeEvent ( QResizeEvent * event );
};

#endif // TETRIXWIDGET_H
(3)TetrixWidget.cpp
/************************************************************************
* 版权全部 (C)2011, 上海欣诺有限公司。
*
* 文件名:  TetrixWidget.cpp
* 文件标识:
* 内容摘要:  TetrixWidget类的实现
* 其他说明:
* 当前版本号: 1.0
* 作    者:
* 完毕日期:
*
* 改动记录1:
*    改动日期:
*    版 本 号:
*    修 改 人:
*    改动内容:
* 改动记录2:…
************************************************************************/

#include "TetrixWidget.h"
#include <QDebug>

/**************************************************************************
 *                            常量                                        *
 **************************************************************************/



/**************************************************************************
 *                            宏                                          *
 **************************************************************************/


/**************************************************************************
 *                          数据类型                                       *
 **************************************************************************/



/**************************************************************************
 *                           全局变量                                      *
 **************************************************************************/



/**************************************************************************
 *                           局部函数原型                                  *
 **************************************************************************/

/**************************************************************************
 *                  类TetrixWidget实现--公有部分                          *
 **************************************************************************/

/**************************************************************************
* 函数名称: TetrixWidget
* 功能描写叙述: 构造函数
* 訪问的表:
* 改动的表:
* 输入參数:
* 输出參数:
* 返 回 值:
* 其他说明:
* 改动日期    版本号号     改动人	     改动内容
* -----------------------------------------------
*
**************************************************************************/


TetrixWidget::TetrixWidget(QWidget *parent)
    :QWidget(parent),nowIndex( -1 )
{
    //初始化。设置其读取ini为后缀的配置文件
    configIni = new QSettings( CONFIGUREPATH,QSettings::IniFormat ) ;
    //首先载入是两个logo文件
    initAndLoadImage( GROUPNAME_LOGO,LOGO_COUNT ) ;
    /*
    设置控件显示的參数,由于其大小是依据logo图片的大小还算的。所以要放在读取配置文件之后
    */
    setTetrixWigAttribute() ;
    //初始化视图的大小也是依据两个logo图片的大小来确定的,所以要放在读取配置文件之后
    initGameSceneAndView() ;

    addGameLogoImageItem() ;      //加入GameLogoImageItem到场景去
    /*
    仅仅所以把GameLogoImageItem加入到场景去再载入全部的图片,
    是由于logo图片有个渐显的效果,能够利用这个间隙把全部的图片
    全部载入进来。该处理的出来掉。

这样能够有效的利用时间,让用户感觉不到 载入图片过程 */ loadAllImageFile() ; //载入全部的图片 /* 依据组名及每组相应的图片数目的A值来读取配置文件,而且记录到namePointHash中去。

*/ initNameAndPointHash( GROUPNAME_COORDINATE ,COORDINATE_COUNT) ; } /*********************************************************************** * 函数名称: ~TetrixWidget() * 功能描写叙述: 析构函数 * 訪问的表: * 改动的表: * 输入參数: * 输出參数: * 返 回 值: * 其他说明: * 改动日期 版本号号 改动人 改动内容 * ----------------------------------------------- * *************************************************************************/ TetrixWidget::~TetrixWidget() { //这个显示delete。qt都能够通过qt来进行delete的 delete gameSound ; } /************************************************************************** * 函数名称: setTetrixWigAttribute * 功能描写叙述: 设置TetrixWidget类的属性 * 訪问的表: * 改动的表: * 输入參数: * 输出參数: * 返 回 值: * 其他说明: * 改动日期 版本号号 改动人 改动内容 * ----------------------------------------------- * **************************************************************************/ void TetrixWidget::setTetrixWigAttribute() { /* 这里是设置屏蔽窗体最大化的button的属性,在linux下没有效果,在windows有效果不知道为啥 */ this->setWindowFlags( Qt::Window | Qt::WindowMinimizeButtonHint | Qt::WindowCloseButtonHint ); //设置居中屏幕显示 QDesktopWidget* desktop = QApplication::desktop(); // =qApp->desktop();也能够 /* 这个是依据logo的大小来确定的,由于控件比图片多一个宽口管理其,所以height加40进行调整 ,以达到初始显示在屏幕中间的效果 */ if( nameImageHash.contains( LOGO_1 ) ) { int width = nameImageHash.value(LOGO_1)->size().width() ; int height = nameImageHash.value(LOGO_1)->size().height() + 40 ; move((desktop->width() - width)/2, (desktop->height() - height)/2); } //安装事件过滤器 this->installEventFilter( this ); setWindowTitle("俄罗斯方块单机版 V1.0"); } /************************************************************************** * 函数名称: initAndLoadImage * 功能描写叙述: 依据组名及每组相应的图片数目的A值来读取配置文件,而且载入图片文件。 * 訪问的表: * 改动的表: * 输入參数: * 输出參数: * 返 回 值: * 其他说明: * 改动日期 版本号号 改动人 改动内容 * ----------------------------------------------- * **************************************************************************/ void TetrixWidget::initAndLoadImage(QString groupname, QString A_valueString) { if( !groupname.isEmpty() ) { configIni->beginGroup( groupname ); configIni->setIniCodec( "UTF-8" ); int count = configIni->value( A_valueString).toInt() ; QStringList keyslist = configIni->allKeys() ; //configIni->allKeys()由于这个里面有包括啦求数目的那条A值 if( keyslist.count() == (count + 1) ) { foreach( QString value,keyslist ) { //假设为数目的A值。则不做处理 if( QString::compare( value , A_valueString ) ) { QString imagePath = configIni->value( value ).toString() ; QImage *iamge = new QImage( imagePath ) ; //假设不能载入图片文件,则退出 if( iamge->isNull() ) { QString errorString = QString("File :%1 is not exit !" ).arg(imagePath) ; DEBUGP( errorString ) ; configIni->endGroup(); return ; } //把图片名字与图片加入到hash表中 nameImageHash.insert( value,iamge ) ; } } } else { DEBUGP( "Configure File Num Error !" ) ; configIni->endGroup(); return ; } configIni->endGroup(); } } /************************************************************************* * 函数名称: initNameAndPointHash * 功能描写叙述: 依据组名及每组相应的图片数目的A值来读取配置文件,而且记录到namePointHash中去 * 訪问的表: * 改动的表: * 输入參数: * 输出參数: * 返 回 值: * 其他说明: * 改动日期 版本号号 改动人 改动内容 * ----------------------------------------------- * **************************************************************************/ void TetrixWidget::initNameAndPointHash(QString groupname, QString A_valueString) { if( !groupname.isEmpty() ) { configIni->beginGroup( groupname ); configIni->setIniCodec( "UTF-8" ); int count = configIni->value( A_valueString ).toInt() ; QStringList keyslist = configIni->allKeys() ; //configIni->allKeys()由于这个里面有包括啦求数目的那条A值 if( keyslist.count() == (count + 1) ) { foreach( QString key,keyslist ) { //假设为数目的A值,则不做处理 if( QString::compare( key , A_valueString ) ) { QPoint pos = configIni->value(key).toPoint() ; //DEBUGP( pos ) ; namePointHash.insert( key,pos ) ; } } } configIni->endGroup(); } } /************************************************************************* * 函数名称: getTransImage * 功能描写叙述: 这个坐标ponit用于取图片上某个坐标点的色素作为透明色。默觉得QPoint( 0,0 ) * 訪问的表: * 改动的表: * 输入參数: * 输出參数: * 返 回 值: * 其他说明: * 改动日期 版本号号 改动人 改动内容 * ----------------------------------------------- * **************************************************************************/ QImage *TetrixWidget::getTransImage(QImage *image, QPoint ponit) { //推断所取的点是否在图片内部 if( image->valid( ponit ) ) { QRgb rgb = image->pixel( ponit ); QVector<QRgb> rgbVector = image->colorTable () ; for (int i = 0; i < rgbVector.size(); ++i) { if( rgbVector.at(i) == rgb ) { /* 注意这里假设要变成黑色背景的话就是QRgb rgb2 = QColor(0, 0, 0, 0).rgb() ; 留意 rgb()与rgba()的差别 */ QRgb rgb2 = QColor(0, 0, 0, 0).rgba() ; image->setColor( i,rgb2 ); return image ; } } } return image ; } /************************************************************************* * 函数名称: initGameSceneAndView * 功能描写叙述: 初始化游戏的场景与视图 * 訪问的表: * 改动的表: * 输入參数: * 输出參数: * 返 回 值: * 其他说明: * 改动日期 版本号号 改动人 改动内容 * ----------------------------------------------- * **************************************************************************/ void TetrixWidget::initGameSceneAndView() { gameScene = new GameGraphicsScene() ; gameScene->setBackgroundBrush(Qt::black); //这里要是不限制场景的大小的话,之后小鱼游动时。其场景会增大,之后显示就会移动 //由于小鱼要被全然隐藏掉之后,才掉头又一次開始游这样就可能增大场景,故再这里给写死 gameScene->setSceneRect(0, 0, SCENEWIDTH, SCENEHEIGHT); gameView = new QGraphicsView(this) ; gameView->setScene(gameScene); //设置文字去锯齿显示 gameView->setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing); //设置大小,跟logo图片的大小一样大,不能写死,这样灵活些 if( nameImageHash.contains( LOGO_1 ) ) { /* 在这里把长宽进行微调,不然会出如今场景中滚动鼠标是,场景上下移动的问题 */ int width = nameImageHash.value(LOGO_1)->size().width()+ 2 ; int height = nameImageHash.value(LOGO_1)->size().height() + 2 ; gameView->resize( width,height ); } //关闭水平滚动栏与垂直滚动栏 gameView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); gameView->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); } /************************************************************************* * 函数名称: loadAllImageFile * 功能描写叙述: 载入全部的图片 * 訪问的表: * 改动的表: * 输入參数: * 输出參数: * 返 回 值: * 其他说明: * 改动日期 版本号号 改动人 改动内容 * ----------------------------------------------- * **************************************************************************/ void TetrixWidget::loadAllImageFile() { //载入ModeWin组的文件 initAndLoadImage( GROUPNAME_MODEWIN,MODEWIN_COUNT ) ; //载入DianWoWin组的文件 initAndLoadImage( GROUPNAME_DIANWOWIN,DIANWOWIN_COUNT ) ; //载入OptionWin组的文件 initAndLoadImage( GROUPNAME_OPTIONWID,OPTIONWID_COUNT ) ; //载入Box组的文件 initAndLoadImage( GROUPNAME_BOX,BOX_COUNT ) ; //载入BackWin组的文件 initAndLoadImage( GROUPNAME_BACKWIN,BACKWIN_COUNT ) ; //载入BombWin组的文件 initAndLoadImage( GROUPNAME_BOMBWIN,BOMBWIN_COUNT ) ; //载入MainWin组的文件 initAndLoadImage( GROUPNAME_MAINWIN,MAINWIN_COUNT ) ; //改动MustModify组A值所相应的图片,去掉其背景粉红色,变为透明背景 dealPinkBackGroundImage( GROUPNAME_MUSTMODIFY,MUSTMODIFY_COUNT ) ; } /************************************************************************* * 函数名称: dealPinkBackGroundImage * 功能描写叙述: 加入dealPinkBackGroundImage到场景去 * 訪问的表: * 改动的表: * 输入參数: * 输出參数: * 返 回 值: * 其他说明: * 改动日期 版本号号 改动人 改动内容 * ----------------------------------------------- * **************************************************************************/ void TetrixWidget::dealPinkBackGroundImage(QString groupname, QString A_valueString ) { if( !groupname.isEmpty() ) { configIni->beginGroup( groupname ); configIni->setIniCodec( "UTF-8" ); int count = configIni->value( A_valueString).toInt() ; QStringList keyslist = configIni->allKeys() ; //configIni->allKeys()由于这个里面有包括啦求数目的那条A值 if( keyslist.count() == (count + 1) ) { foreach( QString key,keyslist ) { //假设为数目的A值。则不做处理 if( QString::compare( key , A_valueString ) ) { //DEBUGP( key ) ; //对图片进行处理,去掉粉红的背景 QImage *image = getTransImage( nameImageHash.value( key ) ); //又一次发改动后的值加入到hash表中 nameImageHash.insert( key,image ) ; } } } //注意读完这个组一定要关闭。否则会影响到以下的读取 configIni->endGroup(); } } /************************************************************************* * 函数名称: addGameLogoImageItem * 功能描写叙述: 加入GameLogoImageItem到场景去 * 訪问的表: * 改动的表: * 输入參数: * 输出參数: * 返 回 值: * 其他说明: * 改动日期 版本号号 改动人 改动内容 * ----------------------------------------------- * **************************************************************************/ void TetrixWidget::addGameLogoImageItem() { logoImageItem = new GameLogoImageItem() ; // connect(logoImageItem,SIGNAL(addGameBackGroundItem()) ,this,SLOT(addGameBackGroundItem())) ; logoImageItem->setGameScene( gameScene,nameImageHash); } /************************************************************************* * 函数名称: addAllSecondLayerItem * 功能描写叙述: 加入全部的第二层的Item,通过一个接口把全部的第二层的Item全部放进来,方便管理 * 訪问的表: * 改动的表: * 输入參数: * 输出參数: * 返 回 值: * 其他说明: * 改动日期 版本号号 改动人 改动内容 * ----------------------------------------------- * **************************************************************************/ void TetrixWidget::addAllSecondLayerItem() { //DEBUGP( "addAllSecondLayerItem" ) ; //点我广告的button addDianWoButton() ; //很多其他的游戏button addMoreGameButton() ; //開始游戏button addStartGameButton() ; //游戏介绍button addInstrGameButton() ; //游戏选项button addGameOptionButton() ; //游戏排行榜button addGameHihgscButton() ; //退出游戏button addExitGameButton() ; //箭头Item addArrowItem() ; } /************************************************************************* * 函数名称: addArrowItem * 功能描写叙述: 加入箭头Item * 訪问的表: * 改动的表: * 输入參数: * 输出參数: * 返 回 值: * 其他说明: * 改动日期 版本号号 改动人 改动内容 * ----------------------------------------------- * **************************************************************************/ void TetrixWidget::addArrowItem() { //箭头Item arrowItem = new GameArrowItem( MODEWIN_ARROW ) ; //在这里连接改变坐标的信号与槽 connect(this,SIGNAL(moveArrowat(int)),arrowItem,SLOT(setPointListIndex(int))) ; //这个是依据当前箭头序号来确定进入到哪个Item的槽函数 connect(arrowItem,SIGNAL(enterIntoButton(int)),this,SLOT(clickOnButton(int))); //通过这个信号返回到第二层----游戏首页 connect(arrowItem,SIGNAL(backToSecondLay(int)),this,SLOT(backToSecondLaySlot(int))); arrowItem->setGameScene(gameScene,nameImageHash,namePointHash); /* 这里为啦保持跟上面的一直。所以把设置Z轴的放在这里,事实上不必要放在这里, 由于箭头类是一个单独的类,仅仅有一个对象在用 */ arrowItem->setZValue(1.0); } /************************************************************************* * 函数名称: addExitGameButton * 功能描写叙述: 加入退出游戏button * 訪问的表: * 改动的表: * 输入參数: * 输出參数: * 返 回 值: * 其他说明: * 改动日期 版本号号 改动人 改动内容 * ----------------------------------------------- * **************************************************************************/ void TetrixWidget::addExitGameButton() { //退出游戏button exitgameButton = new GameButtonItem( MODEWIN_EXIT ) ; connect(exitgameButton,SIGNAL(mouseOnMe()), this,SLOT(mouseOnExitgameButton())) ; connect(exitgameButton,SIGNAL(buttonClick()),this,SLOT(close())) ; exitgameButton->setGameScene(gameScene,nameImageHash,namePointHash); exitgameButton->setZValue(1.0); //由于不是全部都在同一层,全部得分开来设置其Z轴的值 } /************************************************************************* * 函数名称: addGameHihgscButton * 功能描写叙述: 加入游戏排行榜button * 訪问的表: * 改动的表: * 输入參数: * 输出參数: * 返 回 值: * 其他说明: * 改动日期 版本号号 改动人 改动内容 * ----------------------------------------------- * **************************************************************************/ void TetrixWidget::addGameHihgscButton() { //游戏排行榜button gamehihgscButton = new GameButtonItem( MODEWIN_HIGHSCORE ) ; connect(gamehihgscButton,SIGNAL(mouseOnMe()), this,SLOT(mouseOnGameHihgscButton())) ; connect(gamehihgscButton,SIGNAL(buttonClick()),this,SLOT(clickOnGameHihgscButton())); gamehihgscButton->setGameScene(gameScene,nameImageHash,namePointHash); gamehihgscButton->setZValue(1.0); //由于不是全部都在同一层。全部得分开来设置其Z轴的值 } /************************************************************************* * 函数名称: addGameOptionButton * 功能描写叙述: 加入游戏选项button * 訪问的表: * 改动的表: * 输入參数: * 输出參数: * 返 回 值: * 其他说明: * 改动日期 版本号号 改动人 改动内容 * ----------------------------------------------- * **************************************************************************/ void TetrixWidget::addGameOptionButton() { //游戏选项button gameoptionButton = new GameButtonItem( MODEWIN_OPTION ) ; connect(gameoptionButton,SIGNAL(mouseOnMe()), this,SLOT(mouseOnGameOptionButton())) ; connect(gameoptionButton,SIGNAL(buttonClick()), this,SLOT(clickOnGameOptionButton())) ; gameoptionButton->setGameScene(gameScene,nameImageHash,namePointHash); gameoptionButton->setZValue(1.0); //由于不是全部都在同一层,全部得分开来设置其Z轴的值 } /************************************************************************* * 函数名称: addInstrGameButton * 功能描写叙述: 加入游戏介绍button * 訪问的表: * 改动的表: * 输入參数: * 输出參数: * 返 回 值: * 其他说明: * 改动日期 版本号号 改动人 改动内容 * ----------------------------------------------- * **************************************************************************/ void TetrixWidget::addInstrGameButton() { //游戏介绍button instrgameButton = new GameButtonItem( MODEWIN_INSTRUCTION ) ; connect(instrgameButton,SIGNAL(mouseOnMe()), this,SLOT(mouseOnInstrgameButton())) ; connect(instrgameButton,SIGNAL(buttonClick()) ,this,SLOT(clickOnInstrgameButton())) ; instrgameButton->setGameScene(gameScene,nameImageHash,namePointHash); instrgameButton->setZValue(1.0); //由于不是全部都在同一层。全部得分开来设置其Z轴的值 } /************************************************************************* * 函数名称: addDianWoButton * 功能描写叙述: 加入点我button * 訪问的表: * 改动的表: * 输入參数: * 输出參数: * 返 回 值: * 其他说明: * 改动日期 版本号号 改动人 改动内容 * ----------------------------------------------- * **************************************************************************/ void TetrixWidget::addDianWoButton() { //点我广告的button dianwoButton = new GameButtonItem( DIANWOWIN_BUTTON ) ; dianwoButton->setGameScene(gameScene,nameImageHash,namePointHash); dianwoButton->setZValue(1.0); //由于不是全部都在同一层,全部得分开来设置其Z轴的值 } /************************************************************************* * 函数名称: addMoreGameButton * 功能描写叙述: 加入很多其他的游戏button * 訪问的表: * 改动的表: * 输入參数: * 输出參数: * 返 回 值: * 其他说明: * 改动日期 版本号号 改动人 改动内容 * ----------------------------------------------- * **************************************************************************/ void TetrixWidget::addMoreGameButton() { //很多其他的游戏button moregameButton = new GameButtonItem( MODEWIN_MOREGAME ) ; moregameButton->setGameScene(gameScene,nameImageHash,namePointHash); moregameButton->setZValue(1.0); //由于不是全部都在同一层,全部得分开来设置其Z轴的值 } /************************************************************************* * 函数名称: addStartGameButton * 功能描写叙述: 加入開始游戏button * 訪问的表: * 改动的表: * 输入參数: * 输出參数: * 返 回 值: * 其他说明: * 改动日期 版本号号 改动人 改动内容 * ----------------------------------------------- * **************************************************************************/ void TetrixWidget::addStartGameButton() { startgameButton = new GameButtonItem( MODEWIN_START ) ; connect(startgameButton,SIGNAL(mouseOnMe()), this,SLOT(mouseOnStartgameButton())) ; connect(startgameButton,SIGNAL(buttonClick()), this,SLOT(clickOnStartgameButton())) ; startgameButton->setGameScene(gameScene,nameImageHash,namePointHash); startgameButton->setZValue(1.0); //由于不是全部都在同一层。全部得分开来设置其Z轴的值 } /************************************************************************* * 函数名称: setSomeItemVisible * 功能描写叙述: 这里是由于,这个设置的图片太小,要把以下的開始与退出button给隐藏掉。 * 不然用户移动鼠标会误点到 * 訪问的表: * 改动的表: * 输入參数: * 输出參数: * 返 回 值: * 其他说明:控制这四个button的显示与隐藏 * 改动日期 版本号号 改动人 改动内容 * ----------------------------------------------- * **************************************************************************/ void TetrixWidget::setSomeItemVisible(bool visible) { startgameButton->setVisible( visible ); exitgameButton->setVisible( visible ); dianwoButton->setVisible( visible ); moregameButton->setVisible( visible ); } /************************************************************************* * 函数名称: getVolumeValueFromFile * 功能描写叙述: 从配置文件里读出所要的音量的值 * 訪问的表: * 改动的表: * 输入參数: * 输出參数: * 返 回 值: * 其他说明:控制这四个button的显示与隐藏 * 改动日期 版本号号 改动人 改动内容 * ----------------------------------------------- * **************************************************************************/ inline int TetrixWidget::getVolumeValueFromFile(QString groupname, QString A_valueString) { configIni->beginGroup( groupname ); configIni->setIniCodec( "UTF-8" ); int volume = configIni->value( A_valueString ).toInt() ; configIni->endGroup(); return volume ; } /************************************************************************* * 函数名称: getFullScreenValueFromFile * 功能描写叙述: 从配置文件里读取是否要设置全屏 * 訪问的表: * 改动的表: * 输入參数: * 输出參数: * 返 回 值: * 其他说明:控制这四个button的显示与隐藏 * 改动日期 版本号号 改动人 改动内容 * ----------------------------------------------- * **************************************************************************/ inline bool TetrixWidget::getFullScreenValueFromFile(QString groupname, QString A_valueString) { configIni->beginGroup( groupname ); configIni->setIniCodec( "UTF-8" ); bool fullscreen = configIni->value( A_valueString ).toBool() ; configIni->endGroup(); return fullscreen ; } /************************************************************************* * 函数名称: initGameGameSound * 功能描写叙述: 初始化游戏的背景音乐与音效 * 訪问的表: * 改动的表: * 输入參数: * 输出參数: * 返 回 值: * 其他说明: * 改动日期 版本号号 改动人 改动内容 * ----------------------------------------------- * **************************************************************************/ void TetrixWidget::initGameGameSound() { int musicVolume = getVolumeValueFromFile( GROUPNAME_SETTINGS,SETTINGS_MUSIC ) ; int audioVolume = getVolumeValueFromFile( GROUPNAME_SETTINGS,SETTINGS_AUDIO ) ; gameSound = new GameGameSound( musicVolume,audioVolume ) ; gameSound->setGameSceneAndConfigF(gameScene,configIni); } /************************************************************************* * 函数名称: addGameBackGroundItem * 功能描写叙述: 加入addGameBackGroundItem到场景去 * 訪问的表: * 改动的表: * 输入參数: * 输出參数: * 返 回 值: * 其他说明: * 改动日期 版本号号 改动人 改动内容 * ----------------------------------------------- * **************************************************************************/ void TetrixWidget::addGameBackGroundItem() { //在加入背景图片前先移除两个logo图片 gameScene->removeItem( logoImageItem ); backGroundItem = new GameBackGroundItem() ; backGroundItem->setGameScene( gameScene,nameImageHash ); //加入全部的第二层的Item addAllSecondLayerItem() ; //初始化游戏的背景音乐与音效 initGameGameSound(); } /************************************************************************* * 函数名称: mouseOnStartgameButton * 功能描写叙述: 光标在開始游戏button * 訪问的表: * 改动的表: * 输入參数: * 输出參数: * 返 回 值: * 其他说明: 5个Button发送过来的信号分别相应不同的槽函数,在槽函数中又分别发送同一信号 * 不同參数。这样觉得有点麻烦。一下子用啦5个槽函数。眼下没有想到更好的办法。 * 改动日期 版本号号 改动人 改动内容 * ----------------------------------------------- * **************************************************************************/ void TetrixWidget::mouseOnStartgameButton() { //DEBUGP( 0 ) ; emit moveArrowat( 0) ; } /************************************************************************* * 函数名称: mouseOnInstrgameButton * 功能描写叙述: 光标在游戏介绍button * 訪问的表: * 改动的表: * 输入參数: * 输出參数: * 返 回 值: * 其他说明: * 改动日期 版本号号 改动人 改动内容 * ----------------------------------------------- * **************************************************************************/ void TetrixWidget::mouseOnInstrgameButton() { //DEBUGP( 1 ) ; emit moveArrowat( 1 ) ; } /************************************************************************* * 函数名称: mouseOnGameOptionButton * 功能描写叙述: 光标在游戏选项button * 訪问的表: * 改动的表: * 输入參数: * 输出參数: * 返 回 值: * 其他说明: * 改动日期 版本号号 改动人 改动内容 * ----------------------------------------------- * **************************************************************************/ void TetrixWidget::mouseOnGameOptionButton() { //DEBUGP( 2 ) ; emit moveArrowat( 2 ) ; } /************************************************************************* * 函数名称: mouseOnGameHihgscButton * 功能描写叙述: 光标在游戏排行榜button * 訪问的表: * 改动的表: * 输入參数: * 输出參数: * 返 回 值: * 其他说明: * 改动日期 版本号号 改动人 改动内容 * ----------------------------------------------- * **************************************************************************/ void TetrixWidget::mouseOnGameHihgscButton() { //DEBUGP( 3 ) ; emit moveArrowat( 3 ) ; } /************************************************************************* * 函数名称: mouseOnExitgameButton * 功能描写叙述: 光标在退出游戏button * 訪问的表: * 改动的表: * 输入參数: * 输出參数: * 返 回 值: * 其他说明: * 改动日期 版本号号 改动人 改动内容 * ----------------------------------------------- * **************************************************************************/ void TetrixWidget::mouseOnExitgameButton() { //DEBUGP( 4 ) ; emit moveArrowat( 4 ) ; } /************************************************************************* * 函数名称: clickOnStartgameButton * 功能描写叙述: 单击開始游戏button * 訪问的表: * 改动的表: * 输入參数: * 输出參数: * 返 回 值: * 其他说明: * 改动日期 版本号号 改动人 改动内容 * ----------------------------------------------- * **************************************************************************/ void TetrixWidget::clickOnStartgameButton() { movBacGrouItem =new GameMovBackGrouItem( MAINWIN_BACKGROUND ) ; //这个作为序号0记录到hash表中 nowIndex = 0 ; numPointer.insert( nowIndex,(void *)movBacGrouItem ) ; connect( this,SIGNAL(coverOnArowItemSignal(bool)), gameScene,SIGNAL(changeCoveredStateSignal(bool))) ; //转发游戏窗体停用信号到场景中的游戏暂停信号 connect(this,SIGNAL(gameDeactivateSignal()),gameScene,SIGNAL(gameDeactivateSignal())) ; //连接从场景中转发出来的回到游戏首页的信号与槽函数 connect(gameScene,SIGNAL(backToGameHomeSignal()), this,SLOT(backToGameHomeSlot())) ; movBacGrouItem->setGameScene( gameScene,nameImageHash,namePointHash ); movBacGrouItem->setZValue( 3.0 ) ; //这个是作为第三层显示的 //发送信号来还原之前改变的箭头Item的遮蔽状态 emit coverOnArowItemSignal( true ); } /************************************************************************* * 函数名称: clickOnInstrgameButton * 功能描写叙述: 单击游戏介绍button * 訪问的表: * 改动的表: * 输入參数: * 输出參数: * 返 回 值: * 其他说明: * 改动日期 版本号号 改动人 改动内容 * ----------------------------------------------- * **************************************************************************/ void TetrixWidget::clickOnInstrgameButton() { introduItem = new GameIntroductionItem( MODEWIN_HELP ) ; //这个作为序号1记录到hash表中 nowIndex = 1 ; numPointer.insert( nowIndex,(void *)introduItem ) ; //返回游戏首页的信号的槽函数 connect(introduItem,SIGNAL(backToSecondLay(int)),this,SLOT(backToSecondLaySlot(int))) ; connect( this,SIGNAL(coverOnArowItemSignal(bool)), gameScene,SIGNAL(changeCoveredStateSignal(bool))) ; introduItem->setGameScene( gameScene,nameImageHash ); introduItem->setZValue( 3.0 ) ; //这个是作为第三层显示的 //发送信号来还原之前改变的箭头Item的遮蔽状态 emit coverOnArowItemSignal( true ); } /************************************************************************* * 函数名称: clickOnGameOptionButton * 功能描写叙述: 单击游戏选项button * 訪问的表: * 改动的表: * 输入參数: * 输出參数: * 返 回 值: * 其他说明: * 改动日期 版本号号 改动人 改动内容 * ----------------------------------------------- * **************************************************************************/ void TetrixWidget::clickOnGameOptionButton() { int musicVolume = getVolumeValueFromFile( GROUPNAME_SETTINGS,SETTINGS_MUSIC ) ; int audioVolume = getVolumeValueFromFile( GROUPNAME_SETTINGS,SETTINGS_AUDIO ) ; bool fullScreen = getFullScreenValueFromFile( GROUPNAME_SETTINGS,SETTINGS_FULLSCREEN) ; //DEBUGP( audioVolume ) ; optionItem = new GameOptionItem( OPTIONWIN_SETTING,musicVolume,audioVolume,fullScreen ) ; connect(optionItem,SIGNAL(backToSecondLay(int)),this,SLOT(backToSecondLaySlot(int))) ; connect( this,SIGNAL(coverOnArowItemSignal(bool)), gameScene,SIGNAL(changeCoveredStateSignal(bool))) ; //这个作为序号1记录到hash表中 nowIndex = 2 ; numPointer.insert( nowIndex,(void *)optionItem ) ; optionItem->setGameScene( gameScene,nameImageHash,namePointHash ); optionItem->setConfigureFile( configIni ); optionItem->setZValue( 3.0 ) ; //这个是作为第三层显示的 /* 这里是由于,这个设置的图片太小,要把以下的開始与退出button给隐藏掉, 不然用户移动鼠标会误点到 */ setSomeItemVisible( false ) ; //发送信号来还原之前改变的箭头Item的遮蔽状态 emit coverOnArowItemSignal( true ); } /************************************************************************* * 函数名称: clickOnGameHihgscButton * 功能描写叙述: 单击游戏排行榜button * 訪问的表: * 改动的表: * 输入參数: * 输出參数: * 返 回 值: * 其他说明: * 改动日期 版本号号 改动人 改动内容 * ----------------------------------------------- * **************************************************************************/ void TetrixWidget::clickOnGameHihgscButton() { highWinItem = new GameHighWinItem( MODEWIN_HIGHWIN ); connect(highWinItem,SIGNAL(backToSecondLay(int)),this,SLOT(backToSecondLaySlot(int))) ; connect( this,SIGNAL(coverOnArowItemSignal(bool)), gameScene,SIGNAL(changeCoveredStateSignal(bool))) ; //这个作为序号1记录到hash表中 nowIndex = 3 ; numPointer.insert( nowIndex,(void *)highWinItem ) ; highWinItem->setGameScene( gameScene,nameImageHash,namePointHash ); highWinItem->setZValue( 3.0 ) ; //这个是作为第三层显示的 //发送信号来还原之前改变的箭头Item的遮蔽状态 emit coverOnArowItemSignal( true ); } /************************************************************************* * 函数名称: clickOnExitgameButton * 功能描写叙述: 单击退出游戏button * 訪问的表: * 改动的表: * 输入參数: * 输出參数: * 返 回 值: * 其他说明: * 改动日期 版本号号 改动人 改动内容 * ----------------------------------------------- * **************************************************************************/ void TetrixWidget::clickOnExitgameButton() { //退出程序 this->close() ; } /************************************************************************* * 函数名称: clickOnButton * 功能描写叙述: 这个是依据当前箭头序号来确定进入到哪个Item的槽函数 * 訪问的表: * 改动的表: * 输入參数: * 输出參数: * 返 回 值: * 其他说明: * 改动日期 版本号号 改动人 改动内容 * ----------------------------------------------- * **************************************************************************/ void TetrixWidget::clickOnButton(int index) { switch( index ) { case 0: clickOnStartgameButton() ; break ; case 1: clickOnInstrgameButton() ; break ; case 2: clickOnGameOptionButton() ; break ; case 3: clickOnGameHihgscButton() ; break ; case 4: clickOnExitgameButton() ; break ; default: break ; } } /************************************************************************* * 函数名称: backToSecondLaySlot * 功能描写叙述: 用户按Esc键返回到第二层,返回游戏首页的信号的槽函数 * 訪问的表: * 改动的表: * 输入參数: * 输出參数: * 返 回 值: * 其他说明: 通过这个当前箭头所相应的序号的值 * 比方说 * 0---->開始游戏 * 1---->游戏介绍 * 。。

。。。

。 * 在NumAndPointerHash表中查找相应的Item的指针的值 * 改动日期 版本号号 改动人 改动内容 * ----------------------------------------------- * **************************************************************************/ void TetrixWidget::backToSecondLaySlot( int index ) { void * item ; /* 假设当用户本来就在第二层游戏首页时,这个时候却按下Esc键,这个时候这个item为空。 首先得推断hash表中有没这个key值 */ if( numPointer.contains( index ) ) { item = numPointer.value( index ) ; if( item ) { //由于每一个类型的指针的类型是不同的。所以这里得这样分开来写 switch( index ) { case 0: //在这里发送信号,先去删除动态珊瑚背景层之上的东西。也就是第四层与第五层的东西 //由于第四层与第五层都是作为动态珊瑚背景(第三层)的成员变量,所以在这里得在删除第三层前 //删掉第四层与第五层的东西 ((GameMovBackGrouItem *)item)->removeFourthAndFifthItemFun(); gameScene->removeItem( (GameMovBackGrouItem *)item ); delete ((GameMovBackGrouItem *)item); //再次发送信号来还原之前改变的箭头Item的遮蔽状态 emit coverOnArowItemSignal( false ); break ; case 1: gameScene->removeItem( (GameIntroductionItem *)item ); delete (GameIntroductionItem *)item ; //再次发送信号来还原之前改变的箭头Item的遮蔽状态 emit coverOnArowItemSignal( false ); break ; case 2: //使得四个button恢复显示 setSomeItemVisible( true ) ; gameScene->removeItem( (GameOptionItem *)item ); delete (GameOptionItem *)item ; //再次发送信号来还原之前改变的箭头Item的遮蔽状态 emit coverOnArowItemSignal( false ); break ; case 3: gameScene->removeItem( (GameHighWinItem *)item ); delete (GameHighWinItem *)item ; //再次发送信号来还原之前改变的箭头Item的遮蔽状态 emit coverOnArowItemSignal( false ); break ; case 4: break ; default: DEBUGP( "index error !" ) ; break ; } //清空如今的记录,以便下次再进行切换 nowIndex = -1 ; numPointer.remove( index ) ; } } } /************************************************************************* * 函数名称: backToGameHomeSlot * 功能描写叙述: 这个是前景Item的退回到游戏首页的button的槽函数 * 訪问的表: * 改动的表: * 输入參数: * 输出參数: * 返 回 值: * 其他说明: * 改动日期 版本号号 改动人 改动内容 * ----------------------------------------------- * **************************************************************************/ void TetrixWidget::backToGameHomeSlot() { //由于这个时候是进入游戏之后才干够看到游戏的前景 backToSecondLaySlot( 0 ) ; } /************************************************************************* * 函数名称: eventFilter * 功能描写叙述: 事件过滤器 * 訪问的表: * 改动的表: * 输入參数: * 输出參数: * 返 回 值: * 其他说明:这个是重载事件过滤器函数。通过这个函数推断,当鼠标移动到其他的软件的窗体时。 * 这个时候整个游戏软件被停用。

在这个时候发送暂停游戏的消息 * 改动日期 版本号号 改动人 改动内容 * ----------------------------------------------- * **************************************************************************/ bool TetrixWidget::eventFilter(QObject *watched, QEvent *event) { if( watched == this ) { //窗体停用,及一般人觉得的失去焦点 if(QEvent::WindowDeactivate == event->type()) { // //DEBUGP( "eventFilter" ) ; emit gameDeactivateSignal() ; return true ; } else { return false ; } } return false ; } void TetrixWidget::resizeEvent(QResizeEvent *event) { gameScene->setSceneRect(0, 0, gameView->width(), gameView->height()); }

三、总结

(1)上述代码是一个非常不错的项目样例。自己也在拜读代码(也有非常多不懂的地方),并在实际工作中加以应用。
(2)上述代码已上传到CSDN:http://download.csdn.net/detail/taiyang1987912/9480721


(3)若有问题或建议,请留言,在此感谢!


posted @ 2017-07-24 20:32  yangykaifa  阅读(504)  评论(0编辑  收藏  举报