Qt实例--翻金币

1、项目简介

        制作简易翻金币小游戏

2、创建项目并添加项目资源

        2.1 创建项目

-》选择“Qt Widget Application”-》确定项目名称(MainSence)及位置-》选择相应的基类(QMainWindow)以类名。

         2.2 添加项目资源

 -》(先添加前缀,再添加文件,最后保存。)

3、项目的基本配置

        3.1设置背景图标

//设置图标
	setWindowIcon(QIcon(":/res/Coin0001.png"));

        3.2设置固定大小

//设置固定大小
	setFixedSize(320, 588);

         3.3 设置项目标题

setWindowTitle("翻金币主场景");

        3.4 设置背景及背景标题

        重载QPaintEvent事件

void MainScene::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(20,40,pix);
}

        3.5 创建开始菜单以退出功能

        在.ui文件中创建开始菜单,并设置退出功能(actionquit)

//退出按钮实现
	connect(ui.actionquit, &QAction::triggered, [=]() {
		this->close();
		});

  4、构造MyPushButton按钮

        提供MyPushButton的构造的重载版本,可以让MyPushButton提供正常的图片以及按下后显示的图片

右键项目-》添加-》新建项-》Qt Class类

MyPushButton.h

//重写构造函数 参数1:正常显示的图片路径 ,参数2:按下后显示的图片路径
	MyPushButton(QString normalImg, QString pressImg = "");
	//成员属性 保存用户传入的默认显示路径以及按下后显示的图片路径
	QString normalImgPath;
	QString pressImgPath;

MyPushButton.cpp

MyPushButton::MyPushButton(QString normalImg, QString pressImg)
{
	this->normalImgPath = normalImg;
	this->pressImgPath = pressImg;
	QPixmap pix;
	bool ret = pix.load(normalImg);
	if (!ret)
	{
		qDebug() << "图片加载失败";
		return;
	}
	//设置图片固定大小
	this->setFixedSize(pix.width(), pix.height());
	//设置不规则图片样式
	this->setStyleSheet("QPushButton{border:0px}");
	//设置图标
	this->setIcon(pix);
	//设置图标大小
	this->setIconSize(QSize(pix.width(), pix.height()));
}

        zoom1和zoom2为MyPushButton的特效

zoom1与zoom2代码相似,更改起始位置

void MyPushButton::zoom1()//向下跳
{
	//创建动态对象
	QPropertyAnimation * animation = new QPropertyAnimation(this, "geometry");
	//设置动画间隔
	animation->setDuration(200);
	//起始位置
	animation->setStartValue(QRect(this->x(), this->y(), this->width(), this->height()));
	//结束位置
	animation->setStartValue(QRect(this->x(), this->y()+10, this->width(), this->height()));
	//设置弹跳曲线
	animation->setEasingCurve(QEasingCurve::OutBounce);
	//执行动画
	animation->start();
}

5、选择关卡场景基本配置

创建选择关卡场景(Qt Widget Class),基类为(QMainWindow),同主窗口配置相似

.cpp

ChooseLevelScence::ChooseLevelScence(QWidget *parent)
	: QMainWindow(parent)
{
	ui.setupUi(this);
	//设置固定大小
	setFixedSize(320, 588);
	//设置图标
	setWindowIcon(QIcon(":/res/Coin0001.png"));
	setWindowTitle("选择关卡场景");
	//退出按钮实现
	connect(ui.actionquit, &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, [=]() {
		
		});
}
void ChooseLevelScence::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(20, 40, pix);
}

6、选择关卡的返回按钮特效制作

           6.1 点击后切换另一个图片

  重载mousePressEvent、mouseReleaseEvent事件

