俄罗斯方块游戏

1.python代码实现

import sys
import random,copy
import pygame as pg
from pygame.locals import *

EMPTY_CELL=0       
FALLING_BLOCK=1    
STATIC_BLOCK=2     
defaultFont=None      
screen=None    
backSurface=None        
score=0    
clearLineScore=0       
level=1   
clock=None 
nowBlock=None 
nextBlock=None
fallSpeed=10
beginFallSpeed=fallSpeed
speedBuff=0 
keyBuff=None 
maxBlockWidth=10 
maxBlockHeight=18  
blockWidth=30 
blockHeight=30    
blocks=[]      
stage=[]       
gameOver=False   
pause=False   

def printTxt(content,x,y,font,screen,color=(255,255,255)):
    imgTxt=font.render(content,True,color)
    screen.blit(imgTxt,(x,y))
    
    
class point(object):
    def __init__(self,x,y):
        self.__x=x
        self.__y=y
    
    def getx(self):
        return self.__x
    
    def setx(self,x):
        self.__x=x
    
    x=property(getx,setx)
    
    def gety(self):
        return self.__y
    
    def sety(self,y):
        self.__y=y
    
    y=property(gety,sety)    
    
    def __str__(self):
        return "{x:"+"{:.0f}".format(self.__x)+",y:"+"{:.0f}".format(self.__y)+"}"


class blockSprite(object):
    def __init__(self,shape,direction,xy):
        self.shape=shape
        self.direction=direction
        self.xy=xy
    
    def chgDirection(self,direction):
        dirNumb=len(blocks[self.shape])-1
        if direction==1:
            self.direction+=1
            if self.direction>dirNumb:
                self.direction=0
        else:
            self.direction-=1
            if self.direction<0:
                self.direction=dirNumb
    
    def clone(self):
        return blockSprite(self.shape,self.direction,point(self.xy.x,self.xy.y))
        
    def _getBlock(self):
        return blocks[self.shape][self.direction]
        
    block = property(_getBlock)


def getConf(fileName):
    global blocks
    with open(fileName,'rt') as fp:
        for temp in fp.readlines():
            blocks.append([])
            blocksNumb=len(blocks)-1
            blocks[blocksNumb]=[]
            blocks[blocksNumb].append([])
            row=temp.split(";")
            for r in range(len(row)):
                col=[]
                ct=row[r].split(",")
                for c in range(len(ct)):
                    if ct[c]!="1":
                        col.append(0)
                    else:
                        col.append(1)
                for c in range(len(ct)-1,3):
                    col.append(0)
                blocks[blocksNumb][0].append(col)
            for r in range(len(row)-1,3):
                blocks[blocksNumb][0].append([0,0,0,0])
            blocks[blocksNumb][0]=formatBlock(blocks[blocksNumb][0])


def sysInit():
    global defaultFont,screen,backSurface,clock,blocks,stage,gameOver,fallSpeed,beginFallSpeed,nowBlock,nextBlock,score,level,clearLineScore,pause
  
    pg.init()
    screen=pg.display.set_mode((500,550))
    backSurface=pg.Surface((screen.get_rect().width,screen.get_rect().height))
    pg.display.set_caption("block")
    clock=pg.time.Clock()
    pg.mouse.set_visible(False)
    
    defaultFont=pg.font.Font("res/font/yh.ttf",16) 
    nowBlock=None
    nextBlock=None
    gameOver=False
    pause=False
    score=0
    level=1
    clearLineScore=0
    beginFallSpeed=20
    fallSpeed=beginFallSpeed-level*2
    
    stage=[]
    for y in range(maxBlockHeight):
        stage.append([])
        for x in range(maxBlockWidth):
            stage[y].append(EMPTY_CELL)
            
    for x in range(len(blocks)):
        if len(blocks[x])<2:
            t=blocks[x][0]
            for i in range(3):
                t=transform(t,1)
                blocks[x].append(formatBlock(t))
                

