python实现简单的俄罗斯方块
程序员文章站
2022-06-23 13:25:51
本文实例为大家分享了python实现简单的俄罗斯方块的具体代码,供大家参考,具体内容如下1. 案例介绍俄罗斯方块是由 4 个小方块组成不同形状的板块,随机从屏幕上方落下,按方向键调整板块的位置和方向,...
本文实例为大家分享了python实现简单的俄罗斯方块的具体代码,供大家参考,具体内容如下
1. 案例介绍
俄罗斯方块是由 4 个小方块组成不同形状的板块,随机从屏幕上方落下,按方向键调整板块的位置和方向,在底部拼出完整的一行或几行。这些完整的横条会消失,给新落下来的板块腾出空间,并获得分数奖励。没有被消除掉的方块不断堆积,一旦堆到顶端,便告输,游戏结束。本例难度为高级,适合具有 python 进阶和 pygame 编程技巧的用户学习。
2. 设计要点
边框――由 15*25 个空格组成,方块就落在这里面。盒子――组成方块的其中小方块,是组成方块的基本单元。方块――从边框顶掉下的东西,游戏者可以翻转和改变位置。每个方块由 4 个盒子组成。形状――不同类型的方块。这里形状的名字被叫做 t, s, z ,j, l, i , o。如下图所示:
模版――用一个列表存放形状被翻转后的所有可能样式。全部存放在变量里,变量名字如 s or j。着陆――当一个方块到达边框的底部或接触到在其他的盒子话,就说这个方块着陆了。那样的话,另一个方块就会开始下落。
3. 示例效果
4. 示例源码
import pygame import random import os pygame.init() grid_width = 20 grid_num_width = 15 grid_num_height = 25 width, height = grid_width * grid_num_width, grid_width * grid_num_height side_width = 200 screen_width = width + side_width white = (0xff, 0xff, 0xff) black = (0, 0, 0) line_color = (0x33, 0x33, 0x33) cube_colors = [ (0xcc, 0x99, 0x99), (0xff, 0xff, 0x99), (0x66, 0x66, 0x99), (0x99, 0x00, 0x66), (0xff, 0xcc, 0x00), (0xcc, 0x00, 0x33), (0xff, 0x00, 0x33), (0x00, 0x66, 0x99), (0xff, 0xff, 0x33), (0x99, 0x00, 0x33), (0xcc, 0xff, 0x66), (0xff, 0x99, 0x00) ] screen = pygame.display.set_mode((screen_width, height)) pygame.display.set_caption("俄罗斯方块") clock = pygame.time.clock() fps = 30 score = 0 level = 1 screen_color_matrix = [[none] * grid_num_width for i in range(grid_num_height)] # 设置游戏的根目录为当前文件夹 base_folder = os.path.dirname(__file__) def show_text(surf, text, size, x, y, color=white): font_name = os.path.join(base_folder, 'font/font.ttc') font = pygame.font.font(font_name, size) text_surface = font.render(text, true, color) text_rect = text_surface.get_rect() text_rect.midtop = (x, y) surf.blit(text_surface, text_rect) class cubeshape(object): shapes = ['i', 'j', 'l', 'o', 's', 't', 'z'] i = [[(0, -1), (0, 0), (0, 1), (0, 2)], [(-1, 0), (0, 0), (1, 0), (2, 0)]] j = [[(-2, 0), (-1, 0), (0, 0), (0, -1)], [(-1, 0), (0, 0), (0, 1), (0, 2)], [(0, 1), (0, 0), (1, 0), (2, 0)], [(0, -2), (0, -1), (0, 0), (1, 0)]] l = [[(-2, 0), (-1, 0), (0, 0), (0, 1)], [(1, 0), (0, 0), (0, 1), (0, 2)], [(0, -1), (0, 0), (1, 0), (2, 0)], [(0, -2), (0, -1), (0, 0), (-1, 0)]] o = [[(0, 0), (0, 1), (1, 0), (1, 1)]] s = [[(-1, 0), (0, 0), (0, 1), (1, 1)], [(1, -1), (1, 0), (0, 0), (0, 1)]] t = [[(0, -1), (0, 0), (0, 1), (-1, 0)], [(-1, 0), (0, 0), (1, 0), (0, 1)], [(0, -1), (0, 0), (0, 1), (1, 0)], [(-1, 0), (0, 0), (1, 0), (0, -1)]] z = [[(0, -1), (0, 0), (1, 0), (1, 1)], [(-1, 0), (0, 0), (0, -1), (1, -1)]] shapes_with_dir = { 'i': i, 'j': j, 'l': l, 'o': o, 's': s, 't': t, 'z': z } def __init__(self): self.shape = self.shapes[random.randint(0, len(self.shapes) - 1)] # 骨牌所在的行列 self.center = (2, grid_num_width // 2) self.dir = random.randint(0, len(self.shapes_with_dir[self.shape]) - 1) self.color = cube_colors[random.randint(0, len(cube_colors) - 1)] def get_all_gridpos(self, center=none): curr_shape = self.shapes_with_dir[self.shape][self.dir] if center is none: center = [self.center[0], self.center[1]] return [(cube[0] + center[0], cube[1] + center[1]) for cube in curr_shape] def conflict(self, center): for cube in self.get_all_gridpos(center): # 超出屏幕之外,说明不合法 if cube[0] < 0 or cube[1] < 0 or cube[0] >= grid_num_height or \ cube[1] >= grid_num_width: return true # 不为none,说明之前已经有小方块存在了,也不合法 if screen_color_matrix[cube[0]][cube[1]] is not none: return true return false def rotate(self): new_dir = self.dir + 1 new_dir %= len(self.shapes_with_dir[self.shape]) old_dir = self.dir self.dir = new_dir if self.conflict(self.center): self.dir = old_dir return false def down(self): # import pdb; pdb.set_trace() center = (self.center[0] + 1, self.center[1]) if self.conflict(center): return false self.center = center return true def left(self): center = (self.center[0], self.center[1] - 1) if self.conflict(center): return false self.center = center return true def right(self): center = (self.center[0], self.center[1] + 1) if self.conflict(center): return false self.center = center return true def draw(self): for cube in self.get_all_gridpos(): pygame.draw.rect(screen, self.color, (cube[1] * grid_width, cube[0] * grid_width, grid_width, grid_width)) pygame.draw.rect(screen, white, (cube[1] * grid_width, cube[0] * grid_width, grid_width, grid_width), 1) def draw_grids(): for i in range(grid_num_width): pygame.draw.line(screen, line_color, (i * grid_width, 0), (i * grid_width, height)) for i in range(grid_num_height): pygame.draw.line(screen, line_color, (0, i * grid_width), (width, i * grid_width)) pygame.draw.line(screen, white, (grid_width * grid_num_width, 0), (grid_width * grid_num_width, grid_width * grid_num_height)) def draw_matrix(): for i, row in zip(range(grid_num_height), screen_color_matrix): for j, color in zip(range(grid_num_width), row): if color is not none: pygame.draw.rect(screen, color, (j * grid_width, i * grid_width, grid_width, grid_width)) pygame.draw.rect(screen, white, (j * grid_width, i * grid_width, grid_width, grid_width), 2) def draw_score(): show_text(screen, u'得分:{}'.format(score), 20, width + side_width // 2, 100) def remove_full_line(): global screen_color_matrix global score global level new_matrix = [[none] * grid_num_width for i in range(grid_num_height)] index = grid_num_height - 1 n_full_line = 0 for i in range(grid_num_height - 1, -1, -1): is_full = true for j in range(grid_num_width): if screen_color_matrix[i][j] is none: is_full = false continue if not is_full: new_matrix[index] = screen_color_matrix[i] index -= 1 else: n_full_line += 1 score += n_full_line level = score // 20 + 1 screen_color_matrix = new_matrix def show_welcome(screen): show_text(screen, u'俄罗斯方块', 30, width / 2, height / 2) show_text(screen, u'按任意键开始游戏', 20, width / 2, height / 2 + 50) running = true gameover = true counter = 0 live_cube = none while running: clock.tick(fps) for event in pygame.event.get(): if event.type == pygame.quit: running = false elif event.type == pygame.keydown: if gameover: gameover = false live_cube = cubeshape() break if event.key == pygame.k_left: live_cube.left() elif event.key == pygame.k_right: live_cube.right() elif event.key == pygame.k_down: live_cube.down() elif event.key == pygame.k_up: live_cube.rotate() elif event.key == pygame.k_space: while live_cube.down() == true: pass remove_full_line() # level 是为了方便游戏的难度,level 越高 fps // level 的值越小 # 这样屏幕刷新的就越快,难度就越大 if gameover is false and counter % (fps // level) == 0: # down 表示下移骨牌,返回false表示下移不成功,可能超过了屏幕或者和之前固定的 # 小方块冲突了 if live_cube.down() == false: for cube in live_cube.get_all_gridpos(): screen_color_matrix[cube[0]][cube[1]] = live_cube.color live_cube = cubeshape() if live_cube.conflict(live_cube.center): gameover = true score = 0 live_cube = none screen_color_matrix = [[none] * grid_num_width for i in range(grid_num_height)] # 消除满行 remove_full_line() counter += 1 # 更新屏幕 screen.fill(black) draw_grids() draw_matrix() draw_score() if live_cube is not none: live_cube.draw() if gameover: show_welcome(screen) pygame.display.update()
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。