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

编程入门 行业动态 更新时间:2024-10-19 14:44:07

基于PyQt5的图形化界面开发——打砖块<a href=https://www.elefans.com/category/jswz/34/1769974.html style=小游戏"/>

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

目录

  • 0. 前言
  • 1. 砖块类定义
  • 2. 挡板类定义
  • 3. 碰撞检测
  • 4. 小球和游戏初始化
  • 5. 完整代码
  • 6. 运行效果演示
  • 7. Pyinstaller 编译exe程序
  • 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的图形化界面开发——队列动画演示

更多推荐

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

本文发布于:2024-02-24 14:43:14,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1695650.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:小游戏   图形化   打砖块   界面

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!