亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > Python > 正文

Python使用pygame模塊編寫俄羅斯方塊游戲的代碼實例

2020-01-04 17:55:08
字體:
來源:轉載
供稿:網友
這篇文章主要介紹了Python使用pygame模塊編寫俄羅斯方塊游戲的代碼實例,最基本的方塊變換和行消除等功能都在代碼中一一體現,需要的朋友可以參考下
 

文章先介紹了關于俄羅斯方塊游戲的幾個術語。

  • 邊框——由10*20個空格組成,方塊就落在這里面。
  • 盒子——組成方塊的其中小方塊,是組成方塊的基本單元。
  • 方塊——從邊框頂掉下的東西,游戲者可以翻轉和改變位置。每個方塊由4個盒子組成。
  • 形狀——不同類型的方塊。這里形狀的名字被叫做T, S, Z ,J, L, I , O。如下圖所示:

Python使用pygame模塊編寫俄羅斯方塊游戲的代碼實例

模版——用一個列表存放形狀被翻轉后的所有可能樣式。全部存放在變量里,變量名字如S_SHAPE_TEMPLATE or J_SHAPE_TEMPLATE
著陸——當一個方塊到達邊框的底部或接觸到在其他的盒子話,我們就說這個方塊著陸了。那樣的話,另一個方塊就會開始下落。
下面先把代碼敲一遍,試著了解作者意圖,體會俄羅斯方塊游戲的制作過程。

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() 

代碼一開始仍是一些變量的初始化,我們這里還加載了time模塊,后面會用到。BOXSIZE, BOARDWIDTH, BOARDHEIGHT與前面貪吃蛇相關初始化類似,使其與屏幕像素點聯系起來。

MOVESIDEWAYSFREQ = 0.15MOVEDOWNFREQ = 0.1

這兩個變量的作用是這樣的,每當游戲者按下左鍵或右鍵,下降的方塊相應的向左或右移一個格子。然而游戲者也可以一直按下方向左鍵或右鍵讓方塊保持移動。MOVESIDEWAYSFREQ這個固定值表示如果一直按下方向左鍵或右鍵那么每0.15秒方塊才會繼續移動。
MOVEDOWNFREQ 這個固定值與上面的是一樣的除了它是告訴當游戲者一直按下方向下鍵時方塊下落的頻率。

XMARGIN = int((WINDOWWIDTH - BOARDWIDTH * BOXSIZE) / 2)TOPMARGIN = WINDOWHEIGHT - (BOARDHEIGHT * BOXSIZE) - 5

這兩句的意思就看下面這個圖就明白了。

Python使用pygame模塊編寫俄羅斯方塊游戲的代碼實例

然后是一些顏色值的定義。其中要注意的是COLORS和LIGHTCOLORS,COLORS是組成方塊的小方塊的顏色,而LIGHTCOLORS是圍繞在小方塊周圍的顏色,為了強調出輪廓而設計的。
接著是定義方塊了。游戲必須知道每個類型的方塊有多少種形狀,在這里我們用在列表中嵌入含有字符串的列表來構成這個模版,一個方塊類型的模版含有了這個方塊可能變換的所有形狀。比如I的模版如下:

I_SHAPE_TEMPLATE = [['..O..',            '..O..',            '..O..',            '..O..',            '.....'],           ['.....',            '.....',            'OOOO.',            '.....',            '.....']] 

TEMPLATEWIDTH = 5和TEMPLATEHEIGHT = 5則表示組成形狀的行和列,如下圖所示:

Python使用pygame模塊編寫俄羅斯方塊游戲的代碼實例

在看這段定義。

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} 

PIECES這個變量是一個字典,里面儲存了所有的不同模版。因為每個又有一個類型的方塊的所有變換形狀。那就意味著PIECES變量包含了每個類型的方塊和所有的的變換形狀。這就是存放我們游戲中用到的形狀的數據結構。(又加強了對字典的理解)
主函數main()
主函數的前部分主要是創建一些全局變量和在游戲開始之前顯示一個開始畫面。

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') 

