基于PyQt5的图形化界面开发——打砖块

0. 前言

本文使用 PyQt5实现一个打砖块小游戏

在这里插入图片描述

操作系统:Windows10 专业版

开发环境:Pycahrm Comunity 2022.3

Python解释器版本:Python3.8

第三方库:PyQt5

1. 砖块类定义

在构造函数__init__中,Brick类接受两个参数x和y,表示砖块初始化时的位置。通过调用super().__init__来初始化QGraphicsRectItem的基类,传入参数0, 0, 40, 20来设置砖块的初始大小。然后使用setPos方法将砖块的位置设置为给定的x和y。

接下来,使用setBrush方法设置砖块的颜色为红色。QColor(150, 0, 0)表示红色,其中150表示红色通道的亮度,而0表示绿色和蓝色通道的亮度为0。

使用setFlag方法设置QGraphicsItem.ItemIsSelectable标志,表示砖块可以被选中。

destroy方法用于移除砖块。在该方法中,使用self.scene.removeItem(self)将砖块从场景中移除。

class Brick(QtWidgets.QGraphicsRectItem):def __init__(self, x, y):super(Brick, self).__init__(0, 0, 40, 20)self.setPos(x, y)self.setBrush(QtGui.QColor(150, 0, 0))self.setFlag(QtWidgets.QGraphicsItem.ItemIsSelectable, True)def destroy(self):scene.removeItem(self)

2. 挡板类定义

这段代码定义了一个名为Paddle的类,该类继承自QGraphicsRectItem,用于表示打砖块游戏中的挡板。

在函数__init__中,Paddle类使用super().__init__方法来初始化QGraphicsRectItem的基类,设置挡板的初始大小为80像素宽和10像素高。然后使用setPos方法将挡板的位置设置为(360, 540)。

接下来,使用setBrush()方法设置挡板的颜色为蓝色。QColor(0, 0, 150)表示蓝色,其中0表示红色和绿色通道的亮度为0,而150表示蓝色通道的亮度为150。

使用setFlag方法设置QGraphicsItem.ItemIsMovable标志,表示挡板可以通过鼠标拖动来移动。

moveLeft方法用于将挡板向左移动。在该方法中,首先判断当前挡板的x坐标是否大于等于10,以确保挡板不会超出左边界。如果满足条件,则使用setPos方法将挡板的x坐标减去20,实现向左移动。

moveRight方法用于将挡板向右移动。在该方法中,首先判断当前挡板的x坐标是否小于等于710,以确保挡板不会超出右边界。如果满足条件,则使用setPos方法将挡板的x坐标加上20,实现向右移动。

class Paddle(QtWidgets.QGraphicsRectItem):def __init__(self):super(Paddle, self).__init__(0, 0, 80, 10)self.setPos(360, 540)self.setBrush(QtGui.QColor(0, 0, 150))self.setFlag(QtWidgets.QGraphicsItem.ItemIsMovable, True)def moveLeft(self):if self.x() >= 10:self.setPos(self.x() - 20, self.y())def moveRight(self):if self.x() <= 710:self.setPos(self.x() + 20, self.y())

3. 碰撞检测

定义名为Ball的类,该类继承自QGraphicsEllipseItem,用于表示打砖块游戏中的小球。

在构造函数__init__中,Ball类使用super().__init__方法来初始化QGraphicsEllipseItem的基类,设置小球的初始大小为20像素直径。然后使用setPos方法将小球的位置设置为(390, 520)。

接下来,使用setBrush方法设置小球的颜色为绿色。QColor(0, 150, 0)表示绿色,其中0表示红色和蓝色通道的亮度为0,而150表示绿色通道的亮度为150。

Ball类还定义了dx和dy两个变量,分别表示小球在x轴和y轴上的速度。在构造函数中,将dx和dy初始化为-5,表示小球在水平和垂直方向上的速度为-5。

score变量用于记录游戏得分,初始值为0。

advance方法用于在每一帧更新时,更新小球的位置和状态。首先判断是否是更新阶段,如果不是,则直接返回。然后通过改变小球的位置,使用setPos方法将小球的x坐标增加dx,y坐标增加dy,实现小球的移动。

