俄罗斯方块

import random, time, pygame, sys  
from pygame.locals import *  
  
FPS = 25  
WINDOWWIDTH = 640  
WINDOWHEIGHT = 480  
BOXSIZE = 20  
BOARDWIDTH = 10  
BOARDHEIGHT = 20  
BLANK = '.'  
  
MOVESIDEWAYSFREQ = 0.15  
MOVEDOWNFREQ = 0.1  
  
XMARGIN = int((WINDOWWIDTH - BOARDWIDTH * BOXSIZE) / 2)  
TOPMARGIN = WINDOWHEIGHT - (BOARDHEIGHT * BOXSIZE) - 5  
#               R    G    B  
WHITE       = (255, 255, 255)  
GRAY        = (185, 185, 185)  
BLACK       = (  0,   0,   0)  
RED         = (155,   0,   0)  
LIGHTRED    = (175,  20,  20)  
GREEN       = (  0, 155,   0)  
LIGHTGREEN  = ( 20, 175,  20)  
BLUE        = (  0,   0, 155)  
LIGHTBLUE   = ( 20,  20, 175)  
YELLOW      = (155, 155,   0)  
LIGHTYELLOW = (175, 175,  20)  
  
BORDERCOLOR = BLUE  
BGCOLOR = BLACK  
TEXTCOLOR = WHITE  
TEXTSHADOWCOLOR = GRAY  
COLORS      = (     BLUE,      GREEN,      RED,      YELLOW)  
LIGHTCOLORS = (LIGHTBLUE, LIGHTGREEN, LIGHTRED, LIGHTYELLOW)  
assert len(COLORS) == len(LIGHTCOLORS) # each color must have light color  
  
TEMPLATEWIDTH = 5  
TEMPLATEHEIGHT = 5  
  
S_SHAPE_TEMPLATE = [['.....',  
                     '.....',  
                     '..OO.',  
                     '.OO..',  
                     '.....'],  
                    ['.....',  
                     '..O..',  
                     '..OO.',  
                     '...O.',  
                     '.....']]  
  
Z_SHAPE_TEMPLATE = [['.....',  
                     '.....',  
                     '.OO..',  
                     '..OO.',  
                     '.....'],  
                    ['.....',  
                     '..O..',  
                     '.OO..',  
                     '.O...',  
                     '.....']]  
  
I_SHAPE_TEMPLATE = [['..O..',  
                     '..O..',  
                     '..O..',  
                     '..O..',  
                     '.....'],  
                    ['.....',  
                     '.....',  
                     'OOOO.',  
                     '.....',  
                     '.....']]  
  
O_SHAPE_TEMPLATE = [['.....',  
                     '.....',  
                     '.OO..',  
                     '.OO..',  
                     '.....']]  
  
J_SHAPE_TEMPLATE = [['.....',  
                     '.O...',  
                     '.OOO.',  
                     '.....',  
                     '.....'],  
                    ['.....',  
                     '..OO.',  
                     '..O..',  
                     '..O..',  
                     '.....'],  
                    ['.....',  
                     '.....',  
                     '.OOO.',  
                     '...O.',  
                     '.....'],  
                    ['.....',  
                     '..O..',  
                     '..O..',  
                     '.OO..',  
                     '.....']]  
  
L_SHAPE_TEMPLATE = [['.....',  
                     '...O.',  
                     '.OOO.',  
                     '.....',  
                     '.....'],  
                    ['.....',  
                     '..O..',  
                     '..O..',  
                     '..OO.',  
                     '.....'],  
                    ['.....',  
                     '.....',  
                     '.OOO.',  
                     '.O...',  
                     '.....'],  
                    ['.....',  
                     '.OO..',  
                     '..O..',  
                     '..O..',  
                     '.....']]  
  
T_SHAPE_TEMPLATE = [['.....',  
                     '..O..',  
                     '.OOO.',  
                     '.....',  
                     '.....'],  
                    ['.....',  
                     '..O..',  
                     '..OO.',  
                     '..O..',  
                     '.....'],  
                    ['.....',  
                     '.....',  
                     '.OOO.',  
                     '..O..',  
                     '.....'],  
                    ['.....',  
                     '..O..',  
                     '.OO..',  
                     '..O..',  
                     '.....']]  
  
