Refactoring to use numpy. /JL

This commit is contained in:
2025-05-04 20:56:01 +02:00
parent 431dfcc4d7
commit c443df22ef
6 changed files with 154 additions and 19 deletions

View File

@@ -75,7 +75,7 @@ class Brick:
if new_x <= 0 or new_x >= globals.GRID_WIDTH or new_y >= globals.GRID_HEIGHT: if new_x <= 0 or new_x >= globals.GRID_WIDTH or new_y >= globals.GRID_HEIGHT:
print(f"Collision X:{new_x}, Y:{new_y}") print(f"Collision X:{new_x}, Y:{new_y}")
return True return True
if new_y >= 0 and globals.dropgrid[new_y][new_x]: if new_y >= 0 and globals.grid[new_y][new_x]:
return True return True
return False return False

View File

@@ -1,4 +1,5 @@
import pygame import pygame
import numpy as np
import globals import globals
from enums import BrickColor from enums import BrickColor

View File

@@ -1,22 +1,33 @@
import numpy as np
def init(): def init():
global BRICKS global BRICKS
BRICKS = [ BRICKS = {
[[0,1,0], [1,1,1], [0,1,0]], 'I': np.array([[1, 1, 1, 1]]),
[[0, 0, 1], [1, 1, 1]], 'O': np.array([[1, 1],
[[1, 0, 0], [1, 1, 1]], [1, 1]]),
[[1]], 'T': np.array([[0, 1, 0],
[[1, 1, 1, 1]], [1, 1, 1]]),
[[1, 1], [1, 1]], 'S': np.array([[0, 1, 1],
[[0, 1, 1], [1, 1, 0]], [1, 1, 0]]),
[[1, 1, 0], [0, 1, 1]], 'Z': np.array([[1, 1, 0],
[[1, 0, 1], [1, 1, 1]], [0, 1, 1]]),
[[1, 1, 1], [0, 1, 0]] 'J': np.array([[1, 0, 0],
] [1, 1, 1]]),
'L': np.array([[0, 0, 1],
[1, 1, 1]]),
'.': np.array([[1]]),
'+': np.array([[0, 1, 0],
[1, 1, 1],
[0, 1, 0]]),
'U': np.array([[1, 0, 1],
[1, 1, 1]])
}
global TILE_SIZE global TILE_SIZE
TILE_SIZE = 48 TILE_SIZE = 48
global GRID_WIDTH global GRID_WIDTH
GRID_WIDTH = 10 GRID_WIDTH = 10
global GRID_HEIGHT global GRID_HEIGHT
GRID_HEIGHT = 18 GRID_HEIGHT = 18
global dropgrid global grid
dropgrid = [[0 for _ in range(GRID_WIDTH)] for _ in range(GRID_HEIGHT)] grid = np.zeros((GRID_HEIGHT, GRID_WIDTH), dtype=int)

View File

@@ -1,2 +1,3 @@
numpy==2.2.5
pygame==2.6.1 pygame==2.6.1
pygamecontrols==0.1.13 pygamecontrols==0.1.13

121
tet.py Normal file
View File

@@ -0,0 +1,121 @@
import pygame
import numpy as np
import random
# Pygame setup
pygame.init()
CELL_SIZE = 30
ROWS, COLS = 20, 10
WIDTH, HEIGHT = COLS * CELL_SIZE, ROWS * CELL_SIZE
screen = pygame.display.set_mode((WIDTH, HEIGHT))
clock = pygame.time.Clock()
# Tetromino definitions
TETROMINOS = {
'I': np.array([[1, 1, 1, 1]]),
'O': np.array([[1, 1], [1, 1]]),
'T': np.array([[0, 1, 0], [1, 1, 1]]),
'S': np.array([[0, 1, 1], [1, 1, 0]]),
'Z': np.array([[1, 1, 0], [0, 1, 1]]),
'J': np.array([[1, 0, 0], [1, 1, 1]]),
'L': np.array([[0, 0, 1], [1, 1, 1]])
}
# Colors for pieces
COLORS = {
0: (0, 0, 0),
1: (255, 255, 255)
}
# Game state
grid = np.zeros((ROWS, COLS), dtype=int)
def new_piece():
shape = random.choice(list(TETROMINOS.values()))
return shape, [0, COLS // 2 - shape.shape[1] // 2]
def check_collision(grid, piece, offset):
x, y = offset
h, w = piece.shape
if x + h > ROWS or y < 0 or y + w > COLS:
return True
area = grid[x:x+h, y:y+w]
return np.any(area & piece)
def place_piece(grid, piece, offset):
x, y = offset
h, w = piece.shape
grid[x:x+h, y:y+w] |= piece
def clear_lines(grid):
full_rows = [i for i in range(ROWS) if all(grid[i])]
for i in full_rows:
grid[1:i+1] = grid[0:i]
grid[0] = np.zeros(COLS)
def rotate_piece(piece):
return np.rot90(piece, -1)
def draw_grid(surface, grid):
for i in range(ROWS):
for j in range(COLS):
pygame.draw.rect(surface, COLORS[grid[i][j]],
(j * CELL_SIZE, i * CELL_SIZE, CELL_SIZE, CELL_SIZE), 0)
pygame.draw.rect(surface, (40, 40, 40),
(j * CELL_SIZE, i * CELL_SIZE, CELL_SIZE, CELL_SIZE), 1)
def draw_piece(surface, piece, offset):
x, y = offset
for i in range(piece.shape[0]):
for j in range(piece.shape[1]):
if piece[i][j]:
pygame.draw.rect(surface, COLORS[1],
((y + j) * CELL_SIZE, (x + i) * CELL_SIZE, CELL_SIZE, CELL_SIZE))
# Start game
piece, pos = new_piece()
drop_timer = 0
running = True
while running:
screen.fill((0, 0, 0))
draw_grid(screen, grid)
draw_piece(screen, piece, pos)
pygame.display.flip()
clock.tick(60)
drop_timer += 1
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.KEYDOWN:
new_pos = pos[:]
if event.key == pygame.K_LEFT:
new_pos[1] -= 1
elif event.key == pygame.K_RIGHT:
new_pos[1] += 1
elif event.key == pygame.K_DOWN:
new_pos[0] += 1
elif event.key == pygame.K_UP:
rotated = rotate_piece(piece)
if not check_collision(grid, rotated, pos):
piece = rotated
continue
if not check_collision(grid, piece, new_pos):
pos = new_pos
if drop_timer > 30:
drop_pos = [pos[0] + 1, pos[1]]
if not check_collision(grid, piece, drop_pos):
pos = drop_pos
else:
place_piece(grid, piece, pos)
clear_lines(grid)
piece, pos = new_piece()
if check_collision(grid, piece, pos):
print("Game Over")
running = False
drop_timer = 0
pygame.quit()

View File

@@ -5,12 +5,12 @@ globals.init()
from globals import GRID_WIDTH, GRID_HEIGHT, TILE_SIZE, BRICKS from globals import GRID_WIDTH, GRID_HEIGHT, TILE_SIZE, BRICKS
import enums import enums
from bricks import Brick from bricks import Brick
from random import randrange import random
from dropzone import DropZone from dropzone import DropZone
from dropnext import DropNext from dropnext import DropNext
from hud import Hud from hud import Hud
__version__ = "0.1.3" __version__ = "0.2.0"
# Constants # Constants
HAT_REPEAT_DELAY = 0 # milliseconds before first repeat HAT_REPEAT_DELAY = 0 # milliseconds before first repeat
@@ -45,8 +45,8 @@ class Tetris:
self.dropzone = DropZone(GRID_WIDTH, GRID_HEIGHT) self.dropzone = DropZone(GRID_WIDTH, GRID_HEIGHT)
self.dropnext = DropNext(width = TILE_SIZE * 4, height = TILE_SIZE * 4) self.dropnext = DropNext(width = TILE_SIZE * 4, height = TILE_SIZE * 4)
self.current = Brick(brick = randrange(0, len(BRICKS)), state = enums.BrickState.Current) self.current = Brick(brick = random.choice(list(BRICKS.keys())), state = enums.BrickState.Current)
self.next = Brick(brick = randrange(0, len(BRICKS))) self.next = Brick(brick = random.choice(list(BRICKS.keys())))
self.clock = pygame.time.Clock() self.clock = pygame.time.Clock()
self.rumble_timer = pygame.time.get_ticks() self.rumble_timer = pygame.time.get_ticks()
@@ -100,6 +100,7 @@ class Tetris:
case pygame.QUIT: case pygame.QUIT:
self.running = False self.running = False
case pygame.KEYDOWN: case pygame.KEYDOWN:
new_pos = pos[:]
match event.key: match event.key:
case pygame.K_RIGHT: case pygame.K_RIGHT:
if self.current.direction == enums.BrickDirection.Dropped: if self.current.direction == enums.BrickDirection.Dropped: