当前位置:   article > 正文

俄罗斯方块 --基于pygame_俄罗斯方块pyqt pygame

俄罗斯方块pyqt pygame

:主:main.py、color.py、block_template.py、record.json、record.py

1.main.py:主要的执行模块负责 初始化窗口 初始化参数设置  运行操作设置 生成随机的block形状  分数及等级计算  

2.color.py:获取图形颜色

3.block_template.py:方块形状及旋转状态

4.record.json: 存储分数

5.record.py:分数的写入

 


main.py

import pygame, time, random, sys
from pygame.locals import *

from record import *
from color import *
from block_template import *

# 窗口大小
from color import BLACK, YELLOW

WindowWidth = 640
WindowHeight = 480

CellSize = 20  # 单个格子大小

# 10X20 游戏面板
BoardWidth = 10
BoardHeight = 21

Blank = '.'  # 表示空

# 移动时间间隔
MoveSideDuration = 0.2
MoveDownDuration = 0.15

Fps = 25

XMargin = int((WindowWidth - CellSize * BoardWidth) / 2)
YMargin = WindowHeight - (CellSize * BoardHeight) - 5

BorderColor = WHITE  # 边框色
BackgroundColor = BLACK  # 背景色

Colors = (BLUE, GREEN, RED, YELLOW, PURPLE, BROWN)
ColorNames = ['BLUE', 'GREEN', 'RED', 'YELLOW', 'PURPLE', 'BROWN']

TemplateSize = 5

# 各类形状 0 1 2 3 4 5 6
Blocks = [S, Z, J, L, I, O, T]  # 尝试使用字典存储,但是一层层的嵌套太过凌乱,改用两个列表
BlocksNmae = ['S', 'Z', 'J', 'L', 'I', 'O', 'T']


def main():
    global FpsClock, WIN, Font, BigFont
    pygame.init()
    FpsClock = pygame.time.Clock()
    WIN = pygame.display.set_mode((WindowWidth, WindowHeight))
    Font = pygame.font.SysFont('arial', 16)
    BigFont = pygame.font.SysFont('arial', 50)

    while True:
        max = getRecord()
        print('now record is : {}'.format(max))
        score = runGame()

        if score >= max:
            setRecord(score)
            print('you get the highest score : {}'.format(score))
            showTextScreen('get highest score :{}'.format(score))
        else:
            print('game over !')
            showTextScreen('Game Over')


