zoukankan      html  css  js  c++  java
  • 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()

      

  • 相关阅读:
    Pikachu漏洞练习平台实验——SQL注入(四)
    ELMO,BERT和GPT简介
    Self-Attention 和 Transformer
    Seq2Seq和Attention机制入门介绍
    循环神经网络(RNN)入门介绍
    XGBoost的推导和说明
    在Azure DevOps Server中运行基于Spring Boot和Consul的微服务项目单元测试
    Azure DevOps Server(TFS) 客户端分析
    传统码头建设企业:Azure DevOps Server 流水线技术沟通
    ItelliJ Idea 2019提交TFVC变更,系统提示Validation must be performed before checking in
  • 原文地址:https://www.cnblogs.com/kazama/p/9721385.html
Copyright © 2011-2022 走看看