Zurück zum Projekt

#Globale Variabeln initiieren

#Nach Präferenz ändern:
w = 0
h = 0
playerY = 3
playerZ = 20
buildGlass = True

#Nicht ändern:
board = [[0]]
piece = [[0]]
pieceX = 0
pieceY = 0
color = DIAMOND_BLOCK
isRunning = False
origin = player.position()
score = 0
unusedPieces = range(7)



#Generelle Funktionen

def startTetris():
    global w
    global h
    global playerZ
    global board
    global piece
    global pieceX
    global pieceY
    global isRunning
    global origin
    global score
    global unusedPieces
    
    #erstellen einer zweidimensionalen Liste zum Speichern der Spielfläche
    # (0/1) (1/1)
    # (0/0) (1/0)
    board = []
    for i in range(w):
        temparr = range(h)
        board[i] = temparr
        for j in range(h):
            board[i][j] = 0
    
    #erstellen des ersten Tetrominos
    unusedPieces = range(7)
    pieceX = Math.round(w/2) - 2
    pieceY = h - 1
    getPiece()
    
    #Spieler zentrieren und Agenten wegteleportieren
    agent.teleport_to_player()
    player.teleport(agent.get_position())
    origin = player.position()
    player.execute("tp ~ ~ ~ facing ~ ~ ~1")
    agent.teleport(pos(0, -10, 0), SOUTH)
    
    #"Spielkonsole" bauen
    makeBoard(w - 1, h - 1)
    
    #Spiel starten
    isRunning = True
    score = 0
    gameloop()

player.on_chat("start", startTetris)



def makeBoard(w, h):
    global playerY
    global playerZ
    global buildGlass
    
    #Plattform bauen
    blocks.fill(GLASS, pos(-1, -2, -1), pos(1, -2, 1))
    blocks.fill(blocks.block_by_name("scaffolding"), pos(-1, -1, -1), pos(1, -1, 1))
    blocks.fill(GLASS_PANE, pos(-1, 0, -1), pos(1, 0, -1))
    blocks.fill(GLASS_PANE, pos(-1, 0, 1), pos(1, 0, 1))
    blocks.place(GLASS_PANE, pos(-1, 0, 0))
    blocks.place(GLASS_PANE, pos(1, 0, 0))
    
    #Bildschirm bauen
    n = Math.round(w / 2)
    o = Math.round(w/2%1)
    blocks.fill(BLACK_CONCRETE, pos(-n, -playerY, playerZ+1), pos(n+o, h-playerY, playerZ+1))
    blocks.fill(POLISHED_ANDESITE, pos(-n-1, -1-playerY, playerZ+1), pos(-n-1, h+1-playerY, playerZ-1))
    blocks.fill(POLISHED_ANDESITE, pos(n+o+1, -1-playerY, playerZ+1), pos(n+o+1, h+1-playerY, playerZ-1))
    blocks.fill(POLISHED_ANDESITE, pos(-n-1, -1-playerY, playerZ+1), pos(n+o+1, -1-playerY, playerZ-1))
    blocks.fill(POLISHED_ANDESITE, pos(-n-1, h+1-playerY, playerZ+1), pos(n+o+1, h+1-playerY, playerZ-1))
    blocks.fill(AIR, pos(-n, -playerY, playerZ-1), pos(n+o, h-playerY, playerZ))
    if buildGlass:
        blocks.fill(GLASS, pos(-n, -playerY, playerZ-1), pos(n+o, h-playerY, playerZ-1))



def stopTetris():
    global isRunning
    
    #Aus gameloop() ausbrechen
    isRunning = False

player.on_chat("stop", stopTetris)



def getPiece():
    global piece
    global color
    global pieceX
    global unusedPieces
    
    #Eines der Tetrominos wählen
    random = Math.round(Math.random()*unusedPieces.length)
    n = unusedPieces[random]
    if unusedPieces.length < 1:
        unusedPieces = range(7)
    else:
        unusedPieces.remove(n)
    if n < 1:
        #I
        piece = [[0,1,0,0],[0,1,0,0],[0,1,0,0],[0,1,0,0]]
        color = LIGHT_BLUE_WOOL
    elif n < 2:
        #O
        piece = [[1,1],[1,1]]
        color = YELLOW_WOOL
        pieceX = pieceX + 1
    elif n < 3:
        #T
        piece = [[0,1,0],[1,1,0],[0,1,0]]
        color = PURPLE_WOOL
    elif n < 4:
        #S
        piece = [[1,0,0],[1,1,0],[0,1,0]]
        color = RED_WOOL
    elif n < 5:
        #2
        piece = [[0,1,0],[1,1,0],[1,0,0]]
        color = LIME_WOOL
    elif n < 6:
        #L
        piece = [[1,1,0],[0,1,0],[0,1,0]]
        color = ORANGE_WOOL
    elif n < 7:
        #J
        piece = [[0,1,0],[0,1,0],[1,1,0]]
        color = BLUE_WOOL



