Compare commits

..

5 Commits

Author SHA1 Message Date
Anry Das
85a233f33c Added new additional blocks 2025-11-16 09:51:58 +02:00
Anry Das
53b8db31bc Added new base block 2025-11-16 09:20:27 +02:00
Anry Das
b050fd9029 Added new additional blocks 2025-11-16 09:13:15 +02:00
Anry Das
a04e422547 Added config to increase or decrease game speed when score rising 2025-11-16 09:12:29 +02:00
Anry Das
836f635a6b Some improvements and corrections. Added 'Dot' 1x1 sape 2025-11-15 16:22:24 +02:00
5 changed files with 165 additions and 60 deletions

View File

@ -19,6 +19,15 @@
[[1,1,1,1]],[[1],[1],[1],[1]] [[1,1,1,1]],[[1],[1],[1],[1]]
] ]
}, },
"I3": {
"name": "Line3",
"color": [55,180,210],
"min_score": 0,
"shapes": [
[[1,1,1]],
[[1],[1],[1]]
]
},
"L": { "L": {
"name": "L-Shape", "name": "L-Shape",
"color": [255, 0, 255], "color": [255, 0, 255],

View File

@ -3,6 +3,14 @@
"__type__": "EnumClass", "__type__": "EnumClass",
"name": "BlockType", "name": "BlockType",
"members": { "members": {
"D": {
"name": "Dot",
"color": [10, 100, 35],
"min_score": 3500,
"shapes": [
[[1]]
]
},
"U": { "U": {
"name": "U-Shape", "name": "U-Shape",
"color": [135, 135, 135], "color": [135, 135, 135],
@ -43,6 +51,113 @@
"shapes": [ "shapes": [
[[0, 1, 0], [1, 1, 1], [0, 1, 0]] [[0, 1, 0], [1, 1, 1], [0, 1, 0]]
] ]
},
"Cn": {
"name": "Corner",
"color": [15, 180, 180],
"min_score": 5000,
"shapes": [
[[1, 0], [1, 1]],
[[1, 1], [1, 0]],
[[1, 1], [0, 1]],
[[0, 1], [1, 1]]
]
},
"CN": {
"name": "Corner+",
"color": [15, 15, 180],
"min_score": 4000,
"shapes": [
[[1, 0, 0], [1, 0, 0], [1, 1, 1]],
[[1, 1, 1], [1, 0, 0], [1, 0, 0]],
[[1, 1, 1], [0, 0, 1], [0, 0, 1]],
[[0, 0, 1], [0, 0, 1], [1, 1, 1]]
]
},
"W": {
"name": "Dabl",
"color": [180, 25, 230],
"min_score": 15000,
"shapes": [
[[1, 0, 0], [1, 1, 0], [0, 1, 1]],
[[0, 1, 1], [1, 1, 0], [1, 0, 0]],
[[1, 1, 0], [0, 1, 1], [0, 0, 1]],
[[0, 0, 1], [0, 1, 1], [1, 1, 0]]
]
},
"Z1": {
"name": "Zet",
"color": [170, 25, 130],
"min_score": 25000,
"shapes": [
[[1, 1, 0], [0, 1, 0], [0, 1, 1]],
[[0, 0, 1], [1, 1, 1], [1, 0, 0]]
]
},
"I2": {
"name": "Line2",
"color": [50, 25, 60],
"min_score": 25000,
"shapes": [
[[1, 1]],
[[1], [1]]
]
},
"P": {
"name": "P",
"color": [240, 170, 40],
"min_score": 30000,
"shapes": [
[[1, 1], [1, 1], [1, 0]],
[[1, 1, 1], [0, 1, 1]],
[[0, 1], [1, 1], [1, 1]],
[[1, 1, 0], [1, 1, 1]]
]
},
"F": {
"name": "F",
"color": [135, 110, 65],
"min_score": 30000,
"shapes": [
[[0, 1, 1], [1, 1, 0], [0, 1, 0]],
[[0, 1, 0], [1, 1, 1], [0, 0, 1]],
[[0, 1, 0], [0, 1, 1], [1, 1, 0]],
[[1, 0, 0], [1, 1, 1], [0, 1, 0]]
]
},
"S1": {
"name": "S1",
"color": [240, 110, 20],
"min_score": 30000,
"shapes": [
[[1, 0], [1, 0], [1, 1], [0, 1]],
[[0, 1, 1, 1], [1, 1, 0, 0]],
[[1, 0], [1, 1], [0, 1], [0, 1]],
[[0, 0, 1, 1], [1, 1, 1, 0]]
]
},
"L1": {
"name": "L1",
"color": [45, 95, 175],
"min_score": 30000,
"shapes": [
[[1, 0], [1, 0], [1, 0], [1, 1]],
[[1, 1, 1, 1], [1, 0, 0, 0]],
[[1, 1], [0, 1], [0, 1], [0, 1]],
[[0, 0, 0, 1], [1, 1, 1, 1]]
]
},
"F1": {
"name": "F1",
"color": [240, 230, 60],
"min_score": 30000,
"shapes": [
[[0, 1], [1, 1], [0, 1], [0, 1]],
[[0, 0, 1, 0], [1, 1, 1, 1]],
[[1, 0], [1, 0], [1, 1], [1, 0]],
[[1, 1, 1, 1], [0, 1, 0, 0]]
]
}
} }
} }
} }

