鱼C论坛

 找回密码
 立即注册
查看: 1452|回复: 2

[作品展示] pygame俄罗斯方块

[复制链接]
发表于 2018-10-28 22:04:38 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 爱学习的喵 于 2018-10-28 22:21 编辑

前言:
从零基础入门至今学习已经一个半月,谢谢小甲鱼的教学,我由刚开始的python小白到现在已经学会了爬虫,tkinter和pygame等模块,但随着课程的深入,我发现学习的效率不断下降,第87课开始就有点听不下去的,pygame模块真的好难记,所以为深化学习,我自己写了个俄罗斯方块,因为平时自己喜欢玩俄罗斯方块,拥有一款适合自己手感专属的游戏说不定会很有趣喔,就这样做了这个游戏。
代码有点乱,因为是练习和自用的,当中没优化的问题如下:
1.长方形竖立生成的方式(至今在起点只能横向生成,有点后悔生成的游戏太小了)
2.在下降到底部时会出现方块闪现
3.一部分多余的代码,特别是方块的旋转问题,这是个意外,我一开始版本不是2d建模的,所有耗费了大量的代码
综合而言,就是懒得改
操作说明:
下、左右:移动
空格:翻转


import pygame
import sys
from pygame.locals import *
import random
#初始化Pygame

pygame.init()

WHITE = (255,255,255)
BLACK = (0,0,0)

all_blocks = []
def set_background(all_blocks):
    temp1 =[]
    for y in range(21):
        for x in range(12):
            temp1.append(-1)
        all_blocks.append(temp1)
        temp1 = []
    all_blocks = all_blocks[:][:]
        
    return all_blocks

def set_boarder(all_blocks):
    for x in range(12):
        all_blocks[20][x] = 7

    for y in range(21):
        all_blocks[y][0] = 7
        all_blocks[y][11] = 7
    return all_blocks

all_blocks = set_background(all_blocks)

all_blocks = set_boarder(all_blocks)

def block(type_a,dir1,pos_x,pos_y):
    if type_a == 1:
        bottom,left,right,pos_x,pos_y,pos_x1,pos_y1,pos_x2,pos_y2,pos_x3,pos_y3 = block_A(dir1,pos_x,pos_y)
    elif type_a == 2:
        bottom,left,right,pos_x,pos_y,pos_x1,pos_y1,pos_x2,pos_y2,pos_x3,pos_y3 = block_B(dir1,pos_x,pos_y)
    elif type_a == 3:
        bottom,left,right,pos_x,pos_y,pos_x1,pos_y1,pos_x2,pos_y2,pos_x3,pos_y3 = block_C(dir1,pos_x,pos_y)
    elif type_a == 4:
        bottom,left,right,pos_x,pos_y,pos_x1,pos_y1,pos_x2,pos_y2,pos_x3,pos_y3 = block_D(dir1,pos_x,pos_y)
    elif type_a == 5:
        bottom,left,right,pos_x,pos_y,pos_x1,pos_y1,pos_x2,pos_y2,pos_x3,pos_y3 = block_E(dir1,pos_x,pos_y)
    elif type_a == 6:
        bottom,left,right,pos_x,pos_y,pos_x1,pos_y1,pos_x2,pos_y2,pos_x3,pos_y3 = block_F(dir1,pos_x,pos_y)

    return bottom,left,right,pos_x,pos_y,pos_x1,pos_y1,pos_x2,pos_y2,pos_x3,pos_y3

def block_A(dir1,pos_x,pos_y):#长方形
    #1:North,2:east
    if dir1 == 2 or dir1==4:
        pos_x1,pos_y1 = pos_x,pos_y+20
        pos_x2,pos_y2 = pos_x,pos_y-20
        pos_x3,pos_y3 = pos_x,pos_y-40
        bottom = pos_y+20
        left = pos_x
        right = pos_x
        
    if dir1 == 1 or dir1 ==3:
        pos_x1,pos_y1 = pos_x-20,pos_y
        pos_x2,pos_y2 = pos_x+20,pos_y
        pos_x3,pos_y3 = pos_x+40,pos_y
        bottom = pos_y
        left = pos_x-20
        right = pos_x+40
        
    pygame.draw.rect(screen,color(1),(pos_x,pos_y,20,20),0)
    pygame.draw.rect(screen,color(1),(pos_x1,pos_y1,20,20),0)
    pygame.draw.rect(screen,color(1),(pos_x2,pos_y2,20,20),0)
    pygame.draw.rect(screen,color(1),(pos_x3,pos_y3,20,20),0)
    return bottom,left,right,pos_x,pos_y,pos_x1,pos_y1,pos_x2,pos_y2,pos_x3,pos_y3

