做网站需要注册公司吗,网站的主页按钮怎么做的,wordpress前台修改,企业网站开发平台目录
4 选择关卡场景
4.2 背景设置
4.3 创建返回按钮
4.3 返回按钮
4.4 创建选择关卡按钮
4.5 创建翻金币场景
5 翻金币场景
5.1 场景基本设置
5.2 背景设置
5.3 返回按钮
5.4 显示当前关卡
5.5 创建金币背景图片
5.6 创建金币类
5.6.1 创建金币类 MyCoin
5.6.…目录
4 选择关卡场景
4.2 背景设置
4.3 创建返回按钮
4.3 返回按钮
4.4 创建选择关卡按钮
4.5 创建翻金币场景
5 翻金币场景
5.1 场景基本设置
5.2 背景设置
5.3 返回按钮
5.4 显示当前关卡
5.5 创建金币背景图片
5.6 创建金币类
5.6.1 创建金币类 MyCoin
5.6.2 构造函数
5.6.3 测试
5.7 引入关卡数据
5.7.1 添加现有文件dataConfig 5.7.2 添加现有文件
5.7.3 完成添加
5.7.4 数据分析
5.7.5 测试关卡数据
5.8 初始化各个关卡
5.9 翻金币特效
5.9.1 MyCoin类扩展属性和行为
5.9.2 创建特效
5.9.3 测试
5.9.3 禁用按钮
5.10 翻周围金币
5.11 判断是否胜利
5.12 胜利图片显示
5.13 胜利后禁用按钮
6 音效添加
6.1 开始音效
6.2 选择关卡音效
6.3 返回按钮音效
6.4 翻金币与胜利音效
7 优化项目 4 选择关卡场景 4.1 场景基本设置 选择关卡构造函数如下 //设置窗口固定大小this-setFixedSize(320,588);//设置图标this-setWindowIcon(QPixmap(:/res/Coin0001.png));//设置标题this-setWindowTitle(选择关卡);//创建菜单栏QMenuBar * bar this-menuBar();this-setMenuBar(bar);//创建开始菜单QMenu * startMenu bar-addMenu(开始);//创建按钮菜单项QAction * quitAction startMenu-addAction(退出);//点击退出 退出游戏connect(quitAction,QAction::triggered,[](){this-close();});
运行效果如图 4.2 背景设置
void ChooseLevelScene::paintEvent(QPaintEvent *)
{QPainter painter(this);QPixmap pix;pix.load(:/res/OtherSceneBg.png);painter.drawPixmap(0,0,this-width(),this-height(),pix);//加载标题pix.load(:/res/Title.png);painter.drawPixmap( (this-width() - pix.width())*0.5,30,pix.width(),pix.height(),pix);
}
4.3 创建返回按钮 //返回按钮MyPushButton * closeBtn new MyPushButton(:/res/BackButton.png,:/res/BackButtonSelected.png);closeBtn-setParent(this);closeBtn-move(this-width()-closeBtn-width(),this-height()-closeBtn-height());
返回按钮是有正常显示图片和点击后显示图片的两种模式所以我们需要重写MyPushButton中的 MousePressEvent和MouseReleaseEvent。
//鼠标事件
void MyPushButton::mousePressEvent(QMouseEvent *e)
{if(pressedImgPath ! ) //选中路径不为空显示选中图片{QPixmap pixmap;bool ret pixmap.load(pressedImgPath);if(!ret){qDebug() pressedImgPath 加载图片失败!;}this-setFixedSize( pixmap.width(), pixmap.height() );this-setStyleSheet(QPushButton{border:0px;});this-setIcon(pixmap);this-setIconSize(QSize(pixmap.width(),pixmap.height()));}//交给父类执行按下事件return QPushButton::mousePressEvent(e);
}
void MyPushButton::mouseReleaseEvent(QMouseEvent *e)
{if(normalImgPath ! ) //选中路径不为空显示选中图片{QPixmap pixmap;bool ret pixmap.load(normalImgPath);if(!ret){qDebug() normalImgPath 加载图片失败!;}this-setFixedSize( pixmap.width(), pixmap.height() );this-setStyleSheet(QPushButton{border:0px;});this-setIcon(pixmap);this-setIconSize(QSize(pixmap.width(),pixmap.height()));}//交给父类执行 释放事件return QPushButton::mouseReleaseEvent(e);
}
4.3 返回按钮
在这里我们点击返回后延时0.5后隐藏自身并且发送自定义信号告诉外界自身已经选择了返回按钮。
//返回按钮功能实现connect(closeBtn,MyPushButton::clicked,[](){QTimer::singleShot(500, this,[](){this-hide();//触发自定义信号关闭自身该信号写到 signals下做声明emit this-chooseSceneBack();});});
在主场景MainScene中 点击开始按钮显示选择关卡的同时监听选择关卡的返回按钮消息
//监听选择场景的返回按钮 connect(chooseScene,ChooseLevelScene::chooseSceneBack,[](){this-show();});
测试主场景与选择关卡场景的切换功能。
4.4 创建选择关卡按钮
//创建关卡按钮for(int i 0 ; i 20;i){MyPushButton * menuBtn new MyPushButton(:/res/LevelIcon.png);menuBtn-setParent(this);menuBtn-move(25 (i%4)*70 , 130 (i/4)*70);//按钮上显示的文字QLabel * label new QLabel;label-setParent(this);label-setFixedSize(menuBtn-width(),menuBtn-height());label-setText(QString::number(i1));label-setAlignment(Qt::AlignHCenter | Qt::AlignVCenter); //设置居中label-move(25 (i%4)*70 , 130 (i/4)*70);label-setAttribute(Qt::WA_TransparentForMouseEvents,true); //鼠标事件穿透}
运行效果如果 4.5 创建翻金币场景
点击关卡按钮后会进入游戏的核心场景也就是翻金币的场景首先先创建出该场景的.h和.cpp文件
创建PlayScene 点击选择关卡按钮后会跳入到该场景
建立点击按钮跳转场景的信号槽连接 在ChooseLevelScene.h 中声明
PlayScene *pScene NULL; //监听选择关卡按钮的信号槽connect(menuBtn,MyPushButton::clicked,[](){// qDebug() select: i;if(pScene NULL) //游戏场景最好不用复用直接移除掉创建新的场景{this-hide();pScene new PlayScene(i1); //将选择的关卡号 传入给PlayerScenepScene-show();}});
这里pScene new PlayScene(i1); 将用户所选的关卡号发送给pScene也就是翻金币场景当然PlayScene 要提供重载的有参构造版本来接受这个参数。 5 翻金币场景
5.1 场景基本设置
PlayScene.h中 声明成员变量用于记录当前用户选择的关卡。
//成员变量 记录关卡索引int levalIndex;
PlayScene.cpp中 初始化该场景配置。
PlayScene::PlayScene(int index)
{//qDebug() 当前关卡为 index;this-levalIndex index;//设置窗口固定大小this-setFixedSize(320,588);//设置图标this-setWindowIcon(QPixmap(:/res/Coin0001.png));//设置标题this-setWindowTitle(翻金币);//创建菜单栏QMenuBar * bar this-menuBar();this-setMenuBar(bar);//创建开始菜单QMenu * startMenu bar-addMenu(开始);//创建按钮菜单项QAction * quitAction startMenu-addAction(退出);//点击退出 退出游戏connect(quitAction,QAction::triggered,[](){this-close();});
}
5.2 背景设置
void PlayScene::paintEvent(QPaintEvent *)
{//加载背景QPainter painter(this);QPixmap pix;pix.load(:/res/PlayLevelSceneBg.png);painter.drawPixmap(0,0,this-width(),this-height(),pix);//加载标题pix.load(:/res/Title.png);pix pix.scaled(pix.width()*0.5,pix.height()*0.5);painter.drawPixmap( 10,30,pix.width(),pix.height(),pix);
}
5.3 返回按钮 //返回按钮MyPushButton * closeBtn new MyPushButton(:/res/BackButton.png,:/res/BackButtonSelected.png);closeBtn-setParent(this);closeBtn-move(this-width()-closeBtn-width(),this-height()-closeBtn-height());//返回按钮功能实现connect(closeBtn,MyPushButton::clicked,[](){QTimer::singleShot(500, this,[](){this-hide();//触发自定义信号关闭自身该信号写到 signals下做声明emit this-chooseSceneBack();});});
5.4 在ChooseScene选择关卡场景中监听PlayScene的返回信号。
connect(pScene,PlayScene::chooseSceneBack,[](){this-show();delete pScene;pScene NULL;}); 5.4 显示当前关卡
//当前关卡标题QLabel * label new QLabel;label-setParent(this);QFont font;font.setFamily(华文新魏);font.setPointSize(20);label-setFont(font);QString str QString(Leavel: %1).arg(this-levalIndex);label-setText(str);label-setGeometry(QRect(30, this-height() - 50,120, 50)); //设置大小和位置
假设我们选择了第15关卡运行效果如果 5.5 创建金币背景图片
//创建金币的背景图片for(int i 0 ; i 4;i){for(int j 0 ; j 4; j){//绘制背景图片QLabel* label new QLabel;label-setGeometry(0,0,50,50);label-setPixmap(QPixmap(:/res/BoardNode.png));label-setParent(this);label-move(57 i*50,200j*50);}}
运行效果如图 5.6 创建金币类
我们知道金币是本游戏的核心对象并且在游戏中可以利用二维数组进行维护拥有支持点击翻转特效等特殊性因此不妨将金币单独封装到一个类中完成金币所需的所有功能。
5.6.1 创建金币类 MyCoin 并修改MyCoin的基类为QPushButton
5.6.2 构造函数
在资源图片中我们可以看到金币翻转的效果原理是多张图片切换而形成的而以下八张图片中第一张与最后一张比较特殊因此我们在给用户看的时候无非是金币Coin0001或者是银币 Coin0008这两种图。
因此我们在创建一个金币对象时候应该提供一个参数代表着传入的是金币资源路径还是银币资源路径根据路径我们创建不同样式的图案。 在MyCoin.h中声明
MyCoin(QString butImg); //代表图片路径
在MyCoin.cpp中进行实现
MyCoin::MyCoin(QString butImg)
{QPixmap pixmap;bool ret pixmap.load(butImg);if(!ret){qDebug() butImg 加载图片失败!;}this-setFixedSize( pixmap.width(), pixmap.height() );this-setStyleSheet(QPushButton{border:0px;});this-setIcon(pixmap);this-setIconSize(QSize(pixmap.width(),pixmap.height()));}
5.6.3 测试
在翻金币场景 PlayScene中我们测试下封装的金币类是否可用可以在创建好的金币背景代码后添加如下代码 //金币对象MyCoin * coin new MyCoin(:/res/Coin0001.png);coin-setParent(this);coin-move(59 i*50,204j*50);
运行效果如图 5.7 引入关卡数据
当然上述的测试只是为了让我们知道提供的对外接口可行但是每个关卡的初始化界面并非如此因此需要我们引用一个现有的关卡文件文件中记录了各个关卡的金币排列清空也就是二维数组的数值。 5.7.1 添加现有文件dataConfig
首先先将dataConfig.h 和 dataConfig.cpp文件放入到当前项目下 5.7.2 添加现有文件
其次在Qt_Creator项目右键点击添加现有文件。 5.7.3 完成添加
选择当前项目下的文件并进行添加 5.7.4 数据分析
我们可以看到其实dataConfig.h中只有一个数据是对外提供的如下图 在上图中QMapint,QVectorQVectorintmData;都记录着每个关卡中的数据。
其中int代表对应的关卡 也就是QMap中的key值而value值就是对应的二维数组我们利用的是 QVectorQVectorint来记录着其中的二维组。
5.7.5 测试关卡数据
在Main函数可以测试第一关的数据添加如下代码
dataConfig config;for(int i 0 ; i 4;i){for(int j 0 ; j 4; j){//打印第一关所有信息qDebug() config.mData[1][i][j];}qDebug() ;}
输出结果如下图 对应着dataConfig.cpp中第一关数据来看与之匹配成功以后我们就可以用dataConfig中的数据来对关卡进行初始化了。 5.8 初始化各个关卡
首先可以在playScene中声明一个成员变量用户记录当前关卡的二维数组。
int gameArray[4][4]; //二维数组数据 之后在.cpp文件中初始化这个二维数组 //初始化二维数组dataConfig config;for(int i 0 ; i 4;i){for(int j 0 ; j 4; j){gameArray[i][j] config.mData[this-levalIndex][i][j];}}
初始化成功后在金币类 也就是MyCoin类中扩展属性 posXposY以及flag
这三个属性分别代表了该金币在二维数组中 x的坐标y的坐标以及当前的正反标志。
int posX; //x坐标int posY; //y坐标bool flag; //正反标志
然后完成金币初始化代码如下
//金币对象QString img;if(gameArray[i][j] 1){img :/res/Coin0001.png;}else{img :/res/Coin0008.png;}MyCoin * coin new MyCoin(img);coin-setParent(this);coin-move(59 i*50,204j*50);coin-posX i; //记录x坐标coin-posY j; //记录y坐标coin-flag gameArray[i][j]; //记录正反标志
运行测试各个关卡初始化例如第一关效果如图 5.9 翻金币特效
5.9.1 MyCoin类扩展属性和行为 关卡的初始化完成后下面就应该点击金币进行翻转的效果了那么首先我们先在MyCoin类中创建出该方法。 在MyCoin.h中声明
void changeFlag();//改变标志,执行翻转效果QTimer *timer1; //正面翻反面 定时器QTimer *timer2; //反面翻正面 定时器int min 1; //最小图片int max 8; //最大图片
MyCoin.cpp中做实现
void MyCoin::changeFlag()
{if(this-flag) //如果是正面执行下列代码{timer1-start(30);this-flag false;}else //反面执行下列代码{timer2-start(30);this-flag true;}
}
当然在构造函数中记得创建出两个定时器。
//初始化定时器timer1 new QTimer(this);timer2 new QTimer(this);
5.9.2 创建特效
当我们分别启动两个定时器时需要在构造函数中做监听操作并且做出响应翻转金币然后再结束定时器。
构造函数中 进行下列监听代码 //监听正面翻转的信号槽connect(timer1,QTimer::timeout,[](){QPixmap pixmap;QString str QString(:/res/Coin000%1.png).arg(this-min);pixmap.load(str);this-setFixedSize(pixmap.width(),pixmap.height() );this-setStyleSheet(QPushButton{border:0px;});this-setIcon(pixmap);this-setIconSize(QSize(pixmap.width(),pixmap.height()));if(this-min this-max) //如果大于最大值重置最小值并停止定时器{this-min 1;timer1-stop();}});connect(timer2,QTimer::timeout,[](){QPixmap pixmap;QString str QString(:/res/Coin000%1.png).arg((this-max)-- );pixmap.load(str);this-setFixedSize(pixmap.width(),pixmap.height() );this-setStyleSheet(QPushButton{border:0px;});this-setIcon(pixmap);this-setIconSize(QSize(pixmap.width(),pixmap.height()));if(this-max this-min) //如果小于最小值重置最大值并停止定时器{this-max 8;timer2-stop();}});
5.9.3 测试
监听每个按钮的点击效果并翻转金币。
connect(coin,MyCoin::clicked,[](){//qDebug() 点击的位置 x coin-posX y coin-posY ;coin-changeFlag();gameArray[i][j] gameArray[i][j] 0 ? 1 : 0; //数组内部记录的标志同步修改}); 5.9.3 禁用按钮 此时确实已经可以执行翻转金币代码了但是如果快速点击会在金币还没有执行一个完整动作之后 又继续开始新的动画我们应该在金币做动画期间禁止再次点击并在完成动画后开启点击。 在MyCoin类中加入一个标志 isAnimation 代表是否正在做翻转动画。
bool isAnimation false; //做翻转动画的标志
在MyCoin做动画期间加入
this-isAnimation true;
也就是changeFlag函数中将标志设为true 加入位置如下 并且在做完动画时将标志改为false 重写按钮的按下事件判断如果正在执行动画那么直接return掉不要执行后续代码。 代码如下
void MyCoin::mousePressEvent(QMouseEvent *e)
{if(this-isAnimation ){return;}else{return QPushButton::mousePressEvent(e);}
}
5.10 翻周围金币
将用户点击的周围 上下左右4个金币也进行延时翻转代码写到监听点击金币下。
此时我们发现还需要记录住每个按钮的内容所以我们将所有金币按钮也放到一个二维数组中在.h中声明
MyCoin * coinBtn[4][4]; //金币按钮数组
并且记录每个按钮的位置
coinBtn[i][j] coin; 延时翻动其他周围金币 。 QTimer::singleShot(300, this,[](){if(coin-posX1 3){coinBtn[coin-posX1][coin-posY]-changeFlag();gameArray[coin-posX1][coin-posY] gameArray[coin-posX1][coin-posY] 0 ? 1 : 0;}if(coin-posX-10){coinBtn[coin-posX-1][coin-posY]-changeFlag();gameArray[coin-posX-1][coin-posY] gameArray[coin-posX-1][coin-posY] 0 ? 1 : 0;}if(coin-posY13){coinBtn[coin-posX][coin-posY1]-changeFlag();gameArray[coin-posX][coin-posY1] gameArray[coin-posX1][coin-posY] 0 ? 1 : 0;}if(coin-posY-10){coinBtn[coin-posX][coin-posY-1]-changeFlag();gameArray[coin-posX][coin-posY-1] gameArray[coin-posX1][coin-posY] 0 ? 1 : 0;}});
5.11 判断是否胜利
在MyCoin.h中加入 isWin标志代表是否胜利。
bool isWin true; //是否胜利
默认设置为true只要有一个反面的金币就将该值改为false视为未成功。
代码写到延时翻金币后 进行判断。
//判断是否胜利this-isWin true;for(int i 0 ; i 4;i){for(int j 0 ; j 4; j){//qDebug() coinBtn[i][j]-flag ;if( coinBtn[i][j]-flag false){this-isWin false;break;}}}
如果isWin依然是true代表胜利了
if(this-isWin){qDebug() 胜利;} 5.12 胜利图片显示
将胜利的图片提前创建好如果胜利触发了将图片弹下来即可
QLabel* winLabel new QLabel;QPixmap tmpPix;tmpPix.load(:/res/LevelCompletedDialogBg.png);winLabel-setGeometry(0,0,tmpPix.width(),tmpPix.height());winLabel-setPixmap(tmpPix);winLabel-setParent(this);winLabel-move( (this-width() - tmpPix.width())*0.5 , -tmpPix.height());
如果胜利了将上面的图片移动下来
if(this-isWin){qDebug() 胜利;QPropertyAnimation * animation1 new QPropertyAnimation(winLabel,geometry);animation1-setDuration(1000);animation1-setStartValue(QRect(winLabel-x(),winLabel-y(),winLabel-width(),winLabel-height()));animation1-setEndValue(QRect(winLabel-x(),winLabel-y()114,winLabel-width(),winLabel-height()));animation1-setEasingCurve(QEasingCurve::OutBounce);animation1-start();}
5.13 胜利后禁用按钮
当胜利后应该禁用所有按钮的点击状态可以在每个按钮中加入标志位 isWin如果isWin为trueMousePressEvent直接return掉即可MyCoin中.h里添加
bool isWin false;//胜利标志在鼠标按下事件中修改为
void MyCoin::mousePressEvent(QMouseEvent *e)
{if(this-isAnimation|| isWin true ){return;}else{return QPushButton::mousePressEvent(e);}
}
//禁用所有按钮点击事件for(int i 0 ; i 4;i){for(int j 0 ; j 4; j){coinBtn[i][j]-isWin true;}
}
测试胜利后不可以点击任何的金币。
6 音效添加
6.1 开始音效
QSound *startSound new QSound(:/res/TapButtonSound.wav,this);
点击开始按钮播放音效
startSound-play(); //开始音效
6.2 选择关卡音效
在选择关卡场景中添加音效。 //选择关卡按钮音效QSound *chooseSound new QSound(:/res/TapButtonSound.wav,this);
选中关卡后播放音效
chooseSound-play();
6.3 返回按钮音效
在选择关卡场景与翻金币游戏场景中分别添加返回按钮音效如下 //返回按钮音效QSound *backSound new QSound(:/res/BackButtonSound.wav,this);
分别在点击返回按钮后播放该音效 backSound-play();
6.4 翻金币与胜利音效 在PlayScene中添加翻金币的音效以及 胜利的音效
//翻金币音效QSound *flipSound new QSound(:/res/ConFlipSound.wav,this);//胜利按钮音效QSound *winSound new QSound(:/res/LevelWinSound.wav,this);
在翻金币时播放 翻金币音效
flipSound-play();
胜利时播放胜利音效
winSound-play();
测试音效使音效正常播放。
7 优化项目
当我们移动场景后如果进入下一个场景发现场景还在中心位置如果想设置场景的位置需要添加如下下图中的代码 MainScene中添加 ChooseScene中添加 测试切换三个场景的进入与返回都在同一个位置下优化成功。 至此本案例全部制作完成。