Advertisement
1997kobra

Tetris

Jul 6th, 2013
171
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 11.20 KB | None | 0 0
  1. import sys
  2. import random
  3. from PyQt4 import QtCore, QtGui
  4.  
  5. class Tetris(QtGui.QMainWindow):
  6.     def __init__(self):
  7.         QtGui.QMainWindow.__init__(self)
  8.  
  9.         self.setGeometry(300,300,180,380)
  10.         self.setWindowTitle('Tetris')
  11.         self.tetrisboard = Board(self)
  12.  
  13.         self.setCentralWidget(self.tetrisboard)
  14.  
  15.         self.statusbar = self.statusBar()
  16.         self.connect(self.tetrisboard,
  17.                      QtCore.SIGNAL("messageToStatusbar(QString)"),
  18.                      self.statusbar,QtCore.SLOT("showMessage(QString)"))
  19.  
  20.         self.tetrisboard.start()
  21.         self.center()
  22.  
  23.     def center(self):
  24.         screen = QtGui.QDesktopWidget().screenGeometry()
  25.         size = self.geometry()
  26.         self.move((screen.width()-size.width())/2,
  27.                   (screen.height()-size.height())/2)
  28.  
  29.  
  30. class Board(QtGui.QFrame):
  31.     BoardWidth = 10
  32.     BoardHeight = 22
  33.     Speed = 300
  34.  
  35.     def __init__(self,parent):
  36.         QtGui.QFrame.__init__(self,parent)
  37.  
  38.         self.timer = QtCore.QBasicTimer()
  39.         self.isWaitingAfterLine = False
  40.         self.curPiece = Shape()
  41.         self.nextPiece = Shape()
  42.         self.curX = 0
  43.         self.curY = 0
  44.         self.numLinesRemoved = 0
  45.         self.board = []
  46.  
  47.         self.setFocusPolicy(QtCore.Qt.StrongFocus)
  48.         self.isStarted = False
  49.         self.isPaused = False
  50.         self.clearBoard()
  51.  
  52.         self.nextPiece.setRandomShape()
  53.  
  54.     def shapeAt(self, x, y):
  55.         return self.board[int((y*Board.BoardWidth)+x)]
  56.  
  57.     def setShapeAt(self, x, y, shape):
  58.         self.board[int((y * Board.BoardWidth) + x)] = shape
  59.  
  60.     def squareWidth(self):
  61.         return self.contentsRect().width() / Board.BoardWidth
  62.  
  63.     def squareHeight(self):
  64.         return self.contentsRect().height() / Board.BoardHeight
  65.  
  66.     def start(self):
  67.         if self.isPaused:
  68.             return
  69.  
  70.         self.isStarted = True
  71.         self.isWaitingAfterLine = False
  72.         self.numLinesRemoved = 0
  73.         self.clearBoard()
  74.  
  75.         self.emit(QtCore.SIGNAL("messageToStatusbar(QString)"),
  76.                   str(self.numLinesRemoved))
  77.  
  78.         self.newPiece()
  79.         self.timer.start(Board.Speed, self)
  80.  
  81.     def pause(self):
  82.         if not self.isStarted:
  83.             return
  84.  
  85.         self.isPaused = not self.isPaused
  86.         if self.isPaused:
  87.             self.timer.stop()
  88.             self.emit(QtCore.SIGNAL("messageToStatusbar(QString)"),"paused")
  89.         else:
  90.             self.timer.start(Board.Speed,self)
  91.             self.emit(QtCore.SIGNAL("messageToStatusbar(QString)"),
  92.                       str(self.numLinesRemoved))
  93.  
  94.         self.update()
  95.  
  96.     def paintEvent(self, event):
  97.         painter = QtGui.QPainter(self)
  98.         rect = self.contentsRect()
  99.  
  100.         boardTop = rect.bottom() - Board.BoardHeight * self.squareHeight()
  101.  
  102.         for i in range(Board.BoardHeight):
  103.             for j in range(Board.BoardWidth):
  104.                 shape = self.shapeAt(j, Board.BoardHeight - i - 1)
  105.                 if shape != Tetrominoes.NoShape:
  106.                     self.drawSquare(painter,
  107.                                     rect.left() + j * self.squareWidth(),
  108.                                     boardTop + i * self.squareHeight(),shape)
  109.  
  110.         if self.curPiece.shape() != Tetrominoes.NoShape:
  111.             for i in range(4):
  112.                 x = self.curX + self.curPiece.x(i)
  113.                 y = self.curY - self.curPiece.y(i)
  114.                 self.drawSquare(painter, rect.left() + x * self.squareWidth(),
  115.                                 boardTop + (Board.BoardHeight - y -1) *
  116.                                 self.squareHeight(),self.curPiece.shape())
  117.  
  118.     def keyPressEvent(self, event):
  119.         if not self.isStarted or self.curPiece.shape() == Tetrominoes.NoShape:
  120.             QtGui.QWidget.keyPressEvent(self,event)
  121.             return
  122.  
  123.         key = event.key()
  124.         if key == QtCore.Qt.Key_P:
  125.             self.pause()
  126.             return
  127.         if self.isPaused:
  128.             return
  129.         elif key == QtCore.Qt.Key_Left:
  130.             self.tryMove(self.curPiece, self.curX - 1, self.curY)
  131.         elif key == QtCore.Qt.Key_Right:
  132.             self.tryMove(self.curPiece, self.curX + 1, self.curY)
  133.         elif key == QtCore.Qt.Key_Down:
  134.             self.tryMove(self.curPiece.rotatedRight(), self.curX, self.curY)
  135.         elif key == QtCore.Qt.Key_Up:
  136.             self.tryMove(self.curPiece.rotatedLeft(), self.curX, self.curY)
  137.         elif key == QtCore.Qt.Key_Space:
  138.             self.dropDown()
  139.         elif key == QtCore.Qt.Key_D:
  140.             self.oneLineDown()
  141.         else:
  142.             QtGui.QWidget.keyPressEvent(self, event)
  143.  
  144.     def timerEvent(self, event):
  145.         if event.timerId() == self.timer.timerId():
  146.             if self.isWaitingAfterLine:
  147.                 self.isWaitingAfterLine = False
  148.                 self.newPiece()
  149.             else:
  150.                 self.oneLineDown()
  151.         else:
  152.             QtGui.QFrame.timerEvent(self, event)
  153.  
  154.     def clearBoard(self):
  155.         for i in range(Board.BoardHeight * Board.BoardWidth):
  156.             self.board.append(Tetrominoes.NoShape)
  157.  
  158.    
  159.  
  160.     def dropDown(self):
  161.         newY = self.curY
  162.         while newY > 0:
  163.             if not self.tryMove(self.curPiece,self.curX, newY - 1):
  164.                 break
  165.             newY -= 1
  166.  
  167.         self.pieceDropped()
  168.  
  169.     def oneLineDown(self):
  170.         if not self.tryMove(self.curPiece, self.curX, self.curY - 1):
  171.             self.pieceDropped()
  172.  
  173.     def pieceDropped(self):
  174.         for i in range(4):
  175.             x = self.curX + self.curPiece.x(i)
  176.             y = self.curY - self.curPiece.y(i)
  177.             self.setShapeAt(x, y, self.curPiece.shape())
  178.  
  179.         self.removeFullLines()
  180.  
  181.         if not self.isWaitingAfterLine:
  182.             self.newPiece()
  183.  
  184.     def removeFullLines(self):
  185.         numFullLines = 0
  186.  
  187.         rowsToRemove = []
  188.  
  189.         for i in range(Board.BoardHeight):
  190.             n = 0
  191.             for j in range(Board.BoardWidth):
  192.                 if not self.shapeAt(j, i) == Tetrominoes.NoShape:
  193.                     n+=1
  194.  
  195.             if n == 10:
  196.                 rowsToRemove.append(i)
  197.  
  198.         rowsToRemove.reverse()
  199.  
  200.         for m in rowsToRemove:
  201.             for k in range(m, Board.BoardHeight):
  202.                 for l in range(Board.BoardWidth):
  203.                     self.setShapeAt(l, k, self.shapeAt(l, k + 1))
  204.  
  205.         numFullLines += len(rowsToRemove)
  206.  
  207.         if numFullLines > 0:
  208.             self.numLinesRemoved += numFullLines
  209.             self.emit(QtCore.SIGNAL("messageToStatusbar(QString)"),
  210.                       str(self.numLinesRemoved))
  211.             self.isWaitingAfterLine = True
  212.             self.curPiece.setShape(Tetrominoes.NoShape)
  213.             self.update()
  214.  
  215.     def newPiece(self):
  216.         self.curPiece = self.nextPiece
  217.         self.nextPiece.setRandomShape()
  218.         self.curX = Board.BoardWidth / 2 + 1
  219.         self.curY = Board.BoardHeight - 1 + self.curPiece.minY()
  220.  
  221.         if not self.tryMove(self.curPiece, self.curX, self.curY):
  222.             self.curPiece.setShape(Tetrominoes.NoShape)
  223.             self.timer.stop()
  224.             self.isStarted = False
  225.             self.emit(QtCore.SIGNAL("messageToStatusbar(QString)"), "Game over")
  226.  
  227.     def tryMove(self, newPiece, newX, newY):
  228.         for i in range(4):
  229.             x = newX + newPiece.x(i)
  230.             y = newY - newPiece.y(i)
  231.             if x < 0 or x >= Board.BoardWidth or y < 0 or y >= Board.BoardHeight:
  232.                 return False
  233.             if self.shapeAt(x, y) != Tetrominoes.NoShape:
  234.                 return False
  235.  
  236.         self.curPiece = newPiece
  237.         self.curX = newX
  238.         self.curY = newY
  239.         self.update()
  240.         return True
  241.  
  242.     def drawSquare(self, painter, x, y, shape):
  243.         colorTable = [0x000000, 0xCC6666, 0x66CC66, 0x6666CC,
  244.                       0xCCCC66, 0xCC66CC, 0x66CCCC, 0xDAAA00]
  245.  
  246.         color = QtGui.QColor(colorTable[shape])
  247.         painter.fillRect(x + 1, y + 1, self.squareWidth() - 2,
  248.                          self.squareHeight() - 2, color)
  249.  
  250.         painter.setPen(color.light())
  251.         painter.drawLine(x, y + self.squareHeight() - 1, x, y)
  252.         painter.drawLine(x, y, x + self.squareWidth() - 1, y)
  253.  
  254.         painter.setPen(color.dark())
  255.         painter.drawLine(x + 1, y + self.squareHeight() - 1,
  256.                          x + self.squareWidth() - 1, y + self.squareHeight() - 1)
  257.         painter.drawLine(x + self.squareWidth() - 1,
  258.                          y + self.squareHeight() - 1, x + self.squareWidth() - 1, y + 1)
  259.  
  260.  
  261. class Tetrominoes(object):
  262.     NoShape = 0
  263.     ZShape = 1
  264.     SShape = 2
  265.     LineShape = 3
  266.     TShape = 4
  267.     SquareShape = 5
  268.     LShape = 6
  269.     MirroredLShape = 7
  270.  
  271. class Shape(object):
  272.     coordsTable = (
  273.         ((0, 0),     (0, 0),     (0, 0),     (0, 0)),
  274.         ((0, -1),    (0, 0),     (-1, 0),    (-1, 1)),
  275.         ((0, -1),    (0, 0),     (1, 0),     (1, 1)),
  276.         ((0, -1),    (0, 0),     (0, 1),     (0, 2)),
  277.         ((-1, 0),    (0, 0),     (1, 0),     (0, 1)),
  278.         ((0, 0),     (1, 0),     (0, 1),     (1, 1)),
  279.         ((-1, -1),   (0, -1),    (0, 0),     (0, 1)),
  280.         ((1, -1),    (0, -1),    (0, 0),     (0, 1))
  281.     )
  282.  
  283.     def __init__(self):
  284.         self.coords = [[0,0] for i in range(4)]
  285.         self.pieceShape = Tetrominoes.NoShape
  286.  
  287.         self.setShape(Tetrominoes.NoShape)
  288.  
  289.     def shape(self):
  290.         return self.pieceShape
  291.  
  292.     def setShape(self, shape):
  293.         table = Shape.coordsTable[shape]
  294.         for i in range(4):
  295.             for j in range(2):
  296.                 self.coords[i][j] = table[i][j]
  297.  
  298.         self.pieceShape = shape
  299.  
  300.     def setRandomShape(self):
  301.         self.setShape(random.randint(1, 7))
  302.  
  303.     def x(self, index):
  304.         return self.coords[index][0]
  305.  
  306.     def y(self, index):
  307.         return self.coords[index][1]
  308.  
  309.     def setX(self, index, x):
  310.         self.coords[index][0] = x
  311.  
  312.     def setY(self, index, y):
  313.         self.coords[index][1] = y
  314.  
  315.     def minX(self):
  316.         m = self.coords[0][0]
  317.         for i in range(4):
  318.             m = min(m, self.coords[i][0])
  319.  
  320.         return m
  321.  
  322.     def maxX(self):
  323.         m = self.coords[0][0]
  324.         for i in range(4):
  325.             m = max(m, self.coords[i][0])
  326.  
  327.         return m
  328.  
  329.     def minY(self):
  330.         m = self.coords[0][1]
  331.         for i in range(4):
  332.             m = min(m, self.coords[i][1])
  333.  
  334.         return m
  335.  
  336.     def maxY(self):
  337.         m = self.coords[0][1]
  338.         for i in range(4):
  339.             m = max(m, self.coords[i][1])
  340.  
  341.         return m
  342.  
  343.     def rotatedLeft(self):
  344.         if self.pieceShape == Tetrominoes.SquareShape:
  345.             return self
  346.  
  347.         result = Shape()
  348.         result.pieceShape = self.pieceShape
  349.         for i in range(4):
  350.             result.setX(i, self.y(i))
  351.             result.setY(i, -self.x(i))
  352.  
  353.         return result
  354.  
  355.     def rotatedRight(self):
  356.         if self.pieceShape == Tetrominoes.SquareShape:
  357.             return self
  358.  
  359.         result = Shape()
  360.         result.pieceShape = self.pieceShape
  361.         for i in range(4):
  362.             result.setX(i, -self.y(i))
  363.             result.setY(i, self.x(i))
  364.  
  365.         return result
  366.  
  367.  
  368.  
  369. app = QtGui.QApplication(sys.argv)
  370. tetris = Tetris()
  371. tetris.show()
  372. sys.exit(app.exec_())
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement