0.2.0 #10

Merged
Lerking merged 3 commits from 0.2.0 into main 2025-05-10 14:59:49 +02:00
6 changed files with 159 additions and 22 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
@@ -20,7 +21,7 @@ class DropZone():
for row_idx, row in enumerate(brick.shape): for row_idx, row in enumerate(brick.shape):
for col_idx, cell in enumerate(row): for col_idx, cell in enumerate(row):
if cell: if cell:
globals.dropgrid[brick.y + row_idx][brick.x + col_idx] = 1 globals.grid[brick.y + row_idx][brick.x + col_idx] = 1
self.dropzone.blit(brick.brick, (brick.y + row_idx, brick.x + col_idx)) self.dropzone.blit(brick.brick, (brick.y + row_idx, brick.x + col_idx))

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.2.5

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:
@@ -192,7 +193,7 @@ class Tetris:
if not self.current.update(): if not self.current.update():
self.dropzone.lock(self.current) self.dropzone.lock(self.current)
self.current = self.next self.current = self.next
self.next = Brick(brick = randrange(0, len(BRICKS))) self.next = Brick(brick = random.choice(list(BRICKS.keys())))
# Handle hotplugging # Handle hotplugging
case pygame.JOYDEVICEADDED: case pygame.JOYDEVICEADDED:
@@ -216,9 +217,11 @@ class Tetris:
if "left button" in self.joysticks[self.joy.get_instance_id()].controllers[0].mapping: if "left button" in self.joysticks[self.joy.get_instance_id()].controllers[0].mapping:
self.left_button = self.joysticks[self.joy.get_instance_id()].controllers[0].mapping["left button"] self.left_button = self.joysticks[self.joy.get_instance_id()].controllers[0].mapping["left button"]
else: self.left_button = None
if "right button" in self.joysticks[self.joy.get_instance_id()].controllers[0].mapping: if "right button" in self.joysticks[self.joy.get_instance_id()].controllers[0].mapping:
self.right_button = self.joysticks[self.joy.get_instance_id()].controllers[0].mapping["right button"] self.right_button = self.joysticks[self.joy.get_instance_id()].controllers[0].mapping["right button"]
else: self.right_button = None
case pygame.JOYDEVICEREMOVED: case pygame.JOYDEVICEREMOVED:
del self.joysticks[event.instance_id] del self.joysticks[event.instance_id]