记录开发
13. 翻硬币小游戏
3. 关卡选择
首先要添加新的类,命名为 ChooseLevelScene,即关卡选择,然后新建并维护一个该对象 chooseScene;
chooseScene = new ChooseLevelScene;
,随后要隐藏原窗口,显示新窗口;
QTimer::singleShot(500, this,[=](){
this->hide();
chooseScene->show();
});
上述用到的是延时函数,原因在于代码的执行速度快,上一节中的弹跳动画还未演示完就会被隐藏;
接下来配置新窗口的一些基本信息;
ChooseLevelScene::ChooseLevelScene(QWidget *parent) : QMainWindow(parent)
{
//设置窗口基本信息;
this->setFixedSize(320, 588);
this->setWindowIcon(QPixmap(":/res/Coin0001.png"));
this->setWindowTitle("ChooseLevel");
//添加菜单栏;
QMenuBar *bar = menuBar();
setMenuBar(bar);
QMenu *startMenu = bar->addMenu("开始");
QAction *quitAction = startMenu->addAction("退出");
//关联窗口关闭;
connect(quitAction, &QAction::triggered, [=](){
this->close();
});
}
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(10, 30, pix);
}
接下来要配置带动态效果的返回按键,需要用到上一节的 MyPushButton,重载两个鼠标事件;
void MyPushButton::mousePressEvent(QMouseEvent *e)
{
if(this->pressImgPath != "") {
QPixmap pix;
bool ret = pix.load(this->pressImgPath);
if(!ret) {
qDebug() << "Error";
return;
}
this->setFixedSize(pix.width(), pix.height());
this->setStyleSheet("QPushButton{border:0px}"); //边框为 0 像素;
this->setIcon(pix);
this->setIconSize(QSize(pix.width(), pix.height()));
}
//其余交给父类;
return QPushButton::mousePressEvent(e);
}
void MyPushButton::mouseReleaseEvent(QMouseEvent *e)
{
if(this->pressImgPath != "") {
QPixmap pix;
bool ret = pix.load(this->normalImgPath);
if(!ret) {
qDebug() << "Error";
return;
}
this->setFixedSize(pix.width(), pix.height());
this->setStyleSheet("QPushButton{border:0px}"); //边框为 0 像素;
this->setIcon(pix);
this->setIconSize(QSize(pix.width(), pix.height()));
}
//其余交给父类;
return QPushButton::mouseReleaseEvent(e);
}
接下来要使得点击按钮后返回主场景,我们从主场景切换到 Level 场景是用的是 hide 函数,然后
chooseLevel->show()
,这是因为 chooseLevel 是主窗口中的一个窗口成员,所以可以调用,而 mainscene 不是 ChooseLevelScene 下的成员,所以需要借助信号来实现返回
class ChooseLevelScene : public QMainWindow
{
Q_OBJECT
public:
explicit ChooseLevelScene(QWidget *parent = nullptr);
void paintEvent(QPaintEvent *);
signals:
//自定义返回信号;
void chooseSceneBack(); //信号不需要实现;
};
//chooselevelscene.cpp
connect(backBtn, &MyPushButton::clicked, [=](){
emit this->chooseSceneBack();
});
//mainscene.cpp
connect(chooseScene, &ChooseLevelScene::chooseSceneBack, [=](){
chooseScene->hide();
this->show();
});
接着创建关卡选择按钮,步骤差不多,用的也是自建按钮,设置好位置以及 text;
//用一个循环写一个矩阵;
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 );
//监听每个按钮的点击事件,会被下方的 Label 覆盖,所以需要设置鼠标穿透;
connect(menuBtn,&MyPushButton::clicked,[=](){
QString str = QString("您选择的是第 %1 关 ").arg( i + 1);
qDebug() <<str;
});
//单独用 Label 显示数字,不规则按钮显示会出问题;
QLabel *label = new QLabel;
label->setParent(this);
label->setFixedSize(menuBtn->width(),menuBtn->height());
label->setText(QString::number(i+1));
label->move(25 + i%4 * 70 , 130 + i/4 * 70 );
//设置 label上的文字对齐方式 水平居中和 垂直居中
label->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
//设置让鼠标进行穿透 51号属性
label->setAttribute(Qt::WA_TransparentForMouseEvents);
}
4. 游戏关卡场景
所要设置的场景内容相似,就是一些背景,图标以及返回按键
class PlayScene : public QMainWindow
{
Q_OBJECT
public:
//explicit PlayScene(QWidget *parent = nullptr);
PlayScene(int levelNum);
int levelIndex; //记录所选关卡;
void paintEvent(QPaintEvent *);
signals:
void playSceneBack();
};
PlayScene::PlayScene(int levelNum)
{
//初始化游戏场景
//设置固定大小
this->setFixedSize(320,588);
//设置图标
this->setWindowIcon(QPixmap(":/res/Coin0001.png"));
//设置标题
this->setWindowTitle("FlipScene");
//创建菜单栏
QMenuBar * bar = menuBar();
setMenuBar(bar);
//创建开始菜单
QMenu * startMenu = bar->addMenu("开始");
//创建退出 菜单项
QAction * quitAction = startMenu->addAction("退出");
//点击退出 实现退出游戏
connect(quitAction,&QAction::triggered,[=](){
this->close();
});
//返回按钮;
MyPushButton *backBtn = new MyPushButton(":/res/BackButton.png", ":/res/BackButtonSelected.png");
backBtn->setParent(this);
backBtn->move(this->width() - backBtn->width(), this->height() - backBtn->height());
connect(backBtn, &MyPushButton::clicked, [=](){
emit this->playSceneBack();
});
//显示当前关卡数
QLabel * label = new QLabel;
label->setParent(this);
QFont font;
font.setFamily("华文新魏");
font.setPointSize(20);
QString str1 = QString("Level: %1").arg(this->levelIndex);
//将字体设置到标签控件中
label->setFont(font); //都是用类去做参数;
label->setText(str1);
label->setGeometry(30, this->height() - 50, 120, 50);
}
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);
}
在游戏场景里同样创建了返回按钮,加上了信号,所以在关卡选择中需要监听该信号;
//chooselevelscene.cpp
connect(play, &PlayScene::playSceneBack, [=](){
this->show();
delete play; //让旧场景完全释放;
play = NULL;
});