使用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('', horizontal_move_block)
canvas.bind('', horizontal_move_block)
canvas.bind('', rotate_block)
canvas.bind('', 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()