Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 8 additions & 3 deletions block.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
from colors import Colors
import pygame
from position import Position
from constants import CELL_SIZE

class Block:
def __init__(self, id):
self.id = id
self.cells = {}
self.cell_size = 30
self.cell_size = CELL_SIZE
self.row_offset = 0
self.column_offset = 0
self.rotation_state = 0
Expand Down Expand Up @@ -37,6 +38,10 @@ def undo_rotation(self):
def draw(self, screen, offset_x, offset_y):
tiles = self.get_cell_positions()
for tile in tiles:
tile_rect = pygame.Rect(offset_x + tile.column * self.cell_size,
offset_y + tile.row * self.cell_size, self.cell_size -1, self.cell_size -1)
tile_rect = pygame.Rect(
offset_x + tile.column * self.cell_size,
offset_y + tile.row * self.cell_size,
self.cell_size - 1,
self.cell_size - 1
)
pygame.draw.rect(screen, self.colors[self.id], tile_rect)
104 changes: 52 additions & 52 deletions blocks.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

class LBlock(Block):
def __init__(self):
super().__init__(id = 1)
super().__init__(id=1)
self.cells = {
0: [Position(0, 2), Position(1, 0), Position(1, 1), Position(1, 2)],
1: [Position(0, 1), Position(1, 1), Position(2, 1), Position(2, 2)],
Expand All @@ -13,64 +13,64 @@ def __init__(self):
self.move(0, 3)

class JBlock(Block):
def __init__(self):
super().__init__(id = 2)
self.cells = {
0: [Position(0, 0), Position(1, 0), Position(1, 1), Position(1, 2)],
1: [Position(0, 1), Position(0, 2), Position(1, 1), Position(2, 1)],
2: [Position(1, 0), Position(1, 1), Position(1, 2), Position(2, 2)],
3: [Position(0, 1), Position(1, 1), Position(2, 0), Position(2, 1)]
}
self.move(0, 3)
def __init__(self):
super().__init__(id=2)
self.cells = {
0: [Position(0, 0), Position(1, 0), Position(1, 1), Position(1, 2)],
1: [Position(0, 1), Position(0, 2), Position(1, 1), Position(2, 1)],
2: [Position(1, 0), Position(1, 1), Position(1, 2), Position(2, 2)],
3: [Position(0, 1), Position(1, 1), Position(2, 0), Position(2, 1)]
}
self.move(0, 3)

class IBlock(Block):
def __init__(self):
super().__init__(id = 3)
self.cells = {
0: [Position(1, 0), Position(1, 1), Position(1, 2), Position(1, 3)],
1: [Position(0, 2), Position(1, 2), Position(2, 2), Position(3, 2)],
2: [Position(2, 0), Position(2, 1), Position(2, 2), Position(2, 3)],
3: [Position(0, 1), Position(1, 1), Position(2, 1), Position(3, 1)]
}
self.move(-1, 3)
def __init__(self):
super().__init__(id=3)
self.cells = {
0: [Position(1, 0), Position(1, 1), Position(1, 2), Position(1, 3)],
1: [Position(0, 2), Position(1, 2), Position(2, 2), Position(3, 2)],
2: [Position(2, 0), Position(2, 1), Position(2, 2), Position(2, 3)],
3: [Position(0, 1), Position(1, 1), Position(2, 1), Position(3, 1)]
}
self.move(-1, 3)

class OBlock(Block):
def __init__(self):
super().__init__(id = 4)
self.cells = {
0: [Position(0, 0), Position(0, 1), Position(1, 0), Position(1, 1)]
}
self.move(0, 4)
def __init__(self):
super().__init__(id=4)
self.cells = {
0: [Position(0, 0), Position(0, 1), Position(1, 0), Position(1, 1)]
}
self.move(0, 4)

class SBlock(Block):
def __init__(self):
super().__init__(id = 5)
self.cells = {
0: [Position(0, 1), Position(0, 2), Position(1, 0), Position(1, 1)],
1: [Position(0, 1), Position(1, 1), Position(1, 2), Position(2, 2)],
2: [Position(1, 1), Position(1, 2), Position(2, 0), Position(2, 1)],
3: [Position(0, 0), Position(1, 0), Position(1, 1), Position(2, 1)]
}
self.move(0, 3)
def __init__(self):
super().__init__(id=5)
self.cells = {
0: [Position(0, 1), Position(0, 2), Position(1, 0), Position(1, 1)],
1: [Position(0, 1), Position(1, 1), Position(1, 2), Position(2, 2)],
2: [Position(1, 1), Position(1, 2), Position(2, 0), Position(2, 1)],
3: [Position(0, 0), Position(1, 0), Position(1, 1), Position(2, 1)]
}
self.move(0, 3)

class TBlock(Block):
def __init__(self):
super().__init__(id = 6)
self.cells = {
0: [Position(0, 1), Position(1, 0), Position(1, 1), Position(1, 2)],
1: [Position(0, 1), Position(1, 1), Position(1, 2), Position(2, 1)],
2: [Position(1, 0), Position(1, 1), Position(1, 2), Position(2, 1)],
3: [Position(0, 1), Position(1, 0), Position(1, 1), Position(2, 1)]
}
self.move(0, 3)
def __init__(self):
super().__init__(id=6)
self.cells = {
0: [Position(0, 1), Position(1, 0), Position(1, 1), Position(1, 2)],
1: [Position(0, 1), Position(1, 1), Position(1, 2), Position(2, 1)],
2: [Position(1, 0), Position(1, 1), Position(1, 2), Position(2, 1)],
3: [Position(0, 1), Position(1, 0), Position(1, 1), Position(2, 1)]
}
self.move(0, 3)

class ZBlock(Block):
def __init__(self):
super().__init__(id = 7)
self.cells = {
0: [Position(0, 0), Position(0, 1), Position(1, 1), Position(1, 2)],
1: [Position(0, 2), Position(1, 1), Position(1, 2), Position(2, 1)],
2: [Position(1, 0), Position(1, 1), Position(2, 1), Position(2, 2)],
3: [Position(0, 1), Position(1, 0), Position(1, 1), Position(2, 0)]
}
self.move(0, 3)
def __init__(self):
super().__init__(id=7)
self.cells = {
0: [Position(0, 0), Position(0, 1), Position(1, 1), Position(1, 2)],
1: [Position(0, 2), Position(1, 1), Position(1, 2), Position(2, 1)],
2: [Position(1, 0), Position(1, 1), Position(2, 1), Position(2, 2)],
3: [Position(0, 1), Position(1, 0), Position(1, 1), Position(2, 0)]
}
self.move(0, 3)
26 changes: 26 additions & 0 deletions constants.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
CELL_SIZE = 30
NUM_ROWS = 20
NUM_COLS = 10
SCREEN_WIDTH = 500
SCREEN_HEIGHT = 620
GAME_SPEED_MS = 200
MIN_SPEED_MS = 100
SPEED_STEP = 10
SPEED_SCORE_INTERVAL = 500
GRID_OFFSET_X = 11
GRID_OFFSET_Y = 11
SCORE_RECT = (320, 55, 170, 60)
NEXT_RECT = (320, 215, 170, 180)
HIGHSCORE_RECT = (320, 400, 170, 60)
SCORE_LABEL_POS = (365, 20)
NEXT_LABEL_POS = (375, 180)
HIGHSCORE_LABEL_POS = (340, 370)
NEXT_BLOCK_DEFAULT_X = 270
NEXT_BLOCK_DEFAULT_Y = 270
NEXT_BLOCK_IBLOCK_X = 255
NEXT_BLOCK_IBLOCK_Y = 290
NEXT_BLOCK_OBLOCK_X = 255
NEXT_BLOCK_OBLOCK_Y = 280
IBLOCK_ID = 3
OBLOCK_ID = 4
HIGHSCORE_FILE = "highscore.txt"
68 changes: 47 additions & 21 deletions game.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@
from blocks import *
import random
import pygame
from constants import (
GAME_SPEED_MS, MIN_SPEED_MS, SPEED_STEP, SPEED_SCORE_INTERVAL,
GRID_OFFSET_X, GRID_OFFSET_Y, HIGHSCORE_FILE
)

class Game:
def __init__(self):
Expand All @@ -10,12 +14,36 @@ def __init__(self):
self.current_block = self.get_random_block()
self.next_block = self.get_random_block()
self.game_over = False
self.paused = False
self.score = 0
self.rotate_sound = pygame.mixer.Sound("Sounds/rotate.ogg")
self.clear_sound = pygame.mixer.Sound("Sounds/clear.ogg")
self.high_score = self.load_high_score()
self.rotate_sound = None
self.clear_sound = None
try:
self.rotate_sound = pygame.mixer.Sound("Sounds/rotate.ogg")
self.clear_sound = pygame.mixer.Sound("Sounds/clear.ogg")
pygame.mixer.music.load("Sounds/music.ogg")
pygame.mixer.music.play(-1)
except:
pass

pygame.mixer.music.load("Sounds/music.ogg")
pygame.mixer.music.play(-1)
def load_high_score(self):
try:
with open(HIGHSCORE_FILE, "r") as f:
return int(f.read())
except:
return 0

def save_high_score(self):
try:
with open(HIGHSCORE_FILE, "w") as f:
f.write(str(self.high_score))
except:
pass

def get_speed(self):
reduction = (self.score // SPEED_SCORE_INTERVAL) * SPEED_STEP
return max(MIN_SPEED_MS, GAME_SPEED_MS - reduction)

def update_score(self, lines_cleared, move_down_points):
if lines_cleared == 1:
Expand All @@ -25,6 +53,9 @@ def update_score(self, lines_cleared, move_down_points):
elif lines_cleared == 3:
self.score += 500
self.score += move_down_points
if self.score > self.high_score:
self.high_score = self.score
self.save_high_score()

def get_random_block(self):
if len(self.blocks) == 0:
Expand All @@ -35,17 +66,17 @@ def get_random_block(self):

def move_left(self):
self.current_block.move(0, -1)
if self.block_inside() == False or self.block_fits() == False:
if not self.block_inside() or not self.block_fits():
self.current_block.move(0, 1)

def move_right(self):
self.current_block.move(0, 1)
if self.block_inside() == False or self.block_fits() == False:
if not self.block_inside() or not self.block_fits():
self.current_block.move(0, -1)

def move_down(self):
self.current_block.move(1, 0)
if self.block_inside() == False or self.block_fits() == False:
if not self.block_inside() or not self.block_fits():
self.current_block.move(-1, 0)
self.lock_block()

Expand All @@ -57,9 +88,10 @@ def lock_block(self):
self.next_block = self.get_random_block()
rows_cleared = self.grid.clear_full_rows()
if rows_cleared > 0:
self.clear_sound.play()
if self.clear_sound:
self.clear_sound.play()
self.update_score(rows_cleared, 0)
if self.block_fits() == False:
if not self.block_fits():
self.game_over = True

def reset(self):
Expand All @@ -72,31 +104,25 @@ def reset(self):
def block_fits(self):
tiles = self.current_block.get_cell_positions()
for tile in tiles:
if self.grid.is_empty(tile.row, tile.column) == False:
if not self.grid.is_empty(tile.row, tile.column):
return False
return True

def rotate(self):
self.current_block.rotate()
if self.block_inside() == False or self.block_fits() == False:
if not self.block_inside() or not self.block_fits():
self.current_block.undo_rotation()
else:
self.rotate_sound.play()
if self.rotate_sound:
self.rotate_sound.play()

def block_inside(self):
tiles = self.current_block.get_cell_positions()
for tile in tiles:
if self.grid.is_inside(tile.row, tile.column) == False:
if not self.grid.is_inside(tile.row, tile.column):
return False
return True

def draw(self, screen):
self.grid.draw(screen)
self.current_block.draw(screen, 11, 11)

if self.next_block.id == 3:
self.next_block.draw(screen, 255, 290)
elif self.next_block.id == 4:
self.next_block.draw(screen, 255, 280)
else:
self.next_block.draw(screen, 270, 270)
self.current_block.draw(screen, GRID_OFFSET_X, GRID_OFFSET_Y)
29 changes: 15 additions & 14 deletions grid.py
Original file line number Diff line number Diff line change
@@ -1,29 +1,26 @@
import pygame
from colors import Colors
from constants import NUM_ROWS, NUM_COLS, CELL_SIZE, GRID_OFFSET_X, GRID_OFFSET_Y

class Grid:
def __init__(self):
self.num_rows = 20
self.num_cols = 10
self.cell_size = 30
self.num_rows = NUM_ROWS
self.num_cols = NUM_COLS
self.cell_size = CELL_SIZE
self.grid = [[0 for j in range(self.num_cols)] for i in range(self.num_rows)]
self.colors = Colors.get_cell_colors()

def print_grid(self):
for row in range(self.num_rows):
for column in range(self.num_cols):
print(self.grid[row][column], end = " ")
print(self.grid[row][column], end=" ")
print()

def is_inside(self, row, column):
if row >= 0 and row < self.num_rows and column >= 0 and column < self.num_cols:
return True
return False
return 0 <= row < self.num_rows and 0 <= column < self.num_cols

def is_empty(self, row, column):
if self.grid[row][column] == 0:
return True
return False
return self.grid[row][column] == 0

def is_row_full(self, row):
for column in range(self.num_cols):
Expand All @@ -37,12 +34,12 @@ def clear_row(self, row):

def move_row_down(self, row, num_rows):
for column in range(self.num_cols):
self.grid[row+num_rows][column] = self.grid[row][column]
self.grid[row + num_rows][column] = self.grid[row][column]
self.grid[row][column] = 0

def clear_full_rows(self):
completed = 0
for row in range(self.num_rows-1, 0, -1):
for row in range(self.num_rows - 1, 0, -1):
if self.is_row_full(row):
self.clear_row(row)
completed += 1
Expand All @@ -59,6 +56,10 @@ def draw(self, screen):
for row in range(self.num_rows):
for column in range(self.num_cols):
cell_value = self.grid[row][column]
cell_rect = pygame.Rect(column*self.cell_size + 11, row*self.cell_size + 11,
self.cell_size -1, self.cell_size -1)
cell_rect = pygame.Rect(
column * self.cell_size + GRID_OFFSET_X,
row * self.cell_size + GRID_OFFSET_Y,
self.cell_size - 1,
self.cell_size - 1
)
pygame.draw.rect(screen, self.colors[cell_value], cell_rect)
Loading