上面這段代碼中runGame()是程序的核心部分。循環中首先簡單的隨機決定采用哪個背景音樂。然后調用runGame(),當游戲失敗,runGame()就會返回到main()函數,這時會停止背景音樂和顯示游戲失敗的畫面。
當游戲者按下一個鍵,showTextScreen()顯示游戲失敗的函數就會返回。游戲循環會再次開始然后繼續下一次游戲。
runGame()

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() 

在游戲開始和方塊掉落之前,我們需要初始化一些跟游戲開始相關的變量。fallingPiece變量被賦值成當前掉落的變量,nextPiece變量被賦值成游戲者可以在屏幕NEXT區域看見的下一個方塊。

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() 

這部分包含了當方塊往底部掉落時的的所有代碼。fallingPiece變量在方塊著陸后被設置成None。這意味著nextPiece變量中的下一個方塊應該被賦值給fallingPiece變量,然后一個隨機的方塊又會被賦值給nextPiece變量。lastFallTime變量也被賦值成當前時間,這樣我們就可以通過fallFreq變量控制方塊下落的頻率。
來自getNewPiece函數的方塊只有一部分被放置在方框區域中。但是如果這是一個非法的位置,比如此時游戲方框已經被填滿(isVaildPostion()函數返回False),那么我們就知道方框已經滿了,游戲者輸掉了游戲。當這些發生時,runGame()函數就會返回。
事件處理循環
事件循環主要處理當翻轉方塊,移動方塊時或者暫停游戲時的一些事情。
暫停游戲

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() 

如果游戲者按下P鍵,游戲就會暫停。我們應該隱藏掉游戲界面以防止游戲者作弊(否則游戲者會看著畫面思考怎么處理方塊),用DISPLAYSURF.fill(BGCOLOR)就可以實現這個效果。注意的是我們還要保存一些時間變量值。

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 

停止按下方向鍵或ASD鍵會把moveLeft,moveRight,movingDown變量設置為False.,表明游戲者不再想要在此方向上移動方塊。后面的代碼會基于moving變量處理一些事情。注意的上方向鍵和W鍵是用來翻轉方塊的而不是移動方塊。這就是為什么沒有movingUp變量.

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() 

當左方向鍵按下(而且往左移動是有效的,通過調用isVaildPosition()函數知道的),那么我們應該改變一個方塊的位置使其向左移動一個通過讓rallingPiece['x']減1.isVaildPosition()函數有個參數選項是adjX和adjY.平常,isVaildPostion()函數檢查方塊的位置通過函數的第二個參數的傳遞。然而,有時我們不想檢查方塊當前的位置,而是偏離當前方向幾個格子的位置。
比如adjX=-1,則表示向左移動一個格子后方塊的位置,為+1則表示向右移動一個格子后的位置。adjY同理如此。
movingLeft變量會被設置為True,確保方塊不會向右移動,此時movingRight變量設置為False。同時需要更新lastMoveSidewaysTime的值。
這個lastMoveSidewaysTime變量設置的原因是這樣。因為游戲者有可能一直按著方向鍵讓其方塊移動。如果moveLeft被設置為True,程序就會知道方向左鍵已經被按下。如果在lastMoveSidewaysTime變量儲存的時間基礎上,0.15秒(儲存在MOVESIDEAYSFREQ變量中)過去后,那么此時程序就會將方塊再次向左移動一個格子。

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']]) 

如果方向鍵上或W鍵被按下,那么就會翻轉方塊。上面的代碼做的就是將儲存在fallingPiece字典中的‘rotation'鍵的鍵值加1.然而,當增加的'rotation'鍵值大于所有當前類型方塊的形狀的數目的話(此變量儲存在len(SHAPES[fallingPiece['shape']])變量中),那么它翻轉到最初的形狀。
 

if not isValidPosition(board, fallingPiece):             fallingPiece['rotation'] = (fallingPiece['rotation'] - 1) % len(PIECES[fallingPiece['shape']]) 