def runGame():
    print('\n----------------------------------\ngame start !')
    startTime = time.time()

    board = getBlankBoard()  # 初始化 board
    # 上次移动时间,用于控制移动频率
    lastMoveDownTime = time.time()
    lastMOveSideTime = time.time()
    lastFallTime = time.time()
    # 各方向是否移动
    movingDown = False
    movingLeft = False
    movingRight = False

    score = 0
    level, fallFrequency = calcStatuse(score)

    fallingBlock = getNewBlock()
    nextBlock = getNewBlock()

    # 主循环
    while True:

        # print(board)

        # 切换到下一个方块
        if fallingBlock == None:
            fallingBlock = nextBlock
            nextBlock = getNewBlock()
            lastFallTime = time.time()

            # game over
            if not isValidPosition(board, fallingBlock):
                return score

        # 键盘事件处理
        for event in pygame.event.get():
            # 松开按键,不做移动
            if event.type == KEYUP:
                # # 暂停
                # if (event.key == K_p):
                #  # WIN.fill(BackgroundColor)
                #
                #  showTextScreen('Paused')  # pause until a key press
                #  print('game pause !')
                #  lastFallTime = time.time()
                #  lastMoveDownTime = time.time()
                #  lastMOveSideTime = time.time()
                if (event.key == K_a):
                    movingLeft = False
                elif (event.key == K_d):
                    movingRight = False
                elif (event.key == K_s):
                    movingDown = False

            elif event.type == KEYDOWN:

                # 退出游戏
                if event.key == K_ESCAPE:
                    pygame.quit()
                    sys.exit()

                # 暂停游戏
                elif event.key == K_p:
                    showTextScreen('Pause ')
                    print('game pause !')
                    lastFallTime = time.time()
                    lastMoveDownTime = time.time()
                    lastMOveSideTime = time.time()


                #  左右移动
                elif (event.key == K_a) and isValidPosition(board, fallingBlock, adjX=-1):
                    fallingBlock['x'] -= 1
                    movingLeft = True
                    movingRight = False
                    lastMOveSideTime = time.time()

                elif (event.key == K_d) and isValidPosition(board, fallingBlock, adjX=1):
                    fallingBlock['x'] += 1
                    movingRight = True
                    movingLeft = False
                    lastMOveSideTime = time.time()

                # 按 W 旋转
                elif (event.key == K_w):
                    fallingBlock['rotation'] = (fallingBlock['rotation'] + 1) % len(Blocks[fallingBlock['shape']])
                    if not isValidPosition(board, fallingBlock):
                        fallingBlock['rotation'] = (fallingBlock['rotation'] - 1) % len(Blocks[fallingBlock['shape']])
                # # 反向旋转
                # elif (event.key == K_q):  # rotate the other direction
                #  fallingBlock['rotation'] = (fallingBlock['rotation'] - 1) % len(Blocks[fallingBlock['shape']])
                #  if not isValidPosition(board, fallingBlock):
                #     fallingBlock['rotation'] = (fallingBlock['rotation'] + 1) % len(
                #        Blocks[fallingBlock['shape']])

                # 加速下降
                elif (event.key == K_s):
                    movingDown = True
                    if isValidPosition(board, fallingBlock, adjY=1):
                        fallingBlock['y'] += 1
                    lastMoveDownTime = time.time()


                elif event.key == K_SPACE:
                    movingDown = False
                    movingLeft = False
                    movingRight = False
                    for i in range(1, BoardHeight):
                        if not isValidPosition(board, fallingBlock, adjY=i):
                            break
                    fallingBlock['y'] += i - 1

        # 处理长按左右键
        if (movingLeft or movingRight) and time.time() - lastMOveSideTime > MoveSideDuration:
            if movingLeft and isValidPosition(board, fallingBlock, adjX=-1):
                fallingBlock['x'] -= 1
            elif movingRight and isValidPosition(board, fallingBlock, adjX=1):
                fallingBlock['x'] += 1
            lastMOveSideTime = time.time()

        # 方块下落
        if movingDown and time.time() - lastMoveDownTime > MoveDownDuration and isValidPosition(board, fallingBlock,
                                                                                                adjY=1):
            fallingBlock['y'] += 1
            lastMoveDownTime = time.time()

        if time.time() - lastFallTime > fallFrequency:
            # see if the block has landed
            if not isValidPosition(board, fallingBlock, adjY=1):

                addToBoard(board, fallingBlock)
                score += removeCompleteLines(board)
                level, fallFrequency = calcStatuse(score)
                fallingBlock = None
            else:

                fallingBlock['y'] += 1
                lastFallTime = time.time()

        WIN.fill(BackgroundColor)
        drawBoard(board)
        drawStatus(score, level)
        drawNextBlock(nextBlock)
        if fallingBlock != None:
            drawBlock(fallingBlock)

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

    for event in pygame.event.get([KEYDOWN, KEYUP]):
        if event.type == KEYDOWN:
            # print(event.key)
            continue
        return event.key
    return None


# 暂停|| game over 显示提示
def showTextScreen(text):
    titleSurf, titleRect = makeTextObjs(text, BigFont, WHITE)
    titleRect.center = (int(WindowWidth / 2) - 3, int(WindowHeight / 2) - 3)
    WIN.blit(titleSurf, titleRect)

    pressKeySurf, pressKeyRect = makeTextObjs('Press a key to play.', Font, WHITE)
    pressKeyRect.center = (int(WindowWidth / 2), int(WindowHeight / 2) + 100)
    WIN.blit(pressKeySurf, pressKeyRect)

    while checkForKeyPress() == None:
        pygame.display.update()

        FpsClock.tick(1000)


