'Python tetris input delay gets exponentially longer

import turtle
import random

wn = turtle.Screen()
tetris = turtle.Turtle()
wn.tracer(0)
grid = []
tetriminos = ['t','l','j','i','s','z','o']

class square():
    def __init__(self, falling, block, color):
        self.falling = falling
        self.block = block
        self.color = color
for i in range(12):
    grid.append([])
for i in range(12):
    for j in range(25):
        grid[i].append(square(False, False, 'gray'))

def gridsquare(color):
    tetris.setheading(0)
    tetris.color(color)
    tetris.begin_fill()
    for i in range(4):
        tetris.forward(20)
        tetris.right(90)
    tetris.end_fill()
    tetris.color('black')

def refreshGrid():
    for i in range(12):
        for j in range(25):
            tetris.pu()
            tetris.goto(i * 20 - 120, j * 20 - 250)
            tetris.pd()
            if grid[i][j].block == True:
                gridsquare(grid[i][j].color)
            elif grid[i][j].falling == True:
                gridsquare('green')
            else:
                gridsquare('gray')
    wn.update()

def left():
    ok = True
    for i in range(12):
        for j in range(25):
            if grid[i][j].falling == True:
                if grid[i - 1][j].block == True:
                    ok = False
    if ok == True:
        for i in range(12):
            for j in range(25):
                if grid[i][j].falling == True:
                    grid[i][j].falling = False
                    grid[i - 1][j].falling = True
        refreshGrid()

def right():
    ok = True
    for i in range(12):
        for j in range(25):
            if grid[i][j].falling == True:
                if grid[i + 1][j].block == True:
                    ok = False
    if ok == True:
        for i in range(12):
            for j in range(25):
                if grid[11 - i][j].falling == True:
                    grid[11 - i][j].falling = False
                    grid[11 - i + 1][j].falling = True
        refreshGrid()

def down():
    ok = True
    for i in range(12):
        for j in range(25):
            if grid[i][j].falling == True:
                if grid[i][j - 1].block == True:
                    ok = False
    if ok == True:
        for i in range(12):
            for j in range(25):
                if grid[i][j].falling == True:
                    grid[i][j].falling = False
                    grid[i][j - 1].falling = True
        refreshGrid()
    else:
        for i in range(12):
            for j in range(25):
                if grid[i][j].falling == True:
                    grid[i][j].falling = False
                    grid[i][j].block = True
                    grid[i][j].color = 'blue'
        refreshGrid()
        newTetrimino()

def newTetrimino():
    tet = tetriminos[random.randint(0, 6)]
    #'t','l','j','i','s','z','o'
    #middle top - 5, 24
    if tet == 'z':
        grid[5][24].falling = True
        grid[5][23].falling = True
        grid[4][24].falling = True
        grid[6][23].falling = True
    elif tet == 's':
        grid[5][24].falling = True
        grid[5][23].falling = True
        grid[4][23].falling = True
        grid[6][24].falling = True
    elif tet == 't':
        grid[5][23].falling = True
        grid[4][23].falling = True
        grid[6][23].falling = True
        grid[5][24].falling = True
    elif tet == 'l':
        grid[5][23].falling = True
        grid[4][23].falling = True
        grid[6][23].falling = True
        grid[6][24].falling = True
    elif tet == 'j':
        grid[5][23].falling = True
        grid[4][23].falling = True
        grid[6][23].falling = True
        grid[4][24].falling = True
    elif tet == 'i':
        grid[5][24].falling = True
        grid[4][24].falling = True
        grid[6][24].falling = True
        grid[7][24].falling = True
    elif tet == 'o':
        grid[6][24].falling = True
        grid[7][24].falling = True
        grid[6][23].falling = True
        grid[7][23].falling = True
    refreshGrid()

grid[5][23].falling = True
grid[4][23].falling = True
grid[6][23].falling = True
grid[5][24].falling = True
for i in range(25):
    grid[0][i].block = True
    grid[0][i].color = 'black'
for i in range(25):
    grid[11][i].block = True
    grid[11][i].color = 'black'
for i in range(12):
    grid[i][0].block = True
    grid[i][0].color = 'black'

refreshGrid()
wn.listen()
wn.onkeypress(left,'a')
wn.onkeypress(right,'d')
wn.onkeypress(down,'s')
wn.mainloop()

Ok so Sorry for long code I'm trying to code tetris and i have the basics down but for some reason each tetrimino you place, it gets exponentially longer input delay I expect a little bit of input delay because of how much it has to check but i don't see why there gets more after each placement

help would be appreciated a lot

Also I am very much a beginner so please explain it as if I was an old grandma thanks



Solution 1:[1]

You've chosen an inefficient approach, graphics-wise. But let's work with it. I've optimized the code below, trying to avoid unnecessary looping and drawing. This seems to help.