def block_C(dir1,pos_x,pos_y):#倒Z型
    #1:North,2:east
    if dir1 == 1 or dir1 == 3:
        pos_x1,pos_y1 = pos_x-20,pos_y
        pos_x2,  pos_y2 = pos_x,pos_y-20
        pos_x3,pos_y3 = pos_x+20,pos_y-20
        bottom = pos_y
        left = pos_x-20
        right = pos_x+20
        
    if dir1 == 2 or dir1 == 4:
        pos_x1,pos_y1 = pos_x,pos_y+20
        pos_x2,pos_y2 = pos_x-20,pos_y
        pos_x3,pos_y3 = pos_x-20,pos_y-20
        bottom = pos_y+20
        left = pos_x-20
        right = pos_x
        
    pygame.draw.rect(screen,color(3),(pos_x,pos_y,20,20),0)
    pygame.draw.rect(screen,color(3),(pos_x1,pos_y1,20,20),0)
    pygame.draw.rect(screen,color(3),(pos_x2,pos_y2,20,20),0)
    pygame.draw.rect(screen,color(3),(pos_x3,pos_y3,20,20),0)
    return bottom,left,right,pos_x,pos_y,pos_x1,pos_y1,pos_x2,pos_y2,pos_x3,pos_y3

def block_B(dir1,pos_x,pos_y):#Z型
    #1:North,2:east
    if dir1 == 1 or dir1 == 3:
        pos_x1,pos_y1 = pos_x-20,pos_y
        pos_x2,pos_y2 = pos_x,pos_y+20
        pos_x3,pos_y3 = pos_x+20,pos_y+20
        bottom=pos_y+20
        left = pos_x-20
        right = pos_x+20
        
    if dir1 == 2 or dir1 == 4:
        pos_x1,pos_y1 = pos_x,pos_y-20
        pos_x2,pos_y2 = pos_x-20,pos_y
        pos_x3,pos_y3 = pos_x-20,pos_y+20
        bottom = pos_y+20
        left = pos_x-20
        right = pos_x
        
    pygame.draw.rect(screen,color(2),(pos_x,pos_y,20,20),0)
    pygame.draw.rect(screen,color(2),(pos_x1,pos_y1,20,20),0)
    pygame.draw.rect(screen,color(2),(pos_x2,pos_y2,20,20),0)
    pygame.draw.rect(screen,color(2),(pos_x3,pos_y3,20,20),0)
    return bottom,left,right,pos_x,pos_y,pos_x1,pos_y1,pos_x2,pos_y2,pos_x3,pos_y3

def block_D(dir1,pos_x,pos_y):#方型
    #1:North,2:east
    pos_x1,pos_y1 = pos_x-20,pos_y
    pos_x2,pos_y2 = pos_x,pos_y-20
    pos_x3,pos_y3 = pos_x-20,pos_y-20
    pygame.draw.rect(screen,color(4),(pos_x,pos_y,20,20),0)
    pygame.draw.rect(screen,color(4),(pos_x1,pos_y1,20,20),0)
    pygame.draw.rect(screen,color(4),(pos_x2,pos_y2,20,20),0)
    pygame.draw.rect(screen,color(4),(pos_x3,pos_y3,20,20),0)
    bottom = pos_y
    left = pos_x-20
    right = pos_x
    return bottom,left,right,pos_x,pos_y,pos_x1,pos_y1,pos_x2,pos_y2,pos_x3,pos_y3