接下来,进行碰撞检测,判断小球是否与边界、挡板或砖块发生碰撞,并根据碰撞结果进行相应的处理。

class Ball(QtWidgets.QGraphicsEllipseItem):def __init__(self):super(Ball, self).__init__(0, 0, 20, 20)self.setPos(390, 520)self.setBrush(QtGui.QColor(0, 150, 0))self.dx = -5self.dy = -5self.score = 0def advance(self, phase):if not phase:returnself.setPos(self.x() + self.dx, self.y() + self.dy)# 左右边界反弹if self.x() <= 0 or self.x() >= 780:self.dx *= -1# 上边界反弹if self.y() <= 0:self.dy *= -1# 下边界游戏结束if self.y() >= 600:exit()# 触碰挡板反弹if self.collidesWithItem(paddle):self.dy *= -1# 计分数组for brick in bricks:if self.collidesWithItem(brick):brick.destroy()bricks.remove(brick)self.dy *= -1self.score += 10break

4. 小球和游戏初始化

这段代码定义了一个名为MainScene的类,它是基于QtWidgets.QGraphicsScene的子类。这个类用来创建游戏场景,并包括初始化场景大小、添加挡板、添加球、初始化砖块位置和计分面板等功能。

在初始化方法__init__中,设置了场景的大小为800x600,并声明了全局变量bricks、paddle、ball和score。然后创建了一个Paddle对象,并将其添加到场景中,接着创建了一个Ball对象,并将其也添加到场景中。

接下来使用一个循环来初始化砖块的位置,创建了20个Brick对象,并根据位置将其添加到场景中,并将这些砖块对象存储在bricks列表中。

在代码的最后,创建了一个QLabel对象score用于显示得分,并设置其位置和字体样式,然后将其添加到场景中。同时定义了一个keyPressEvent方法,用来捕捉键盘按键事件,当按下左方向键时,调用paddle对象的moveLeft方法,当按下右方向键时,调用paddle对象的moveRight方法。

在advance方法中,利用父类的advance方法来更新场景状态,同时根据当前球的得分来更新显示的得分文本。

class MainScene(QtWidgets.QGraphicsScene):def __init__(self, parent=None):super(MainScene, self).__init__(parent)self.setSceneRect(0, 0, 800, 600)global bricks, paddle, ball, scorepaddle = Paddle()self.addItem(paddle)ball = Ball()self.addItem(ball)# 初始化砖块位置bricks = []for i in range(20):brick = Brick((i % 4) * 200, (i // 4) * 40)if random.randint(0,2):self.addItem(brick)bricks.append(brick)score = QtWidgets.QLabel()# 设置得分面板位置score.move(350,580)score.setText("Score: 00  ")score.setFont(QtGui.QFont("Arial", 12, QtGui.QFont.Bold))self.addWidget(score)def keyPressEvent(self, event):# 左方向键if event.key() == QtCore.Qt.Key_Left:paddle.moveLeft()# 右方向键elif event.key() == QtCore.Qt.Key_Right:paddle.moveRight()# 计分显示def advance(self):super(MainScene, self).advance()score.setText("Score: {}  ".format(str(ball.score)))

5. 完整代码

只需要这一个文件就能运行:
main.py

