这个小游戏是我许久以前做的,像素画风,也没有炫酷的消除动画和动听的背景音乐,但也着实是让我重温了一把用(盗版的)15合1的游戏卡玩游戏的童年时光。
import pygame, sys, time, random, pprint
class Diamonds:
def __init__(self):
pygame.init()
self.row = 15
self.col = 8
self.diamond_size = 50
self.screen = pygame.display.set_mode((self.col * self.diamond_size, self.row * self.diamond_size), 0, 32)
pygame.display.set_caption("钻石方块")
self.init()
# 游戏初始化
def init(self):
self.finished = False
self.distribution = [["" for i in range(self.col)] for i in range(self.row)]
self.diamonds = []
self.score = 0
group = DiamondGroup(self.screen, -3, self.col // 2, 50)
self.diamonds.append(group)
# 计时器归零
self.start_time = time.time()
self.pace = 1 / 3
self.steps = 0
def running(self):
while True:
self.check_events()
if self.finished:
font = pygame.font.SysFont(None, 100)
text = font.render("Restart: R", True, "white", None)
self.screen.blit(text, (10, 10))
pygame.display.flip()
continue
self.update()
self.draw()
def check_events(self):
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
if event.type == pygame.KEYDOWN:
# 按下 键,在全屏和原始窗口间切换
diamond = self.diamonds[-1]
# 在全屏模式下关闭窗口
elif event.key == pygame.K_q:
sys.exit()
# 移动钻石
elif event.key == pygame.K_LEFT:
# 碰撞阻止
if not self.check_coincidence(-1):
diamond.move(event.key)
elif event.key == pygame.K_RIGHT:
if not self.check_coincidence(1):
diamond.move(event.key)
# 加快对象更新的速度
elif event.key == pygame.K_DOWN:
self.start_time = time.time()
self.pace *= 1/3
self.steps = 0
# 变换方块排序
elif event.key == pygame.K_SPACE:
diamond.change_order()
# 重新启动
elif event.key == pygame.K_r and self.finished:
self.init()
elif event.type == pygame.KEYUP:
# 恢复初始速度
if event.key == pygame.K_DOWN:
self.start_time = time.time()
self.pace *= 3
self.steps = 0
# 每隔pace秒,更新一次对象
def update(self):
if (time.time() - self.start_time) // self.pace > self.steps:
self.steps += 1
# 先画出移动再检查移动
self.check_collision()
self.diamonds[-1].fall()
diamond_on_line = self.check_line()
# 多更新几次
while diamond_on_line:
self.emit_line(diamond_on_line)
self.draw()
time.sleep(0.2)
diamond_on_line = self.check_line()
# pprint.pprint(self.distribution)
# 更新屏幕情况
def update_distribution(self):
for diamond in self.diamonds:
for diamond in diamond.diamonds:
row, col = diamond.row, diamond.col
self.distribution[row][col] = diamond.colour
# pprint.pprint(self.distribution)
# 检查碰撞
def check_collision(self):
diamond = self.diamonds[-1]
if diamond.collide_on_bottom() or diamond.collide_list(self.diamonds):
# 更新方块位置
self.update_distribution()
# 把新的方块组放进列表
new_diamond = DiamondGroup(self.screen, -4, 4, self.diamond_size)
self.diamonds.append(new_diamond)
# 结束游戏
if diamond.row <= -1:
self.finished = True
def check_coincidence(self, i):
group = self.diamonds[-1]
diamond = group.diamonds[-1]
for g in self.diamonds[:-1]:
for d in g.diamonds:
if diamond.row == d.row and diamond.col + i == d.col:
return True
return False
# 分四个方向检查连线
def check_line(self):
diamond_on_line = []
for row in range(self.row):
for col in range(self.col):
# 由左往右
if self.distribution[row][col] and col + 2 <= self.col - 1:
if self.distribution[row][col] == self.distribution[row][col + 1] == self.distribution[row][col + 2]:
diamond_on_line += [(col, row), (col + 1, row), (col + 2, row)]
# 检查连线上剩余的方块
for c in range(col + 3, self.col):
if self.distribution[row][c] == self.distribution[row][col]:
diamond_on_line += [(c, row)]
else:
break
# 由上到下
if self.distribution[row][col] and row + 2 <= self.row - 1:
if self.distribution[row][col] == self.distribution[row + 1][col] == self.distribution[row + 2][col]:
diamond_on_line += [(col, row), (col, row + 1), (col, row + 2)]
# 检查连线上剩余的方块
for r in range(row + 3, self.row):
if self.distribution[r][col] == self.distribution[row][col]:
diamond_on_line += [(col, r)]
else:
break
# 从左上到右下
if self.distribution[row][col] and row + 2 <= self.row - 1 and col + 2 <= self.col -1:
if self.distribution[row][col] == self.distribution[row + 1][col + 1] == self.distribution[row + 2][col + 2]:
diamond_on_line += [(col, row), (col + 1, row + 1), (col + 2, row + 2)]
# 检查连线上剩余的方块
for i in range(3, min(self.row - row, self.col - col)):
if self.distribution[row + i][col + i] == self.distribution[row][col]:
diamond_on_line += [(col + i, row + i)]
else:
break
# 从左下到右上
if self.distribution[row][col] and row - 2 >= 0 and col + 2 <= self.col -1:
if self.distribution[row][col] == self.distribution[row - 1][col + 1] == self.distribution[row - 2][col + 2]:
diamond_on_line += [(col, row), (col + 1, row - 1), (col + 2, row - 2)]
# 检查连线上剩余的方块
for i in range(3, min(self.row - row, self.col - col)):
if self.distribution[row - i][col + i] == self.distribution[row][col]:
diamond_on_line += [(col + i, row - i)]
else:
break
return diamond_on_line
# 消除一条连线上的方块
def emit_line(self, diamonds):
for col, row in diamonds:
# 遍历所有方块
for d_group in self.diamonds:
for d in d_group.diamonds:
# 删除方块,更新方块组,修改方块分布图
if d.row == row and d.col == col:
d_group.diamonds.remove(d)
# 得1分
self.score += 1
if len(d_group.diamonds) == 0:
self.diamonds.remove(d_group)
elif d_group.diamonds != []:
d_group.row = d_group.diamonds[0].row
self.distribution[row][col] = ""
self.update_diamonds()
self.update_diamonds()
self.update_diamonds()
# 强迫下方有空格的方块向下移动
def update_diamonds(self):
for group in self.diamonds[:-1]:
for diamond in group.diamonds:
try:
row, col = diamond.row, diamond.col
while self.distribution[row + 1][col] == "":
# 清除原位置的颜色,继续向下
diamond.row += 1
self.distribution[row + 1][col] = diamond.colour
self.distribution[row][col] = ""
if row + 1 == self.row:
break
row += 1
except :
pass
def show_score(self):
font = pygame.font.SysFont(None, 20)
text = font.render(f"{self.score}", True, "white", None)
self.screen.blit(text, (self.col * self.diamond_size - 40, 10))
def draw(self):
self.screen.fill((30, 30, 30))
for diamond in self.diamonds:
diamond.draw()
self.show_score()
pygame.display.flip()
class Diamond:
def __init__(self, screen, row, col, size, colour):
self.row, self.col = row, col
self.size = size
self.colour = colour
self.screen = screen
self.rect = pygame.Rect(col * size, row * size, size, size)
def fall(self, pace):
self.rect.y += self.size * pace
self.row += pace
def draw(self):
self.rect.y = self.row * self.size
pygame.draw.rect(self.screen, self.colour, self.rect, 0)
pygame.draw.rect(self.screen, "white", self.rect, 1)
class DiamondGroup:
def __init__(self, screen, row, col, size):
self.col, self.row = col, row
self.size = size
self.span = 1
self.bottom_row = self.row + 2
self.screen = screen
self.diamonds = []
self.colours = ["yellow", "green", "purple", "blue", "red", "white"]
for i in range(3):
diamond = Diamond(screen, row + i, col, size, random.choice(self.colours))
diamond.index = i
self.diamonds.append(diamond)
def fall(self):
for diamond in self.diamonds:
diamond.fall(self.span)
self.row += 1
def move(self, key):
"""水平移动方块组"""
if key == pygame.K_LEFT and 0 <= self.col - 1:
self.col -= 1
for diamond in self.diamonds:
diamond.rect.left -= self.size
diamond.col -= 1
elif key == pygame.K_RIGHT and (self.col + 2) * self.size <= self.screen.get_width():
self.col += 1
for diamond in self.diamonds:
diamond.rect.left += self.size
diamond.col += 1
# 碰撞屏幕底部,速度降为零
def collide_on_bottom(self):
if self.diamonds[-1].rect.bottom >= self.screen.get_height():
self.span = 0
return True
else:
return False
# 方块是否与列表中的对象碰撞
def collide_list(self, diamonds):
for diamond_group in diamonds:
if self.diamonds[-1].row + 1 == diamond_group.diamonds[0].row and self.diamonds[-1].col == diamond_group.diamonds[0].col:
self.span = 0
return True
# 由下往上变换三颗钻石的颜色
def change_order(self):
d1, d2, d3 = self.diamonds
d1.colour, d2.colour, d3.colour = d3.colour, d1.colour, d2.colour
# 从下往上绘制三颗方块
def draw(self):
for diamond in self.diamonds:
diamond.draw()
game = Diamonds()
game.running()
轻映录屏 2022-07-01 21-07-32



