'Tetris remove completed lines and shift all the remaining blocks

So I wrote Tetris in pygame and all I need now is to remove the completed lines and shift all the remaining blocks. But I don't know how to implement this. Can anyone help me, please?

I tried to get the color of the different points of a line or to check collision somehow but I cant get it to work.

This is some basic setup. import random import pygame from sys import exit

pygame.init()

# window
window = pygame.display.set_mode((1000, 800))
pygame.display.set_caption("Tetris")

here are all the classes of the shapes

# classes
class Ishape(pygame.sprite.Sprite):
    def __init__(self):
        super().__init__()
        self.image = pygame.image.load("I-rotation1png.png").convert_alpha()
        self.image = pygame.transform.scale(self.image, (104, 26))
        self.rect = self.image.get_rect(topleft = (484, 26))
        self.mask = pygame.mask.from_surface(self.image)
        self.pressed = False
        self.run_once = True
        self.run_once2 = True
        self.run_once3 = True
        self.do_stuff = True

    def movement(self):
        keys = pygame.key.get_pressed()

        if keys[pygame.K_d] and self.run_once:
            self.rect.x += 26
            self.run_once = False
        if not keys[pygame.K_d]:
            self.run_once = True

        if keys[pygame.K_a] and self.run_once2:
            self.rect.x -= 26
            self.run_once2 = False
        if not keys[pygame.K_a]:
            self.run_once2 = True

        if keys[pygame.K_s] and self.run_once3:
            self.rect.y += 26
            self.run_once3 = False
        if not keys[pygame.K_s]:
            self.run_once3 = True

    def rotate(self):
        keys = pygame.key.get_pressed()

        if keys[pygame.K_r]:
            self.pressed = True
        if not keys[pygame.K_r] and self.pressed:
            self.pressed = False
            self.image = pygame.transform.rotate(self.image, 90)
            self.rect = self.image.get_rect(topleft=(self.rect.x, self.rect.y))
            self.mask = pygame.mask.from_surface(self.image)

    def update(self):
        if self.do_stuff:
            self.rotate()
            self.movement()


class Jshape(pygame.sprite.Sprite):
    def __init__(self):
        super().__init__()
        self.image = pygame.image.load("J1.png").convert_alpha()
        self.image = pygame.transform.scale(self.image, (52, 78))
        self.rect = self.image.get_rect(topleft = (484, 26))
        self.mask = pygame.mask.from_surface(self.image)
        self.pressed = False
        self.run_once = True
        self.run_once2 = True
        self.run_once3 = True
        self.do_stuff = True

    def movement(self):
        keys = pygame.key.get_pressed()

        if keys[pygame.K_d] and self.run_once:
            self.rect.x += 26
            self.run_once = False
        if not keys[pygame.K_d]:
            self.run_once = True

        if keys[pygame.K_a] and self.run_once2:
            self.rect.x -= 26
            self.run_once2 = False
        if not keys[pygame.K_a]:
            self.run_once2 = True

        if keys[pygame.K_s] and self.run_once3:
            self.rect.y += 26
            self.run_once3 = False
        if not keys[pygame.K_s]:
            self.run_once3 = True

    def rotate(self):
        keys = pygame.key.get_pressed()

        if keys[pygame.K_r]:
            self.pressed = True
        if not keys[pygame.K_r] and self.pressed:
            self.pressed = False
            self.image = pygame.transform.rotate(self.image, 90)
            self.rect = self.image.get_rect(topleft=(self.rect.x, self.rect.y))
            self.mask = pygame.mask.from_surface(self.image)

    def update(self):
        if self.do_stuff:
            self.rotate()
            self.movement()