PIECES = {'S': S_SHAPE_TEMPLATE,  
          'Z': Z_SHAPE_TEMPLATE,  
          'J': J_SHAPE_TEMPLATE,  
          'L': L_SHAPE_TEMPLATE,  
          'I': I_SHAPE_TEMPLATE,  
          'O': O_SHAPE_TEMPLATE,  
          'T': T_SHAPE_TEMPLATE}  
  
  
def main():  
    global FPSCLOCK, DISPLAYSURF, BASICFONT, BIGFONT  
    pygame.init()  
    FPSCLOCK = pygame.time.Clock()  
    DISPLAYSURF = pygame.display.set_mode((WINDOWWIDTH, WINDOWHEIGHT))  
    BASICFONT = pygame.font.Font('freesansbold.ttf', 18)  
    BIGFONT = pygame.font.Font('freesansbold.ttf', 100)  
    pygame.display.set_caption('Tetromino')  
  
    showTextScreen('Tetromino')  
    while True: # game loop  
        '''if random.randint(0, 1) == 0:  
            pygame.mixer.music.load('tetrisb.mid')  
        else:  
            pygame.mixer.music.load('tetrisc.mid')  
        pygame.mixer.music.play(-1, 0.0)'''  
        runGame()  
        #pygame.mixer.music.stop()  
        showTextScreen('Game Over')  
  
  