from PyQt5 import QtWidgets, QtCore, QtGui
from PyQt5.QtWidgets import QApplication, QMainWindow
import sys
import randomclass Brick(QtWidgets.QGraphicsRectItem):def __init__(self, x, y):super(Brick, self).__init__(0, 0, 40, 20)self.setPos(x, y)self.setBrush(QtGui.QColor(150, 0, 0))self.setFlag(QtWidgets.QGraphicsItem.ItemIsSelectable, True)def destroy(self):scene.removeItem(self)class Paddle(QtWidgets.QGraphicsRectItem):def __init__(self):super(Paddle, self).__init__(0, 0, 80, 10)self.setPos(360, 540)self.setBrush(QtGui.QColor(0, 0, 150))self.setFlag(QtWidgets.QGraphicsItem.ItemIsMovable, True)def moveLeft(self):if self.x() >= 10:self.setPos(self.x() - 20, self.y())def moveRight(self):if self.x() <= 710:self.setPos(self.x() + 20, self.y())class Ball(QtWidgets.QGraphicsEllipseItem):def __init__(self):super(Ball, self).__init__(0, 0, 20, 20)self.setPos(390, 520)self.setBrush(QtGui.QColor(0, 150, 0))self.dx = -5self.dy = -5self.score = 0def advance(self, phase):if not phase:returnself.setPos(self.x() + self.dx, self.y() + self.dy)# 左右边界反弹if self.x() <= 0 or self.x() >= 780:self.dx *= -1# 上边界反弹if self.y() <= 0:self.dy *= -1# 下边界游戏结束if self.y() >= 600:exit()# 触碰挡板反弹if self.collidesWithItem(paddle):self.dy *= -1# 计分数组for brick in bricks:if self.collidesWithItem(brick):brick.destroy()bricks.remove(brick)self.dy *= -1self.score += 10breakclass MainScene(QtWidgets.QGraphicsScene):def __init__(self, parent=None):super(MainScene, self).__init__(parent)self.setSceneRect(0, 0, 800, 600)global bricks, paddle, ball, scorepaddle = Paddle()self.addItem(paddle)ball = Ball()self.addItem(ball)# 初始化砖块位置bricks = []for i in range(20):brick = Brick((i % 4) * 200, (i // 4) * 40)if random.randint(0,2):self.addItem(brick)bricks.append(brick)score = QtWidgets.QLabel()# 设置得分面板位置score.move(350,580)score.setText("Score: 00  ")score.setFont(QtGui.QFont("Arial", 12, QtGui.QFont.Bold))self.addWidget(score)def keyPressEvent(self, event):# 左方向键if event.key() == QtCore.Qt.Key_Left:paddle.moveLeft()# 右方向键elif event.key() == QtCore.Qt.Key_Right:paddle.moveRight()# 计分显示def advance(self):super(MainScene, self).advance()score.setText("Score: {}  ".format(str(ball.score)))if __name__ == '__main__':app = QApplication([])window = QMainWindow()window.setWindowTitle("打砖块小游戏 ——By IoT_H2")view = QtWidgets.QGraphicsView()scene = MainScene(window)view.setScene(scene)window.setCentralWidget(view)timer = QtCore.QTimer()timer.timeout.connect(scene.advance)timer.start(20)window.show()sys.exit(app.exec_())

6. 运行效果演示

由于我是使用了random库生成砖块位置,所以每一局场景都是不同的:
在这里插入图片描述

在这里插入图片描述

7. Pyinstaller 编译exe程序

在这里插入图片描述
输入这个:

Pyinstaller -F main.py

在这里插入图片描述
等待编译完成

在./dist可以找到main.exe
在这里插入图片描述
双击它就能进入打砖块小游戏啦

PyQt5

基于PyQt5的图形化界面开发——天气应用

基于PyQt5的图形化界面开发——自制MQTT客户端

基于PyQt5的图形化界面开发——Windows内存资源监视助手[附带编译exe教程]

基于PyQt5的图形化界面开发——模拟医院管理系统

基于PyQt5的图形化界面开发——自制ssh工具

基于PyQt5的图形化界面开发——PyQt示例_计算器

基于PyQt5的图形化界面开发——PyQt示例_扫雷

基于PyQt5的图形化界面开发——自制Redis图形化客户端(文末附源码)

基于PyQt5的图形化界面开发——堆栈动画演示

基于PyQt5的图形化界面开发——队列动画演示

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/22420.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

走进Linux世界【三、Linux文件与路径】

第三章 Linux文件与路径 1、文件结构 ​ Windows和Linux文件系统区别 ​ 在windows平台下&#xff0c;打开“此电脑”&#xff0c;我们可以看到盘符分区 ​ 每个驱动器都有自己的根目录结构&#xff0c;这样形成了多个树并列的情形 ​ 但是在 Linux 下&#xff0c;我们是看…

STM32 Proteus仿真ili9341 TFT2048小游戏 -0067

