python,基于tkinter模块编写的完整俄罗斯方块游戏代码
使用python编写小游戏挺容易的,常用的模块是pygame, 本文用tkinter,实现了俄罗斯方块小游戏,感觉还是比较容易的。
import tkinter as tk import time import random from tkinter import messagebox import pygame pygame.mixer.pre_init(44100, -16, 2, 512) pygame.mixer.init() # 初始化混音器 # 读取最高纪录 with open('record.txt', 'r') as f: record = int(f.read()) # 定义游戏中的常量 R = 20 # 20行 C = 12 # 30列 cell_size = 30 #方块边长 with open('speed.txt', 'r') as f: FPS = int(f.readline()) # 读取刷新时间 height = R * cell_size #画布高度 width = C * cell_size #画布宽度 #定义形状的座标矩阵 SHAPES = { 'O': [(-1, -1), (0, -1), (-1, 0), (0, 0)], 'S': [(-1, 0), (0, 0), (0, -1), (1, -1)], 'T': [(-1, 0), (0, 0), (0, -1), (1, 0)], 'I': [(0, 1), (0, 0), (0, -1), (0, -2)], 'L': [(-1, 0), (0, 0), (-1, -1), (-1, -2)], 'J': [(-1, 0), (0, 0), (0, -1), (0, -2)], 'Z': [(-1, -1), (0, -1), (0, 0), (1, 0)] } # 定义每个形状的颜色 SHAPECOLOR = { 'O': 'blue', 'S': 'red', 'T': 'yellow', 'I': 'green', 'L': 'purple', 'J': 'orange', 'Z': 'Cyan' } # 定义函数,在画板指定的行列上画指定颜色的方格 def draw_cell_by_cr(canvas, c, r, color = '#CCCCCC'): #定义左上角和右下角座标 x0 = c * cell_size y0 = r * cell_size x1 = c * cell_size + cell_size y1 = r * cell_size + cell_size canvas.create_rectangle(x0, y0, x1, y1, fill = color, outline = 'white', width = 2) # 定义函数,画背景画布 def draw_board(canvas, block_list): for ri in range(R): for ci in range(C): cell_type = block_list[ri][ci] if cell_type: draw_cell_by_cr(canvas, ci, ri, SHAPECOLOR[cell_type]) else: draw_cell_by_cr(canvas, ci, ri) # 定义在指定的行列,绘制指定颜色的图形 def draw_cell(canvas, c, r, cell_list, color = '#cccccc'): for cell in cell_list: cell_c, cell_r = cell ci = cell_c + c # 实际列座标 ri = cell_r + r # 实际行座标 if 0 <= c < C and 0 <= r < R: draw_cell_by_cr(canvas, ci, ri, color) # 画出一个方格 win = tk.Tk() canvas = tk.Canvas(win, width = width, height = height) #定义画布控件 win.geometry('+800+10') canvas.pack() # draw_blank_board(canvas) # draw_cell(canvas, 3, 3, SHAPES['O'], SHAPECOLOR['O']) # draw_cell(canvas, 3, 8, SHAPES['S'], SHAPECOLOR['S']) # draw_cell(canvas, 3, 13, SHAPES['T'], SHAPECOLOR['T']) # draw_cell(canvas, 8, 3, SHAPES['I'], SHAPECOLOR['I']) # draw_cell(canvas, 8, 8, SHAPES['L'], SHAPECOLOR['L']) # draw_cell(canvas, 8, 13, SHAPES['J'], SHAPECOLOR['J']) # draw_cell(canvas, 5, 18, SHAPES['Z'], SHAPECOLOR['Z']) block_list = [] # 定义记录已经生成的方块的列表 for i in range(R): i_row = ['' for i in range(C)] block_list.append(i_row) # 生成由空字符串组成的R行C列的列表 draw_board(canvas, block_list) # 定义移动方块函数 def draw_block_move(canvas, block, direction = [0, 0]): ''' :param: :param canvas: 画布 :param block: 方块对象 :param direction: 移动方向 :return: ''' shape_type = block['kind'] c, r = block['cr'] cell_list = block['cell_list'] draw_cell(canvas, c, r, cell_list) # 擦除旧位置的形状 dc, dr = direction new_c, new_r = c + dc, r + dr block['cr'] = [new_c, new_r] draw_cell(canvas, new_c, new_r, cell_list, SHAPECOLOR[shape_type]) # 绘制新位置的形状 # draw_block_move(canvas, a_block) # 定义一个随机生成形状的函数 def generate_new_block(): kind = random.choice(list(SHAPES.keys())) cr = [C // 2, 0] new_block = { 'kind': kind, 'cell_list': SHAPES[kind], 'cr': cr } return(new_block) # 定义检测方块是否移动到最底部的函数 def check_move(block, direction = [0, 0]): cc, cr = block['cr'] # 定义当前的行列座标 cell_list = block['cell_list'] for cell in cell_list: cell_c, cell_r = cell c = cell_c + cc + direction[0] r = cell_r + cr + direction[1] if c < 0 or c >= C or r >= R: return False if r >= 0 and block_list[r][c]: return False return True # 定义一个存储已生成方块列表的函数 def save_to_block_list(block): shape_type = block['kind'] cc, cr = block['cr'] cell_list = block['cell_list'] for cell in cell_list: cell_c, cell_r = cell c = cell_c + cc r = cell_r + cr block_list[r][c] = shape_type def horizontal_move_block(event): ''' :左右移动方块 :param event: 键鼠标事件 :return: ''' direction = [0, 0] #默认方向为不动 if event.keysym == 'Left': direction = [-1, 0] elif event.keysym == 'Right': direction = [1, 0] else: return global current_block if current_block is not None and check_move(current_block, direction): draw_block_move(canvas, current_block, direction) # 定义旋转方块函数 def rotate_block(event): global current_block if current_block is None: return cell_list = current_block['cell_list'] rotate_list = [] for cell in cell_list: cell_c, cell_r = cell rotate_cell = [cell_r, -cell_c] rotate_list.append(rotate_cell) block_after_rotate = { 'kind': current_block['kind'], 'cell_list': rotate_list, 'cr': current_block['cr'] } if check_move(block_after_rotate): cc, cr = current_block['cr'] draw_cell(canvas, cc, cr, current_block['cell_list']) draw_cell(canvas, cc, cr, rotate_list, SHAPECOLOR[current_block['kind']]) current_block = block_after_rotate # 定义一个按向下键直接着陆的函数 def land(event): global current_block if current_block is None: return cell_list = current_block['cell_list'] cc, cr = current_block['cr'] min_height = R for cell in cell_list: cell_c, cell_r = cell c, r = cell_c + cc, cell_r + cr if block_list[r][c]: return h = 0 for ri in range(r + 1, R): if block_list[ri][c]: break else: h += 1 if h < min_height: min_height = h down = [0, min_height] if check_move(current_block, down): draw_block_move(canvas, current_block, down) # wave_down.play() # 定义保存得分的变量 score = 0 win.title('To lotus! Scores:%s The record is %s' % (score, record)) # 定义函数判断指定行是否已经满了 def check_row_complete(row): for cell in row: if cell == '': return False return True # 定义函数检查是否满了,同时清除满行方块 def check_and_clear(): has_complete_row = False for ri in range(len(block_list)): if check_row_complete(block_list[ri]): has_complete_row = True if ri > 0: for cur_ri in range(ri, 0, -1): block_list[cur_ri] = block_list[cur_ri -1][:] block_list[0] = ['' for i in range(C)] else: block_list[ri] = ['' for i in range(C)] global score score += 10 if has_complete_row: remove.play() draw_board(canvas, block_list) win.title('To lotus! Scores:%s The record is %s' % (score, record)) # 定义定时刷新函数 def game_loop(): win.update() global current_block if current_block == None: new_block = generate_new_block() draw_block_move(canvas, new_block) # 绘制形状(未输入direction,在new_block点绘制,不移动) current_block = new_block if not check_move(current_block): game_over.play() if score >= record: messagebox.showinfo('Game Over!', '宝贝,我爱你!Your score is %s! Congratulations on setting a new record!' % score) with open('record.txt', 'w') as f: f.write(str(score)) else: messagebox.showinfo('Game Over!', 'Your score is %s!' % score) win.destroy() return else: if check_move(current_block, [0, 1]): draw_block_move(canvas, current_block, [0, 1]) else: save_to_block_list(current_block) current_block = None wave_down.play() check_and_clear() win.after(FPS, game_loop) current_block = None canvas.focus_set() # 聚焦到画板对象 canvas.bind('<KeyPress-Left>', horizontal_move_block) canvas.bind('<KeyPress-Right>', horizontal_move_block) canvas.bind('<KeyPress-Up>', rotate_block) canvas.bind('<KeyPress-Down>', land) game_loop() pygame.mixer.pre_init(44100, -16, 2, 512) pygame.mixer.init() # 初始化混音器 #加载音乐文件 # mp3_backGround = pygame.mixer.music.load("background.mp3") background = pygame.mixer.Sound('background.wav') #加载wave文件 wave_down = pygame.mixer.Sound("down.wav") remove = pygame.mixer.Sound("remove.wav") game_over = pygame.mixer.Sound("gameover.wav") #设置背景音乐的音量 # pygame.mixer.music.set_volume(Config.bgMusicVolume) #播放背景音乐,参数-1表示循环播放 background.play(-1) win.mainloop()