def runGame():  
    # setup variables for the start of the game  
    board = getBlankBoard()  
    lastMoveDownTime = time.time()  
    lastMoveSidewaysTime = time.time()  
    lastFallTime = time.time()  
    movingDown = False # note: there is no movingUp variable  
    movingLeft = False  
    movingRight = False  
    score = 0  
    level, fallFreq = calculateLevelAndFallFreq(score)  
  
    fallingPiece = getNewPiece()  
    nextPiece = getNewPiece()  
  
    while True: # game loop  
        if fallingPiece == None:  
            # No falling piece in play, so start a new piece at the top  
            fallingPiece = nextPiece  
            nextPiece = getNewPiece()  
            lastFallTime = time.time() # reset lastFallTime  
  
            if not isValidPosition(board, fallingPiece):  
                return # can't fit a new piece on the board, so game over  
  
        checkForQuit()  
        for event in pygame.event.get(): # event handling loop  
            if event.type == KEYUP:  
                if (event.key == K_p):  
                    # Pausing the game  
                    DISPLAYSURF.fill(BGCOLOR)  
                    #pygame.mixer.music.stop()  
                    showTextScreen('Paused') # pause until a key press  
                    #pygame.mixer.music.play(-1, 0.0)  
                    lastFallTime = time.time()  
                    lastMoveDownTime = time.time()  
                    lastMoveSidewaysTime = time.time()  
                elif (event.key == K_LEFT or event.key == K_a):  
                    movingLeft = False  
                elif (event.key == K_RIGHT or event.key == K_d):  
                    movingRight = False  
                elif (event.key == K_DOWN or event.key == K_s):  
                    movingDown = False  
  
            elif event.type == KEYDOWN:  
                # moving the piece sideways  
                if (event.key == K_LEFT or event.key == K_a) and isValidPosition(board, fallingPiece, adjX=-1):  
                    fallingPiece['x'] -= 1  
                    movingLeft = True  
                    movingRight = False  
                    lastMoveSidewaysTime = time.time()  
  
                elif (event.key == K_RIGHT or event.key == K_d) and isValidPosition(board, fallingPiece, adjX=1):  
                    fallingPiece['x'] += 1  
                    movingRight = True  
                    movingLeft = False  
                    lastMoveSidewaysTime = time.time()  
  
                # rotating the piece (if there is room to rotate)  
                elif (event.key == K_UP or event.key == K_w):  
                    fallingPiece['rotation'] = (fallingPiece['rotation'] + 1) % len(PIECES[fallingPiece['shape']])  
                    if not isValidPosition(board, fallingPiece):  
                        fallingPiece['rotation'] = (fallingPiece['rotation'] - 1) % len(PIECES[fallingPiece['shape']])  
                elif (event.key == K_q): # rotate the other direction  
                    fallingPiece['rotation'] = (fallingPiece['rotation'] - 1) % len(PIECES[fallingPiece['shape']])  
                    if not isValidPosition(board, fallingPiece):  
                        fallingPiece['rotation'] = (fallingPiece['rotation'] + 1) % len(PIECES[fallingPiece['shape']])  
  
                # making the piece fall faster with the down key  
                elif (event.key == K_DOWN or event.key == K_s):  
                    movingDown = True  
                    if isValidPosition(board, fallingPiece, adjY=1):  
                        fallingPiece['y'] += 1  
                    lastMoveDownTime = time.time()  
  
                # move the current piece all the way down  
                elif event.key == K_SPACE:  
                    movingDown = False  
                    movingLeft = False  
                    movingRight = False  
                    for i in range(1, BOARDHEIGHT):  
                        if not isValidPosition(board, fallingPiece, adjY=i):  
                            break  
                    fallingPiece['y'] += i - 1  
  
        # handle moving the piece because of user input  
        if (movingLeft or movingRight) and time.time() - lastMoveSidewaysTime > MOVESIDEWAYSFREQ:  
            if movingLeft and isValidPosition(board, fallingPiece, adjX=-1):  
                fallingPiece['x'] -= 1  
            elif movingRight and isValidPosition(board, fallingPiece, adjX=1):  
                fallingPiece['x'] += 1  
            lastMoveSidewaysTime = time.time()  
  
        if movingDown and time.time() - lastMoveDownTime > MOVEDOWNFREQ and isValidPosition(board, fallingPiece, adjY=1):  
            fallingPiece['y'] += 1  
            lastMoveDownTime = time.time()  
  
        # let the piece fall if it is time to fall  
        if time.time() - lastFallTime > fallFreq:  
            # see if the piece has landed  
            if not isValidPosition(board, fallingPiece, adjY=1):  
                # falling piece has landed, set it on the board  
                addToBoard(board, fallingPiece)  
                score += removeCompleteLines(board)  
                level, fallFreq = calculateLevelAndFallFreq(score)  
                fallingPiece = None  
            else:  
                # piece did not land, just move the piece down  
                fallingPiece['y'] += 1  
                lastFallTime = time.time()  
  
        # drawing everything on the screen  
        DISPLAYSURF.fill(BGCOLOR)  
        drawBoard(board)  
        drawStatus(score, level)  
        drawNextPiece(nextPiece)  
        if fallingPiece != None:  
            drawPiece(fallingPiece)  
  
        pygame.display.update()  
        FPSCLOCK.tick(FPS)  
  
  
def makeTextObjs(text, font, color):  
    surf = font.render(text, True, color)  
    return surf, surf.get_rect()  
  
  
def terminate():  
    pygame.quit()  
    sys.exit()  
  
  
def checkForKeyPress():  
    # Go through event queue looking for a KEYUP event.  
    # Grab KEYDOWN events to remove them from the event queue.  
    checkForQuit()  
  
    for event in pygame.event.get([KEYDOWN, KEYUP]):  
        if event.type == KEYDOWN:  
            continue  
        return event.key  
    return None  
  
  
def showTextScreen(text):  
    # This function displays large text in the  
    # center of the screen until a key is pressed.  
    # Draw the text drop shadow  
    titleSurf, titleRect = makeTextObjs(text, BIGFONT, TEXTSHADOWCOLOR)  
    titleRect.center = (int(WINDOWWIDTH / 2), int(WINDOWHEIGHT / 2))  
    DISPLAYSURF.blit(titleSurf, titleRect)  
  
    # Draw the text  
    titleSurf, titleRect = makeTextObjs(text, BIGFONT, TEXTCOLOR)  
    titleRect.center = (int(WINDOWWIDTH / 2) - 3, int(WINDOWHEIGHT / 2) - 3)  
    DISPLAYSURF.blit(titleSurf, titleRect)  
  
    # Draw the additional "Press a key to play." text.  
    pressKeySurf, pressKeyRect = makeTextObjs('Press a key to play.', BASICFONT, TEXTCOLOR)  
    pressKeyRect.center = (int(WINDOWWIDTH / 2), int(WINDOWHEIGHT / 2) + 100)  
    DISPLAYSURF.blit(pressKeySurf, pressKeyRect)  
  
    while checkForKeyPress() == None:  
        pygame.display.update()  
        FPSCLOCK.tick()  
  
  
def checkForQuit():  
    for event in pygame.event.get(QUIT): # get all the QUIT events  
        terminate() # terminate if any QUIT events are present  
    for event in pygame.event.get(KEYUP): # get all the KEYUP events  
        if event.key == K_ESCAPE:  
            terminate() # terminate if the KEYUP event was for the Esc key  
        pygame.event.post(event) # put the other KEYUP event objects back  
  
  
def calculateLevelAndFallFreq(score):  
    # Based on the score, return the level the player is on and  
    # how many seconds pass until a falling piece falls one space.  
    level = int(score / 10) + 1  
    fallFreq = 0.27 - (level * 0.02)  
    return level, fallFreq  
  
def getNewPiece():  
    # return a random new piece in a random rotation and color  
    shape = random.choice(list(PIECES.keys()))  
    newPiece = {'shape': shape,  
                'rotation': random.randint(0, len(PIECES[shape]) - 1),  
                'x': int(BOARDWIDTH / 2) - int(TEMPLATEWIDTH / 2),  
                'y': -2, # start it above the board (i.e. less than 0)  
                'color': random.randint(0, len(COLORS)-1)}  
    return newPiece  
  
  
def addToBoard(board, piece):  
    # fill in the board based on piece's location, shape, and rotation  
    for x in range(TEMPLATEWIDTH):  
        for y in range(TEMPLATEHEIGHT):  
            if PIECES[piece['shape']][piece['rotation']][y][x] != BLANK:  
                board[x + piece['x']][y + piece['y']] = piece['color']  
  
  
def getBlankBoard():  
    # create and return a new blank board data structure  
    board = []  
    for i in range(BOARDWIDTH):  
        board.append([BLANK] * BOARDHEIGHT)  
    return board  
  
  
def isOnBoard(x, y):  
    return x >= 0 and x < BOARDWIDTH and y < BOARDHEIGHT  
  
  
def isValidPosition(board, piece, adjX=0, adjY=0):  
    # Return True if the piece is within the board and not colliding  
    for x in range(TEMPLATEWIDTH):  
        for y in range(TEMPLATEHEIGHT):  
            isAboveBoard = y + piece['y'] + adjY < 0  
            if isAboveBoard or PIECES[piece['shape']][piece['rotation']][y][x] == BLANK:  
                continue  
            if not isOnBoard(x + piece['x'] + adjX, y + piece['y'] + adjY):  
                return False  
            if board[x + piece['x'] + adjX][y + piece['y'] + adjY] != BLANK:  
                return False  
    return True  
  
def isCompleteLine(board, y):  
    # Return True if the line filled with boxes with no gaps.  
    for x in range(BOARDWIDTH):  
        if board[x][y] == BLANK:  
            return False  
    return True  
  
  
def removeCompleteLines(board):  
    # Remove any completed lines on the board, move everything above them down, and return the number of complete lines.  
    numLinesRemoved = 0  
    y = BOARDHEIGHT - 1 # start y at the bottom of the board  
    while y >= 0:  
        if isCompleteLine(board, y):  
            # Remove the line and pull boxes down by one line.  
            for pullDownY in range(y, 0, -1):  
                for x in range(BOARDWIDTH):  
                    board[x][pullDownY] = board[x][pullDownY-1]  
            # Set very top line to blank.  
            for x in range(BOARDWIDTH):  
                board[x][0] = BLANK  
            numLinesRemoved += 1  
            # Note on the next iteration of the loop, y is the same.  
            # This is so that if the line that was pulled down is also  
            # complete, it will be removed.  
        else:  
            y -= 1 # move on to check next row up  
    return numLinesRemoved  
  
  
