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

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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