pyqt5实现俄罗斯方块游戏

论坛 期权论坛 脚本     
niminba   2021-5-23 03:53   1048   0

本章我们要制作一个俄罗斯方块游戏。

Tetris

译注:称呼:方块是由四个小方格组成的

俄罗斯方块游戏是世界上最流行的游戏之一。是由一名叫Alexey Pajitnov的俄罗斯程序员在1985年制作的,从那时起,这个游戏就风靡了各个游戏平台。

俄罗斯方块归类为下落块迷宫游戏。游戏有7个基本形状:S、Z、T、L、反向L、直线、方块,每个形状都由4个方块组成,方块最终都会落到屏幕底部。所以玩家通过控制形状的左右位置和旋转,让每个形状都以合适的位置落下,如果有一行全部被方块填充,这行就会消失,并且得分。游戏结束的条件是有形状接触到了屏幕顶部。

方块展示:

PyQt5是专门为创建图形界面产生的,里面一些专门为制作游戏而开发的组件,所以PyQt5是能制作小游戏的。

制作电脑游戏也是提高自己编程能力的一种很好的方式。

开发

没有图片,所以就自己用绘画画出来几个图形。每个游戏里都有数学模型的,这个也是。

开工之前:

  • 用QtCore.QBasicTimer()创建一个游戏循环
  • 模型是一直下落的
  • 模型的运动是以小块为基础单位的,不是按像素
  • 从数学意义上来说,模型就是就是一串数字而已

代码由四个类组成:Tetris, Board, Tetrominoe和Shape。Tetris类创建游戏,Board是游戏主要逻辑。Tetrominoe包含了所有的砖块,Shape是所有砖块的代码。

#!/usr/bin/python3
# -*- coding: utf-8 -*-

"""
ZetCode PyQt5 tutorial 
This is a Tetris game clone.

Author: Jan Bodnar
Website: zetcode.com 
Last edited: August 2017
"""

from PyQt5.QtWidgets import QMainWindow, QFrame, QDesktopWidget, QApplication
from PyQt5.QtCore import Qt, QBasicTimer, pyqtSignal
from PyQt5.QtGui import QPainter, QColor 
import sys, random

class Tetris(QMainWindow):
  
  def __init__(self):
    super().__init__()
    
    self.initUI()
    
    
  def initUI(self):  
    '''initiates application UI'''

    self.tboard = Board(self)
    self.setCentralWidget(self.tboard)

    self.statusbar = self.statusBar()    
    self.tboard.msg2Statusbar[str].connect(self.statusbar.showMessage)
    
    self.tboard.start()
    
    self.resize(180, 380)
    self.center()
    self.setWindowTitle('Tetris')    
    self.show()
    

  def center(self):
    '''centers the window on the screen'''
    
    screen = QDesktopWidget().screenGeometry()
    size = self.geometry()
    self.move((screen.width()-size.width())/2, 
      (screen.height()-size.height())/2)
    

class Board(QFrame):
  
  msg2Statusbar = pyqtSignal(str)
  
  BoardWidth = 10
  BoardHeight = 22
  Speed = 300

  def __init__(self, parent):
    super().__init__(parent)
    
    self.initBoard()
    
    
  def initBoard(self):   
    '''initiates board'''

    self.timer = QBasicTimer()
    self.isWaitingAfterLine = False
    
    self.curX = 0
    self.curY = 0
    self.numLinesRemoved = 0
    self.board = []

    self.setFocusPolicy(Qt.StrongFocus)
    self.isStarted = False
    self.isPaused = False
    self.clearBoard()
    
    
  def shapeAt(self, x, y):
    '''determines shape at the board position'''
    
    return self.board[(y * Board.BoardWidth) + x]

    
  def setShapeAt(self, x, y, shape):
    '''sets a shape at the board'''
    
    self.board[(y * Board.BoardWidth) + x] = shape
    

  def squareWidth(self):
    '''returns the width of one square'''
    
    return self.contentsRect().width() // Board.BoardWidth
    

  def squareHeight(self):
    '''returns the height of one square'''
    
    return self.contentsRect().height() // Board.BoardHeight
    

  def start(self):
    '''starts game'''
    
    if self.isPaused:
      return

    self.isStarted = True
    self.isWaitingAfterLine = False
    self.numLinesRemoved = 0
    self.clearBoard()

    self.msg2Statusbar.emit(str(self.numLinesRemoved))

    self.newPiece()
    self.timer.start(Board.Speed, self)

    
  def pause(self):
    '''pauses game'''
    
    if not self.isStarted:
      return

    self.isPaused = not self.isPaused
    
    if self.isPaused:
      self.timer.stop()
      self.msg2Statusbar.emit("paused")
      
    else:
      self.timer.start(Board.Speed, self)
      self.msg2Statusbar.emit(str(self.numLinesRemoved))

    self.update()

    
  def paintEvent(self, event):
    '''paints all shapes of the game'''
    
    painter = QPainter(self)
    rect = self.contentsRect()

    boardTop = rect.bottom() - Board.BoardHeight * self.squareHeight()

    for i in range(Board.BoardHeight):
      for j in range(Board.BoardWidth):
        shape = self.shapeAt(j, Board.BoardHeight - i - 1)
        
        if shape != Tetrominoe.NoShape:
          self.drawSquare(painter,
            rect.left() + j * self.squareWidth(),
            boardTop + i * self.squareHeight(), shape)

    if self.curPiece.shape() != Tetrominoe.NoShapevC&#4(4)ɑХt4(v"oZjCVgVRvZ_jvC4(vC?n4(4(е聍顽啙4(vjn>*"GnBvC?SjZ_n>?4(4)х1С4(MMM4(4(4(йMM4(4(Ф4(й4(й4(4(4(1РBG>^/Z_ZjZ_^/3n:jbZjg^/jvC4(/h4(е聍顽4(е聱brZj3ro疒j惚r'&*rokkR2
分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:1060120
帖子:212021
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP