PyQt5–蛇形游戏

PyQt5–蛇形游戏

在这篇文章中,我们将看到如何使用PyQt5设计一个简单的蛇形游戏。

蛇形 游戏是一个视频游戏概念的通用名称,玩家操纵一条长度不断增长的线,线本身就是一个主要障碍。这个概念起源于1976年的街机游戏《Blockade》,由于Snake易于实现,因此在许多平台上出现了数以百计的版本(其中一些版本的标题中有蛇或虫的字样)。

实施步骤:

  1. 创建一个主窗口,为其添加状态栏,以显示分数,并创建一个board类的对象,将其作为中心部件。
  2. 创建一个名为board的类,它继承了QFrame。
  3. 在board类中创建一个定时器对象,在一定时间后调用定时器方法。
  4. 在定时器方法中调用蛇游戏的其他动作,如移动、吃的食物和蛇是否自杀。
  5. 创建一个按键事件方法,检查方向键是否被按下,并根据它来改变蛇的方向。
  6. 创建一个绘画事件方法,画出蛇和食物。
  7. 创建移动方法,根据方向移动蛇。
  8. 创建食物被吃掉的方法,检查蛇的当前位置,如果食物被吃掉,则删除当前的食物,增加蛇的长度,并在随机位置投放一个新的食物。
  9. 创建检查自杀的方法,检查蛇头的位置是否与身体的位置相似,如果匹配则停止计时器并显示信息。

下面是实现方法。

# importing libraries
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
import random
import sys
 
# creating game window
 
 
class Window(QMainWindow):
    def __init__(self):
        super(Window, self).__init__()
 
        # creating a board object
        self.board = Board(self)
 
        # creating a status bar to show result
        self.statusbar = self.statusBar()
 
        # adding border to the status bar
        self.statusbar.setStyleSheet(& quot
                                      border: 2px solid black
                                      & quot
                                      )
 
        # calling showMessage method when signal received by board
        self.board.msg2statusbar[str].connect(self.statusbar.showMessage)
 
        # adding board as a central widget
        self.setCentralWidget(self.board)
 
        # setting title to the window
        self.setWindowTitle('Snake game')
 
        # setting geometry to the window
        self.setGeometry(100, 100, 600, 400)
 
        # starting the board object
        self.board.start()
 
        # showing the main window
        self.show()
 