def block_E(dir1,pos_x,pos_y):#L型
    #1:North,2:east3:south4:west
    if dir1 == 1:
        pos_x1,pos_y1 = pos_x,pos_y-20
        pos_x2,pos_y2 = pos_x,pos_y+20
        pos_x3,pos_y3 = pos_x+20,pos_y+20
        bottom = pos_y+20
        left = pos_x
        right = pos_x+20
        
    if dir1 == 2:
        pos_x1,pos_y1 = pos_x+20,pos_y
        pos_x2,pos_y2 = pos_x-20,pos_y
        pos_x3,pos_y3 = pos_x-20,pos_y+20
        bottom = pos_y+20
        left = pos_x-20
        right = pos_x+20

    if dir1 == 3:
        pos_x1,pos_y1 = pos_x,pos_y+20
        pos_x2,pos_y2 = pos_x,pos_y-20
        pos_x3,pos_y3 = pos_x-20,pos_y-20
        bottom = pos_y+20
        left = pos_x-20
        right = pos_x+20

    if dir1 == 4:
        pos_x1,pos_y1 = pos_x-20,pos_y
        pos_x2,pos_y2 = pos_x+20,pos_y
        pos_x3,pos_y3 = pos_x+20,pos_y-20
        bottom = pos_y
        left = pos_x-20
        right = pos_x+20
        
    pygame.draw.rect(screen,color(5),(pos_x,pos_y,20,20),0)
    pygame.draw.rect(screen,color(5),(pos_x1,pos_y1,20,20),0)
    pygame.draw.rect(screen,color(5),(pos_x2,pos_y2,20,20),0)
    pygame.draw.rect(screen,color(5),(pos_x3,pos_y3,20,20),0)

    return bottom,left,right,pos_x,pos_y,pos_x1,pos_y1,pos_x2,pos_y2,pos_x3,pos_y3

def block_F(dir1,pos_x,pos_y):#倒L型
    #1:North,2:east3:south4:west
    if dir1 == 1:
        pos_x1,pos_y1 = pos_x,pos_y-20
        pos_x2,pos_y2 = pos_x,pos_y+20
        pos_x3,pos_y3 = pos_x-20,pos_y+20
        bottom = pos_y+20
        left = pos_x-20
        right = pos_x
        
    if dir1 == 2:
        pos_x1,pos_y1 = pos_x+20,pos_y
        pos_x2,pos_y2 = pos_x-20,pos_y
        pos_x3,pos_y3 = pos_x-20,pos_y-20
        bottom = pos_y
        left = pos_x-20
        right = pos_x+20

    if dir1 == 3:
        pos_x1,pos_y1 = pos_x,pos_y+20
        pos_x2,pos_y2 = pos_x,pos_y-20
        pos_x3,pos_y3 = pos_x+20,pos_y-20
        bottom = pos_y+20
        left = pos_x
        right = pos_x+20

    if dir1 == 4:
        pos_x1,pos_y1 = pos_x-20,pos_y
        pos_x2,pos_y2 = pos_x+20,pos_y
        pos_x3,pos_y3 = pos_x+20,pos_y+20
        bottom = pos_y+20
        left = pos_x-20
        right = pos_x+20
        
    pygame.draw.rect(screen,color(6),(pos_x,pos_y,20,20),0)
    pygame.draw.rect(screen,color(6),(pos_x1,pos_y1,20,20),0)
    pygame.draw.rect(screen,color(6),(pos_x2,pos_y2,20,20),0)
    pygame.draw.rect(screen,color(6),(pos_x3,pos_y3,20,20),0)

    return bottom,left,right,pos_x,pos_y,pos_x1,pos_y1,pos_x2,pos_y2,pos_x3,pos_y3

size = width , height = 400,420
screen = pygame.display.set_mode(size)
pygame.display.set_caption('Tetris')

#第一块方块值
dir1 = 1
pos_x = 120
pos_y = 0
#下降计时器
timer=0
#选择方块色彩
def color(num):
    if num ==1:
        return (0,0,255)
    if num ==2:
        return (0,255,0)
    if num ==3:
        return (255,0,0)
    if num ==4:
        return (127,127,0)
    if num ==5:
        return (127,0,127)
    if num ==6:
        return (0,127,127)
    if num == 7:
        return (0,0,0)
   

