implemented ghost tetrominos and made some optimisation (gamescore and visually)
This commit is contained in:
@@ -37,8 +37,8 @@ This isn't just about coding; it's about building something I love from the grou
|
|||||||
### **Step 2: Additional Game Features**
|
### **Step 2: Additional Game Features**
|
||||||
1. [x] **Next Tetromino Preview**:
|
1. [x] **Next Tetromino Preview**:
|
||||||
- [x] Show the upcoming Tetromino in a small box.
|
- [x] Show the upcoming Tetromino in a small box.
|
||||||
2. [ ] **Ghost Piece**:
|
2. [x] **Ghost Piece**:
|
||||||
- [ ] Display a transparent outline where the current Tetromino will land.
|
- [x] Display a transparent outline where the current Tetromino will land.
|
||||||
3. [x] **Pause and Resume**:
|
3. [x] **Pause and Resume**:
|
||||||
- [x] Allow the game to pause (e.g., with the Escape key) and resume.
|
- [x] Allow the game to pause (e.g., with the Escape key) and resume.
|
||||||
4. [ ] **Basic Leaderboard**:
|
4. [ ] **Basic Leaderboard**:
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ class Game:
|
|||||||
self.game_grid = Grid(rows, cols, cell_size)
|
self.game_grid = Grid(rows, cols, cell_size)
|
||||||
|
|
||||||
self.current_tetromino = Tetrominos(cols, cell_size)
|
self.current_tetromino = Tetrominos(cols, cell_size)
|
||||||
|
self.ghost_tetromino = Tetrominos(cols, cell_size)
|
||||||
self.next_tetromino = Tetrominos(cols, cell_size)
|
self.next_tetromino = Tetrominos(cols, cell_size)
|
||||||
self.hold_tetromino = None
|
self.hold_tetromino = None
|
||||||
|
|
||||||
@@ -33,6 +34,10 @@ class Game:
|
|||||||
def run(self):
|
def run(self):
|
||||||
"""Main game loop."""
|
"""Main game loop."""
|
||||||
self.playing = True
|
self.playing = True
|
||||||
|
if settings.gamestate == False:
|
||||||
|
self.game_grid = Grid(rows, cols, cell_size)
|
||||||
|
settings.gamestate = True
|
||||||
|
|
||||||
while self.playing:
|
while self.playing:
|
||||||
self.clock.tick(fps)
|
self.clock.tick(fps)
|
||||||
self.handle_events()
|
self.handle_events()
|
||||||
@@ -84,6 +89,8 @@ class Game:
|
|||||||
|
|
||||||
self.fall_timer = current_time
|
self.fall_timer = current_time
|
||||||
|
|
||||||
|
self.update_ghost_tetromino()
|
||||||
|
|
||||||
def draw(self):
|
def draw(self):
|
||||||
"""Render the game elements."""
|
"""Render the game elements."""
|
||||||
self.screen.fill((138, 138, 138))
|
self.screen.fill((138, 138, 138))
|
||||||
@@ -93,6 +100,8 @@ class Game:
|
|||||||
self.game_grid.draw_grid(self.grid_surface)
|
self.game_grid.draw_grid(self.grid_surface)
|
||||||
self.current_tetromino.draw(self.grid_surface)
|
self.current_tetromino.draw(self.grid_surface)
|
||||||
|
|
||||||
|
self.ghost_tetromino.draw_ghost_tetromino(self.grid_surface)
|
||||||
|
|
||||||
# Draw next and hold previews
|
# Draw next and hold previews
|
||||||
self.next_surface.fill((0, 0, 0))
|
self.next_surface.fill((0, 0, 0))
|
||||||
self.next_tetromino.draw_next_tetromino(self.next_surface)
|
self.next_tetromino.draw_next_tetromino(self.next_surface)
|
||||||
@@ -136,6 +145,14 @@ class Game:
|
|||||||
self.current_tetromino.y = 0
|
self.current_tetromino.y = 0
|
||||||
self.hold_used = True
|
self.hold_used = True
|
||||||
|
|
||||||
|
def update_ghost_tetromino(self):
|
||||||
|
self.ghost_tetromino.shape = self.current_tetromino.shape
|
||||||
|
self.ghost_tetromino.x = self.current_tetromino.x
|
||||||
|
self.ghost_tetromino.y = self.current_tetromino.y
|
||||||
|
|
||||||
|
while not self.game_grid.check_collision(self.ghost_tetromino.shape, self.ghost_tetromino.x, self.ghost_tetromino.y + 1):
|
||||||
|
self.ghost_tetromino.y += 1
|
||||||
|
|
||||||
def show_game_over(self):
|
def show_game_over(self):
|
||||||
"""Handle game over screen."""
|
"""Handle game over screen."""
|
||||||
settings.gamestate = False
|
settings.gamestate = False
|
||||||
|
|||||||
+23
-7
@@ -1,4 +1,5 @@
|
|||||||
import pygame
|
import pygame
|
||||||
|
from game.tetrominos import set_color
|
||||||
import game.settings as settings
|
import game.settings as settings
|
||||||
|
|
||||||
class Grid():
|
class Grid():
|
||||||
@@ -6,13 +7,30 @@ class Grid():
|
|||||||
self.cell_size = cell_size
|
self.cell_size = cell_size
|
||||||
self.rows = rows
|
self.rows = rows
|
||||||
self.cols = cols
|
self.cols = cols
|
||||||
|
self.color = set_color()
|
||||||
self.grid = [[0 for j in range(self.cols)] for k in range(self.rows)]
|
self.grid = [[0 for j in range(self.cols)] for k in range(self.rows)]
|
||||||
|
|
||||||
def draw_grid(self, surface):
|
def draw_grid(self, surface):
|
||||||
for row in range(self.rows):
|
for row in range(self.rows):
|
||||||
for col in range(self.cols):
|
for col in range(self.cols):
|
||||||
cell_value = self.grid[row][col]
|
cell_value = self.grid[row][col]
|
||||||
color = (0, 0, 0) if cell_value == 0 else (255, 0, 0) # Black for empty, red for filled
|
if cell_value == 0:
|
||||||
|
color = (0, 0, 0)
|
||||||
|
elif cell_value == 1:
|
||||||
|
color = self.color[0]
|
||||||
|
elif cell_value == 2:
|
||||||
|
color = self.color[1]
|
||||||
|
elif cell_value == 3:
|
||||||
|
color = self.color[2]
|
||||||
|
elif cell_value == 4:
|
||||||
|
color = self.color[3]
|
||||||
|
elif cell_value == 5:
|
||||||
|
color = self.color[4]
|
||||||
|
elif cell_value == 6:
|
||||||
|
color = self.color[5]
|
||||||
|
else:
|
||||||
|
color = self.color[6]
|
||||||
|
|
||||||
cell_rect = pygame.Rect(
|
cell_rect = pygame.Rect(
|
||||||
col * self.cell_size + 1,
|
col * self.cell_size + 1,
|
||||||
row * self.cell_size + 1,
|
row * self.cell_size + 1,
|
||||||
@@ -29,7 +47,7 @@ class Grid():
|
|||||||
grid_x = tetromino.x + col_idx
|
grid_x = tetromino.x + col_idx
|
||||||
grid_y = tetromino.y + row_idx
|
grid_y = tetromino.y + row_idx
|
||||||
if 0 <= grid_y < self.rows and 0 <= grid_x < self.cols:
|
if 0 <= grid_y < self.rows and 0 <= grid_x < self.cols:
|
||||||
self.grid[grid_y][grid_x] = 1
|
self.grid[grid_y][grid_x] = tetromino.shape_number
|
||||||
|
|
||||||
def check_collision(self, shape, x, y):
|
def check_collision(self, shape, x, y):
|
||||||
"""Check if the tetromino collides with the grid or boundaries."""
|
"""Check if the tetromino collides with the grid or boundaries."""
|
||||||
@@ -49,11 +67,9 @@ class Grid():
|
|||||||
|
|
||||||
def check_full_row(self):
|
def check_full_row(self):
|
||||||
"""Check for and clear any full rows."""
|
"""Check for and clear any full rows."""
|
||||||
new_grid = [row for row in self.grid if not all(cell == 1 for cell in row)]
|
new_grid = [row for row in self.grid if not all(cell != 0 for cell in row)]
|
||||||
cleared_rows = len(self.grid) - len(new_grid)
|
cleared_rows = len(self.grid) - len(new_grid)
|
||||||
self.grid = [[0] * self.cols for _ in range(cleared_rows)] + new_grid
|
self.grid = [[0] * self.cols for _ in range(cleared_rows)] + new_grid
|
||||||
|
|
||||||
if cleared_rows >= 4:
|
score_table = {1: 100, 2: 300, 3: 500, 4: 800}
|
||||||
settings.game_score += 100 * cleared_rows * 2
|
settings.game_score += score_table.get(cleared_rows, 0)
|
||||||
else:
|
|
||||||
settings.game_score += 100 * cleared_rows
|
|
||||||
+4
-3
@@ -1,5 +1,6 @@
|
|||||||
import pygame as pg
|
import pygame as pg
|
||||||
from game.settings import *
|
from game.settings import *
|
||||||
|
import game.settings as setting
|
||||||
from game.util import draw_text
|
from game.util import draw_text
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
@@ -72,11 +73,11 @@ class GameMenu:
|
|||||||
|
|
||||||
self.screen.fill((0, 0, 0))
|
self.screen.fill((0, 0, 0))
|
||||||
|
|
||||||
if gamestate:
|
if setting.gamestate:
|
||||||
draw_text(self.screen, "Game Paused", 50, width // 2, HEIGHT // 2 - 50, (255, 255, 255))
|
draw_text(self.screen, "Game Paused", 50, width // 2, HEIGHT // 2 - 50, (255, 255, 255))
|
||||||
draw_text(self.screen, "Press ESC to Resume", 30, width // 2, HEIGHT // 2 + 10, (200, 200, 200))
|
draw_text(self.screen, "Press ESC to Resume", 30, width // 2, HEIGHT // 2 + 10, (200, 200, 200))
|
||||||
else:
|
else:
|
||||||
draw_text(self.screen, "Game Over", 50, WIDTH // 2, HEIGHT // 2 - 50, (255, 0, 0))
|
draw_text(self.screen, "Game Over", 50, width // 2, HEIGHT // 2 - 50, (255, 0, 0))
|
||||||
draw_text(self.screen, "Press Enter to Restart", 30, WIDTH // 2, HEIGHT // 2 + 50, (200, 200, 200))
|
draw_text(self.screen, "Press Enter to Restart", 30, width // 2, HEIGHT // 2 + 50, (200, 200, 200))
|
||||||
|
|
||||||
pg.display.update()
|
pg.display.update()
|
||||||
+14
-2
@@ -30,7 +30,7 @@ class Tetrominos:
|
|||||||
self.shape = self.SHAPES[self.shape_number - 1]
|
self.shape = self.SHAPES[self.shape_number - 1]
|
||||||
self.colors = set_color()
|
self.colors = set_color()
|
||||||
self.x = cols // 2 - len(self.shape[0]) // 2 # Center horizontally
|
self.x = cols // 2 - len(self.shape[0]) // 2 # Center horizontally
|
||||||
self.y = 0 # Start at the top
|
self.y = 0
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -80,4 +80,16 @@ class Tetrominos:
|
|||||||
cell_size,
|
cell_size,
|
||||||
cell_size
|
cell_size
|
||||||
)
|
)
|
||||||
pygame.draw.rect(surface, self.colors[self.shape_number - 1], cell_rect) # Red color for tetromino
|
pygame.draw.rect(surface, self.colors[self.shape_number - 1], cell_rect)
|
||||||
|
|
||||||
|
def draw_ghost_tetromino(self, screen):
|
||||||
|
"""Draw the tetromino on the screen."""
|
||||||
|
for row_idx, row in enumerate(self.shape):
|
||||||
|
for col_idx, cell in enumerate(row):
|
||||||
|
if cell:
|
||||||
|
x = (self.x + col_idx) * self.cell_size + 1
|
||||||
|
y = (self.y + row_idx) * self.cell_size + 1
|
||||||
|
rect = pygame.Rect(x, y, self.cell_size - 2, self.cell_size - 2)
|
||||||
|
pygame.draw.rect(screen, (61, 61, 61), rect)
|
||||||
|
pygame.draw.rect(screen, (255, 255, 255), rect, 1)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user