def transform(block,direction=0):  
    result=[]
    for y in range(4):
        result.append([])
        for x in range(4):
            if direction==0:
                result[y].append(block[x][3-y])
            else:
                result[y].append(block[3-x][y])
    return result 


def removeTopBlank(block):
    result=copy.deepcopy(block)
    blankNumb=0
    while sum(result[0])<1 and blankNumb<4:
        del result[0]
        result.append([0,0,0,0])
        blankNumb+=1
    return result
    

def formatBlock(block):
    result=removeTopBlank(block)
    result=transform(result, 1)
    result=removeTopBlank(result)
    result=transform(result,0)
    return result


def checkDeany(sprite):
    topX=sprite.xy.x
    topY=sprite.xy.y
    for y in range(len(sprite.block)):
        for x in range(len(sprite.block[y])):
            if sprite.block[y][x]==1:
                yInStage=topY+y
                xInStage=topX+x
                if yInStage>maxBlockHeight-1 or yInStage<0:
                    return True
                if xInStage>maxBlockWidth-1 or xInStage<0:
                    return True
                if stage[yInStage][xInStage]==STATIC_BLOCK:
                    return True                
    return False


def checkLine():
    global stage
    clearCount=0   
    tmpStage=[]    
    
    for y in stage:
        if sum(y)>=maxBlockWidth*2:
            tmpStage.insert(0,maxBlockWidth*[0])
            clearCount+=1
        else:
            tmpStage.append(y)
    if clearCount>0:
        stage=tmpStage
        updateScore(clearCount)
    return clearCount
   

def updateStage(sprite,updateType=1): 
    global stage
    topX=sprite.xy.x
    topY=sprite.xy.y
    for y in range(len(sprite.block)):
        for x in range(len(sprite.block[y])):
            if sprite.block[y][x]==1:
                if updateType==0:
                    if stage[topY+y][topX+x]==FALLING_BLOCK:
                        stage[topY+y][topX+x]=EMPTY_CELL
                elif updateType==1:
                    if stage[topY+y][topX+x]==EMPTY_CELL:
                        stage[topY+y][topX+x]=FALLING_BLOCK
                else:
                    stage[topY+y][topX+x]=STATIC_BLOCK


def updateScore(clearCount):
    global score,fallSpeed,level,clearLineScore
    
    prizePoint=0
    if clearCount>1:
        if clearCount<4:
            prizePoint=clearCount**clearCount
        else:
            prizePoint=clearCount*5
    score+=(clearCount+prizePoint)*level
    if score>99999999:
        score=0
    clearLineScore+=clearCount
    if clearLineScore>100:
        clearLineScore=0
        level+=1
        if level>(beginFallSpeed/2):
            level=1
            fallSpeed=beginFallSpeed
        fallSpeed=beginFallSpeed-level*2
    return score


def drawStage(drawScreen):
    staticColor=30,102,76     
    activeColor=255,239,0
    fontColor=200,10,120
    baseRect=0,0,blockWidth*maxBlockWidth+1,blockHeight*maxBlockHeight+1
    
    drawScreen.fill((180,200,170))
    pg.draw.rect(drawScreen, staticColor, baseRect,1)
    
    for y in range(len(stage)):
        for x in range(len(stage[y])):
            baseRect=x*blockWidth,y*blockHeight,blockWidth,blockHeight
            if stage[y][x]==2:
                pg.draw.rect(drawScreen, staticColor, baseRect)
            elif stage[y][x]==1:
                pg.draw.rect(drawScreen, activeColor, baseRect)
                
    printTxt("Next:",320,350,defaultFont,backSurface,fontColor)
    if nextBlock!=None:
        for y in range(len(nextBlock.block)):
            for x in range(len(nextBlock.block[y])):
                baseRect=320+x*blockWidth,380+y*blockHeight,blockWidth,blockHeight
                if nextBlock.block[y][x]==1:
                    pg.draw.rect(drawScreen, activeColor, baseRect)
                
    printTxt("Level:%d" % level,320,40,defaultFont,backSurface,fontColor)
    printTxt("Score:%d" % score,320,70,defaultFont,backSurface,fontColor)
    printTxt("Clear:%d" % clearLineScore,320,100,defaultFont,backSurface,fontColor)
    
    if gameOver:
        printTxt("GAME OVER",230,200,defaultFont,backSurface,fontColor)   
        printTxt("<PRESS RETURN TO REPLAY>",200,260,defaultFont,backSurface,fontColor)   
    if pause:
        printTxt("Game pausing",230,200,defaultFont,backSurface,fontColor)   
        printTxt("<PRESS RETURN TO CONTINUE>",200,260,defaultFont,backSurface,fontColor)   