class Lshape(pygame.sprite.Sprite):
    def __init__(self):
        super().__init__()
        self.image = pygame.image.load("L1.png").convert_alpha()
        self.image = pygame.transform.scale(self.image, (52, 78))
        self.rect = self.image.get_rect(topleft = (484, 26))
        self.mask = pygame.mask.from_surface(self.image)
        self.pressed = False
        self.run_once = True
        self.run_once2 = True
        self.run_once3 = True
        self.do_stuff = True

    def movement(self):
        keys = pygame.key.get_pressed()

        if keys[pygame.K_d] and self.run_once:
            self.rect.x += 26
            self.run_once = False
        if not keys[pygame.K_d]:
            self.run_once = True

        if keys[pygame.K_a] and self.run_once2:
            self.rect.x -= 26
            self.run_once2 = False
        if not keys[pygame.K_a]:
            self.run_once2 = True

        if keys[pygame.K_s] and self.run_once3:
            self.rect.y += 26
            self.run_once3 = False
        if not keys[pygame.K_s]:
            self.run_once3 = True

    def rotate(self):
        keys = pygame.key.get_pressed()

        if keys[pygame.K_r]:
            self.pressed = True
        if not keys[pygame.K_r] and self.pressed:
            self.pressed = False
            self.image = pygame.transform.rotate(self.image, 90)
            self.rect = self.image.get_rect(topleft=(self.rect.x, self.rect.y))
            self.mask = pygame.mask.from_surface(self.image)

    def update(self):
        if self.do_stuff:
            self.rotate()
            self.movement()


class Oshape(pygame.sprite.Sprite):
    def __init__(self):
        super().__init__()
        self.image = pygame.image.load("O.png").convert_alpha()
        self.image = pygame.transform.scale(self.image, (52, 52))
        self.rect = self.image.get_rect(topleft = (484, 26))
        self.mask = pygame.mask.from_surface(self.image)
        self.pressed = False
        self.run_once = True
        self.run_once2 = True
        self.run_once3 = True
        self.do_stuff = True

    def movement(self):
        keys = pygame.key.get_pressed()

        if keys[pygame.K_d] and self.run_once:
            self.rect.x += 26
            self.run_once = False
        if not keys[pygame.K_d]:
            self.run_once = True

        if keys[pygame.K_a] and self.run_once2:
            self.rect.x -= 26
            self.run_once2 = False
        if not keys[pygame.K_a]:
            self.run_once2 = True

        if keys[pygame.K_s] and self.run_once3:
            self.rect.y += 26
            self.run_once3 = False
        if not keys[pygame.K_s]:
            self.run_once3 = True

    def rotate(self):
        keys = pygame.key.get_pressed()

        if keys[pygame.K_r]:
            self.pressed = True
        if not keys[pygame.K_r] and self.pressed:
            self.pressed = False
            self.image = pygame.transform.rotate(self.image, 90)
            self.rect = self.image.get_rect(topleft=(self.rect.x, self.rect.y))
            self.mask = pygame.mask.from_surface(self.image)

    def update(self):
        if self.do_stuff:
            self.rotate()
            self.movement()


class Sshape(pygame.sprite.Sprite):
    def __init__(self):
        super().__init__()
        self.image = pygame.image.load("S1.png").convert_alpha()
        self.image = pygame.transform.scale(self.image, (78, 52))
        self.rect = self.image.get_rect(topleft = (484, 26))
        self.mask = pygame.mask.from_surface(self.image)
        self.pressed = False
        self.run_once = True
        self.run_once2 = True
        self.run_once3 = True
        self.do_stuff = True

    def movement(self):
        keys = pygame.key.get_pressed()

        if keys[pygame.K_d] and self.run_once:
            self.rect.x += 26
            self.run_once = False
        if not keys[pygame.K_d]:
            self.run_once = True

        if keys[pygame.K_a] and self.run_once2:
            self.rect.x -= 26
            self.run_once2 = False
        if not keys[pygame.K_a]:
            self.run_once2 = True

        if keys[pygame.K_s] and self.run_once3:
            self.rect.y += 26
            self.run_once3 = False
        if not keys[pygame.K_s]:
            self.run_once3 = True

    def rotate(self):
        keys = pygame.key.get_pressed()

        if keys[pygame.K_r]:
            self.pressed = True
        if not keys[pygame.K_r] and self.pressed:
            self.pressed = False
            self.image = pygame.transform.rotate(self.image, 90)
            self.rect = self.image.get_rect(topleft=(self.rect.x, self.rect.y))
            self.mask = pygame.mask.from_surface(self.image)

    def update(self):
        if self.do_stuff:
            self.rotate()
            self.movement()