void MyPushButton::mousePressEvent(QMouseEvent* e)
{
	if (this->pressImgPath != "")//传入的按下图片不为空 说明需要有按下状态 切换图片
	{
		QPixmap pix;
		bool ret = pix.load(this->pressImgPath);
		if (!ret)
		{
			qDebug() << "图片加载失败";
			return;
		}
		//设置图片固定大小
		this->setFixedSize(pix.width(), pix.height());
		//设置不规则图片样式
		this->setStyleSheet("QPushButton{border:0px}");
		//设置图标
		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() << "图片加载失败";
			return;
		}
		//设置图片固定大小
		this->setFixedSize(pix.width(), pix.height());
		//设置不规则图片样式
		this->setStyleSheet("QPushButton{border:0px}");
		//设置图标
		this->setIcon(pix);
		//设置图标大小
		this->setIconSize(QSize(pix.width(), pix.height()));
	}
	//让父亲执行其他内容
	return QPushButton::mouseReleaseEvent(e);
}

        6.2 功能实现(点击返回按钮,返回主窗口)

.h

signals:
	//写一个自定义信号,告诉主场景 点击了返回
	void chooseSceneBack();

.cpp

//点击返回
	connect(backBtn, &MyPushButton::clicked, [=]() {
		//告诉主场景 我返回了,主场景监听信号
		emit this->chooseSceneBack();
		});

        6.3 选择关卡按钮创建

//创建选择关卡的按钮
	for (int i = 0; i < 20; i++)
	{
		MyPushButton* memuBtn = new MyPushButton(":/res/LevelIcon.png");
		memuBtn->setParent(this);
		memuBtn->move(25 + i % 4 * 70, 130 + i / 4 * 70);

		QLabel* label = new QLabel(this);
		label->setFixedSize(memuBtn->width(), memuBtn->height());
		label->setText(QString::number(1 + i));
		label->move(25 + i % 4 * 70, 130 + i / 4 * 70);
		//设置label上的文字对齐方式(水平居中和垂直居中)
		label->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
		//设置让鼠标穿透事件
		label->setAttribute(Qt::WA_TransparentForMouseEvents);
	}

   7、创建翻金币场景

        点击关卡按钮后,会进入游戏的核心场景,也就是翻金币的场景,首先创建出该场景的.h和.cpp文件

创建PlayScence:右键项目-》添加-》新建项-》Qt Class类

        7.1 重写PlayScene的构造函数

Playscene::Playscene(int levelNum)
{
	this->levelIndex = levelNum;
	//初始化游戏场景
	//设置固定大小
	setFixedSize(320, 588);
	//设置图标
	setWindowIcon(QIcon(":/res/Coin0001.png"));
	setWindowTitle("游戏场景");
	//创建菜单栏
	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(this);
	QFont font;
	font.setFamily("华文新魏");
	font.setPointSize(20);
	QString str = QString("Level:%1").arg(this->levelIndex);
	//将字体设置到标签控件中
	label->setFont(font);
	label->setText(str);
	label->setGeometry(30, this->height() - 50, 120, 50);
//显示金币背景图案
	for (int i = 0; i < 4; i++)
	{
		for (int j = 0; j < 4; j++)
		{
			//绘制背景图片
			QLabel* label = new QLabel(this);
			label->setGeometry(0, 0, 50, 50);
			label->setPixmap(QPixmap(":/res/BoardNode.png"));
			label->move(57 + i * 50, 200 + j * 50);
		}
	}
}

重写绘图事件与主窗口类似.

        7.2 创建金币类(MyCoin)

MyCoin::MyCoin(QString btnImg)
{
	QPixmap pix;
	bool ret = pix.load(btnImg);
	if (!ret)
	{
		QString str = QString("图片%1加载失败").arg(btnImg);
		qDebug() << str;
		return;
	}
	//设置图片固定大小
	this->setFixedSize(pix.width(), pix.height());
	//设置不规则图片样式
	this->setStyleSheet("QPushButton{border:0px}");
	//设置图标
	this->setIcon(pix);
	//设置图标大小
	this->setIconSize(QSize(pix.width(), pix.height()));
}

        7.2.1 在游戏窗口中显示金币

//创建金币
			MyCoin* coin = new MyCoin(":/res/Coin0001.png");
			coin->setParent(this);
			coin->move(59 + i * 50, 204 + j * 50);

        7.2.2 进入关卡数据

添加现有文件dataconfig.cpp,dataconfig.h

初始化各个关卡:

        (1)在playScence中声明一个成员变量,记录当前关卡的二维数据

int gameArray[4][4];//二维数组 维护每个关卡的具体数据

        (2)初始化每个关卡的二维数组

