用python 和pyqt5写俄罗斯方块游戏

本文介绍如何利用Python的PyQt5库创建一个功能完整的俄罗斯方块游戏,详细阐述了从界面设计到游戏逻辑实现的全过程,帮助读者理解图形界面编程和游戏开发的基本原理。
摘要由CSDN通过智能技术生成
# 俄罗斯方块游戏

效果展示



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


## Tetris


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


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


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




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


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


## 开发


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


开工之前:


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


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


```python
#!/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):
        '''p
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值