import random
import sys
import time
from bisect import bisect
from copy import deepcopy
import pygame
from blocks import BLOCKS
SCREEN_WIDTH, SCREEN_HEIGHT = 450, 750
BLOCK_COL_NUM = 10 # 每行的方格数
BLOCK_ROW_NUM = 25 # 每列的方个数
SIZE = 30 # 每个小方格大小
BG_COLOR = (40, 40, 60) # 背景色
RED = (200, 30, 30) # 红色,GAME OVER 的字体颜色
WHITE = (255,255,255) # 白色
BLACK = (0,0,0) # 黑色
GREEN = (60, 128, 80) # 绿色
STOP_LST = [[0 for _ in range(BLOCK_COL_NUM)]
for _ in range(BLOCK_ROW_NUM)]
# 消除逻辑
def judgeLines(stopLst):
# 记录刚刚消除的行数
i, N, count = 0, len(stopLst), 0
for i in range(N):
if 0 not in stopLst[i]:
line = [0]*len(stopLst.pop(i))
stopLst.insert(0, line)
count += 10
return count
# 将停止移动的block添加到堆积方块
def addToStopLst(stopLst, block, stRow, stCol):
for row, line in enumerate(block):
for col, b in enumerate(line):
if b: stopLst[stRow + row][stCol + col] = 1
def rotateBlock(block):
newBlock = [[[] for _ in block] for b in block[0]]
for i,row in enumerate(block, 1):
for j,r in enumerate(row, 0):
newBlock[j][-i] = r
return newBlock
# 判断是否可以向左右移动
# isR为True,判断能否向右移动;isR为False,判断能否向左移动
def judgeMoveLR(block, stCol, isR):
nCol = len(block[0])
cols = range(nCol-1, -1, -1) if isR else range(nCol)
for col in cols:
lstCol = [line[col] for line in block]
if 1 not in lstCol:
continue
if not 0 <= stCol + col < BLOCK_COL_NUM:
return False
return True
# 相左或者向右移动
def moveLR(block, stCol, key):
isR = key == pygame.K_RIGHT
stCol = stCol + 1 if isR else stCol - 1
if judgeMoveLR(block ,stCol, isR):
return 1 if isR else -1
return 0
# 判断是否可以继续下落
def judgeMoveDown(block, stRow, stCol, stopLst):
# 堆积方块的位置
stopPosition = list()
for row, line in enumerate(stopLst):
for col, b in enumerate(line):
if b: stopPosition.append((row, col))
# 判断碰撞
for row, line in enumerate(block):
if 1 in line and stRow + row >= BLOCK_ROW_NUM:
return False
for col, b in enumerate(line):
if b and (stRow + row, stCol + col) in stopPosition:
return False
return True
def canMove(block, stRow, stCol, stopLst):
flag = judgeMoveLR(block, stCol, False)
flag &= judgeMoveLR(block, stCol, True)
flag &= judgeMoveDown(block, stRow, stCol, stopLst)
return flag
# 创建一个图形
def newBlock():
block = random.choice(BLOCKS)
for _ in range(random.randint(0,4)):
block = rotateBlock(block)
return block
def drawBackground(screen):
screen.fill(BG_COLOR)
width = SIZE * BLOCK_COL_NUM
pygame.draw.line(screen, BLACK, (width, 0), (width, SCREEN_HEIGHT), 4)
for x in range(BLOCK_COL_NUM):
pygame.draw.line(screen, BLACK, (x * SIZE, 0), (x * SIZE, SCREEN_HEIGHT), 1)
for y in range(BLOCK_ROW_NUM):
pygame.draw.line(screen, BLACK, (0, y * SIZE), (width, y * SIZE), 1)
def drawRight(screen, score, speedInfo):
fontPath = r'C:\Windows\Fonts\msyh.ttc'
font = pygame.font.Font(fontPath, 24) # 黑体24
posDct = {
'得分: ':10, str(score): 50,
'速度: ':100, speedInfo: 150,
'下一个:':200
}
for k,v in posDct.items():
msg = font.render(k, True, WHITE)
screen.blit(msg, (BLOCK_COL_NUM * SIZE + 10, v))
def drawBlock(screen, row, col, stRow, stCol):
stRow += row * SIZE
stCol += SIZE * col
rect = pygame.Rect(stCol, stRow, SIZE, SIZE)
pygame.draw.rect(screen, GREEN, rect, 0)
pygame.draw.rect(screen, BLACK, rect, 1)
def drawBlocks(screen, block, stRow, stCol):
for row, line in enumerate(block):
for col, b in enumerate(line):
if not b: continue
drawBlock(screen, row, col, stRow, stCol)
def drawGamerOver(screen):
fontPath = r'C:\Windows\Fonts\msyh.ttc'
font = pygame.font.Font(fontPath, 72)
w, h = font.size('GAME OVER')
msg = font.render('GAME OVER', True, RED)
screen.blit(msg, ((SCREEN_WIDTH - w) // 2, (SCREEN_HEIGHT - h) // 2))
# 显示"鼠标点击任意位置,再来一局"
font = pygame.font.Font(fontPath, 24)
w, h = font.size('点击任意位置,再来一局')
msg = font.render('点击任意位置,再来一局', True, RED)
screen.blit(msg, ((SCREEN_WIDTH - w) // 2, (SCREEN_HEIGHT - h) // 2 + 80))
def changeSpeed(score):
scores = [20, 50, 100, 200]
infos = "12345"
speeds = [0.5, 0.4, 0.3, 0.2, 0.1]
ind = bisect(scores, score)
return infos[ind], speeds[ind]
def initBlock(nextBlock=None):
stRow, stCol = -2, 4
nowBlock = nextBlock if nextBlock else newBlock()
nextBlock = newBlock()
return stRow, stCol, nowBlock, nextBlock
def main():
pygame.init()
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption('俄罗斯方块')
# 初始化当前图形的位置,当前图形,以及下一个图形
stRow, stCol, nowBlock, nextBlock = initBlock()
last_time = time.time()
speed, speedInfo = 0.5, '1'
score, gameOver = 0, False
stopLst = deepcopy(STOP_LST)
clock = pygame.time.Clock()
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
elif event.type == pygame.KEYDOWN:
if event.key in [pygame.K_LEFT, pygame.K_RIGHT]:
stCol += moveLR(nowBlock, stCol, event.key)
elif event.key == pygame.K_UP:
rotBlock = rotateBlock(nowBlock)
if canMove(rotBlock, stRow, stCol, stopLst):
nowBlock = rotBlock
elif event.key == pygame.K_DOWN:
# 判断是否可以向下移动,如果碰到底部或者其它的图形就不能移动了
while judgeMoveDown(nowBlock, stRow + 1, stCol, stopLst):
stRow += 1
if gameOver:
stRow, stCol, nowBlock, nextBlock = initBlock()
stopLst = deepcopy(STOP_LST)
score = 0
gameOver = False
# 判断是否修改当前图形显示的起始行
if not gameOver and time.time() - last_time > speed:
last_time = time.time()
# 可以向下移动的情形
if judgeMoveDown(nowBlock, stRow + 1, stCol, stopLst):
stRow += 1
else:
# 不可向下移动,则需新建一个block然后下落
addToStopLst(stopLst, nowBlock, stRow, stCol)
score += judgeLines(stopLst)
gameOver = 1 in stopLst[0] # 第一行中间有1则游戏结束
speedInfo, speed = changeSpeed(score) # 调整速度
stRow, stCol, nowBlock, nextBlock = initBlock(nextBlock)
drawBackground(screen)
drawRight(screen, score, speedInfo)
drawBlocks(screen, nowBlock, stRow*SIZE, stCol*SIZE) # 当前方块
drawBlocks(screen, stopLst, 0, 0) # 堆积方块
drawBlocks(screen, nextBlock, 300, 320) # 下一个方块
# 显示游戏结束画面
if gameOver:
drawGamerOver(screen)
pygame.display.update()
clock.tick(60) # 通过一定的延时,实现1秒钟能够循环60次
if __name__ == '__main__':
main()
没有合适的资源?快使用搜索试试~ 我知道了~
PyGame俄罗斯方块源代码
共4个文件
py:2个
png:1个
md:1个
1.该资源内容由用户上传,如若侵权请联系客服进行举报
2.虚拟产品一经售出概不退款(资源遇到问题,请及时私信上传者)
2.虚拟产品一经售出概不退款(资源遇到问题,请及时私信上传者)
版权申诉
0 下载量 83 浏览量
2023-12-09
23:22:35
上传
评论
收藏 34KB ZIP 举报
温馨提示
俄罗斯方块的逻辑很简单,就是几个方块组合在一起,然后下落,当其碰到四周的墙壁后便无法移动。若某行被方块所填满,那么就删除这一行,然后此行上面的所有方块下降一行。 为了将这个逻辑代码化,可以用布尔矩阵来表示具体的方块类型,比如长条形方块可用如下矩阵表示。里面包含两个矩阵,分别是横条和竖条,在实际实用中,通过按键可以旋转其状态。原理十分简单,但想要写出一个可以玩的游戏,却还需要注意一些细节问题。比如俄罗斯方块在碰到墙壁时的行为;旋转方块的方法。 博客地址:https://tinycool.blog.csdn.net/article/details/134902678
资源推荐
资源详情
资源评论
收起资源包目录
Russia.zip (4个子文件)
Russia.png 33KB
main.py 8KB
blocks.py 4KB
博客.md 11KB
共 4 条
- 1
资源评论
微小冷
- 粉丝: 2w+
- 资源: 47
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功