//初始化每个关卡的二维数组
	for (int i = 0; i < 4; i++)
	{
		for (int j = 0; j < 4; j++)
		{
			this->gameArray[i][j] = config.mData[this->levelIndex][i][j];
		}
	}

        (3)金币翻转特效实现

        添加金币属性,定位金币的位置

//金币的属性
	int posX;//x坐标位置
	int posY;//y坐标位置
	bool flag;//正反标志
//给金币属性赋值
			coin->posX = i;
			coin->posY = j;
			coin->flag = this->gameArray[i][j];//1正面,0反面

        单个金币翻转实现:

在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);
	//监听正面翻反面的信号,并且反转金币
	connect(timer1, &QTimer::timeout, [=]() {
		QPixmap pix;
		QString str = QString(":/res/Coin000%1").arg(this->min++);
		pix.load(str);
		//设置图片固定大小
		this->setFixedSize(pix.width(), pix.height());
		//设置不规则图片样式
		this->setStyleSheet("QPushButton{border:0px}");
		//设置图标
		this->setIcon(pix);
		//设置图标大小
		this->setIconSize(QSize(pix.width(), pix.height()));
		//判断 如果翻完了,将min重置为1
		if (this->min > this->max)
		{
			this->min = 1;
			timer1->stop();
		}
		});
	//监听反面翻正面的信号,并且反转金币
	connect(timer2, &QTimer::timeout, [=]() {
		QPixmap pix;
		QString str = QString(":/res/Coin000%1").arg(this->max--);
		pix.load(str);
		//设置图片固定大小
		this->setFixedSize(pix.width(), pix.height());
		//设置不规则图片样式
		this->setStyleSheet("QPushButton{border:0px}");
		//设置图标
		this->setIcon(pix);
		//设置图标大小
		this->setIconSize(QSize(pix.width(), pix.height()));
		//判断 如果翻完了,将min重置为1
		if (this->max< this->min)
		{
			this->max = 8;
			timer2->stop();
		}
		});

        周围金币翻转实现:

//将金币放到金币的二维数组里 以便于后期的维护
			coinBtn[i][j] = coin;
			//点击金币翻转
			connect(coin, &MyCoin::clicked, [=]() {
				coin->changeFlag();
				this->gameArray[i][j] == this->gameArray[i][j] == 0 ? 1 : 0;
				//翻转周围金币
				//右侧金币的翻转
				if (coin->posX + 1 <= 3)
				{
					coinBtn[coin->posX + 1][coin->posY]->changeFlag();
					this->gameArray[coin->posX + 1][coin->posY] == this->gameArray[i][j] == 0 ? 1 : 0;
				}
				//左侧金币翻转
				if (coin->posX- 1  >= 0)
				{
					coinBtn[coin->posX - 1][coin->posY]->changeFlag();
					this->gameArray[coin->posX - 1][coin->posY] == this->gameArray[i][j] == 0 ? 1 : 0;
				}
				//上侧金币翻转
				if (coin->posY + 1 <= 3)
				{
					coinBtn[coin->posX ][coin->posY+1]->changeFlag();
					this->gameArray[coin->posX ][coin->posY+1] == this->gameArray[i][j] == 0 ? 1 : 0;
				}
				//下侧金币翻转
				if (coin->posY - 1 >= 0)
				{
					coinBtn[coin->posX][coin->posY - 1]->changeFlag();
					this->gameArray[coin->posX][coin->posY - 1] == this->gameArray[i][j] == 0 ? 1 : 0;
				}
				});

        判断胜利

在MyCoin.h中加入isWin标志,代表是否胜利

//判断是否胜利
				this->isWin = true;
				for (int i = 0; i < 4; i++)
				{
					for (int j = 0; j < 4; j++)
					{
						if (coinBtn[i][j]->flag == false)
						{
							this->isWin = false;
							break;
						}
					}
				}
				if (this->isWin == true)
				{
					//将所有按钮的胜利标志改为true
					for (int i = 0; i < 4; i++)
					{
						for (int j = 0; j < 4; j++)
						{	
							coinBtn[i][j]->isWin = true;
						}
					}

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值