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()
源代码来自:详细链接
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。