# creating a board class
# that inherits QFrame
 
 
class Board(QFrame):
 
    # creating signal object
    msg2statusbar = pyqtSignal(str)
 
    # speed of the snake
    # timer countdown time
    SPEED = 80
 
    # block width and height
    WIDTHINBLOCKS = 60
    HEIGHTINBLOCKS = 40
 
    # constructor
    def __init__(self, parent):
        super(Board, self).__init__(parent)
 
        # creating a timer
        self.timer = QBasicTimer()
 
        # snake
        self.snake = [[5, 10], [5, 11]]
 
        # current head x head
        self.current_x_head = self.snake[0][0]
        # current y head
        self.current_y_head = self.snake[0][1]
 
        # food list
        self.food = []
 
        # growing is false
        self.grow_snake = False
 
        # board list
        self.board = []
 
        # direction
        self.direction = 1
 
        # called drop food method
        self.drop_food()
 
        # setting focus
        self.setFocusPolicy(Qt.StrongFocus)
 
    # square width method
    def square_width(self):
        return self.contentsRect().width() / Board.WIDTHINBLOCKS
 
    # square height
    def square_height(self):
        return self.contentsRect().height() / Board.HEIGHTINBLOCKS
 
    # start method
    def start(self):
        # msg for status bar
        # score = current len - 2
        self.msg2statusbar.emit(str(len(self.snake) - 2))
 
        # starting timer
        self.timer.start(Board.SPEED, self)
 
    # paint event
    def paintEvent(self, event):
 
        # creating painter object
        painter = QPainter(self)
 
        # getting rectangle
        rect = self.contentsRect()
 
        # board top
        boardtop = rect.bottom() - Board.HEIGHTINBLOCKS * self.square_height()
 
        # drawing snake
        for pos in self.snake:
            self.draw_square(painter, rect.left() + pos[0] * self.square_width(),
                             boardtop + pos[1] * self.square_height())
 
        # drawing food
        for pos in self.food:
            self.draw_square(painter, rect.left() + pos[0] * self.square_width(),
                             boardtop + pos[1] * self.square_height())
 
    # drawing square
    def draw_square(self, painter, x, y):
        # color
        color = QColor(0x228B22)
 
        # painting rectangle
        painter.fillRect(x + 1, y + 1, self.square_width() - 2,
                         self.square_height() - 2, color)
 
    # key press event
    def keyPressEvent(self, event):
 
        # getting key pressed
        key = event.key()
 
        # if left key pressed
        if key == Qt.Key_Left:
            # if direction is not right
            if self.direction != 2:
                # set direction to left
                self.direction = 1
 
        # if right key is pressed
        elif key == Qt.Key_Right:
            # if direction is not left
            if self.direction != 1:
                # set direction to right
                self.direction = 2
 
        # if down key is pressed
        elif key == Qt.Key_Down:
            # if direction is not up
            if self.direction != 4:
                # set direction to down
                self.direction = 3
 
        # if up key is pressed
        elif key == Qt.Key_Up:
            # if direction is not down
            if self.direction != 3:
                # set direction to up
                self.direction = 4
 
    # method to move the snake
    def move_snake(self):
 
        # if direction is left change its position
        if self.direction == 1:
            self.current_x_head, self.current_y_head = self.current_x_head - 1, self.current_y_head
 
            # if it goes beyond left wall
            if self.current_x_head & lt
            0:
                self.current_x_head = Board.WIDTHINBLOCKS - 1
 
        # if direction is right change its position
        if self.direction == 2:
            self.current_x_head, self.current_y_head = self.current_x_head + 1, self.current_y_head
            # if it goes beyond right wall
            if self.current_x_head == Board.WIDTHINBLOCKS:
                self.current_x_head = 0
 
        # if direction is down change its position
        if self.direction == 3:
            self.current_x_head, self.current_y_head = self.current_x_head, self.current_y_head + 1
            # if it goes beyond down wall
            if self.current_y_head == Board.HEIGHTINBLOCKS:
                self.current_y_head = 0
 
        # if direction is up change its position
        if self.direction == 4:
            self.current_x_head, self.current_y_head = self.current_x_head, self.current_y_head - 1
            # if it goes beyond up wall
            if self.current_y_head & lt
            0:
                self.current_y_head = Board.HEIGHTINBLOCKS
 
        # changing head position
        head = [self.current_x_head, self.current_y_head]
        # inset head in snake list
        self.snake.insert(0, head)
 
        # if snake grow is False
        if not self.grow_snake:
            # pop the last element
            self.snake.pop()
 
        else:
            # show msg in status bar
            self.msg2statusbar.emit(str(len(self.snake)-2))
            # make grow_snake to false
            self.grow_snake = False
 
    # time event method
    def timerEvent(self, event):
 
        # checking timer id
        if event.timerId() == self.timer.timerId():
 
            # call move snake method
            self.move_snake()
            # call food collision method
            self.is_food_collision()
            # call is suicide method
            self.is_suicide()
            # update the window
            self.update()
 
    # method to check if snake collides itself
    def is_suicide(self):
        # traversing the snake
        for i in range(1, len(self.snake)):
            # if collision found
            if self.snake[i] == self.snake[0]:
                # show game ended msg in status bar
                self.msg2statusbar.emit(str(& quot
                                             Game Ended & quot
                                             ))
                # making background color black
                self.setStyleSheet(& quot
                                    background-color: black
                                    & quot
                                    )
                # stopping the timer
                self.timer.stop()
                # updating the window
                self.update()
 
    # method to check if the food cis collied
    def is_food_collision(self):
 
        # traversing the position of the food
        for pos in self.food:
            # if food position is similar of snake position
            if pos == self.snake[0]:
                # remove the food
                self.food.remove(pos)
                # call drop food method
                self.drop_food()
                # grow the snake
                self.grow_snake = True
 
    # method to drop food on screen
    def drop_food(self):
        # creating random co-ordinates
        x = random.randint(3, 58)
        y = random.randint(3, 38)
 
        # traversing if snake position is not equal to the
        # food position so that food do not drop on snake
        for pos in self.snake:
            # if position matches
            if pos == [x, y]:
                # call drop food method again
                self.drop_food()
 
        # append food location
        self.food.append([x, y])
 
 
# main method
if __name__ == '__main__':
    app = QApplication([])
    window = Window()
    sys.exit(app.exec_())
Python

