导读:本文我们要制作一个俄罗斯方块游戏。
01 俄罗斯方块 Tetris
俄罗斯方块游戏是世界上最流行的游戏之一。是由一名叫Alexey Pajitnov的俄罗斯程序员在1985年制作的,从那时起,这个游戏就风靡了各个游戏平台。
俄罗斯方块归类为下落块迷宫游戏。游戏有7个基本形状:S、Z、T、L、反向L、直线、方块,每个形状都由4个方块组成,方块最终都会落到屏幕底部。所以玩家通过控制形状的左右位置和旋转,让每个形状都以合适的位置落下,如果有一行全部被方块填充,这行就会消失,并且得分。游戏结束的条件是有形状接触到了屏幕顶部。
方块展示:
PyQt5是专门为创建图形界面产生的,里面一些专门为制作游戏而开发的组件,所以PyQt5是能制作小游戏的。
制作电脑游戏也是提高自己编程能力的一种很好的方式。
02 开发
没有图片,所以就自己用绘画画出来几个图形。每个游戏里都有数学模型的,这个也是。
开工之前:
-
用
QtCore.QBasicTimer()
QtCore.QBasicTimer()创建一个游戏循环 -
模型是一直下落的
-
模型的运动是以小块为基础单位的,不是按像素
-
从数学意义上来说,模型就是就是一串数字而已
代码由四个类组成:Tetris, Board, Tetrominoe和Shape。Tetris类创建游戏,Board是游戏主要逻辑。Tetrominoe包含了所有的砖块,Shape是所有砖块的代码。
1#!/usr/bin/python3
2# -*- coding: utf-8 -*-
3
4"""
5ZetCode PyQt5 tutorial
6This is a Tetris game clone.
7
8Author: Jan Bodnar
9Website: zetcode.com
10Last edited: August 2017
11"""
12
13from PyQt5.QtWidgets import QMainWindow, QFrame, QDesktopWidget, QApplication
14from PyQt5.QtCore import Qt, QBasicTimer, pyqtSignal
15from PyQt5.QtGui import QPainter, QColor
16import sys, random
17
18class Tetris(QMainWindow):
19
20 def __init__(self):
21 super().__init__()
22
23 self.initUI()
24
25
26 def initUI(self):
27 '''initiates application UI'''
28
29 self.tboard = Board(self)
30 self.setCentralWidget(self.tboard)
31
32 self.statusbar = self.statusBar()
33 self.tboard.msg2Statusbar[str].connect(self.statusbar.showMessage)
34
35 self.tboard.start()
36
37 self.resize(180, 380)
38 self.center()
39 self.setWindowTitle('Tetris')
40 self.show()
41
42
43 def center(self):
44 '''centers the window on the screen'''
45
46 screen = QDesktopWidget().screenGeometry()
47 size = self.geometry()
48 self.move((screen.width()-size.width())/2,
49 (screen.height()-size.height())/2)
50
51
52class Board(QFrame):
53
54 msg2Statusbar = pyqtSignal(str)
55
56 BoardWidth = 10
57 BoardHeight = 22
58 Speed = 300
59
60 def __init__(self, parent):
61 super().__init__(parent)
62
63 self.initBoard()
64
65
66 def initBoard(self):
67 '''initiates board'''
68
69 self.timer = QBasicTimer()
70 self.isWaitingAfterLine = False
71
72 self.curX = 0
73 self.curY = 0
74 self.numLinesRemoved = 0
75 self.board = []
76
77 self.setFocusPolicy(Qt.StrongFocus)
78 self.isStarted = False
79 self.isPaused = False
80 self.clearBoard()
81
82
83 def shapeAt(self, x, y):
84 '''determines shape at the board position'''
85
86 return self.board[(y * Board.BoardWidth) + x]
87
88
89 def setShapeAt(self, x, y, shape):
90 '''sets a shape at the board'''
91
92 self.board[(y * Board.BoardWidth) + x] = shape
93
94
95 def squareWidth(self):
96 '''returns the width of one square'''
97
98 return self.contentsRect().width() // Board.BoardWidth
99
100
101 def squareHeight(self):
102 '''returns the height of one square'''
103
104 return self.contentsRect().height() // Board.BoardHeight
105
106
107 def start(self):
108 '''starts game'''
109
110 if self.isPaused:
111 return
112
113 self.isStarted = True
114 self.isWaitingAfterLine = False
115 self.numLinesRemoved = 0
116 self.clearBoard()
117
118 self.msg2Statusbar.emit(str(self.numLinesRemoved))
119
120 self.newPiece()
121 self.timer.start(Board.Speed, self)
122
123
124 def pause(self):
125 '''pauses game'''
126
127 if not self.isStarted:
128 return
129
130 self.isPaused = not self.isPaused
131
132 if self.isPaused:
133 self.timer.stop()
134 self.msg2Statusbar.emit("paused")
135
136 else:
137 self.timer.start(Board.Speed, self)
138 self.msg2Statusbar.emit(str(self.numLinesRemoved))
139
140 self.update()
141
142
143 def paintEvent(self, event):
144 '&#