STM32 Proteus仿真ili9341 TFT2048小游戏 -0067 Proteus仿真小实验&#xff1a; STM32 Proteus仿真ili9341 TFT2048小游戏 -0067 功能&#xff1a; 硬件组成&#xff1a;STM32F103R6单片机 ili9341 TFT显示器上下左右方向键赢了按键输了按键 1.标准2048经典游戏玩法&#…

FFmpeg5.0源码阅读—— av_read_frame

摘要&#xff1a;本文主要描述了FFmpeg中用于打开编解码器接口av_read_frame的具体调用流程&#xff0c;详细描述了该接口被调用时所作的具体工作。   关键字&#xff1a;ffmpeg、av_read_frame   读者须知&#xff1a;读者需要了解FFmpeg的基本使用流程&#xff0c;以及一…

并不简单的代理,Dubbo是如何做服务引用的

系列文章目录 【收藏向】从用法到源码&#xff0c;一篇文章让你精通Dubbo的SPI机制 面试Dubbo &#xff0c;却问我和Springcloud有什么区别&#xff1f; 超简单&#xff0c;手把手教你搭建Dubbo工程&#xff08;内附源码&#xff09; Dubbo最核心功能——服务暴露的配置、使用…

Django实现接口自动化平台(九)环境envs序列化器及视图【持续更新中】

相关文章&#xff1a; Django实现接口自动化平台&#xff08;八&#xff09;测试报告reports序列化器及视图【持续更新中】_做测试的喵酱的博客-CSDN博客 本章是项目的一个分解&#xff0c;查看本章内容时&#xff0c;要结合整体项目代码来看&#xff1a; python django vue …

Git详解

Git详解 认识GitGit的组成三个区域二大类&#xff0c;四种状态 Git add所做的操作Git commit所做的操作分支&#xff08;branch&#xff09;标签Tag Git checkout的作用创建分支切换分支切换提交快照撤销更改 Git安装Linux版本yum源方式安装编译方式安装 Windows Git命令使用比…

【电动车】基于多目标优化遗传算法NSGAII的峰谷分时电价引导下的电动汽车充电负荷优化研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

VisualStudio2022将printf信息打印到控制台

点击“解决方案管理器”&#xff0c;选中项目名称&#xff0c;点击鼠标右键---->属性---->生成事件---->生成后事件&#xff0c;在命令行的右侧输入框里填写如下内容&#xff1a; editbin /SUBSYSTEM:CONSOLE $(OUTDIR)\$(ProjectName).exe接下来在编译运行时&#x…

机器学习-sigmoid函数和relu函数-个人解读

机器学习-sigmoid函数和relu函数-个人解读 今天博主来解读一下sigmoid函数和relu函数&#xff0c;我觉得很多同学可能都知道这两个函数是什么&#xff0c;他们干什么的&#xff0c;他们有什么用&#xff0c;但是呢&#xff1f;我想这两个常用的激活函数内在的本质&#xff0c;…

【C++】模板(函数模板与类模板)讲解

本篇文章会对C中的模板进行讲解&#xff0c;其中会对函数模板和类模板进行讲解。希望本篇文章会对你有所帮助。 文章目录 一、函数模板 1、1 模板的引入 1、2 函数模板举例讲解 1、2、1 函数模板的概念 1、2、2 函数模板格式 1、2、3 函数模板实例化 1、2、4 模板参数的匹配原则…

如何将SAP数据抽取到Azure数据湖平台?

经过多年的发展&#xff0c;SNP Glue 在全球已成为值得信赖且广为人知的解决方案&#xff0c;支持客户将其 SAP 数据与现代化的平台集成。SNP Glue 打破了数据孤岛&#xff0c;向数据科学家开放了 SAP&#xff0c;支持基于企业 SAP 数据的多个新用例。 随着时间的推移&#xff…

详解 HTTPS、TLS、SSL、HTTP区别和关系

一、什么是HTTPS、TLS、SSL HTTPS&#xff0c;也称作HTTP over TLS。TLS的前身是SSL&#xff0c;TLS 1.0通常被标示为SSL 3.1&#xff0c;TLS 1.1为SSL 3.2&#xff0c;TLS 1.2为SSL 3.3。下图描述了在TCP/IP协议栈中TLS(各子协议)和HTTP的关系。 二、HTTP和HTTPS协议的区别 …