#能否移动左边
def moveleft(all_blocks,pos_x,pos_y,pos_x1,pos_y1,pos_x2,pos_y2,pos_x3,pos_y3):
    pos_x//=20
    pos_y//=20
    pos_x1//=20
    pos_y1//=20
    pos_x2//=20
    pos_y2//=20
    pos_x3//=20
    pos_y3//=20
    #print(pos_x,pos_y,pos_x1,pos_y1,pos_x2,pos_y2,pos_x3,pos_y3)
    if all_blocks[pos_y][pos_x-1] != -1 \
       or all_blocks[pos_y1][pos_x1-1] != -1 \
       or all_blocks[pos_y2][pos_x2-1] != -1 \
       or all_blocks[pos_y3][pos_x3-1]!= -1:
        return False
    return True
#能否移到右边
def moveright(all_blocks,pos_x,pos_y,pos_x1,pos_y1,pos_x2,pos_y2,pos_x3,pos_y3):
    pos_x//=20
    pos_y//=20
    pos_x1//=20
    pos_y1//=20
    pos_x2//=20
    pos_y2//=20
    pos_x3//=20
    pos_y3//=20
    #print(pos_x,pos_y,pos_x1,pos_y1,pos_x2,pos_y2,pos_x3,pos_y3)
    if all_blocks[pos_y][pos_x+1] != -1 \
       or all_blocks[pos_y1][pos_x1+1] != -1 \
       or all_blocks[pos_y2][pos_x2+1] != -1 \
       or all_blocks[pos_y3][pos_x3+1]!= -1:
        return False
    return True

def movedown(all_blocks,pos_x,pos_y,pos_x1,pos_y1,pos_x2,pos_y2,pos_x3,pos_y3):
    pos_x//=20
    pos_y//=20
    pos_x1//=20
    pos_y1//=20
    pos_x2//=20
    pos_y2//=20
    pos_x3//=20
    pos_y3//=20
    #print(pos_x,pos_y,pos_x1,pos_y1,pos_x2,pos_y2,pos_x3,pos_y3)
    if pos_y>0 and pos_y1>0 and pos_y2>0 and pos_y3>0:
        if all_blocks[pos_y][pos_x] != -1 \
           or all_blocks[pos_y1][pos_x1] != -1 \
           or all_blocks[pos_y2][pos_x2] != -1 \
           or all_blocks[pos_y3][pos_x3] != -1:
            return False
    return True