View File

@ -65,6 +65,7 @@
} }
}, },
"store_width": 10, "store_width": 10,
"block_size": 30 "block_size": 30,
"high_score_inc_speed": true
} }
} }

View File

@ -63,15 +63,15 @@ class TetrisGame:
# Initialize game # Initialize game
self.spawn_piece() self.spawn_piece()
def get_block_min_score(self, block_type: cfg.BlockType) -> int: def get_block_min_score(self, block_type: BLOCK_TYPE) -> int:
"""Get minimal score of block to be shown""" """Get minimal score of block to be shown"""
return block_type.value['min_score'] return block_type.value['min_score']
def get_block_shapes(self, block_type: cfg.BlockType) -> List[List[List[int]]]: def get_block_shapes(self, block_type: BLOCK_TYPE) -> List[List[List[int]]]:
"""Get all rotation shapes for a block type""" """Get all rotation shapes for a block type"""
return block_type.value['shapes'] return block_type.value['shapes']
def get_block_color(self, block_type: cfg.BlockType) -> Tuple[int, int, int]: def get_block_color(self, block_type: BLOCK_TYPE) -> Tuple[int, int, int]:
"""Get color for a block type""" """Get color for a block type"""
return block_type.value['color'] return block_type.value['color']
@ -97,18 +97,18 @@ class TetrisGame:
self.current_block_rotation, self.current_block): self.current_block_rotation, self.current_block):
self.game_over = True self.game_over = True
def choice_random_block(self) -> cfg.BlockType: def choice_random_block(self) -> BLOCK_TYPE:
block: cfg.BlockType = random.choice(list(cfg.BlockType)) block: BLOCK_TYPE = random.choice(list(BLOCK_TYPE))
while self.get_block_min_score(block) > self.score: while self.get_block_min_score(block) > self.score:
block = random.choice(list(cfg.BlockType)) block = random.choice(list(BLOCK_TYPE))
return block return block
def get_block_shape(self, block_type: cfg.BlockType, rotation: int) -> List[List[int]]: def get_block_shape(self, block_type: BLOCK_TYPE, rotation: int) -> List[List[int]]:
"""Get the shape matrix for a block at specific rotation""" """Get the shape matrix for a block at specific rotation"""
shapes = self.get_block_shapes(block_type) shapes = self.get_block_shapes(block_type)
return shapes[rotation % len(shapes)] return shapes[rotation % len(shapes)]
def can_place_block(self, x: int, y: int, rotation: int, block_type: cfg.BlockType) -> bool: def can_place_block(self, x: int, y: int, rotation: int, block_type: BLOCK_TYPE) -> bool:
"""Check if a block can be placed at given position""" """Check if a block can be placed at given position"""
shape = self.get_block_shape(block_type, rotation) shape = self.get_block_shape(block_type, rotation)
@ -130,7 +130,7 @@ class TetrisGame:
return True return True
def place_block(self, x: int, y: int, rotation: int, block_type: cfg.BlockType, block_id: int): def place_block(self, x: int, y: int, rotation: int, block_type: BLOCK_TYPE, block_id: int):
"""Place a block on the field""" """Place a block on the field"""
shape = self.get_block_shape(block_type, rotation) shape = self.get_block_shape(block_type, rotation)
@ -176,7 +176,7 @@ class TetrisGame:
# Block can't move down, place it # Block can't move down, place it
self.place_block(self.current_block_x, self.current_block_y, self.place_block(self.current_block_x, self.current_block_y,
self.current_block_rotation, self.current_block, self.current_block_rotation, self.current_block,
list(cfg.BlockType).index(self.current_block) + 1) list(BLOCK_TYPE).index(self.current_block) + 1)
# Check for complete lines # Check for complete lines
self.clear_lines() self.clear_lines()
@ -220,12 +220,20 @@ class TetrisGame:
elapsed = (current_ticks - self.last_time) / 1000.0 # Convert to seconds elapsed = (current_ticks - self.last_time) / 1000.0 # Convert to seconds
self.last_time = current_ticks self.last_time = current_ticks
if cfg.HIGH_SCORE_INC_SPEED:
if self.score > 5000: if self.score > 5000:
self.fall_speed = 0.55 self.fall_speed = 0.55
elif self.score > 10000: elif self.score > 10000:
self.fall_speed = 0.6 self.fall_speed = 0.6
elif self.score > 15000: elif self.score > 15000:
self.fall_speed = 0.65 self.fall_speed = 0.65
else:
if self.score > 5000:
self.fall_speed = 0.45
elif self.score > 10000:
self.fall_speed = 0.4
elif self.score > 15000:
self.fall_speed = 0.35
if not self.game_over and not self.paused: if not self.game_over and not self.paused:
self.fall_time += elapsed self.fall_time += elapsed
@ -348,7 +356,7 @@ class TetrisRenderer:
for row_idx, row in enumerate(game.field): for row_idx, row in enumerate(game.field):
for col_idx, cell in enumerate(row): for col_idx, cell in enumerate(row):
if cell != 0: if cell != 0:
block_type = list(cfg.BlockType)[cell - 1] block_type = list(BLOCK_TYPE)[cell - 1]
color = game.get_block_color(block_type) color = game.get_block_color(block_type)
x = self.field_x + col_idx * self.block_size x = self.field_x + col_idx * self.block_size
y = self.field_y + row_idx * self.block_size y = self.field_y + row_idx * self.block_size

