# 主程序(启动)
import pygame, sys # 导入pygame模块
from day07.tetris.settings import Setting # 导入settings模块中的Setting类
from day07.tetris.Tetromino import Tetromino # 导入Tetromino模块中的Tetromino类
pygame.init() # 初始化窗口
screen = pygame.display.set_mode((525, 550)) # 创建屏幕(窗口),并设置屏幕大小
pygame.display.set_caption("俄罗斯方块")
clockObj = pygame.time.Clock() # 确定程序运行最大帧速度
set = Setting() # 创建Settings对象
wall = [[None for col in range(0, 10)] for row in range(0, 20)] # 打墙
# wall = [[None,None,None,None,....],[None,None,None,None,....],....]
RUNNING = 0 # 运行状态
PAUSE = 1 # 暂停状态
GAMEOVER = 2 # 结束状态
state = RUNNING
def full_cell(row): # 检查某一行是否满了
# row:当前行,有一个cell为None就是不满
for cell in wall[row]:
if cell is None:
return False
return True
def delete_row(row): # 删除某一行
while row > 0:
col = 0
while col < 10:
wall[row][col] = wall[row - 1][col]
col += 1
row -= 1
for cell in wall[0]:
cell = None
scoreTable = [0, 1, 5, 10, 50]
def destory_lines(): # 删除若干行
global lines, score, scoreTable
one_time_lines = 0
row = 0
while row < 19:
if full_cell(row):
delete_row(row)
one_time_lines += 1
row += 1
score += scoreTable[one_time_lines]
lines += one_time_lines
level = 1;
lines = 0;
score = 0
def score_blit(): # 绘制分数和等级
fontObj = pygame.font.Font("arial.ttf", 35) # 得到字体对象
scoreObj = fontObj.render("SCORE:" + str(score), True, (50, 20, 240)) # 得到绘制的文本
linesObj = fontObj.render("LINES:" + str(lines), True, (50, 20, 240))
levelObj = fontObj.render("LEVEL:" + str(level), True, (50, 20, 240))
screen.blit(scoreObj, (310, 150)) # 绘制分数
screen.blit(linesObj, (310, 205)) # 绘制行
screen.blit(levelObj, (310, 260)) # 绘制等级
speed = 40 # 下落的速度
index = 0 # 下落的频率
def drop_action(): # 下落流程的控制
global speed, index, score, lines, level
speed = 40 - (lines // 100) # 每100行速度减1
if speed < 1: speed = 1
level = 41 - speed
index += 1
if index % speed == 0:
soft_drop()
if index > 10000:
index = 0
def can_drop(): # 该方法主要用来判断图形是否可以继续下落
global currentOne
# 不能下落情况:1.当图形中有任意一个方块触底的时候
# 2.当图形中有任意一个方块落到墙不是None的位置
for cell in currentOne.cells:
row = cell.row
col = cell.col
if row == 19: return False
if col >= 0 and col < 10 and row + 1 > 0 and row + 1 <= 19 and wall[row + 1][col] is not None:
return False
return True
# 不能继续下落的方块固定在墙上
def land_into_wall():
global currentOne
for cell in currentOne.cells: # 利用循环将图形中的每个小方块取出来
row = cell.row
col = cell.col
wall[row][col] = cell # 将小方块放到墙的列表中去,这样该位置的None就被替换了
def soft_drop(): # 软下落
global currentOne, nextOne
if can_drop():
currentOne.drop()
else:
land_into_wall()
destory_lines()
currentOne = nextOne
nextOne = Tetromino.rand_one()
def hard_drop_action(): # 硬下落
global currentOne, nextOne # 声明此处的变量是全部变量不是局部变量
while can_drop():
soft_drop() # 调用软下落
destory_lines()
land_into_wall()
currentOne = nextOne
nextOne = Tetromino.rand_one()
# 绘制当前图形和下一个图形
currentOne = Tetromino.rand_one() # 当前图形
nextOne = Tetromino.rand_one() # 下一个图形
def current_next_blit():
for cell in currentOne.cells: # 将当前图形中的每个小方块取出来
x = cell.col
y = cell.row
screen.blit(cell.img, (x * 26 + 15 - 1, y * 26 + 15 - 1)) # 绘制当前图形
for cell in nextOne.cells: # 将下一个图形的每一个小方块取出来
x = cell.col
y = cell.row
screen.blit(cell.img, ((x + 10) * 26 + 15, (y + 1) * 26 + 15)) # 绘制下一个图形
def bg_wall_blit():
'''绘制背景图和墙壁'''
screen.blit(set.bgImage, (0, 0)) # 绘制背景图
# 绘制墙壁
for row in range(0, 20):
for col in range(0, 10):
if wall[row][col] is None: # 绘制空白墙
pygame.draw.rect(screen, (0, 0, 0), (col * 26 + 15, row * 26 + 15, 26, 26), 1)
else: # 绘制实心墙(图性墙)
screen.blit(wall[row][col].img, (col * 26 + 15 - 1, row * 26 + 15 - 1))
# 判断是否越界
def out_of_bounds():
for cell in currentOne.cells:
col = cell.col
if col < 0 or col > 9:
return True
return False
# 判断是否重合
def coincide():
for cell in currentOne.cells:
row = cell.row
col = cell.col
if wall[row][col] is not None:
return True
return False
# 左移流程的控制
def move_left_action():
currentOne.move_left()
if out_of_bounds() or coincide():
move_right_action()
# 右移流程的控制
def move_right_action():
currentOne.move_right()
if out_of_bounds() or coincide():
move_left_action()
def process_running(key): # 运行状态下按键时的控制
global state
if key == pygame.K_LEFT: move_left_action() # 左键 向左移动
if key == pygame.K_RIGHT: move_right_action() # 右键 向右移动
if key == pygame.K_SPACE: hard_drop_action() # 空格键硬下落
if key == pygame.K_UP: rotate_right_action() # 向右旋转
def rotate_right_action():
currentOne.rotate_right()
if out_of_bounds() or coincide():
currentOne.rotate_left() # 向左旋转
def rotate_left_action():
currentOne.rotate_right()
if out_of_bounds() or coincide():
currentOne.rotate_right() # 向右旋转
def action():
bg_wall_blit() # 调用绘制背景图和墙壁的方法
current_next_blit() # 调用绘制当前图形和下一个图形
# hard_drop_action()# 调用硬下落方法
score_blit() # 调用绘制分数,等级,消去的行
drop_action() # 下落流程的控制
def main():
while True:
# 遍历事件的列表(鼠标事件,键盘事件,。。。)
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
if event.type == pygame.KEYDOWN:
process_running(event.key)
pygame.display.update() # 刷新
clockObj.tick(60) # 设置帧数
action() # 调用action方法
if __name__ == '__main__':
main() # 启动程序
class State:
def __init__(self,row0,col10,row1,col1,row2,col2,row3,col3):
self.row0 = row0
self.col0 = col10
self.row1 = row1
self.col1 = col1
self.row2 = row2
self.col2 = col2
self.row3 = row3
self.col3 = col3
# 加载图片
import pygame
class Setting:
def __init__(self):
self.bgImage = pygame.image.load("img/tetris.jpg")
self.T = pygame.image.load("img/T.jpg")
self.S = pygame.image.load("img/S.jpg")
self.Z = pygame.image.load("img/Z.jpg")
self.O = pygame.image.load("img/O.jpg")
self.L = pygame.image.load("img/L.jpg")
self.J = pygame.image.load("img/J.jpg")
self.I = pygame.image.load("img/I.jpg")
self.pause = pygame.image.load("img/pause.jpg")
self.gameover = pygame.image.load("img/game-over.jpg")
#小方块类
class Cell:
def __init__(self,row,col,img):
self.row=row
self.col=col
self.img=img
def drop(self):
"下降,纵坐标+1"
self.row += 1
def move_left(self):
"左移,横坐标-1"
self.col -= 1
def move_right(self):
"右移,横坐标+1"
self.col +=1
# 图形类
from day07.tetris.cell import Cell
from day07.tetris.settings import Setting
import random
from day07.tetris.state import State
class Tetromino:
'''基类'''
index = 1000
def drop(self): # 下降
for cell in self.cells: # 循环获取方块列表中的所有小方块
cell.drop() # 每个小方块都调用下降的方法
def move_left(self): # 左移
for cell in self.cells: # 循环获取方块列表中的所有小方块
cell.move_left() # 每个小方块都调用左移的方法
def move_right(self): # 右移
for cell in self.cells: # 循环获取方块列表中的所有小方块
cell.move_right() # 每个小方块都调用右移的方法
@classmethod
def rand_one(cls): # 使用类方法是因为可以直接用类名调用,不需要创建Tetromino对象
i = random.randint(1,7) # 随机产生1-7之间的任意整数
if i == 1:return T() # 产生不同的整数就返回不同的图形对象,保证每次产生图形的随机性
if i == 2: return J()
if i == 3:return O()
if i == 4: return Z()
if i == 5:return S()
if i == 6: return I()
if i == 7:return L()
def rotate_right(self): #向右旋转
self.index += 1
s = self.states[self.index % len(self.states)]
row = self.cells[3].row
col = self.cells[3].col
self.cells[0].row = row+s.row1
self.cells[1].row = row + s.row2
self.cells[2].row = row + s.row3
self.cells[0].col = col + s.col0
self.cells[1].col = col + s.col1
self.cells[2].col = col + s.col2
def rotate_left(self): # 向左旋转
self.index += 1
s = self.states[self.index % len(self.states)]
row = self.cells[3].row
col = self.cells[3].col
self.cells[0].row = row - s.row1
self.cells[1].row = row - s.row2
self.cells[2].row = row - s.row3
self.cells[0].col = col - s.col0
self.cells[1].col = col - s.col1
self.cells[2].col = col - s.col2
set = Setting() # 创建Settings()对象
class T(Tetromino):
def __init__(self):
self.cells = [Cell(1, 4, set.T), Cell(0, 3, set.T),
Cell(0, 5, set.T), Cell(0, 4, set.T)]
self.states = [State(1, 0, 0, -1, 0, 1, 0, 0), State(0, -1, -1, 0, 1, 0, 0, 0),
State(-1, 0, 0, 1, 0, -1, 0, 0), State(0, 1, 1, 0, -1, 0, 0, 0)]
class L(Tetromino):
def __init__(self):
self.cells = [Cell(1, 3, set.L), Cell(0, 3, set.L),
Cell(0, 5, set.L), Cell(0, 4, set.L)]
self.states = [State( 1, -1, 0, -1, 0, 1, 0, 0), State( -1, -1, -1, 0, 1, 0, 0, 0),
State(-1, 1, 0, 1, 0, -1, 0, 0), State( 1, 1, 1, 0, -1, 0, 0, 0)]
class S(Tetromino):
def __init__(self):
self.cells = [Cell(1, 4, set.S), Cell(1, 3, set.S),
Cell(0, 4, set.S), Cell(0, 5, set.S)]
self.state = [State(0,0,0,-1,-1,0,-1,1), State(0,0,-1,0,0,1,1,1)]
class O(Tetromino):
def __init__(self):
self.cells = [Cell(1, 3, set.O), Cell(0, 4, set.O),
Cell(0, 3, set.O), Cell(1, 4, set.O)]
self.state = [State(1,0,0,1,0,0,1,1), State(1,0,0,1,0,0,1,1)]
class I(Tetromino):
def __init__(self):
self.cells = [Cell(0, 4, set.I), Cell(0, 3, set.I),
Cell(0, 5, set.I), Cell(0, 6, set.I)]
self.state = [State(0,0,0,-1,0,1,0,2), State(0,0,-1,0,1,0,2,0)]
class Z(Tetromino):
def __init__(self):
self.cells = [Cell(1, 4, set.Z), Cell(0, 3, set.Z),
Cell(0, 4, set.Z), Cell(1, 5, set.Z)]
self.states = [State(0, 0, -1, -1, -1, 0, 0, 1), State(0, 0, -1, 1, 0, 1, 1, 0)]
class J(Tetromino):
def __init__(self):
self.cells = [Cell(1, 5, set.J), Cell(0, 3, set.J),
Cell(0, 5, set.J), Cell(0, 4, set.J)]
self.states = [State( 1, 1, 0, -1, 0, 1, 0, 0), State(1, -1, -1, 0, 1, 0, 0, 0),
State( -1, -1, 0, 1, 0, -1, 0, 0), State(-1, 1, 1, 0, -1, 0, 0, 0)]
相似问题