class Tshape(pygame.sprite.Sprite):
    def __init__(self):
        super().__init__()
        self.image = pygame.image.load("T1.png").convert_alpha()
        self.image = pygame.transform.scale(self.image, (78, 52))
        self.rect = self.image.get_rect(topleft = (484, 26))
        self.mask = pygame.mask.from_surface(self.image)
        self.pressed = False
        self.run_once = True
        self.run_once2 = True
        self.run_once3 = True
        self.do_stuff = True

    def movement(self):
        keys = pygame.key.get_pressed()

        if keys[pygame.K_d] and self.run_once:
            self.rect.x += 26
            self.run_once = False
        if not keys[pygame.K_d]:
            self.run_once = True

        if keys[pygame.K_a] and self.run_once2:
            self.rect.x -= 26
            self.run_once2 = False
        if not keys[pygame.K_a]:
            self.run_once2 = True

        if keys[pygame.K_s] and self.run_once3:
            self.rect.y += 26
            self.run_once3 = False
        if not keys[pygame.K_s]:
            self.run_once3 = True

    def rotate(self):
        keys = pygame.key.get_pressed()

        if keys[pygame.K_r]:
            self.pressed = True
        if not keys[pygame.K_r] and self.pressed:
            self.pressed = False
            self.image = pygame.transform.rotate(self.image, 90)
            self.rect = self.image.get_rect(topleft=(self.rect.x, self.rect.y))
            self.mask = pygame.mask.from_surface(self.image)

    def update(self):
        if self.do_stuff:
            self.rotate()
            self.movement()


class Zshape(pygame.sprite.Sprite):
    def __init__(self):
        super().__init__()
        self.image = pygame.image.load("Z1.png").convert_alpha()
        self.image = pygame.transform.scale(self.image, (78, 52))
        self.rect = self.image.get_rect(topleft = (484, 26))
        self.mask = pygame.mask.from_surface(self.image)
        self.pressed = False
        self.run_once = True
        self.run_once2 = True
        self.run_once3 = True
        self.do_stuff = True

    def movement(self):
        keys = pygame.key.get_pressed()

        if keys[pygame.K_d] and self.run_once:
            self.rect.x += 26
            self.run_once = False
        if not keys[pygame.K_d]:
            self.run_once = True

        if keys[pygame.K_a] and self.run_once2:
            self.rect.x -= 26
            self.run_once2 = False
        if not keys[pygame.K_a]:
            self.run_once2 = True

        if keys[pygame.K_s] and self.run_once3:
            self.rect.y += 26
            self.run_once3 = False
        if not keys[pygame.K_s]:
            self.run_once3 = True

    def rotate(self):
        keys = pygame.key.get_pressed()

        if keys[pygame.K_r]:
            self.pressed = True
        if not keys[pygame.K_r] and self.pressed:
            self.pressed = False
            self.image = pygame.transform.rotate(self.image, 90)
            self.rect = self.image.get_rect(topleft=(self.rect.x, self.rect.y))
            self.mask = pygame.mask.from_surface(self.image)

    def update(self):
        if self.do_stuff:
            self.rotate()
            self.movement()

here I created groups of the classes

# groups
I = pygame.sprite.GroupSingle()
I.add(Ishape())

J = pygame.sprite.GroupSingle()
J.add(Jshape())

L = pygame.sprite.GroupSingle()
L.add(Lshape())

O = pygame.sprite.GroupSingle()
O.add(Oshape())

S = pygame.sprite.GroupSingle()
S.add(Sshape())

T = pygame.sprite.GroupSingle()
T.add(Tshape())

Z = pygame.sprite.GroupSingle()
Z.add(Zshape())