View File

@ -23,6 +23,7 @@ class BlockType(Enum):
""" """
Define block types with their shapes and colors Define block types with their shapes and colors
All shapes draws starting in top left corner from left to right All shapes draws starting in top left corner from left to right
Every line mean the share rotated in clockwise direction
""" """
O = { O = {
'name': 'Square', 'name': 'Square',
@ -44,6 +45,15 @@ class BlockType(Enum):
[[1], [1], [1], [1]] [[1], [1], [1], [1]]
] ]
} }
I3 = {
'name': 'Line3',
'color': (55, 180, 210),
'min_score': 0,
'shapes': [
[[1, 1, 1]],
[[1], [1], [1]]
]
}
L = { L = {
'name': 'L-Shape', 'name': 'L-Shape',
'color': (255, 0, 255), # Magenta 'color': (255, 0, 255), # Magenta
@ -95,47 +105,6 @@ class BlockType(Enum):
[[0, 1], [1, 1], [0, 1]] [[0, 1], [1, 1], [0, 1]]
] ]
} }
U = {
'name': 'U-Shape',
'color': (135, 135, 135), # Change color
'min_score': 4500,
'shapes': [
[[1, 0, 1], [1, 1, 1]],
[[1, 1], [1, 0], [1, 1]],
[[1, 1, 1], [1, 0, 1]],
[[1, 1], [0, 1], [1, 1]]
]
}
# T1 = {
# 'name': 'T-Shape+',
# 'color': (200, 200, 200), # Change color
# 'min_score': 10000,
# 'shapes': [
# [[1, 1, 1], [0, 1, 0], [0, 1, 0]],
# [[0, 0, 1], [1, 1, 1], [0, 0, 1]],
# [[0, 1, 0], [0, 1, 0], [1, 1, 1]],
# [[1, 0, 0], [1, 1, 1], [1, 0, 0]]
# ]
# }
# U1 = {
# 'name': 'U-Shape+',
# 'color': (250, 250, 250), # Change color
# 'min_score': 10000,
# 'shapes': [
# [[1, 1, 1], [1, 0, 1], [1, 0, 1]],
# [[1, 1, 1], [1, 0, 0], [1, 1, 1]],
# [[1, 0, 1], [1, 0, 1], [1, 1, 1]],
# [[1, 1, 1], [0, 0, 1], [1, 1, 1]]
# ]
# }
# X = {
# 'name': 'X-Shape',
# 'color': (250, 250, 250), # Change color
# 'min_score': 15000,
# 'shapes': [
# [[0, 1, 0], [1, 1, 1], [0, 1, 0]]
# ]
# }
BLOCK_TYPE = BlockType BLOCK_TYPE = BlockType
@ -173,6 +142,8 @@ COLORS = {
'game_over': (255, 0, 0) 'game_over': (255, 0, 0)
} }
HIGH_SCORE_INC_SPEED = False
def store_config(): def store_config():
blocks_to_save = {'ALL_BLOCKS': BlockType} blocks_to_save = {'ALL_BLOCKS': BlockType}
@ -191,7 +162,7 @@ def store_config():
def load_config(): def load_config():
global KEY_CONFIG, COLORS, CONTROLS_TEXT, STORE_WIDTH, BLOCK_SIZE, BLOCK_TYPE global KEY_CONFIG, COLORS, CONTROLS_TEXT, STORE_WIDTH, BLOCK_SIZE, BLOCK_TYPE, HIGH_SCORE_INC_SPEED
es = EnumSerializer es = EnumSerializer
if not os.path.isfile(CONFIG_JSON) or not os.path.isfile(CONFIG_JSON) : if not os.path.isfile(CONFIG_JSON) or not os.path.isfile(CONFIG_JSON) :
@ -204,6 +175,7 @@ def load_config():
COLORS = config_data['CONFIG']['colors'] COLORS = config_data['CONFIG']['colors']
STORE_WIDTH = config_data['CONFIG']['store_width'] STORE_WIDTH = config_data['CONFIG']['store_width']
BLOCK_SIZE = config_data['CONFIG']['block_size'] BLOCK_SIZE = config_data['CONFIG']['block_size']
HIGH_SCORE_INC_SPEED = True if str(config_data['CONFIG']['high_score_inc_speed']).lower() == 'true' else False
with open(CONFIG_BLOCKS_JSON) as block_fd: with open(CONFIG_BLOCKS_JSON) as block_fd:
blocks_data = json.load(block_fd) blocks_data = json.load(block_fd)