def process():
    global gameOver,nowBlock,nextBlock,speedBuff,backSurface,keyBuff,pause
    
    if nextBlock is None:
        nextBlock=blockSprite(random.randint(0,len(blocks)-1),random.randint(0,3),point(maxBlockWidth+4,maxBlockHeight))
    if nowBlock is None:
        nowBlock=nextBlock.clone()
        nowBlock.xy=point(maxBlockWidth//2,0)
        nextBlock=blockSprite(random.randint(0,len(blocks)-1),random.randint(0,3),point(maxBlockWidth+4,maxBlockHeight))
        gameOver=checkDeany(nowBlock)
        if gameOver:
            updateStage(nowBlock,2)
  
    tmpBlock=nowBlock.clone()    
    for event in pg.event.get():
        if event.type== pg.QUIT:
            sys.exit()
            pg.quit()
        elif event.type==pg.KEYDOWN:
            if event.key==pg.K_ESCAPE:
                sys.exit()
                pg.quit()
            elif event.key==pg.K_RETURN:
                if gameOver:
                    sysInit()
                    return
                elif pause:
                    pause=False
                else:
                    pause=True
                    return
            elif not gameOver and not pause:
                if event.key==pg.K_SPACE:
                    tmpBlock.chgDirection(1)
                elif event.key==pg.K_UP:
                    tmpBlock.chgDirection(0)
                    
    if not gameOver and not pause:
        keys=pg.key.get_pressed()
        if keys[K_DOWN]:
            tmpBlock.xy=point(tmpBlock.xy.x,tmpBlock.xy.y+1)
            keyBuff=None
        elif keys[K_LEFT]:
            if keyBuff!=pg.K_LEFT:
                tmpBlock.xy=point(tmpBlock.xy.x-1,tmpBlock.xy.y)
                keyBuff=pg.K_LEFT
            else:
                keyBuff=None
        elif keys[K_RIGHT]:
            if keyBuff!=pg.K_RIGHT:
                tmpBlock.xy=point(tmpBlock.xy.x+1,tmpBlock.xy.y)
                keyBuff=pg.K_RIGHT
            else:
                keyBuff=None
        if not checkDeany(tmpBlock):
            updateStage(nowBlock,0)
            nowBlock=tmpBlock.clone()

        speedBuff+=1
        if speedBuff>=fallSpeed:
            speedBuff=0
            tmpBlock=nowBlock.clone()
            tmpBlock.xy=point(nowBlock.xy.x,nowBlock.xy.y+1)
            if not checkDeany(tmpBlock):
                updateStage(nowBlock,0)
                nowBlock=tmpBlock.clone()
                updateStage(nowBlock,1)
            else:
                updateStage(nowBlock,2)
                checkLine()
                nowBlock=None
        else:
            updateStage(nowBlock,1)
    drawStage(backSurface)
    screen.blit(backSurface,(0,0))
    pg.display.update()
    clock.tick(40)

    
def main():
    sysInit()
    while True:
        process() 
  
    
if __name__ == "__main__":
    main()
源代码出自https://www.cnblogs.com/lykyl/p/5946102.html
在此基础上进行了一些细节上的小优化,让游戏体验感更好一点。
2.
 
posted @ 2020-11-29 22:03  20201210徐铭泽  阅读(102)  评论(0编辑  收藏  举报