def rotate(all_blocks,pos_x,pos_y,pos_x1,pos_y1,pos_x2,pos_y2,pos_x3,pos_y3):
    temp = pos_y1
   
    pos_y1 = pos_y-(pos_x1 - pos_x)
    pos_x1 = pos_x-(temp-pos_y)
    temp = pos_y2
    pos_y2 = pos_y-(pos_x2 - pos_x)
    pos_x2 = pos_x-(temp-pos_y)
    temp = pos_y3
    pos_y3 = pos_y-(pos_x3 - pos_x)
    pos_x3 = pos_x-(temp-pos_y)

    if all_blocks[pos_y1//20][pos_x1//20]== -1 and all_blocks[pos_y2//20][pos_x2//20]== -1\
                                   and all_blocks[pos_y3//20][pos_x3//20]== -1:
        #print('a')
        return True

def level_up(points):
    level = 1
    if points >20:
        level = 2
    if points >40:
        level = 3
    if points >60:
        level = 4
    if points >80:
        level = 5
    if points >100:
        level = 6
    if points >120:
        level = 7
    if points >140:
        level = 8
    if points >160:
        level = 9
    return level
   
def get_point(all_blocks,points):
    for y in range(20):
        if -1 not in all_blocks[y]:
            points+=1
            for x in range(1,11,1):
                all_blocks[y][x]=-1
            for i in range(y):
                for x in range(1,11,1):
                    if i!=y:
                        all_blocks[y-i][x]= all_blocks[y-i-1][x]
    return all_blocks,points

def game_over(all_blocks):
    for x in range(1,11,1):
        if all_blocks[0][x]!=-1:
            return True
    return False
#设定等级
level = 1
levels = {1:500,2:450,3:400,4:350,5:300,6:250,7:200,8:150,9:100}
#
next_block_type = random.randint(1,6)
myfont = pygame.font.Font(None, 18)
block_timer = 0
points = 0
block_type = random.randint(1,6)  
clock = pygame.time.Clock()
while not game_over(all_blocks):
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()

        if event.type == KEYDOWN:
            #if event.key == K_LEFT and moveleft(all_blocks,pos_x,pos_y,pos_x1,pos_y1,pos_x2,pos_y2,pos_x3,pos_y3):
                #pos_x -= 20
            #if event.key == K_RIGHT and moveright(all_blocks,pos_x,pos_y,pos_x1,pos_y1,pos_x2,pos_y2,pos_x3,pos_y3):
                #pos_x += 20
            if event.key == K_SPACE and rotate(all_blocks,pos_x,pos_y,pos_x1,pos_y1,pos_x2,pos_y2,pos_x3,pos_y3):
                if 4>dir1>=1:
                    dir1 += 1
                else:
                    dir1 =1
   
    screen.fill(WHITE)

    #载入背景
    for y in range(21):
        for x in range(12):
            if all_blocks[y][x] != -1:
                pygame.draw.rect(screen,color(all_blocks[y][x]),(x*20,y*20,20,20),0)

    #载入方块
    bottom,left,right,pos_x,pos_y,pos_x1,pos_y1,pos_x2,pos_y2,pos_x3,pos_y3 = block(block_type,dir1,pos_x,pos_y)
    block(next_block_type,1,300,40)

   
    if not movedown(all_blocks,pos_x,pos_y,pos_x1,pos_y1,pos_x2,pos_y2,pos_x3,pos_y3):
        pos_y//=20
        pos_x//=20
        pos_y1//=20
        pos_x1//=20
        pos_y2//=20
        pos_x2//=20
        pos_y3//=20
        pos_x3//=20
        all_blocks[pos_y-1][pos_x]=block_type
        all_blocks[pos_y1-1][pos_x1]=block_type
        all_blocks[pos_y2-1][pos_x2]=block_type
        all_blocks[pos_y3-1][pos_x3]=block_type
        #print(block_type)
        pos_x = 120
        pos_y = 0
        block_type = next_block_type
        next_block_type = random.randint(1,6)
        dir1 =1
    textImage1 = myfont.render('Points', True,(0,0,0))   
    textImage2 = myfont.render(str(points), True,(0,0,0))
    screen.blit(textImage1, (280, 190))
    screen.blit(textImage2, (280, 210))
    textImage3 = myfont.render('Level', True,(0,0,0))   
    textImage4 = myfont.render(str(level), True,(0,0,0))
    screen.blit(textImage3, (280, 150))
    screen.blit(textImage4, (280, 170))
   
    if timer>levels[level]:
        pos_y+=20
        timer=0
    all_blocks,points = get_point(all_blocks,points)
    pygame.display.flip()
    level = level_up(points)
    temp = clock.tick(60)
    key_pressed = pygame.key.get_pressed()
    if key_pressed[pygame.K_DOWN] and movedown(all_blocks,pos_x,pos_y,pos_x1,pos_y1,pos_x2,pos_y2,pos_x3,pos_y3):
        pos_y += 20
    else:
        timer+=temp
    block_timer += 1
    if block_timer>2:#可改善手感
        if key_pressed[pygame.K_LEFT] and moveleft(all_blocks,pos_x,pos_y,pos_x1,pos_y1,pos_x2,pos_y2,pos_x3,pos_y3):
            pos_x -= 20
        if key_pressed[pygame.K_RIGHT] and moveright(all_blocks,pos_x,pos_y,pos_x1,pos_y1,pos_x2,pos_y2,pos_x3,pos_y3):
            pos_x += 20
        block_timer = 0



小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2018-10-28 22:20:19 | 显示全部楼层
66666
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-1-21 21:44:32 | 显示全部楼层
666666666
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-7-7 02:45

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表