# variables
running = False
clock = pygame.time.Clock()
only_base_groups = [I, J, L, O, S, T, Z]
group_list = [I, J, L, O, S, T, Z]
placed_groups = []
colors = []
current_class = random.choice(group_list)
next_class = random.choice(group_list)
score = 0


# function
def display_grid():
    for y in range(155, 671, 26):
        pygame.draw.line(window, "white", (380, y), (630, y))
    for x in range(380, 625, 26):
        pygame.draw.line(window, "white", (x, 155), (x, 665))


def add_class(group):
    global placed_groups
    placed_groups.append(group)


# surfaces
background = pygame.image.load("background.png").convert_alpha()
backgroundRect = background.get_rect(topleft = (0, 0))

scoreFont = pygame.font.Font(None, 40)

# timer
moveTimer = pygame.USEREVENT + 1
pygame.time.set_timer(moveTimer, 700)

this is where it should be implemented (in the main game section) while True: if running: pygame.display.update() clock.tick(60)

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                exit()
            if event.type == moveTimer:
                current_class.sprite.rect.y += 26

        window.blit(background, backgroundRect)

        # score
        score = score + 0.1
        scoreSurf = scoreFont.render('Score: ' + str(int(score)), False, 'white')
        window.blit(scoreSurf, (200, 340))

        # main game
        if background.get_at((383, 675)) != (38, 38, 38, 255):
            print(background.get_at((383, 675)))

        current_class.draw(window)
        current_class.update()
        add_class(current_class)

        for i in placed_groups:
            if placed_groups:
                i.draw(window)
                i.update()

        if not current_class.sprite.do_stuff:
            current_class = next_class
            next_class = random.choice(only_base_groups)

            if current_class == I:
                current_class = current_class.copy()
                group_list.append(current_class)
                current_class.add(Ishape())
            elif current_class == J:
                current_class = current_class.copy()
                group_list.append(current_class)
                current_class.add(Jshape())
            elif current_class == L:
                current_class = current_class.copy()
                group_list.append(current_class)
                current_class.add(Lshape())
            elif current_class == O:
                current_class = current_class.copy()
                group_list.append(current_class)
                current_class.add(Oshape())
            elif current_class == S:
                current_class = current_class.copy()
                group_list.append(current_class)
                current_class.add(Sshape())
            elif current_class == T:
                current_class = current_class.copy()
                group_list.append(current_class)
                current_class.add(Tshape())
            elif current_class == Z:
                current_class = current_class.copy()
                group_list.append(current_class)
                current_class.add(Zshape())

        # display next class
        window.blit(next_class.sprite.image, (670, 170))

        # collision
        for group in group_list:
            if group.sprite.rect.bottom >= 675:
                group.sprite.rect.bottom = 675
                group.sprite.do_stuff = False
        for group in group_list:
            if group.sprite.rect.right >= 640:
                group.sprite.rect.right = 640
        for group in group_list:
            if group.sprite.rect.left <= 380:
                group.sprite.rect.left = 380

        for group in placed_groups:
            if group != current_class:
                if pygame.sprite.spritecollide(current_class.sprite, group, False, pygame.sprite.collide_mask):
                    current_class.sprite.rect.y -= 1
                    current_class.sprite.do_stuff = False

        for group in placed_groups:
            if not group.sprite.do_stuff:
                if group.sprite.rect.top <= 155:
                    running = False

        display_grid()
    else:
        pygame.display.update()
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                exit()
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_SPACE:
                    running = True
                    group_list = [I, J, L, O, S, T, Z]
                    placed_groups = []
                    current_class = random.choice(group_list)
                    next_class = random.choice(group_list)
                    score = 0

        if score > 0:
            end_font = pygame.font.Font(None, 90)
            end_surf = end_font.render('Your score was: ' + str(int(score)), False, 'white')
            window.blit(end_surf, (70, 400))
        else:
            start_font = pygame.font.Font(None, 90)
            start_surf = start_font.render("Press space to start the game", False, 'white')
            window.blit(start_surf, (70, 400))


Sources

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

Source: Stack Overflow

Solution Source