diff --git a/main.py b/main.py new file mode 100644 index 0000000..44bd130 --- /dev/null +++ b/main.py @@ -0,0 +1,504 @@ +import pygame +from pygame.locals import * +from sys import exit +import random + +# 初始化 +pygame.init() + +# 常量 +MAX_I = 34 # 让地图预留4行作为放入方块的地方 +MAX_J = 15 +SIZE = 15 + +COLORS = [(0, 0, 0), (255, 0, 0), (0, 255, 0), (0, 0, 255), (255, 255, 0), (255, 255, 255)] + +gameMap = [[0 for j in range(MAX_J + 3)] for i in range(MAX_I + 3)] # 全局地图 +tetrisHeight = 0 # 塔高 + +# 基本方块 +tetrises = [ + [ + [1, 0, 0, 0], + [1, 0, 0, 0], + [1, 0, 0, 0], + [1, 0, 0, 0] + ], + [ + [0, 0, 0, 0], + [0, 1, 1, 0], + [0, 1, 1, 0], + [0, 0, 0, 0] + ], + [ + [1, 0, 0, 0], + [1, 1, 0, 0], + [0, 1, 0, 0], + [0, 0, 0, 0] + ], + [ + [0, 1, 0, 0], + [1, 1, 0, 0], + [1, 0, 0, 0], + [0, 0, 0, 0] + ], + [ + [0, 1, 0, 0], + [1, 1, 1, 0], + [0, 0, 0, 0], + [0, 0, 0, 0] + ], + [ + [1, 0, 0, 0], + [1, 1, 1, 0], + [0, 0, 0, 0], + [0, 0, 0, 0] + ], + [ + [0, 0, 1, 0], + [1, 1, 1, 0], + [0, 0, 0, 0], + [0, 0, 0, 0] + ] +] + +# 分数 +score = 10 + +# 等级 +level = 10 + +# 音乐开关 +isMusic = True + +# 游戏暂停 +isPause = False + + +# 播放音乐 +def playMyMusic(src): + if isMusic: + sound = pygame.mixer.Sound(src) + sound.play() + + +# 方块类 +class Tetris: + __i = 0 + __j = 0 + __color = 0 + __nextColor = 0 + __nextType = 0 + + def __init__(self): + self.__nextColor = random.randint(0, 3) + 1 # 一共四种颜色 + self.__nextType = random.randint(0, 6) # 一共七种类型 + self.createTetris() + + def createTetris(self): + # 根据类型调整一下快出现的位置 + if self.__nextType == 0: + self.__i = 1 + self.__j = 7 + else: + self.__i = 2 + self.__j = 6 + + self.__color = self.__nextColor + + # 根据方块模板,放置整个到地图 + for i in range(4): + for j in range(4): + if tetrises[self.__nextType][i][j] == 1: + if gameMap[self.__i + i][self.__j + j] == 0: + gameMap[self.__i + i][self.__j + j] = self.__color + else: + print('游戏失败!') + exit() + return -1 + + # 产生下一种类型和颜色 + self.__nextColor = random.randint(0, 3) + 1 # 一共四种颜色 + self.__nextType = random.randint(0, 6) # 一共七种类型 + + playMyMusic('music/get.wav') + + def moveDown(self): + global gameMap + + # 判断是否可以下移 + for j in range(4): + for i in range(3, -1, -1): + if gameMap[self.__i + i][self.__j + j] == self.__color: + # 判断是否到底 + if self.__i + i + 1 > MAX_I: + return 1 + + # 判断前面是否有东西 + if gameMap[self.__i + i + 1][self.__j + j] != 0: + return 1 + + break + + # 下移 + for j in range(4): + for i in range(3, -1, -1): + if gameMap[self.__i + i][self.__j + j] == self.__color: + gameMap[self.__i + i][self.__j + j], gameMap[self.__i + i + 1][self.__j + j] = \ + gameMap[self.__i + i + 1][self.__j + j], gameMap[self.__i + i][self.__j + j] + + self.__i += 1 + + def stopTetris(self): + global tetrisHeight + + flag = True + + for i in range(4): + for j in range(4): + if gameMap[self.__i + i][self.__j + j] == self.__color: + gameMap[self.__i + i][self.__j + j] += 10 + + # 找到第一个颜色方块 + if flag: + tetrisHeight = MAX_I - self.__i if tetrisHeight < MAX_I - self.__i else tetrisHeight + flag = False + + self.deleteRow() + + def moveLeft(self): + # 判断是否能够左移 + for i in range(4): + for j in range(4): + if gameMap[self.__i + i][self.__j + j] == self.__color: + if self.__j + j - 1 < 0: + return 1 + if gameMap[self.__i + i][self.__j + j - 1] != 0: + return 1 + + break + + # 左移 + for i in range(4): + for j in range(4): + if gameMap[self.__i + i][self.__j + j] == self.__color: + gameMap[self.__i + i][self.__j + j], gameMap[self.__i + i][self.__j + j - 1] = \ + gameMap[self.__i + i][self.__j + j - 1], gameMap[self.__i + i][self.__j + j] + + self.__j -= 1 + + def moveRight(self): + # 判断是否能右移 + for i in range(4): + for j in range(3, -1, -1): + if gameMap[self.__i + i][self.__j + j] == self.__color: + if self.__j + j + 1 >= MAX_J: + return 1 + if gameMap[self.__i + i][self.__j + j + 1] != 0: + return 1 + + break + + # 右移 + for i in range(4): + for j in range(3, -1, -1): + if gameMap[self.__i + i][self.__j + j] == self.__color: + gameMap[self.__i + i][self.__j + j], gameMap[self.__i + i][self.__j + j + 1] = \ + gameMap[self.__i + i][self.__j + j + 1], gameMap[self.__i + i][self.__j + j] + + self.__j += 1 + + def change(self): + tMap = [[0 for j in range(4)] for i in range(4)] + + # 将所有方块顺时针旋转90度赋值到 tMap 中 + i = 0 + k = 3 + while i < 4: + for j in range(4): + if MAX_I > self.__i + j >= 0 and MAX_J > self.__j + k >= 0 and gameMap[self.__i + j][ + self.__j + k] == 0 or \ + gameMap[self.__i + j][self.__j + k] == self.__color: + tMap[j][k] = gameMap[self.__i + i][self.__j + j] + + else: + return + + i += 1 + k -= 1 + + # 赋值 + for i in range(4): + for j in range(4): + gameMap[self.__i + i][self.__j + j] = tMap[i][j] + + playMyMusic('music/change.wav') + + def deleteRow(self): + # 找到有方块的最后一行 + lastRow = 0 + t = False + for i in range(3, -1, -1): + for j in range(4): + if gameMap[self.__i + i][self.__j + j] == self.__color + 10: + lastRow = self.__i + i + t = True + break + if t: + break + + for i in range(lastRow, MAX_I - tetrisHeight - 1, -1): + for j in range(MAX_J): + if gameMap[i][j] == 0: + break + else: + global score + score += 10 + playMyMusic('music/delete.wav') + + # 删除行 + gameMap.pop(i) + gameMap.insert(0, [0 for j in range(MAX_J + 3)]) + + # 增加等级 + global level + level += score // 1000 + + # 再次调用删除行函数操作删行 + self.deleteRow() + + def nextTetris(self): + return self.__nextType, self.__nextColor + + +# 全局变量 +screen = '' # 屏幕 +gameTetris = Tetris() + + +# 绘制游戏地图 +def drawMap(): + # 画上边框 + for i in range(MAX_I - 4): + # 画右边 + myRect(screen, COLORS[2], [0, i * SIZE, SIZE, SIZE]) + # 画左边 + myRect(screen, COLORS[2], [(MAX_J + 1) * SIZE, i * SIZE, SIZE, SIZE]) + + # 画下面 + for i in range(MAX_J + 2): + myRect(screen, COLORS[2], [i * SIZE, (MAX_I - 4) * SIZE, SIZE, SIZE]) + + # 给地图涂色 + for i in range(4, MAX_I): + for j in range(MAX_J): + t = gameMap[i][j] - 10 if gameMap[i][j] > 10 else gameMap[i][j] + + myRect(screen, COLORS[t], [(j + 1) * SIZE, (i - 4) * SIZE, SIZE, SIZE]) + + # 文字内容,下一个方块 + drawMyText(screen, "下一块:", 305, 18, 15, (255, 255, 255)) + + # 绘制下一块方块 + startX = 270 + startY = 30 + + nextType, nextColor = gameTetris.nextTetris() + + # 显示下一个方块的背景 + pygame.draw.rect(screen, COLORS[5], [startX, startY, SIZE * 4, SIZE * 4], 1) + mySize = SIZE * 0.8 # 缩小下一个方块大小 + + # 根据形状,修改方块的位置(居中) + if nextType == 0: + startX += (SIZE * 4 - mySize) / 2 + startY += (SIZE * 4 - mySize * 4) / 2 + elif nextType == 2 or nextType == 3: + startX += (SIZE * 4 - mySize * 2) / 2 + startY += (SIZE * 4 - mySize * 3) / 2 + elif nextType == 4 or nextType == 5 or nextType == 6: + startX += (SIZE * 4 - mySize * 3) / 2 + startY += (SIZE * 4 - mySize * 2) / 2 + elif nextType == 1: + startX += (SIZE * 4 - mySize * 4) / 2 + startY += (SIZE * 4 - mySize * 4) / 2 + + # 绘制下一个方块 + for i in range(4): + for j in range(4): + # 绘制有图形地方 + if tetrises[nextType][i][j] == 1: + # 根据不同的 + myRect(screen, COLORS[nextColor], [startX + j * mySize, startY + i * mySize, mySize, mySize]) + + color = (255, 0, 0) + # 绘制分数 + scoreText = "分数:{}".format(score) + drawMyText(screen, scoreText, 300, 120, 15, color) + + # 等级 + drawMyText(screen, "等级:{}".format(level), 300, 140, 15, color) + + color = (255, 0, 255) + # 绘制音乐 + textMusic = "音乐:" + + if isMusic: + textMusic += "开" + else: + textMusic += '关' + + drawMyText(screen, textMusic, 300, 220, 15, color) + + # 绘制游戏暂停 + textPause = "暂停:" + + if isPause: + textPause += "开" + else: + textPause += '关' + + drawMyText(screen, textPause, 300, 240, 15, color) + + + # 绘制键值 + color = (130, 205, 255) + drawMyText(screen, "↑ 旋转90度", 300, 300, 15, color) + drawMyText(screen, "← 向左移动", 300, 320, 15, color) + drawMyText(screen, "→ 向右移动", 300, 340, 15, color) + drawMyText(screen, "↓ 快速向下", 300, 360, 15, color) + + # 绘制背景 + startY = 410 + color = (255, 255, 0) + flower = "★" + drawMyText(screen, flower, 300, startY + 0, 15, color) + flower = "★★" + drawMyText(screen, flower, 300, startY + 20, 15, color) + flower = "★★★" + drawMyText(screen, flower, 300, startY + 40, 15, color) + + +# 游戏初始化 +def initGame(): + # 将地图倒数对大行全部赋值为-1 + for j in range(MAX_J): + gameMap[MAX_I][j] = -1 + + # 将地图倒数最大列全部赋值为-1 + for i in range(MAX_I): + gameMap[i][MAX_J] = -1 + + # 分数初始化 + score = 0 + + # 加载背景音乐文件 + pygame.mixer.music.load('music/bgm.mp3') + + if isMusic: + # 播放背景音乐,第一个参数为播放的次数(-1表示无限循环),第二个参数是设置播放的起点(单位为秒) + pygame.mixer.music.play(-1, 0.0) + + +# 绘制有边框矩形 +def myRect(screen, colorRect, pos, lineColor=COLORS[0], bold=1): + pygame.draw.rect(screen, colorRect, pos) + pygame.draw.rect(screen, lineColor, pos, bold) + + +# 绘制我的文字 +def drawMyText(screen, text, x, y, bold, fColor, bColor=None): + # 通过字体文件获得字体对象 + fontObj = pygame.font.Font('font/SIMYOU.TTF', bold) + + # 配置要显示的文字 + textSurfaceObj = fontObj.render(text, False, fColor, bColor) + + # 获得要显示的对象的rect + textRectObj = textSurfaceObj.get_rect() + + # 设置显示对象的坐标 + textRectObj.center = (x, y) + + # 绘制字体 + screen.blit(textSurfaceObj, textRectObj) + + +# 游戏主体 +def my_game(): + # 得到屏幕 + global screen, isMusic, isPause + screen = pygame.display.set_mode((350, 465)) + + # 设置标题 + pygame.display.set_caption('俄罗斯方块') + + # 初始化游戏 + initGame() + + # 用于控制下落速度 + count = 0 + + while True: + + if count == 3 + level * 2: + if not isPause: # 只有暂停是 False 才能下移 + if gameTetris.moveDown() == 1: + gameTetris.stopTetris() + gameTetris.createTetris() + + count = 0 + + # 事件判断 + for event in pygame.event.get(): + if event.type == pygame.QUIT: + # 停止播放背景音乐 + pygame.mixer.music.stop() + + pygame.quit() + exit() + elif event.type == pygame.MOUSEBUTTONDOWN: + # 控制音乐开关 + if 270 < event.pos[0] < 330 and 210 < event.pos[1] < 225: + # 处理音乐开关 + if isMusic: + # 停止播放背景音乐 + pygame.mixer.music.stop() + else: + # 播放背景音乐,第一个参数为播放的次数(-1表示无限循环),第二个参数是设置播放的起点(单位为秒) + pygame.mixer.music.play(-1, 0.0) + + isMusic = not isMusic + + # 处理游戏暂停开关 + if 270 < event.pos[0] < 327 and 233 < event.pos[1] < 248: + isPause = not isPause + + if isPause: + pygame.display.set_caption('俄罗斯方块:已暂停') + else: + pygame.display.set_caption('俄罗斯方块') + + elif event.type == pygame.KEYDOWN: + if event.key == K_UP: + gameTetris.change() + + keyPressList = pygame.key.get_pressed() + + if keyPressList[K_DOWN]: + gameTetris.moveDown() + elif keyPressList[K_LEFT]: + gameTetris.moveLeft() + elif keyPressList[K_RIGHT]: + gameTetris.moveRight() + + screen.fill((0, 0, 0)) + drawMap() + pygame.display.update() + count += 1 + + pygame.time.Clock().tick(10) + + +if __name__ == '__main__': + my_game()