突发奇想写了个落方块的小游戏。
回车键是开始,方向键控制方块走向,无向上键。
游戏不难,下面是可复现的代码:
import pygame
import time
from Tetris_WangDada.blocks_by_myself import *
from pygame.locals import *
class Tetris:
def __init__(self):
pygame.init()
pygame.display.set_caption("乌克兰方块")
self.screen = pygame.display.set_mode(SCREEN_RECT.size)
pygame.time.set_timer(BLOCK_DOWN, BLOCK_DOWN_TIME)
self.block = None
self.bg_color = (230, 230, 230)
self.line_color = (0, 0, 180)
self.start_flag = False
self.block_colcor = (0, 0, 255)
self.block_width = 0
self.block_fall_time_monitoring = 0
self.time_block_down = 0
@staticmethod
def __end():
pygame.quit()
print("游戏结束")
def draw_funs(self):
self.screen.fill(self.bg_color)
self.draw_lines()
self.draw_block(self.block)
self.draw_screen_by_matrix()
def start(self):
print("游戏开始")
while True:
self.__event_detection()
if self.start_flag:
self.draw_funs()
Tetris.update_game_area()
self.block.boundary_detection()
self.fixed_block_position(self.block)
pygame.display.flip() # 屏幕绘制
@staticmethod
def update_game_area():
for raw_value in game_area:
if raw_value == '1' * X_num:
game_area.remove(raw_value)
game_area.insert(0, '0' * X_num)
def draw_screen_by_matrix(self):
for raw_index, raw_value in enumerate(game_area):
for column_index, column_value in enumerate(list(raw_value)):
if column_value == '1':
self.draw_block(column_index, raw_index)
def fixed_block_position(self, block):
x, y = self.calculate_block_coordinates(block)
self.block_fall_time_monitoring = time.time()
time_difference = self.block_fall_time_monitoring - self.time_block_down
# 判断下落时间及产生新方块
if (y == Y_num - 1) and (float(time_difference) >= 1.3):
self.pinning_and_generating_new_block(x, y)
elif Tetris.get_position(x, y + 1) == '1' and (float(time_difference) >= 1.3):
self.pinning_and_generating_new_block(x, y)
else:
return
def pinning_and_generating_new_block(self, x, y):
print(f'固定方块')
Tetris.update_matrix_based_on_coordinates(x, y)
print(f'产生新方块')
self.block = eval("SingleBlock")()
@staticmethod
def update_matrix_based_on_coordinates(x, y):
# 完成矩阵更新
s = list(game_area[y])
s[x] = '1'
game_area[y] = "".join(s)
def config_start(self, event):
if event.key == K_RETURN:
self.start_flag = True
self.block = eval("SingleBlock")()
def key_detection(self, event, block_coordinates):
_x = block_coordinates[0]
_y = block_coordinates[1]
if event.key == pygame.K_RIGHT:
if Tetris.get_position(_x + 1, _y) == '0':
self.block.x += self.block.speed
elif event.key == pygame.K_LEFT:
if Tetris.get_position(_x - 1, _y) == '0':
self.block.x -= self.block.speed
elif event.key == pygame.K_DOWN:
if Tetris.get_position(_x, _y + 1) == '0':
self.block.y += self.block.speed
else:
return
def block_falling(self):
self.time_block_down = time.time()
_x, _y = Tetris.calculate_block_coordinates(self.block)
if Tetris.get_position(_x, _y + 1) == '0':
self.block.move()
print(f'方块正在下落-{Tetris.calculate_block_coordinates(self.block)}')
def __event_detection(self):
for event in pygame.event.get():
if event.type == pygame.QUIT:
Tetris.__end()
if self.start_flag and event.type == BLOCK_DOWN:
self.block_falling()
if event.type == pygame.KEYDOWN:
self.config_start(event)
if self.start_flag:
block_coordinates = Tetris.calculate_block_coordinates(self.block)
self.key_detection(event, block_coordinates)
@staticmethod
def get_position(x, y):
if 0 <= x < X_num and y < Y_num:
return game_area[y][x]
@staticmethod
def calculate_block_coordinates(block):
return int(block.x / BLOCK_SIZE), int(block.y / BLOCK_SIZE)
def draw_block(self, *para):
if len(para) == 1:
position = (para[0].x, para[0].y, BLOCK_SIZE, BLOCK_SIZE)
elif len(para) == 2:
position = (para[0] * BLOCK_SIZE, para[1] * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE)
else:
return
pygame.draw.rect(self.screen, self.block_colcor, position, self.block_width)
# 画网格线
def draw_lines(self):
for x in range(1, X_num):
pygame.draw.line(self.screen, self.line_color, (x * BLOCK_SIZE, 0), (x * BLOCK_SIZE, HEIGHT), 1)
for y in range(1, Y_num):
pygame.draw.line(self.screen, self.line_color, (0, y * BLOCK_SIZE), (WIDTH + BLOCK_SIZE, y * BLOCK_SIZE), 1)
if __name__ == '__main__':
tetris = Tetris()
tetris.start()
import pygame
import random
X_num = 10
Y_num = 20
BLOCK_SIZE = 35
WIDTH = BLOCK_SIZE * X_num
HEIGHT = BLOCK_SIZE * Y_num
SCREEN_RECT = pygame.Rect(0, 0, WIDTH, HEIGHT)
BLOCK_DOWN = pygame.USEREVENT
BLOCK_DOWN_TIME = 1500
# 10 * 20 的一个矩阵,初始值为0
game_area = ['0' * X_num for _ in range(Y_num)]
class Blocks:
def __init__(self):
self.speed = BLOCK_SIZE
num = random.randint(0, X_num - 2)
self.x = BLOCK_SIZE * num
print(f'self.x-{self.x}')
self.y = - BLOCK_SIZE
def move(self):
self.y += self.speed
class SingleBlock(Blocks):
def __init__(self):
super().__init__()
def move(self):
super().move()
self.boundary_detection()
def boundary_detection(self):
if self.x <= 0:
self.x = 0
elif self.x >= WIDTH - BLOCK_SIZE:
self.x = WIDTH - BLOCK_SIZE
if self.y >= HEIGHT - BLOCK_SIZE:
self.y = HEIGHT - BLOCK_SIZE