Python+Qt5实现flappybird

Posted 风间6324

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python+Qt5实现flappybird相关的知识,希望对你有一定的参考价值。

  算是对最近一直在看的py和Qt5 for python的一次小实战(当然离不开Siri老师的帮助1551我真是蒟蒻本弱

  先写了一个initial interface嘛,打算写完扔github上。

遇到的问题:

  1.一开始使用的是QVBoxLayout垂直布局,把QLabel放进垂直布局里,但是出现了类似于margin无法等于0的问题,始终存在外边距(当然尝试了使用QSS设置为0但无卵用),layout也有setmargin的方法但调用了提示参数error(?) 反正后来是改成了现在这样(似乎现在思路清楚但其实是BoxLayout不会用(?)QAQ

  2.一个解决游戏界面切换的思路:当前游戏界面hide,目标游戏界面show

  3.对于green bar的滚动思路

  4.对于鸟飞行状态的图片切换

  5.对于buttom两个状态的图片切换:hover,clicked

  其实花时间多的主要还是1和3

 

  •   main.py

  创建一个应用对象,sys.argv提供对脚本控制的功能

# -*- coding:utf-8 -*-
"""
@author:Kazama
@file:main.py
@time:2018/9/28 11:03
"""
import sys

from PyQt5.QtWidgets import QApplication

from MainWindow import MainWindow

if __name__ == \'__main__\':

    app = QApplication([])

    mainWindow = MainWindow()

    sys.exit(app.exec_())
  • MainWindow.py
# -*- coding:utf-8 -*-
"""
@author:Kazama
@file:MainWindow.py
@time:2018/9/28 11:13
"""
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QMainWindow, QDesktopWidget, QVBoxLayout, QLabel

from GameScene import GameScene
from MainScene import MainScene
from srcImg import srcImg


class MainWindow(QMainWindow):

    def __init__(self):
        super().__init__()

        self.srcImg = srcImg()

        self.initUI()

    def initUI(self):
        self.setWindowTitle("Flappy bird")
        self.setFixedSize(384, 512)
        self.center()#窗口居中

        # self.menuBar()
        #
        # self.statusBar()

        """
        centerLabel为什么需要?因为MainWindow只能同时设置一个CentralWidget,如果要重新setCentralWidget,
        则将会自动销毁原有的Widget
        QVBoxLayout可以不用传参:centerLabel,也就是说mainScene可以少修改一个clabel。但是用了它会出现一个边框,
        类似于margin!=0
        """
        self.centerLabel = QLabel()#建个中心标签

        self.mainScene = MainScene(self.centerLabel,self)#把MainScene画在centerLabel,MainScene类实例化
        self.mainScene.setFixedSize(384, 512)#使窗口大小固定
        self.mainScene.move(0,0)

        self.gameScene=GameScene(self.centerLabel,self)
        self.gameScene.setFixedSize(384, 512)
        self.gameScene.move(0, 0)
        self.gameScene.hide()#游戏中界面切换的思路

        self.setCentralWidget(self.centerLabel)  # 设置CentralWidget(把centerLabel放进去

        self.show()  # 展示8

    def center(self):
        qr = self.frameGeometry()
        cp = QDesktopWidget().availableGeometry().center()
        qr.moveCenter(cp)
        self.move(qr.topLeft())

    def switch2GameScene(self):
        self.mainScene.hide()
        self.gameScene.show()

    def switch2MainScene(self):
        self.mainScene.show()
        self.gameScene.hide()
  • MainScene.py
# -*- coding:utf-8 -*-
"""
@author:Kazama
@file:MainScene.py
@time:2018/9/28 11:31
"""
from PyQt5.QtCore import QBasicTimer
from PyQt5.QtGui import QPainter
from PyQt5.QtWidgets import QWidget, QLabel, QVBoxLayout, QPushButton


class MainScene(QWidget):

    # MainScene是MainWindow的一个成员,父组件ParentWindow,其实获取的是MainWindow(因为要调用父级的组件)
    # clabel对应前面传进来的centerLabel
    #父级init需要传进参数才能init
    def __init__(self,clabel,ParentWindow):
        super().__init__(clabel)

        self.parentWindow=ParentWindow
        self.timer=QBasicTimer()#控制60帧
        self.painter=QPainter()#加图片
        self.countTime=0#计数器
        self.groundPosition=0#记录grass bar的pos

        self.initUI()

    def initUI(self):

        self.btn_play=QPushButton(self)
        self.btn_play.move(35,360)
        self.btn_play.resize(140,78)
        self.btn_play.setStyleSheet(\'QPushButton{background:url(data/Picture/other/Again.png);border-radius:10px}\'\\
                                    \'QPushButton:hover{background:url(data/Picture/other/AgainHover.png);border-radius:10px}\'\\
                                    \'QPushButton:pressed{background:url(data/Picture/other/AgainPressed.png);border-radius:10px}\')
        self.btn_play.clicked.connect(self.on_btn_play_clicked)


        self.btn_rank = QPushButton(self)
        self.btn_rank.move(210, 360)
        self.btn_rank.resize(140, 78)
        self.btn_rank.setStyleSheet(\'QPushButton{background:url(data/Picture/other/Ranking.png);border-radius:10px}\'\\
                                    \'QPushButton:hover{background:url(data/Picture/other/RankingHover.png);border-radius:10px}\' \\
                                    \'QPushButton:pressed{background:url(data/Picture/other/RankingPressed.png);border-radius:10px}\')



        self.show()

    """
    paintEvent三种调用情形:1.调用show()2.窗口有变化(属性改变时)3.(前2被动调用,3主动)self.repaint和update()
    repaint会立即执行,update是向消息循环中加入绘图事件
    """
    def paintEvent(self, event):
        self.painter.begin(self)

        self.rendBackground()

        self.rendBird()

        self.painter.end()
        super().paintEvent(event)

    def rendBird(self):
        if self.countTime<15:
            self.painter.drawPixmap(175, 220, self.parentWindow.srcImg.wingCentered0)
        elif self.countTime<30:
            self.painter.drawPixmap(175, 216, self.parentWindow.srcImg.wingUp0)
        elif self.countTime<45:
            self.painter.drawPixmap(175, 220, self.parentWindow.srcImg.wingCentered0)
        else:
            self.painter.drawPixmap(175, 224, self.parentWindow.srcImg.wingDown0)

    def rendBackground(self):

        self.painter.drawPixmap(0,0,self.parentWindow.srcImg.background_dayCopyy)#白天图
        self.painter.drawPixmap( self.groundPosition, 448,self.parentWindow.srcImg.ground);
        self.painter.drawPixmap(self.groundPosition - 384, 448,self.parentWindow.srcImg.ground);

    def timerEvent(self, event):

        if event.timerId()==self.timer.timerId():
            self.countTime=self.countTime%60+1#60帧

            self.update_groundPosition()

            self.update()#手动刷新,update()是QT默认调用所有的event,然后一直循环
        else:
            super().timerEvent()

    def update_groundPosition(self):

        self.groundPosition -= 2
        if self.groundPosition <= 0:
            self.groundPosition = 384


    def show(self):
        self.timer.start(1000/60,self)#1帧=1000/60ms就是60帧
        super().show()

    def hide(self):
        self.timer.stop()
        super().hide()

    def on_btn_play_clicked(self):
        self.parentWindow.switch2GameScene()

 

 

 

  

以上是关于Python+Qt5实现flappybird的主要内容,如果未能解决你的问题,请参考以下文章

Python3.8+Qt5.0感知哈希算法实现图像检索系统

一个简单用原生js实现的小游戏----FlappyBird

原生JS实现FlappyBird游戏 超详细解析 快来做一个自己玩吧

为啥我执行 Python QT5 代码时没有显示图标和图像?

人工智能大报告(FlappyBird游戏AI训练)作业练习

开源移动小游戏项目《FlappyBird》学习心得