如果翻轉后的形狀無效因為其中的一些小方塊已經超過邊框的范圍,那么我們就要把它變回原來的形狀通過將fallingPiece['rotation')減去1.

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']]) 

這段代碼與上面之前的那段代碼是一個意思,不同的是這段代碼是當游戲者按下Q鍵時翻轉方塊朝相反的方向。這里我們減去1而不是加1.

elif (event.key == K_DOWN or event.key == K_s):   movingDown = True   if isValidPosition(board, fallingPiece, adjY=1):     fallingPiece['y'] += 1   lastMoveDownTime = time.time() 

如果下鍵被按下,游戲者此時希望方塊下降的比平???。fallingPiece['y'] += 1使方塊下落一個格子(前提是這是一個有效的下落)moveDown被設置為True,lastMoceDownTime變量也被設置為當前時間。這個變量以后將被檢查當方向下鍵一直按下時從而保證方塊以一個比平??斓乃俾氏陆怠?/p>

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 

當游戲者按下空格鍵,方塊將會迅速的下落至著陸。程序首先需要找出到它著陸需要下降個多少個格子。其中有關moving的三個變量都要被設置為False(保證程序后面部分的代碼知道游戲者已經停止了按下所有的方向鍵)。

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() 

這段代碼是處理一直按下某個方向鍵時的情況。
如果用戶按住鍵超過0.15秒。那么表達式(movingLeft or movingRight) and time.time() - lastMoveSidewaysTime > MOVESIDEWAYSFREQ:返回True。這樣的話我們就可以移動方塊向左或向右移動一個格子。
這個做法是很用的,因為如果用戶重復的按下方向鍵讓方塊移動多個格子是很煩人的。好的做法是,用戶可以按住方向鍵讓方塊保持移動直到松開鍵為止。最后別忘了更新lastMoveSideWaysTime變量。

if movingDown and time.time() - lastMoveDownTime > MOVEDOWNFREQ and isValidPosition(board, fallingPiece, adjY=1):   fallingPiece['y'] += 1   lastMoveDownTime = time.time() 

這段代碼的意思跟上面的代碼差不多。

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() 