def checkForQuit():
    for event in pygame.event.get(QUIT):
        terminate()
    for event in pygame.event.get(KEYUP):
        if event.key == K_ESCAPE:
            terminate()
        pygame.event.post(event)


# 等级和下落频率
def calcStatuse(score):
    level = int(score / 5) + 1
    fallFrequency = 0.3 - (level * 0.03)
    return level, fallFrequency


#  生成一个新的 block
def getNewBlock():
    shapeNum = random.randint(0, len(Blocks) - 1)  # 随机生成形状
    colorNum = random.randint(0, len(Colors) - 1)  # 随机颜色
    newBlock = {'shape': shapeNum,
                'rotation': random.randint(0, len(Blocks[shapeNum]) - 1),  # 随机旋转状态
                'x': int(BoardWidth / 2) - int(TemplateSize / 2),  # 从中间生成
                'y': -3,  # 从屏幕上方生成
                'color': colorNum
                }

    print('生成 {} 型方块,颜色:{}'.format(BlocksNmae[shapeNum], ColorNames[colorNum]))
    return newBlock


def addToBoard(board, block):
    for x in range(TemplateSize):
        for y in range(TemplateSize):

            if Blocks[block['shape']][block['rotation']][y][x] != Blank:
                board[x + block['x']][y + block['y']] = block['color']


def getBlankBoard():
    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, block, adjX=0, adjY=0):
    for x in range(TemplateSize):
        for y in range(TemplateSize):
            isAboveBoard = y + block['y'] + adjY < 0
            if isAboveBoard or Blocks[block['shape']][block['rotation']][y][x] == Blank:
                continue
            if not isOnBoard(x + block['x'] + adjX, y + block['y'] + adjY):
                return False
            if board[x + block['x'] + adjX][y + block['y'] + adjY] != Blank:
                return False
    return True


def isCompleteLine(board, y):
    for x in range(BoardWidth):
        if board[x][y] == Blank:
            return False
    return True


# 消去一行
def removeCompleteLines(board):
    numLinesRemoved = 0
    y = BoardHeight - 1  # y从最底部开始向上扫
    while y >= 0:
        if isCompleteLine(board, y):
            for pullDownY in range(y, 0, -1):
                for x in range(BoardWidth):
                    board[x][pullDownY] = board[x][pullDownY - 1]

            for x in range(BoardWidth):
                board[x][0] = Blank
            numLinesRemoved += 1

        else:
            y -= 1
    return numLinesRemoved


def convertToPixelCoords(boxx, boxy):
    return (XMargin + (boxx * CellSize)), (YMargin + (boxy * CellSize))


def drawBox(boxx, boxy, colorNum, pixelx=None, pixely=None):
    if colorNum == Blank:
        return

    if pixelx == None and pixely == None:
        pixelx, pixely = convertToPixelCoords(boxx, boxy)
    pygame.draw.rect(WIN, Colors[colorNum], (pixelx + 1, pixely + 1, CellSize - 1, CellSize - 1))


def drawBoard(board):
    # 画边框
    pygame.draw.rect(WIN, BorderColor,
                     (XMargin - 3, YMargin - 7, (BoardWidth * CellSize) + 8, (BoardHeight * CellSize) + 8), 5)
    pygame.draw.rect(WIN, BackgroundColor, (XMargin, YMargin, CellSize * BoardWidth, CellSize * BoardHeight))
    for x in range(BoardWidth):
        for y in range(BoardHeight):
            drawBox(x, y, board[x][y])