代码解释

  1. 代码从创建一个新的类–Window开始。
  2. 这个类将是我们应用程序的主窗口。
    1. 接下来,调用 init() 方法。
    1. 在这个方法中,我们设置窗口的标题并配置其几何形状。
  3. 5.我们还调用UiComponents(),这是一个特殊的方法,它将在窗口中显示我们所有的小部件。
  4. 现在让我们来看看当我们运行这段代码时会发生什么。
  5. 首先,我们创建一个Window的实例,并将其标题设为 “Python”。
  6. 然后我们配置窗口的几何形状,将其大小设置为100×100像素,在屏幕上的位置设置为320×400像素(见图1-1)。
  7. 图 1-1: 配置了几何图形的 Python 窗口 接下来,我们调用 UiComponents() 。
  8. 这个方法将在窗口中显示我们所有的小部件(见图1-2)。
  9. 窗口对象 图 1-2: 显示所有部件的 Python 窗口 在这个例子中,我们的窗口中只有两个部件 – 文本框和按钮。
  10. 12.然而,你可以添加尽可能多的部件
  11. 代码创建了一个新的窗口,并将其标题设为 “Python”。
  12. 然后它将窗口的几何图形设置为(100, 100, 320, 400)。
  13. 最后,它在窗口对象上调用UiComponents()方法。
  14. 16.UiComponents()方法负责显示窗口中所有的小部件。
  15. 该代码首先通过调用show()来显示所有的部件。
  16. 在显示完所有的部件后,代码调用一个叫做updateWidget()的方法。
  17. 这个方法负责更新窗口中的每个部件。
  18. 代码开始创建一个QLabel对象,并将其几何形状设置为宽20、10、280像素,高60像素。
  19. 21.然后将标签的字体设置为Times New Roman,并启用粗体和斜体设置,同时启用下划线。
  20. 最后,头部的对齐方式被设置为Qt.AlignCenter。
  21. 接下来,代码创建了一个选择变量,并将其设置为0。
  22. 选择变量将存储用户在石头(0)和纸(1)之间的选择。
  23. 下一行代码创建了一个头部标签对象,并将其几何形状设置为20,10,280像素宽,60像素高。
  24. 然后,标签的字体被设置为Times New Roman,并启用粗体和斜体设置,同时禁用下划线。
  25. 最后,头部的对齐方式被设置为Qt.AlignLeftJustified。
  26. 接下来,我们使用QPushButton对象创建两个按钮。
  27. 一个按钮将用于选择石头或纸,而另一个将用于取消游戏。
  28. 我们首先创建一个名为 “rock “的QPushButton对象。
  29. 这个按钮将用于选择玩家是否要用石头玩。
  30. 该代码创建了一个QLabel对象,并将其几何形状设置为20×10像素,左上角为(280,60)像素。
  31. 然后,字体被设置为Times New Roman字体,粗体、斜体和下划线属性被设置为True。
  32. 最后,头部的对齐方式被设置为Qt.AlignCenter。
  33. 代码开始创建一个新的QGraphicsItem,它是用户界面的头部。
  34. 头部对象有一个GraphicsEffect属性,可以被设置为几种颜色效果之一。
  35. 在这个例子中,我们使用QGraphicsColorizeEffect类来改变头部对象的颜色为深青色。
  36. 接下来,我们创建一个新的QLabel对象,并将其几何尺寸设置为150 x 110像素,宽度为30像素,高度为50像素。
  37. 我们还将其字体属性设置为下划线(false)和斜体(false),这样它就不会显示任何文字。
  38. 最后,我们创建另一个名为user的QLabel对象,并将其几何尺寸设置为50 x 100像素,宽度为70像素,高度为70像素。
  39. 现在让我们看一下使用这些对象的一些代码。# 设置颜色 self.head.setGraphicsEffect(Qt.darkCyan) # 创建 vs 标签 self.vs = QLabel(“vs”, self) # 设置几何形状 self.vs.setGeometry(150, 110, 30, 50)
  40. 该代码将创建一个名为head的QGraphicsItem对象,并将图形效果设置为着色。
  41. 头部也将创建一个QLabel对象,并将其作为父对象。
  42. 标签将被赋予150 x 110像素的几何形状,宽度为30像素,高度为50像素。
  43. 接下来,标签的字体将被设置为斜体,并禁用下划线。
  44. 最后,用户的QLabel对象将被创建,尺寸与头部相同。
  45. 代码从创建一个用户界面开始。
  46. 用户界面由三个标签、一个计算机选择标签和三个按钮组成。
  47. 第一个按钮,岩石按钮,被设置为30×270像素的几何形状,边界为80像素,中心点为35像素。
    1. 第二个按钮,即纸张按钮,其几何尺寸为120×270像素,边界为80像素,中心点为35像素。
  48. 第三个按钮,即剪刀按钮,其几何尺寸为210×270像素,边界为80像素,中心点为35像素。
  49. 接下来,代码为每个按钮设置了动作。
  50. 对于 “岩石 “按钮,代码将其连接到一个动作,当它被点击时,在屏幕上打印出 “岩石”。
  51. 对于 “纸 “按钮,代码将其连接到一个动作,当它被点击时在屏幕上打印出 “纸”。
  52. 对于剪刀按钮,代码将其连接到一个动作,当它被点击时在屏幕上打印出 “剪刀”。
  53. 该代码创建了一个有三个按钮的用户界面。
  54. 第一个按钮,”岩石”,被配置为具有以下几何形状。30 x 270 x 80像素。
  55. 第二个按钮,”纸”,被配置为具有以下几何形状:120 x 270 x 80像素。
  56. 第三个按钮 “剪刀 “被配置为具有以下几何图形:210 x 270 x 80像素。
  57. 每个按钮都有一个与之相关的动作。
  58. 岩石按钮的动作与rock_action函数相连,当它被点击时将被执行。
  59. 纸张按钮的动作与paper_action函数相连,当它被点击时将被执行。
  60. 剪刀按钮的动作与sc_action函数相连,并在点击时执行。
  61. 代码从创建一个名为game_reset的QPushButton对象开始。
  62. 该按钮有以下属性: name: “game_reset” label: “重置 “图标。”ui/images/pushbutton.png” 接下来,代码使用setGeometry()设置按钮的几何形状。
  63. 坐标是(100,320,120,50)。
  64. 按钮的大小也是指定的(它将是100×32像素)。
  65. 最后,用setGraphicsEffect()给按钮添加一个颜色效果。
  66. 这个效果使用Qt的红色作为它的基础颜色。
  67. 下一步是为game_reset按钮创建一个动作处理程序。
  68. 当有人点击它时,这个处理程序将被调用。
  69. 该代码创建了一个QTimer对象,并给它附加了一个名为timeout()的动作。
  70. 这个动作将使定时器运行1000毫秒(1秒)。
  71. 在这段时间过后,showTime()函数将被执行。
  72. 这个函数只是在屏幕上显示一条信息:”定时器开始”。
  73. 该代码创建了一个名为game_reset的QPushButton,并将其几何形状设置为100 x 320像素,宽度为120像素,高度为50像素。
  74. 它还将按钮的颜色设置为红色。
  75. 接下来,代码创建了一个QGraphicsColorizeEffect对象,并将其颜色设置为Qt.red。
  76. 最后,代码为game_reset按钮添加了一个名为clicked的动作,将其连接到self.reset_action函数。
  77. 当用户点击game_reset按钮时,这个函数将被执行。
  78. 这段代码的最后一部分负责创建一个定时器对象,并为其添加一个名为timeout的动作,将其连接到self.showTime函数。
  79. 这个函数将
  80. 这段代码以初始化一些变量开始。
  81. 第一个变量是self.counter,它将跟踪石头、纸和剪刀按钮被点击的次数。
  82. 接下来,代码设置了三个按钮(石头、纸和剪刀)并定义了它们各自的动作。
  83. 当用户点击岩石按钮时,代码将self.choice设为1,并将用户标签的边框图片设为rock.png。
  84. 当用户点击paper按钮时,代码将self.choice设为2,并将用户标签的边框图片设为Paper.png。
  85. 最后,当用户点击剪刀按钮时,代码将self.choice设为3,并将用户标签的边框图像设为Scissor.png。
  86. 接下来是一些逻辑,检查谁赢得了用户之间的 “石头对布”、”石头对剪刀 “和 “布对剪刀 “的每场比赛。
  87. 如果这些比赛之一已经完成(由任何一个玩家点击这些按钮之一),那么什么也不会发生;屏幕上不会显示或以任何方式改变新的图像,因为没有必要这样做,因为两个玩家都是如此。
  88. 代码首先设置了一些变量来存储用户的选择信息。
  89. 这些变量在后面的代码中用于检查谁赢得了比赛。
  90. 接下来,代码检查是否有任何按钮被点击过。
  91. 如果有一个按钮被点击了,就会采取适当的行动。
  92. 如果没有按钮被点击,那么代码将设置三个按钮,并通过检查用户的选择变量来决定用户将选择哪一个。
  93. 一旦做出这个决定,适当的岩石图像、纸张图像或剪刀图像将被设置为用户的标签,计数器的值将减少1。

Python教程

Java教程

Web教程

数据库教程

图形图像教程

大数据教程

开发工具教程

计算机教程

登录

注册