Pygame Tetris

andreasGames3 months ago200 Views

Requirements:

Install dependencies if not already done:

pip install pygame

Sound Files:

You’ll need to include sound files:

  • line.wav (for line clear)
  • rotate.wav (for rotation)
  • gameover.wav (for game over)
import pygame
import random
import json
import os

# --- Game Configuration ---
CELL_SIZE = 30
COLS = 10
ROWS = 20
WIDTH = CELL_SIZE * COLS
HEIGHT = CELL_SIZE * ROWS
FPS = 60

# Colors
BLACK = (0, 0, 0)
GRAY = (128, 128, 128)
WHITE = (255, 255, 255)
COLORS = [
    (0, 255, 255), (255, 255, 0), (128, 0, 128),
    (0, 255, 0), (255, 0, 0), (0, 0, 255), (255, 165, 0)
]

# Tetromino Shapes
SHAPES = {
    'I': [[1, 1, 1, 1]],
    'O': [[1, 1], [1, 1]],
    'T': [[0, 1, 0], [1, 1, 1]],
    'S': [[0, 1, 1], [1, 1, 0]],
    'Z': [[1, 1, 0], [0, 1, 1]],
    'J': [[1, 0, 0], [1, 1, 1]],
    'L': [[0, 0, 1], [1, 1, 1]]
}

class Tetromino:
    def __init__(self, shape):
        self.shape = shape
        self.color = random.choice(COLORS)
        self.x = COLS // 2 - len(shape[0]) // 2
        self.y = 0

    def rotate(self):
        self.shape = [list(row) for row in zip(*self.shape[::-1])]

class Tetris:
    def __init__(self):
        pygame.init()
        self.screen = pygame.display.set_mode((WIDTH, HEIGHT))
        pygame.display.set_caption("Tetris")
        self.clock = pygame.time.Clock()
        self.grid = [[None for _ in range(COLS)] for _ in range(ROWS)]
        self.score = 0
        self.level = 1
        self.load_highscore()
        self.drop_time = 1000
        self.last_drop = pygame.time.get_ticks()
        self.running = True
        self.font = pygame.font.SysFont('Arial', 24)
        self.sounds = {
            'line': pygame.mixer.Sound('line.wav'),
            'rotate': pygame.mixer.Sound('rotate.wav'),
            'gameover': pygame.mixer.Sound('gameover.wav')
        }
        self.tetromino = self.new_tetromino()

    def new_tetromino(self):
        shape = random.choice(list(SHAPES.values()))
        return Tetromino(shape)

    def valid_position(self, shape, offset_x, offset_y):
        for y, row in enumerate(shape):
            for x, cell in enumerate(row):
                if cell:
                    nx, ny = offset_x + x, offset_y + y
                    if nx < 0 or nx >= COLS or ny >= ROWS:
                        return False
                    if ny >= 0 and self.grid[ny][nx]:
                        return False
        return True

    def lock_tetromino(self):
        for y, row in enumerate(self.tetromino.shape):
            for x, cell in enumerate(row):
                if cell:
                    self.grid[self.tetromino.y + y][self.tetromino.x + x] = self.tetromino.color
        self.clear_lines()
        self.tetromino = self.new_tetromino()
        if not self.valid_position(self.tetromino.shape, self.tetromino.x, self.tetromino.y):
            self.running = False
            self.sounds['gameover'].play()
            self.save_highscore()

    def clear_lines(self):
        lines = 0
        new_grid = []
        for row in self.grid:
            if all(row):
                lines += 1
                new_grid.insert(0, [None] * COLS)
            else:
                new_grid.append(row)
        self.grid = new_grid
        if lines:
            self.sounds['line'].play()
            self.score += lines * 100
            self.level = self.score // 500 + 1
            self.drop_time = max(100, 1000 - (self.level - 1) * 100)

    def draw_grid(self):
        for y in range(ROWS):
            for x in range(COLS):
                rect = pygame.Rect(x * CELL_SIZE, y * CELL_SIZE, CELL_SIZE, CELL_SIZE)
                pygame.draw.rect(self.screen, GRAY, rect, 1)
                if self.grid[y][x]:
                    pygame.draw.rect(self.screen, self.grid[y][x], rect)

    def draw_tetromino(self):
        for y, row in enumerate(self.tetromino.shape):
            for x, cell in enumerate(row):
                if cell:
                    rect = pygame.Rect((self.tetromino.x + x) * CELL_SIZE, (self.tetromino.y + y) * CELL_SIZE, CELL_SIZE, CELL_SIZE)
                    pygame.draw.rect(self.screen, self.tetromino.color, rect)

    def draw_ui(self):
        score_text = self.font.render(f"Score: {self.score}", True, WHITE)
        level_text = self.font.render(f"Level: {self.level}", True, WHITE)
        highscore_text = self.font.render(f"Highscore: {self.highscore}", True, WHITE)
        self.screen.blit(score_text, (10, 10))
        self.screen.blit(level_text, (10, 40))
        self.screen.blit(highscore_text, (10, 70))

    def move(self, dx):
        if self.valid_position(self.tetromino.shape, self.tetromino.x + dx, self.tetromino.y):
            self.tetromino.x += dx

    def rotate(self):
        old_shape = self.tetromino.shape
        self.tetromino.rotate()
        if self.valid_position(self.tetromino.shape, self.tetromino.x, self.tetromino.y):
            self.sounds['rotate'].play()
        else:
            self.tetromino.shape = old_shape

    def drop(self):
        if self.valid_position(self.tetromino.shape, self.tetromino.x, self.tetromino.y + 1):
            self.tetromino.y += 1
        else:
            self.lock_tetromino()

    def load_highscore(self):
        try:
            with open('highscore.json', 'r') as f:
                self.highscore = json.load(f).get('highscore', 0)
        except:
            self.highscore = 0

    def save_highscore(self):
        if self.score > self.highscore:
            with open('highscore.json', 'w') as f:
                json.dump({'highscore': self.score}, f)

    def run(self):
        while self.running:
            self.screen.fill(BLACK)
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    self.running = False
                elif event.type == pygame.KEYDOWN:
                    if event.key == pygame.K_LEFT:
                        self.move(-1)
                    elif event.key == pygame.K_RIGHT:
                        self.move(1)
                    elif event.key == pygame.K_DOWN:
                        self.drop()
                    elif event.key == pygame.K_UP:
                        self.rotate()

            now = pygame.time.get_ticks()
            if now - self.last_drop > self.drop_time:
                self.drop()
                self.last_drop = now

            self.draw_grid()
            self.draw_tetromino()
            self.draw_ui()
            pygame.display.flip()
            self.clock.tick(FPS)

        pygame.quit()

if __name__ == '__main__':
    Tetris().run()

0 Votes: 0 Upvotes, 0 Downvotes (0 Points)

Leave a reply

Previous Post

Next Post

Loading Next Post...
Loading

Signing-in 3 seconds...