pyQt4实现俄罗斯方块游戏
本文实例为大家分享了pyQt4实现俄罗斯方块游戏的具体代码,供大家参考,具体内容如下
#!/usr/bin/python
#-*-coding:utf-8-*-
importsys,random
fromPyQt4importQtCore,QtGui
classTetris(QtGui.QMainWindow):
#Tetris的构造函数,由于是QMainWindow的子类,所以要先调用父类的构造函数
def__init__(self):
super(Tetris,self).__init__()
#QtGui.QMainWindow.__init__(self)
self.initUI()
definitUI(self):
self.tboard=Board(self)#创建一个Board类的实例
self.setCentralWidget(self.tboard)#将游戏窗口放到屏幕的中间
self.statusbar=self.statusBar()#创建状态栏
self.tboard.msg2Statusbar[str].connect(self.statusbar.showMessage)#3种可能的信息:1.score2.gameover3.pause
self.tboard.start()#开始初始化程序
self.resize(180,380)#游戏窗口的大小
#self.resize(480,380)#游戏窗口的大小
self.center()
self.setWindowTitle('Tetris')#窗口的名字
self.show()#这句一定不能忘了,显示窗口
defcenter(self):
#将游戏窗口放到屏幕的中间
screen=QtGui.QDesktopWidget().screenGeometry()
size=self.geometry()
self.move((screen.width()-size.width())/2,
(screen.height()-size.height())/2)
classBoard(QtGui.QFrame):
msg2Statusbar=QtCore.pyqtSignal(str)
#游戏窗口的宽和高(单位为块)
BoardWidth=10#宽度为10块
BoardHeight=22#高度为22块
Speed=300#游戏的速度
def__init__(self,parent):
super(Board,self).__init__(parent)
self.initBoard()
definitBoard(self):
'''''
初始化一些关键的变量
'''
self.timer=QtCore.QBasicTimer()#创建一个定时器
self.isWaitingAfterLine=False
self.curX=0
self.curY=0
self.numLinesRemoved=0
#alistofnumbersfrom0-7.
#Itrepresentsthepositionofvariousshapesandremainsoftheshapesontheboard.
self.board=[]
self.setFocusPolicy(QtCore.Qt.StrongFocus)
self.isStarted=False
self.isPaused=False
self.clearBoard()
#determinethetypeofashapeatagivenblock.
#返回(x,y)坐标处对应的点的类型
defshapeAt(self,x,y):
returnself.board[(y*Board.BoardWidth)+x]
#设置(x,y)坐标处对应的点的类型
defsetShapeAt(self,x,y,shape):
self.board[(y*Board.BoardWidth)+x]=shape
#calculatethewidthofthesinglesquareinpixelsandreturnit
#TheBoard.BoardWidthisthesizeoftheboardinblocks
defsquareWidth(self):
returnself.contentsRect().width()/Board.BoardWidth
defsquareHeight(self):
returnself.contentsRect().height()/Board.BoardHeight
defstart(self):
ifself.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)
defpause(self):
ifnotself.isStarted:
return
self.isPaused=notself.isPaused
ifself.isPaused:
self.timer.stop()
self.msg2Statusbar.emit("paused")
else:
self.timer.start(Board.Speed,self)
self.msg2Statusbar.emit(str(self.numLinesRemoved))
self.update()
defpaintEvent(self,event):
painter=QtGui.QPainter(self)
rect=self.contentsRect()
boardTop=rect.bottom()-Board.BoardHeight*self.squareHeight()
foriinrange(Board.BoardHeight):
forjinrange(Board.BoardWidth):
shape=self.shapeAt(j,Board.BoardHeight-i-1)
ifshape!=Tetrominoe.NoShape:
self.drawSquare(painter,
rect.left()+j*self.squareWidth(),
boardTop+i*self.squareHeight(),shape)
ifself.curPiece.shape()!=Tetrominoe.NoShape:
foriinrange(4):
x=self.curX+self.curPiece.x(i)
y=self.curY-self.curPiece.y(i)
self.drawSquare(painter,rect.left()+x*self.squareWidth(),
boardTop+(Board.BoardHeight-y-1)*self.squareHeight(),
self.curPiece.shape())
#按键相应函数
defkeyPressEvent(self,event):
#如果游戏没有开始(暂停)或者curPiece为空(游戏结束),响应父窗口的按键事件,返回
ifnotself.isStartedorself.curPiece.shape()==Tetrominoe.NoShape:
super(Board,self).keyPressEvent(event)
return
key=event.key()#捕获按键
ifkey==QtCore.Qt.Key_P:#如果按键为P,暂停或者重新继续
self.pause()
return
ifself.isPaused:#暂停时不响应按键
return
elifkey==QtCore.Qt.Key_Left:#如果按下了左箭头会尝试向左移动(也有可能移动不了)
self.tryMove(self.curPiece,self.curX-1,self.curY)
elifkey==QtCore.Qt.Key_Right:
self.tryMove(self.curPiece,self.curX+1,self.curY)
elifkey==QtCore.Qt.Key_Down:#按下下箭头,向右旋转
self.tryMove(self.curPiece.rotateRight(),self.curX,self.curY)
elifkey==QtCore.Qt.Key_Up:#按下上箭头,向左旋转
self.tryMove(self.curPiece.rotateLeft(),self.curX,self.curY)
elifkey==QtCore.Qt.Key_Space:#按下空格键,直接掉到底部
self.dropDown()
elifkey==QtCore.Qt.Key_D:
self.oneLineDown()
else:
super(Board,self).keyPressEvent(event)
deftimerEvent(self,event):
'''''
weeithercreateanewpiece,afterthepreviousonewasdroppedtothebottom,
orwemoveafallingpieceonelinedown.
'''
ifevent.timerId()==self.timer.timerId():
ifself.isWaitingAfterLine:
self.isWaitingAfterLine=False
self.newPiece()
else:
self.oneLineDown()
else:
super(Board,self).timerEvent(event)
defclearBoard(self):
#清除board,全部设置为NoShape
foriinrange(Board.BoardHeight*Board.BoardWidth):
self.board.append(Tetrominoe.NoShape)
defdropDown(self):
newY=self.curY
whilenewY>0:
#使curPiece一直沿着y减小的方向移动,直到不能移动或者到达底部为止
ifnotself.tryMove(self.curPiece,self.curX,newY-1):
break
newY-=1#自减1
self.pieceDropped()
defoneLineDown(self):
ifnotself.tryMove(self.curPiece,self.curX,self.curY-1):
self.pieceDropped()
#到达底部的时候
defpieceDropped(self):
foriinrange(4):
x=self.curX+self.curPiece.x(i)
y=self.curY-self.curPiece.y(i)
self.setShapeAt(x,y,self.curPiece.shape())
self.removeFullLines()#清除排满的行
ifnotself.isWaitingAfterLine:#如果不是在暂停,开始新的块
self.newPiece()
defremoveFullLines(self):
'''''
Ifthepiecehitsthebottom,wecalltheremoveFullLines()method.
Wefindoutallfulllinesandremovethem.
Wedoitbymovingalllinesabovethecurrentfulllinetoberemovedonelinedown.
Noticethatwereversetheorderofthelinestoberemoved.
Otherwise,itwouldnotworkcorrectly.
Inourcaseweuseanaivegravity.Thismeans,thatthepiecesmaybefloatingaboveemptygaps.
'''
numFullLines=0
rowsToRemove=[]
foriinrange(Board.BoardHeight):
n=0#n记录每行shape的个数
forjinrange(Board.BoardWidth):
ifnotself.shapeAt(j,i)==Tetrominoe.NoShape:
n=n+1
#如果n等于10,将行号加入要删除的队列
ifn==10:
rowsToRemove.append(i)
rowsToRemove.reverse()#行号队列反置
forminrowsToRemove:
#从m行以上的shape均下移一行
forkinrange(m,Board.BoardHeight):
forlinrange(Board.BoardWidth):
self.setShapeAt(l,k,self.shapeAt(l,k+1))
numFullLines=numFullLines+len(rowsToRemove)#统计消除的行数
ifnumFullLines>0:
self.numLinesRemoved=self.numLinesRemoved+numFullLines
self.msg2Statusbar.emit(str(self.numLinesRemoved))
self.isWaitingAfterLine=True
self.curPiece.setShape(Tetrominoe.NoShape)
self.update()
defnewPiece(self):
'''''
ThenewPiece()methodcreatesrandomlyanewtetrispiece.
Ifthepiececannotgointoitsinitialposition,thegameisover.
随机地创建一个方块。如果方块不能在它起始的位置,游戏结束。
'''
self.curPiece=Shape()#当前块
self.curPiece.setRandomShape()#随机设置
self.curX=Board.BoardWidth/2+1#currentX位置在中心
self.curY=Board.BoardHeight-1+self.curPiece.minY()
#将self.curPiece移动到当前的坐标处,如果不能移动,游戏结束。
#curPiece置为空,timer停止,显示消息'gameover'
ifnotself.tryMove(self.curPiece,self.curX,self.curY):
self.curPiece.setShape(Tetrominoe.NoShape)
self.timer.stop()
self.isStarted=False
self.msg2Statusbar.emit("Gameover")
deftryMove(self,newPiece,newX,newY):
'''''
如果theshapeisattheedgeoftheboard或者isadjacenttosomeotherpiece,返回False
否则的话,变动位置并返回True
'''
foriinrange(4):
x=newX+newPiece.x(i)
y=newY-newPiece.y(i)
'''''
如果x<0说明已经到了左边缘;如果x>=Board.BoardWidth,说明已经到了右边缘
如果y<0说明已经到了底部;如果x>=Board.BoardHeight,说明已经到了最顶部
以上情况均不能移动,返回False
'''
ifx<0orx>=Board.BoardWidthory<0ory>=Board.BoardHeight:
returnFalse
#如果当前的位置不为空,返回False
ifself.shapeAt(x,y)!=Tetrominoe.NoShape:
returnFalse
self.curPiece=newPiece
self.curX=newX#现在的坐标变为新坐标
self.curY=newY
self.update()#frame更新
returnTrue
defdrawSquare(self,painter,x,y,shape):
colorTable=[0x000000,0xCC6666,0x66CC66,0x6666CC,
0xCCCC66,0xCC66CC,0x66CCCC,0xDAAA00]
color=QtGui.QColor(colorTable[shape])
painter.fillRect(x+1,y+1,self.squareWidth()-2,
self.squareHeight()-2,color)
painter.setPen(color.light())
painter.drawLine(x,y+self.squareHeight()-1,x,y)
painter.drawLine(x,y,x+self.squareWidth()-1,y)
painter.setPen(color.dark())
painter.drawLine(x+1,y+self.squareHeight()-1,
x+self.squareWidth()-1,y+self.squareHeight()-1)
painter.drawLine(x+self.squareWidth()-1,
y+self.squareHeight()-1,x+self.squareWidth()-1,y+1)
classTetrominoe(object):
'''''
定义游戏中出现的形状,共有8种,分别用0-7表示。
其中0表示没有形状,1-7表示可能出现的形状:Z,S,Line,T,Square,L,MirroredL。
相当于C++中的枚举类型,用有意义的字符串名代替数字
'''
NoShape=0
ZShape=1
SShape=2
LineShape=3
TShape=4
SquareShape=5
LShape=6
MirroredLShape=7
classShape(object):
'''''
Shape类保存每种方块的信息
'''
#coordsTabletupleholdsallpossiblecoordinatevaluesofourTetrispieces.0-7
coordsTable=(
((0,0),(0,0),(0,0),(0,0)),
((0,-1),(0,0),(-1,0),(-1,1)),
((0,-1),(0,0),(1,0),(1,1)),
((0,-1),(0,0),(0,1),(0,2)),
((-1,0),(0,0),(1,0),(0,1)),
((0,0),(1,0),(0,1),(1,1)),
((-1,-1),(0,-1),(0,0),(0,1)),
((1,-1),(0,-1),(0,0),(0,1))
)
def__init__(self):
self.coords=[[0,0]foriinrange(4)]#[[0,0],[0,0],[0,0],[0,0]]
self.pieceShape=Tetrominoe.NoShape
self.setShape(Tetrominoe.NoShape)
#返回当前shape类型
defshape(self):
returnself.pieceShape
defsetShape(self,shape):
table=Shape.coordsTable[shape]#table是对应的tuple元组
#将对应的table赋给self.coords
foriinrange(4):
forjinrange(2):
self.coords[i][j]=table[i][j]
self.pieceShape=shape
#随机获取一个块形状(从1,2,3,4,5,6,7中随机选1个)
defsetRandomShape(self):
self.setShape(random.randint(1,7))
#返回index的x坐标,index是从0-3,分别表示方块对应的4个点
defx(self,index):
returnself.coords[index][0]
#返回index的y坐标
defy(self,index):
returnself.coords[index][1]
#设置当前index的x坐标
defsetX(self,index,x):
self.coords[index][0]=x
#设置当前index的y坐标
defsetY(self,index,y):
self.coords[index][1]=y
#返回当前块的最小x坐标
defminX(self):
m=self.coords[0][0]
foriinrange(4):
m=min(m,self.coords[i][0])
returnm
#返回当前块的最大x坐标
defmaxX(self):
m=self.coords[0][0]
foriinrange(4):
m=max(m,self.coords[i][0])
returnm
#返回当前块的最小y坐标
defminY(self):
m=self.coords[0][1]
foriinrange(4):
m=min(m,self.coords[i][1])
returnm
#返回当前块的最大y坐标
defmaxY(self):
m=self.coords[0][1]
foriinrange(4):
m=max(m,self.coords[i][1])
returnm
defrotateLeft(self):#rotateapiecetotheleft
#如果块是方块的话,直接返回当前块,不做任何处理
ifself.pieceShape==Tetrominoe.SquareShape:
returnself
result=Shape()
result.pieceShape=self.pieceShape
foriinrange(4):
#将i点的x坐标换为y坐标
result.setX(i,self.y(i))
#将i点的y坐标换为-x坐标
result.setY(i,-self.x(i))
#返回新的左旋后的方块
returnresult
defrotateRight(self):
#如果块是方块的话,直接返回当前块,不做任何处理
ifself.pieceShape==Tetrominoe.SquareShape:
returnself
result=Shape()
result.pieceShape=self.pieceShape
foriinrange(4):
#将i点的x坐标换为-y坐标
result.setX(i,-self.y(i))
#将i点的y坐标换为x坐标
result.setY(i,self.x(i))
#返回新的右旋后的方块
returnresult
'''''
Thegameissimplifiedabitsothatitiseasiertounderstand.
Thegamestartsimmediatelyafteritislaunched.
Wecanpausethegamebypressingthepkey.
ThespacekeywilldroptheTetrispieceinstantlytothebottom.
Thegamegoesatconstantspeed,noaccelerationisimplemented.
Thescoreisthenumberoflinesthatwehaveremoved.
'''
defmain():
#创建一个界面app
app=QtGui.QApplication([])
#创建一个俄罗斯方块类
tetris=Tetris()
#进入主循环
app.exec_()
if__name__=='__main__':
main()
源代码来自:详细链接
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。