Move improvement seems to have come from clearing the old drawing before drawing a new one. That is, you were stacking complete drawings atop all previous drawings whenever you did refreshGrid(). We think of the old drawings as dead ink turtle-wise, but to the underlying tkinter graphics, they are all live entities. By clearing the old drawing before making the new one, we clear out the dead elements we no longer consider valid:

from turtle import Screen, Turtle
from random import choice

tetriminos = ['t', 'l', 'j', 'i', 's', 'z', 'o']

class square():
    def __init__(self, falling, block, color):
        self.falling = falling
        self.block = block
        self.color = color

def gridsquare(color):
    tetris.color(color)
    tetris.pendown()
    tetris.begin_fill()

    for _ in range(4):
        tetris.forward(20)
        tetris.right(90)

    tetris.end_fill()
    tetris.penup()

def refreshGrid():
    tetris.clear()

    for j in range(25):
        tetris.goto(-120, j * 20 - 250)

        for i in range(12):
            if grid[i][j].block:
                gridsquare(grid[i][j].color)
            elif grid[i][j].falling:
                gridsquare('green')
            else:
                gridsquare('gray')

            tetris.forward(20)

    screen.update()

def left():
    for i in range(1, 11):
        for j in range(1, 25):
            if grid[i][j].falling and grid[i - 1][j].block:
                return

    screen.onkeypress(None, 'a')

    for i in range(1, 11):
        for j in range(1, 25):
            if grid[i][j].falling:
                grid[i][j].falling = False
                grid[i - 1][j].falling = True

    refreshGrid()

    screen.onkeypress(left, 'a')

def right():
    for i in range(1, 11):
        for j in range(1, 25):
            if grid[i][j].falling and grid[i + 1][j].block:
                return

    screen.onkeypress(None, 'd')

    for i in range(11, 0, -1):
        for j in range(1, 25):
            if grid[i][j].falling:
                grid[i][j].falling = False
                grid[i + 1][j].falling = True
    refreshGrid()

    screen.onkeypress(right, 'd')

def down():
    screen.onkeypress(None, 's')  # disable handler inside handler

    ok = True

    for i in range(1, 11):
        for j in range(1, 25):
            if grid[i][j].falling and grid[i][j - 1].block:
                ok = False

    if ok:
        for i in range(1, 11):
            for j in range(1, 25):
                if grid[i][j].falling:
                    grid[i][j].falling = False
                    grid[i][j - 1].falling = True
        refreshGrid()
    else:
        for i in range(1, 11):
            for j in range(1, 25):
                if grid[i][j].falling:
                    grid[i][j].falling = False
                    grid[i][j].block = True
                    grid[i][j].color = 'blue'
        refreshGrid()
        newTetrimino()

    screen.onkeypress(down, 's')  # reenable handler on exit


def newTetrimino():
    tetrimino = choice(tetriminos)  # 't','l','j','i','s','z','o'

    # middle top - 5, 24
    if tetrimino == 'z':
        grid[5][24].falling = True
        grid[5][23].falling = True
        grid[4][24].falling = True
        grid[6][23].falling = True
    elif tetrimino == 's':
        grid[5][24].falling = True
        grid[5][23].falling = True
        grid[4][23].falling = True
        grid[6][24].falling = True
    elif tetrimino == 't':
        grid[5][23].falling = True
        grid[4][23].falling = True
        grid[6][23].falling = True
        grid[5][24].falling = True
    elif tetrimino == 'l':
        grid[5][23].falling = True
        grid[4][23].falling = True
        grid[6][23].falling = True
        grid[6][24].falling = True
    elif tetrimino == 'j':
        grid[5][23].falling = True
        grid[4][23].falling = True
        grid[6][23].falling = True
        grid[4][24].falling = True
    elif tetrimino == 'i':
        grid[5][24].falling = True
        grid[4][24].falling = True
        grid[6][24].falling = True
        grid[7][24].falling = True
    elif tetrimino == 'o':
        grid[6][24].falling = True
        grid[7][24].falling = True
        grid[6][23].falling = True
        grid[7][23].falling = True

    refreshGrid()

grid = [[square(False, False, 'gray') for j in range(25)] for i in range(12)]

for j in range(25):
    grid[0][j].block = True
    grid[0][j].color = 'black'

    grid[11][j].block = True
    grid[11][j].color = 'black'

for i in range(1, 11):
    grid[i][0].block = True
    grid[i][0].color = 'black'

screen = Screen()
screen.tracer(0)

tetris = Turtle()
tetris.hideturtle()
tetris.penup()

newTetrimino()

screen.onkeypress(left, 'a')
screen.onkeypress(right, 'd')
screen.onkeypress(down, 's')
screen.listen()

screen.mainloop()

See if this fixes your exponential delays.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 cdlane