def convertToPixelCoords(boxx, boxy):  
    # Convert the given xy coordinates of the board to xy  
    # coordinates of the location on the screen.  
    return (XMARGIN + (boxx * BOXSIZE)), (TOPMARGIN + (boxy * BOXSIZE))  
  
  
def drawBox(boxx, boxy, color, pixelx=None, pixely=None):  
    # draw a single box (each tetromino piece has four boxes)  
    # at xy coordinates on the board. Or, if pixelx & pixely  
    # are specified, draw to the pixel coordinates stored in  
    # pixelx & pixely (this is used for the "Next" piece).  
    if color == BLANK:  
        return  
    if pixelx == None and pixely == None:  
        pixelx, pixely = convertToPixelCoords(boxx, boxy)  
    pygame.draw.rect(DISPLAYSURF, COLORS[color], (pixelx + 1, pixely + 1, BOXSIZE - 1, BOXSIZE - 1))  
    pygame.draw.rect(DISPLAYSURF, LIGHTCOLORS[color], (pixelx + 1, pixely + 1, BOXSIZE - 4, BOXSIZE - 4))  
  
  
def drawBoard(board):  
    # draw the border around the board  
    pygame.draw.rect(DISPLAYSURF, BORDERCOLOR, (XMARGIN - 3, TOPMARGIN - 7, (BOARDWIDTH * BOXSIZE) + 8, (BOARDHEIGHT * BOXSIZE) + 8), 5)  
  
    # fill the background of the board  
    pygame.draw.rect(DISPLAYSURF, BGCOLOR, (XMARGIN, TOPMARGIN, BOXSIZE * BOARDWIDTH, BOXSIZE * BOARDHEIGHT))  
    # draw the individual boxes on the board  
    for x in range(BOARDWIDTH):  
        for y in range(BOARDHEIGHT):  
            drawBox(x, y, board[x][y])  
  
  
def drawStatus(score, level):  
    # draw the score text  
    scoreSurf = BASICFONT.render('Score: %s' % score, True, TEXTCOLOR)  
    scoreRect = scoreSurf.get_rect()  
    scoreRect.topleft = (WINDOWWIDTH - 150, 20)  
    DISPLAYSURF.blit(scoreSurf, scoreRect)  
  
    # draw the level text  
    levelSurf = BASICFONT.render('Level: %s' % level, True, TEXTCOLOR)  
    levelRect = levelSurf.get_rect()  
    levelRect.topleft = (WINDOWWIDTH - 150, 50)  
    DISPLAYSURF.blit(levelSurf, levelRect)  
  
  
def drawPiece(piece, pixelx=None, pixely=None):  
    shapeToDraw = PIECES[piece['shape']][piece['rotation']]  
    if pixelx == None and pixely == None:  
        # if pixelx & pixely hasn't been specified, use the location stored in the piece data structure  
        pixelx, pixely = convertToPixelCoords(piece['x'], piece['y'])  
  
    # draw each of the boxes that make up the piece  
    for x in range(TEMPLATEWIDTH):  
        for y in range(TEMPLATEHEIGHT):  
            if shapeToDraw[y][x] != BLANK:  
                drawBox(None, None, piece['color'], pixelx + (x * BOXSIZE), pixely + (y * BOXSIZE))  
  
  
def drawNextPiece(piece):  
    # draw the "next" text  
    nextSurf = BASICFONT.render('Next:', True, TEXTCOLOR)  
    nextRect = nextSurf.get_rect()  
    nextRect.topleft = (WINDOWWIDTH - 120, 80)  
    DISPLAYSURF.blit(nextSurf, nextRect)  
    # draw the "next" piece  
    drawPiece(piece, pixelx=WINDOWWIDTH-120, pixely=100)  
  
  
if __name__ == '__main__':
    main()
 
    

老外的那个声音文件不知道从哪下载,我把声音注释了。。。



评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值