#Durchgehend wiederholende Funktion die Spiel "steuert"

def gameloop():
    global isRunning
    frame = 0
    
    #Wiederholen bis Spieler "stop" schreibt
    while isRunning:
        #Bei Bewegung den Tetromino bewegen
        movedDirection = playerMoved()
        if movedDirection[0] != "":
            movePiece(movedDirection[0], movedDirection[1])
            player.teleport(origin)
        
        #Alle 20 Durchläufe den Tetromino nach unten bewegen
        if frame % 20 == 0:
            moveDown()
        frame += 1



#Bewegen der Tetrominos

def playerMoved():
    
    #neue und alte Position vergleichen
    cPos = player.position()
    if origin.to_string() == cPos.to_string():
        return ["", ""]
    else:
        #Richtung bestimmen
        x = origin.get_value(Axis.X) - cPos.get_value(Axis.X)
        y = origin.get_value(Axis.Y) - cPos.get_value(Axis.Y)
        z = origin.get_value(Axis.Z) - cPos.get_value(Axis.Z)
        if x < 0:
            return ["x", "+"]
        elif x > 0:
            return ["x", "-"]
        elif y != 0:
            return ["y", "+"]
        elif z < 0:
            return ["z", "+"]
        else:
            return ["z", "-"]



def movePiece(direction, sign):
    global piece
    
    #Je nach Richtung richtige Bewegung ausführen
    if direction == "x" and sign == "-":
        move(-1)
    elif direction == "x" and sign == "+":
        move(1)
    elif direction == "y":
        moveToBottom()
    elif direction == "z" and sign == "-":
        rotateLeft()
    else:
        rotateRight()



def move(n):
    global piece
    global pieceX
    global pieceY
    
    #X Wert des Tetrominos ändern
    newX = pieceX + n
    if not checkCollisions(piece, newX, pieceY, False):
        checkCollisions(piece, newX, pieceY, True)



def moveDown():
    global piece
    global pieceX
    global pieceY
    
    #Y Wert des Tetrominos ändern
    newY = pieceY - 1
    checkCollisions(piece, pieceX, newY, True)



def moveToBottom():
    global piece
    global pieceX
    global pieceY
    global board
    global playerY
    global playerZ
    
    #Y Wert des Tetrominos senken bis Kollision stattfindet
    newY = pieceY
    while not checkCollisions(piece, pieceX, newY, False):
        newY = newY - 1
    player.execute("fill ~" + str(-w/2-1) + " ~" + str(-playerY) + " ~" + str(playerZ) + " ~" + str(w/2+1) + " ~" + str(h-playerY) + " ~" + str(playerZ) + " air 0 replace wool " + id(color))
    pieceY = newY + 1
    placePiece()



def rotateLeft():
    global piece
    global pieceX
    global pieceY
    tempPiece = []
    newPiece = []
    for i in range(piece.length):
        tr = range(piece.length)
        tempPiece[i] = tr
        newPiece[i] = tr
        for j in range(piece.length):
            tempPiece[i][j] = 0
            newPiece[i][j] = 0
    newPiece = piece
    tPiece = piece
    
    #gedrehtes Tetromino in neue Liste speichern
    for i in range(piece.length):
        for j in range(piece.length):
            tempPiece[i][j] = tPiece[i][piece.length-1-j]
    for i in range(piece.length):
        for j in range(piece.length):
            newPiece[j][i] = tempPiece[i][j]
    player.execute("fill ~" + str(-w/2) + " ~" + str(-playerY) + " ~" + str(playerZ) + " ~" + str(w/2) + " ~" + str(h-playerY) + " ~" + str(playerZ+1) + " air 0 replace wool " + id(color))
    checkCollisions(newPiece, pieceX, pieceY, True)



def rotateRight():
    global piece
    global pieceX
    global pieceY
    tempPiece = []
    newPiece = []
    for i in range(piece.length):
        tr = range(piece.length)
        tempPiece[i] = tr
        newPiece[i] = tr
        for j in range(piece.length):
            tempPiece[i][j] = 0
            newPiece[i][j] = 0
    newPiece = piece
    
    #gedrehtes Tetromino in neue Liste speichern
    for i in range(piece.length):
        for j in range(piece.length):
            tempPiece[j][i] = piece[i][j]
    for i in range(tempPiece.length):
        for j in range(tempPiece.length):
            newPiece[i][tempPiece.length-1-j] = tempPiece[i][j]
    player.execute("fill ~" + str(-w/2) + " ~" + str(-playerY) + " ~" + str(playerZ) + " ~" + str(w/2) + " ~" + str(h-playerY) + " ~" + str(playerZ-1) + " air 0 replace wool " + id(color))
    checkCollisions(newPiece, pieceX, pieceY, True)



