俄罗斯方块是一款世界级经典游戏,每门语言开发学习初步都会考虑制作俄罗斯方块游戏今天带着大家把俄罗斯方块用python语言开发一次
1.安装python
2.引入游戏库pygame
3.引入随机数
import pygame
import random
这里使用一个二维数组 用来标记俄罗斯相对应的方块形状 代码如下:
# 定义方块的基本形状
blocks = [
# I
[
[1, 1, 1, 1],
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
],
# O
[
[1, 1, 0, 0],
[1, 1, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
],
# T
[
[1, 1, 1, 0],
[0, 1, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
],
# S
[
[0, 1, 1, 0],
[1, 1, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
],
# Z
[
[1, 1, 0, 0],
[0, 1, 1, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
],
# J
[
[1, 1, 1, 0],
[0, 0, 1, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
],
# L
[
[1, 1, 1, 0],
[1, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
],
]
这里为了不让他出现穿墙,跨过方块下落 都做对应的碰撞判断 具体代码如下:
# 判断方块是否可以向左移动
def can_move_left(x, y, block):
for i in range(len(block)):
for j in range(len(block[i])):
if block[i][j] == 1:
if x + j - 1 < 0 or play_area[y + i][x + j - 1] != EMPTY:
return False
return True
# 判断方块是否可以向右移动
def can_move_right(x, y, block):
for i in range(len(block)):
for j in range(len(block[i])):
if block[i][j] == 1:
if x + j + 1 >= COLS or play_area[y + i][x + j + 1] != EMPTY:
return False
return True
# 判断方块是否可以向下移动
def can_move_down(x, y, block):
for i in range(len(block)):
for j in range(len(block[i])):
if block[i][j] == 1:
if y + i + 1 >= ROWS or play_area[y + i + 1][x + j] != EMPTY:
global count
count += 1
print(y,",",x,";不能下降了",count)
return False
return True
# 判断方块是否可以变形
def can_rotate(x, y, block):
return rotate_block(x, y, block) != block
# 变形方块
def rotate_block(x, y, block):
new_block = []
for i in range(len(block)):
row = []
for j in range(len(block[i])):
row.append(block[len(block) - j - 1][i])
new_block.append(row)
if x + len(new_block[0]) > COLS or y + len(new_block) > ROWS:
return block
for i in range(len(new_block)):
for j in range(len(new_block[i])):
if new_block[i][j] == 1 and play_area[y + i][x + j] != EMPTY:
return block
return new_block
# 删除行
def delete_rows():
full_rows = [] # 总共要删除的行号列表
for i in range(len(play_area)): # 检测整行没有空格了
if EMPTY not in play_area[i]:
full_rows.append(i) # 加入删除这行
# 偏移量bu 在一次性删除多行的时候 因为边删边补 会引起删除索引改变
bu = 0
for row in sorted(full_rows, reverse=True): # 必须逆序 删除没有空格的行
del play_area[row+bu]
play_area.insert(0, [EMPTY] * COLS)
bu += 1
return len(full_rows) # 返回删除的总行数
一次一行得10分 一次2行得30分 一次3行得50分 一次四行得100分,代码如下:
# 消除几行加分规则
def add_score(drow):
global score
if drow == 1:
score += 10 # 一次消除一行 得分加10
elif drow == 2: # 一次消除2行 得分加30
score += 30
elif drow == 3:
score += 50
elif drow == 4:
score += 100
# 游戏结束,重置游戏
def reset_game():
global score
# 绘制提示语言
font = pygame.font.Font("simsun.ttc", 24)
# font = pygame.font.SysFont(None, 24)
text = font.render("游戏结束您的得分是{},重新开始请按空格键".format(score), True, WHITE)
screen.blit(text, (10, height//2-12))
pygame.display.update()
flag = True
while flag:
for event in pygame.event.get():
if event.type == pygame.KEYDOWN and event.key == pygame.K_SPACE:
flag = False
break
global play_area, cur_block, cur_color
play_area = [[EMPTY] * COLS for i in range(ROWS)]
# play_area = [[EMPTY] * width for i in range(height)]
# 随机生成俄罗斯方块
cur_block = blocks[random.randint(0, len(blocks) - 1)]
cur_color = random.randint(0, 255), random.randint(0, 255), random.randint(0, 255)
# 重置分数
score = 0
# 颜色定义
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
# 初始化游戏
pygame.init()
# 设置游戏界面大小
size = width, height = 640, 480
# 游戏设置
EMPTY = -1
FPS = 60 ## 祯数
SIZE = 20
ROWS = height//SIZE
COLS = width//SIZE
count = 0
# 创建游戏界面
screen = pygame.display.set_mode(size)
# 设置游戏标题
pygame.display.set_caption("俄罗斯方块")
# 随机生成俄罗斯方块
cur_block = blocks[random.randint(0, len(blocks) - 1)]
cur_color = random.randint(0, 255), random.randint(0, 255), random.randint(0, 255)
play_area = [[EMPTY] * COLS for i in range(ROWS)]
x, y = width // 2//SIZE, 0 # 方块的初始位置
clock = pygame.time.Clock()
score = 0 # 分数
speed = 1000 #下降速度 目前没用到 后续会根据这个值来调整关卡速度(方块下落速度)
# 设置定时器来控制下降速度 如果用帧数控制游戏速度的话 会影响按键 帧数低的时候 按键也失灵 这里用定时器来控制速度
pygame.time.set_timer(pygame.USEREVENT ,speed)
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit()
elif event.type == pygame.USEREVENT:
y += 1 # 一秒下降一格
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT and can_move_left(x, y, cur_block):
x -= 1
elif event.key == pygame.K_RIGHT and can_move_right(x, y, cur_block):
x += 1
elif event.key == pygame.K_UP and can_rotate(x, y, cur_block):
cur_block = rotate_block(x, y, cur_block)
elif event.key == pygame.K_DOWN and can_move_down(x, y+3, cur_block):
y += 3
# print(x,",",y)
# 消除行并计分
add_score(delete_rows())
# 随机生成新方块
if not can_move_down(x, y, cur_block):
# 将方块添加到游戏区域
for i in range(len(cur_block)):
for j in range(len(cur_block[i])):
if cur_block[i][j] == 1:
print("y=",y,";x=",x,";i=",i,";j=",j)
play_area[y + i][x + j] = cur_color
# 随机生成俄罗斯方块
cur_block = blocks[random.randint(0, len(blocks) - 1)]
cur_color = random.randint(0, 255), random.randint(0, 255), random.randint(0, 255)
x, y = width // 2//SIZE, 0 # 方块的初始位置
# 判断游戏是否结束
for i in play_area[0]:
if i != EMPTY:
reset_game()
# 绘制游戏区域
screen.fill(BLACK)
# print(play_area)
for i in range(ROWS):
for j in range(COLS):
if play_area[i][j] != EMPTY:
pygame.draw.rect(screen, play_area[i][j], pygame.Rect(j * 20, i * 20, 20, 20), 0)
# 绘制当前方块
for i in range(len(cur_block)):
for j in range(len(cur_block[i])):
if cur_block[i][j] == 1:
pygame.draw.rect(screen, cur_color, pygame.Rect((x + j) * 20, (y + i) * 20, 20, 20), 0)
# 绘制分数
font = pygame.font.SysFont(None, 24)
text = font.render("Score: {}".format(score), True, WHITE)
screen.blit(text, (10, 10))
pygame.display.update()
clock.tick(FPS)
整个项目下载链接: pygame-俄罗斯方块游戏项目
1.游戏细节比较多,容易出错,需要清晰的逻辑思维,
2.速度控制上原先一直用FPS(帧数)来调节速度发现 按键灵敏度也跟帧数息息相关,所以这里用定时器来控制。不知道如果有多个定时器同时使用的话 会不会有新的问题,后续继续研究
3.消除行判断 原先没考虑到整个屏幕用二维列表来定义是否占格,浪费了很长时间无法很好的实现消除整行,这里用二维可以完美解决这个问题。
4.要显示中文字体需要加载字体,后面我会放整个项目下载链接,里面包括字体,后续持续更新 可能会加上音效等。
5.整个游戏花费了我5,6个小时的精力,还有很多心得 得大家一起去写写用用改改才能发现。有什么问题可以互相交流