方塊自然下落的速率由lastFallTime變量決定。如果自從上個方塊掉落了一個格子后過去了足夠的時間,那么上面代碼就會再讓方塊移動一個格子。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
www国产亚洲精品久久网站| 国产精品久久久久久网站| 国产精品福利在线观看网址| 高跟丝袜欧美一区| 97香蕉超级碰碰久久免费软件| 日韩av电影中文字幕| 久久久999成人| 国产午夜精品一区二区三区| 亚洲黄色av网站| 欧美激情亚洲一区| 18性欧美xxxⅹ性满足| 国内精品视频久久| 日本精品免费一区二区三区| 亚洲一区二区三区sesese| 日韩欧美在线字幕| 欧美激情久久久| 在线日韩av观看| 亚洲香蕉av在线一区二区三区| 欧美日韩一区二区免费视频| 啪一啪鲁一鲁2019在线视频| 亚洲xxxxx性| 亚洲美女视频网站| 精品色蜜蜜精品视频在线观看| 亚洲精品一区二三区不卡| 亚洲一区二区三区sesese| 中文字幕日韩欧美| 亚洲第一区中文99精品| 福利一区视频在线观看| 精品久久久久久久久中文字幕| 欧美日韩综合视频网址| 免费97视频在线精品国自产拍| 亚洲自拍欧美另类| 97精品一区二区视频在线观看| 亚洲a∨日韩av高清在线观看| 欧美在线观看网址综合| 成人激情视频免费在线| 国产精品永久免费| 97福利一区二区| 色婷婷久久av| 色偷偷噜噜噜亚洲男人的天堂| 成人黄色av网站| 中文字幕亚洲一区二区三区| 久久噜噜噜精品国产亚洲综合| 亚洲人精选亚洲人成在线| 88国产精品欧美一区二区三区| 国产精品久久久久77777| 国产精品激情自拍| 色悠悠久久88| 国产精品老牛影院在线观看| 久久天天躁夜夜躁狠狠躁2022| 久久久人成影片一区二区三区| 91精品久久久久| 久久视频在线观看免费| 久久久国产精品亚洲一区| 在线看片第一页欧美| 成人黄色在线播放| 欧美理论片在线观看| 亚洲精品一区中文| 国产精品吴梦梦| 国产91精品久久久久久| 亚洲热线99精品视频| 成人午夜在线视频一区| 久久人人爽人人爽人人片av高清| 欧美亚洲视频在线观看| 91夜夜揉人人捏人人添红杏| 精品国产一区二区三区久久久狼| 亚洲性猛交xxxxwww| 午夜欧美不卡精品aaaaa| 日韩在线观看免费高清完整版| 91av成人在线| 麻豆成人在线看| 国产精品稀缺呦系列在线| 中文字幕日韩视频| 久久久久久久久久久国产| 一区二区三区国产视频| 国产91对白在线播放| 中文字幕欧美日韩在线| 欧美性猛交xxxx免费看| 久久久精品电影| 国产一区二区丝袜| 久久久综合免费视频| 亚洲大胆人体视频| 色中色综合影院手机版在线观看| 久久久久99精品久久久久| 欧美国产第二页| 少妇高潮 亚洲精品| 日韩女在线观看| 一色桃子一区二区| 久久久久久久久久久人体| 黑人巨大精品欧美一区二区免费| 亚洲欧美日韩在线一区| 这里只有精品在线播放| 亚洲国产精品久久久久秋霞蜜臀| 日韩精品一区二区三区第95| 亚洲伦理中文字幕| 久久久人成影片一区二区三区观看| 国产精品福利观看| 一区二区亚洲欧洲国产日韩| 丝袜亚洲欧美日韩综合| 亚洲福利影片在线| 日韩欧美在线视频日韩欧美在线视频| 日韩在线视频国产| 日韩电影免费观看中文字幕| 亚洲精品一二区| 亚洲亚裔videos黑人hd| 亚洲精品美女久久久| 国产精品va在线播放| 久久影视电视剧免费网站| 色偷偷噜噜噜亚洲男人的天堂| 午夜精品美女自拍福到在线| 91精品免费视频| 欧美精品久久一区二区| 色先锋资源久久综合5566| 欧美激情一区二区久久久| 日韩av成人在线| 久久国产精品亚洲| 国产精品成人播放| 海角国产乱辈乱精品视频| 久久精品视频va| 最近2019中文字幕第三页视频| 韩国福利视频一区| 欧美自拍视频在线| 欧美有码在线观看视频| 欧美日韩国产在线看| 国产亚洲一区精品| 九九精品视频在线| 亚洲国产三级网| 亚洲第一天堂无码专区| 久久好看免费视频| 91精品成人久久| 国产精品国模在线| 成人午夜激情免费视频| 亚洲天堂成人在线| 国产亚洲a∨片在线观看| 2018日韩中文字幕| 欧美午夜丰满在线18影院| 日韩精品一区二区三区第95| 成人免费网站在线观看| 亚洲日本中文字幕免费在线不卡| 亚洲资源在线看| 国产午夜精品视频免费不卡69堂| 亚洲精品国产精品国自产在线| 亚洲欧洲国产伦综合| 亚洲精品久久久久中文字幕二区| 欧美性猛交xxxx| 国产精品户外野外| 国产精品久久久久久久久免费| 久久久亚洲成人| 亚州精品天堂中文字幕| 欧美激情中文字幕在线| 亚洲一区二区自拍| 欧美亚洲激情在线| 亚洲福利视频网站| 亚洲精品aⅴ中文字幕乱码| 欧美成人一区在线| 色综合老司机第九色激情| 国产欧美欧洲在线观看| 欧美日韩国产限制| 日韩av一区在线观看| 久久久国产一区二区| 51色欧美片视频在线观看| 欧美高跟鞋交xxxxxhd| 国产在线观看不卡| 亚洲最大成人在线|