前言
? ? 事情的起因需要從一只蝙蝠說起,那是2020年過年時,沒有攜帶所有娛樂性工具的我回到老家后,經(jīng)過麻將、電影、電視的洗禮,終于掏出來mac想學(xué)習(xí)一下c++。
? ? c++基礎(chǔ)學(xué)完后,發(fā)現(xiàn)了Qt這門語言,經(jīng)過了解是一門c++編寫的跨平臺桌面程序開發(fā)的框架,就繼續(xù)進(jìn)行學(xué)習(xí)觀看,這個demo也是Qt教學(xué)視頻中的老師最后帶著一起完成的翻金幣小游戲,日常生活中我從事的方向時J2EE方向,并不是過多的使用到學(xué)習(xí)到的東西,記錄到簡書中便于以后觀看查閱。
? ? 視頻學(xué)習(xí)網(wǎng)站:B站
? ? 視頻路徑:B站-Qt學(xué)習(xí)視頻
? ? *素材是在評論中翻找好多以后某位大哥的,很多鏈接都失效了
? ? *如有侵權(quán),請聯(lián)系我進(jìn)行刪除及修改
? ? 個人建議有興趣的同學(xué)最好還是自己來一遍,如果實在敲的過程中有問題,也可以去我Github下載成品的所有代碼。Github地址
????在學(xué)習(xí)的最后老師也提到過新加一些功能,我要立一個Flag:在閑暇的時候也會對這個成品進(jìn)行一定程度的優(yōu)化和修改。
1.代碼結(jié)構(gòu)說明
項目結(jié)構(gòu)
主窗體-mainscene
選擇關(guān)卡-chooseselevelscene
翻金幣-playscene
金幣封裝-mycoin
關(guān)卡數(shù)據(jù)封裝-dataconfig
自定義按鈕類-mypushbutton
2.難點記錄
? ? 01.跳轉(zhuǎn)設(shè)置新窗打開位置屬性
????????跳轉(zhuǎn)時設(shè)置新窗體的geometry屬性和本窗體相同,這樣設(shè)置會解決窗體移動過后,打開的新窗體和舊窗體位置不同的bug;
? ? 02.創(chuàng)建新窗體,初始化屬性
? ? ? ? //設(shè)置固定大小,并且讓窗體無法被更改
? ? ? ? setFixedSize(320, 588);
? ? ? ? //設(shè)置應(yīng)用圖標(biāo)
? ? ? ? setWindowIcon(QPixmap(":/res/Coin0001.png"));
? ? ? ? //設(shè)置窗口標(biāo)題
? ? ? ? setWindowTitle("選擇關(guān)卡");
? ? ? ? //設(shè)置菜單欄
? ? ? ? QMenuBar * qMenuBar = menuBar();
? ? ? ? QAction * qAction = qMenuBar->addMenu("開始")->addAction("退出");
? ? ? ? this->setMenuBar(qMenuBar);
? ? ? ? //點擊退出完成程序退出
? ? ? ? connect(qAction , &QAction::triggered, [=](){
? ? ? ? ? ? this->close();
? ? ? ? });
? ? 重寫窗體的畫家事件,繪制窗體的背景圖
? ? void ChooseLevelScene::paintEvent(QPaintEvent *event)? ?
? ? {
? ? ? ? //繪制背景圖
? ? ? ? QPainter qPainter(this);
? ? ? ? QPixmap qPixmap;
? ? ? ? qPixmap.load(":/res/PlayLevelSceneBg.png");
? ? ? ? //繪制背景圖
? ? ? ? qPainter.drawPixmap(0,0,this->width(),this->height(),qPixmap);
? ? ? ? //繪制左上角游戲名稱
? ? ? ? qPixmap.load(":/res/Title.png");
? ? ? ? qPainter.drawPixmap(20,30,qPixmap.width(),qPixmap.height(),qPixmap);
? ? }
03.定時器QTimer使用
? ? Qt的定時器實現(xiàn)有兩種,一個是重寫定時事件(沒使用過不清楚),另一個就是使用QTimer的靜態(tài)方法:
? ? //500是延遲多少時間執(zhí)行代碼,單位是毫秒
? ? //[=](){ ... }? ? Lamda表達(dá)式(很屌,推薦學(xué)習(xí)而且使用不難)
? ? QTimer::singleShot(500, this, [=](){
? ? ? ? //operator code
? ? });
04.事件穿透設(shè)置上下對齊居中
? ? 選擇關(guān)卡時繪制關(guān)卡是通過自定義按鈕MyPushButton進(jìn)行繪制,顯示關(guān)卡名稱是通過QLabel相同大小覆蓋在自定義按鈕上。
? ? 此時點擊時無法觸發(fā)自定義按鈕上選擇關(guān)卡后的操作,可使用鼠標(biāo)點擊事件穿透設(shè)置到QLabel上,label->setAttribute(Qt::WA_TransparentForMouseEvents);這時鼠標(biāo)點擊后QLabel不會阻攔點擊事件,可以正常觸發(fā)自定義按鈕。
? ? 在QLabel中設(shè)置text后默認(rèn)時居左,設(shè)置上下左右對齊居中,label->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
05.設(shè)置開始游戲按鈕的點擊下沉彈回的動畫
? ? //圖標(biāo)下沉
? ? void MyPushButton::zoom1()
? ? {
? ? ? ? QPropertyAnimation * animation1 = new QPropertyAnimation(this, "geometry");
? ? ? ? //設(shè)置事件間隔
? ? ? ? animation1->setDuration(200);
? ? ? ? //設(shè)置起始位置
? ? ? ? animation1->setStartValue(QRect(this->x(), this->y(), this->width(), this->height()));
? ? ? ? animation1->setEndValue(QRect(this->x(), this->y()+10, this->width(), this->height()));
? ? ? ? //設(shè)置動畫,彈跳式,類似彈性球
? ? ? ? animation1->setEasingCurve(QEasingCurve::OutBounce);
? ? ? ? animation1->start();
? ? }
? ? //圖標(biāo)上浮
? ? void MyPushButton::zoom2()
? ? {
? ? ? ? QPropertyAnimation * animation1 = new QPropertyAnimation(this, "geometry");
? ? ? ? //設(shè)置事件間隔
? ? ? ? animation1->setDuration(200);
? ? ? ? //設(shè)置起始位置
? ? ? ? animation1->setStartValue(QRect(this->x(), this->y()+10, this->width(), this->height()));
? ? ? ? animation1->setEndValue(QRect(this->x(), this->y(), this->width(), this->height()));
? ? ? ? //設(shè)置動畫,彈跳式,類似彈性球
? ? ? ? animation1->setEasingCurve(QEasingCurve::OutBounce);
? ? ? ? animation1->start();
? ? }
? ? //給start按鈕綁定點擊事件
? ? connect(btn_start, &QPushButton::clicked, [=](){
? ? ? ? btn_start->zoom1();
? ? ? ? btn_start->zoom2();
? ? ? ? //點擊音效
? ? ? ? startSound->play();
? ? ? ? //延時0.5秒執(zhí)行切換,展示start按鈕的動效
? ? ? ? QTimer::singleShot(500, this, [=](){
? ? ? ? ? ? chooseLevel->setGeometry(this->geometry());
? ? ? ? ? ? this->hide();
? ? ? ? ? ? chooseLevel->show();
? ? ? ? });
? ? });
06.繪制一個4*4的選擇關(guān)卡矩陣,不使用雙層for循環(huán)的前提下,一個for循環(huán)完成繪制
? ? //創(chuàng)建關(guān)卡選擇icon
? ? for(int i = 0; i < 20 ; i++)
? ? {
? ? ? ? MyPushButton * levelIcon = new MyPushButton(":/res/LevelIcon.png");
? ? ? ? levelIcon->setParent(this);
? ? ? ? levelIcon->move(25 + (i%4)*70 , 160 + (i/4)*70);
? ? }
* x軸:25 + (i%4)*70? ? 25為偏移量,70是每個矩陣x軸大小,i%4在第一行0、1、2、3四列,每一行計算的值是0*70、1*70、2*70、3*70;
*y軸:160 + (i/4)*70? ? 160為偏移量,70是每個矩陣y軸大小,i/4在第一列0、1、2、3四行,每一行計算的值是0*70、1*70、2*70、3*70;
*在記錄其中每一個金幣的坐標(biāo)時,構(gòu)建了新的二維數(shù)組保存位置信息,因為這種構(gòu)建不太好保存位置信息
