You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

505 lines
14 KiB

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