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:
print(f"Collision X:{new_x}, Y:{new_y}")
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 False

View File

@@ -1,4 +1,5 @@
import pygame
import numpy as np
import globals
from enums import BrickColor
@@ -20,7 +21,7 @@ class DropZone():
for row_idx, row in enumerate(brick.shape):
for col_idx, cell in enumerate(row):
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))

View File

@@ -1,22 +1,33 @@
import numpy as np
def init():
global BRICKS
BRICKS = [
[[0,1,0], [1,1,1], [0,1,0]],
[[0, 0, 1], [1, 1, 1]],
[[1, 0, 0], [1, 1, 1]],
[[1]],
[[1, 1, 1, 1]],
[[1, 1], [1, 1]],
[[0, 1, 1], [1, 1, 0]],
[[1, 1, 0], [0, 1, 1]],
[[1, 0, 1], [1, 1, 1]],
[[1, 1, 1], [0, 1, 0]]
]
BRICKS = {
'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]]),
'.': 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
TILE_SIZE = 48
global GRID_WIDTH
GRID_WIDTH = 10
global GRID_HEIGHT
GRID_HEIGHT = 18
global dropgrid
dropgrid = [[0 for _ in range(GRID_WIDTH)] for _ in range(GRID_HEIGHT)]
global grid
grid = np.zeros((GRID_HEIGHT, GRID_WIDTH), dtype=int)

View File

@@ -1,2 +1,3 @@
numpy==2.2.5
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
import enums
from bricks import Brick
from random import randrange
import random
from dropzone import DropZone
from dropnext import DropNext
from hud import Hud
__version__ = "0.1.3"
__version__ = "0.2.0"
# Constants
HAT_REPEAT_DELAY = 0 # milliseconds before first repeat
@@ -45,8 +45,8 @@ class Tetris:
self.dropzone = DropZone(GRID_WIDTH, GRID_HEIGHT)
self.dropnext = DropNext(width = TILE_SIZE * 4, height = TILE_SIZE * 4)
self.current = Brick(brick = randrange(0, len(BRICKS)), state = enums.BrickState.Current)
self.next = Brick(brick = randrange(0, len(BRICKS)))
self.current = Brick(brick = random.choice(list(BRICKS.keys())), state = enums.BrickState.Current)
self.next = Brick(brick = random.choice(list(BRICKS.keys())))
self.clock = pygame.time.Clock()
self.rumble_timer = pygame.time.get_ticks()
@@ -100,6 +100,7 @@ class Tetris:
case pygame.QUIT:
self.running = False
case pygame.KEYDOWN:
#new_pos = pos[:]
match event.key:
case pygame.K_RIGHT:
if self.current.direction == enums.BrickDirection.Dropped:
@@ -192,7 +193,7 @@ class Tetris:
if not self.current.update():
self.dropzone.lock(self.current)
self.current = self.next
self.next = Brick(brick = randrange(0, len(BRICKS)))
self.next = Brick(brick = random.choice(list(BRICKS.keys())))
# Handle hotplugging
case pygame.JOYDEVICEADDED:
@@ -216,9 +217,11 @@ class Tetris:
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"]
else: self.left_button = None
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"]
else: self.right_button = None
case pygame.JOYDEVICEREMOVED:
del self.joysticks[event.instance_id]