@@ -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
|
||||||
|
|
||||||
|
@@ -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))
|
||||||
|
|
||||||
|
|
39
globals.py
39
globals.py
@@ -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)
|
@@ -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
121
tet.py
Normal 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()
|
13
tetris.py
13
tetris.py
@@ -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]
|
||||||
|
Reference in New Issue
Block a user