# 写字 分数和等级
def drawStatus(score, level):
    # 得分
    scoreSurf = Font.render('Score: {}'.format(score), True, WHITE)
    scoreRect = scoreSurf.get_rect()
    scoreRect.topleft = (WindowWidth - 150, 20)
    WIN.blit(scoreSurf, scoreRect)

    # 级别
    levelSurf = Font.render('Level: {}'.format(level), True, WHITE)
    levelRect = levelSurf.get_rect()
    levelRect.topleft = (WindowWidth - 150, 50)
    WIN.blit(levelSurf, levelRect)

    # 历史最高分
    recordSurf = Font.render('record: {}'.format(getRecord()), True, WHITE)
    recordRect = recordSurf.get_rect()
    recordRect.topleft = (WindowWidth - 150, 70)
    WIN.blit(recordSurf, recordRect)


def drawBlock(block, pixelx=None, pixely=None):
    # 一个5x5 列表 ,元素 Blank 和 数字(代表颜色)
    shapeToDraw = Blocks[block['shape']][block['rotation']]
    if pixelx == None and pixely == None:
        pixelx, pixely = convertToPixelCoords(block['x'], block['y'])

    for x in range(TemplateSize):
        for y in range(TemplateSize):
            if shapeToDraw[y][x] != Blank:
                drawBox(None, None, block['color'], pixelx + (x * CellSize), pixely + (y * CellSize))


def drawNextBlock(block):
    nextSurf = Font.render('Next:', True, WHITE)
    nextRect = nextSurf.get_rect()
    nextRect.topleft = (WindowWidth - 150, 160)
    WIN.blit(nextSurf, nextRect)

    drawBlock(block, pixelx=WindowWidth - 150, pixely=200)


# if __name__ == '__main__':
#     main()
main()

color.py

'''
颜色
'''
WHITE = (255, 255, 255)
GRAY = (185, 185, 185)
BLACK = (0, 0, 0)
RED = (155, 0, 0)
GREEN = (0, 155, 0)
BLUE = (0, 0, 155)
YELLOW = (155, 155, 0)
PURPLE = (160, 32, 240)
BROWN = (139, 69, 19)

block_template.py

'''
七种类型 及其 各种旋转状态
'''
S = [['.....',
      '.....',
      '..OO.',
      '.OO..',
      '.....'],
     ['.....',
      '..O..',
      '..OO.',
      '...O.',
      '.....']]

Z = [['.....',
      '.....',
      '.OO..',
      '..OO.',
      '.....'],
     ['.....',
      '..O..',
      '.OO..',
      '.O...',
      '.....']]

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

O = [['.....',
      '.....',
      '.OO..',
      '.OO..',
      '.....']]

J = [['.....',
      '.O...',
      '.OOO.',
      '.....',
      '.....'],
     ['.....',
      '..OO.',
      '..O..',
      '..O..',
      '.....'],
     ['.....',
      '.....',
      '.OOO.',
      '...O.',
      '.....'],
     ['.....',
      '..O..',
      '..O..',
      '.OO..',
      '.....']]

L = [['.....',
      '...O.',
      '.OOO.',
      '.....',
      '.....'],
     ['.....',
      '..O..',
      '..O..',
      '..OO.',
      '.....'],
     ['.....',
      '.....',
      '.OOO.',
      '.O...',
      '.....'],
     ['.....',
      '.OO..',
      '..O..',
      '..O..',
      '.....']]

T = [['.....',
      '..O..',
      '.OOO.',
      '.....',
      '.....'],
     ['.....',
      '..O..',
      '..OO.',
      '..O..',
      '.....'],
     ['.....',
      '.....',
      '.OOO.',
      '..O..',
      '.....'],
     ['.....',
      '..O..',
      '.OO..',
      '..O..',
      '.....']]

record.py

import json
'''
处理历史最高记录
'''

def getRecord():
   with open('record.json', 'r') as f:
      data = json.load(f)
   return data['score']

def setRecord(score):
   data={'score':score }
   with open('record.json', 'w') as f:
      json.dump(data,f)

record.json

{"score": 10}

运行效果图:


 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/寸_铁/article/detail/832638
推荐阅读
相关标签
  

闽ICP备14008679号