def checkCollisions(newPiece, newX, newY, proceed):
    global board
    
    #Kollisionen finden und testen ob Tetromino zuunterst ist
    #Ohne tempPiece entsteht Error, weil type von newPiece nicht bekannt ist
    tempPiece = [[0]]
    tempPiece = newPiece
    collided = False
    bottom = False
    walls = False
    for i in range(newPiece.length):
        for j in range(newPiece.length):
            if newPiece[i][j] == 1:
                if i + newX >= board.length or i + newX < 0:
                    walls = True
                elif board[i + newX][j + newY] == 1:
                    collided = True
                elif j + newY < 0:
                    bottom = True
    if proceed and not walls :
        if bottom:
            placePiece()
        elif not collided:
            updatePiece(newPiece, newX, newY)
        else:
            placePiece()
    elif bottom or collided or walls:
        return(True)
    return(False)



#Funktionen zum Ändern des Bildschirms der "Konsole"

def updatePiece(newPiece, newX, newY):
    global board
    global piece
    global pieceX
    global pieceY
    global h
    global playerY
    global playerZ
    global color
    player.execute("fill ~" + str(-w/2-1) + " ~" + str(-playerY) + " ~" + str(playerZ) + " ~" + str(w/2+1) + " ~" + str(h-playerY) + " ~" + str(playerZ) + " air 0 replace wool " + id(color))
    for i in range(newPiece.length):
        for j in range(newPiece.length):
            if newPiece[i][j] == 1:
                if newY + j < h:
                    blocks.place(color, positions.add(origin, pos(-w/2+newX+i, newY+j-playerY, playerZ)))
    piece = newPiece
    pieceX = newX
    pieceY = newY



def placePiece():
    global board
    global piece
    global pieceX
    global pieceY
    global score
    global isRunning
    
    #Tetromino zur "board" Liste hinzufügen
    for i in range(piece.length):
        for j in range(piece.length):
            if piece[i][j] == 1:
                board[i + pieceX][j + pieceY] = 1
                if pieceY + j < h:
                    blocks.place(placeColor(color), positions.add(origin, pos(-w/2+pieceX+i, pieceY+j-playerY, playerZ)))
                if pieceY + j >= h:
                    isRunning = False
    
    if isRunning:
        #Komplette Reihen entfernen
        removeRow(i)
        #Neues Tetromino generieren
        score = score + 1
        pieceX = Math.round(w/2) - 2
        pieceY = h - 1
        getPiece()
    else:
        player.say("Zu langsam ☹")
        player.say("score: " + str(score))



def removeRow(j):
    global board
    global w
    global h
    y = 0
    
    for _ in range(h):
        complete = 1
        for i in range(w):
            complete = complete * board[i][y]
        if complete == 1:
            #alles über der Reihe nach unten schieben
            for k in range(w):
                for l in range(y, h):
                    board[k][l] = board[k][l+1]
            for l in range(y, h-1):
                blocks.clone(positions.add(origin, pos(-w/2, l+1-playerY, playerZ)), positions.add(origin, pos(w/2, l+1-playerY, playerZ)), positions.add(origin, pos(-w/2, l-playerY, playerZ)), CloneMask.REPLACE, CloneMode.NORMAL)
            for k in range(w-2):
                board[k][h-1]=0
                blocks.fill(AIR, positions.add(origin, pos(-w/2,h-1-playerY, playerZ)), positions.add(origin, pos(w/2-1, h-1-playerY, playerZ)))
        else:
            y = y + 1



def placeColor(color):
    if color == LIGHT_BLUE_WOOL:
        return(LIGHT_BLUE_CONCRETE)
    elif color == YELLOW_WOOL:
        return(YELLOW_CONCRETE)
    elif color == PURPLE_WOOL:
        return(PURPLE_CONCRETE)
    elif color == LIME_WOOL:
        return(LIME_CONCRETE)
    elif color == RED_WOOL:
        return(RED_CONCRETE)
    elif color == ORANGE_WOOL:
        return(ORANGE_CONCRETE)
    else:
        return(BLUE_CONCRETE)



def id(color):
    if color == LIGHT_BLUE_WOOL:
        return 3
    elif color == YELLOW_WOOL:
        return 4
    elif color == PURPLE_WOOL:
        return 10
    elif color == LIME_WOOL:
        return 5
    elif color == RED_WOOL:
        return 14
    elif color == ORANGE_WOOL:
        return 1
    else:
        return 11