11import os , arcade , arcade .gui , random , json , time , copy
22
33from game .sprites import Shape
4- from utils .constants import SHAPES , CELL_SIZE , ROWS , COLS , OUTLINE_WIDTH , COLORS , COMBO_MOVES , button_style
4+ from utils .constants import SHAPES , CELL_SIZE , ROWS , COLS , OUTLINE_WIDTH , COLORS , COMBO_MOVES , button_style , POWER_UPS
55from utils .preload import button_texture , button_hovered_texture , click_sound , break_sound
66class Game (arcade .gui .UIView ):
77 def __init__ (self , pypresence_client ):
@@ -13,6 +13,8 @@ def __init__(self, pypresence_client):
1313
1414 self .tile_grid = {}
1515 self .sprite_grid = {}
16+
17+ self .state_before = []
1618
1719 self .shape_to_place = random .choice (list (SHAPES .keys ()))
1820 self .shape_color = random .choice (COLORS )
@@ -22,11 +24,21 @@ def __init__(self, pypresence_client):
2224
2325 self .start_x = self .window .width / 2 - (COLS * (CELL_SIZE + OUTLINE_WIDTH )) / 2
2426 self .start_y = self .window .height - (ROWS * (CELL_SIZE + OUTLINE_WIDTH )) - (CELL_SIZE / 2 )
27+
2528 self .shape_center_x = 0
2629 self .shape_center_y = 0
30+
2731 self .can_place_shape = True
2832 self .is_game_over = False
33+
34+ self .combo = 0
2935 self .combo_moves_left = COMBO_MOVES
36+ self .combo_booster_active = False
37+ self .combo_booster_moves_left = 0
38+
39+ self .score = 0
40+ self .score_booster_active = False
41+ self .score_booster_moves_left = 0
3042
3143 if os .path .exists ("data.json" ):
3244 with open ("data.json" , "r" ) as file :
@@ -36,15 +48,59 @@ def __init__(self, pypresence_client):
3648
3749 self .tiles_to_destroy : list [tuple [int , int ]] = []
3850
39- self .score = 0
40- self .combo = 0
41- self .last_combo = time .perf_counter ()
42-
4351 self .anchor = self .add_widget (arcade .gui .UIAnchorLayout ())
4452
4553 with open ("settings.json" , "r" ) as file :
4654 self .settings_dict = json .load (file )
4755
56+ def undo_move (self ):
57+ if self .score >= POWER_UPS ["undo_move" ]:
58+ self .score -= POWER_UPS ["undo_move" ]
59+ else :
60+ return
61+
62+ if self .state_before :
63+ self .tile_grid , self .shape_to_place , self .next_shape_to_place , self .shape_color , self .next_shape_color , self .score , self .combo , self .combo_moves_left = self .state_before .pop (- 1 )
64+ self .shape_data = SHAPES [self .shape_to_place ]
65+
66+ for row in range (ROWS ):
67+ for col in range (COLS ):
68+ color = self .tile_grid [row ][col ]
69+ self .sprite_grid [row ][col ].color = color if color else arcade .color .GRAY
70+ self .sprite_grid [row ][col ].original_color = color if color else arcade .color .GRAY
71+
72+ def clear_screen (self ):
73+ if self .score >= POWER_UPS ["clear_screen" ]:
74+ self .score -= POWER_UPS ["clear_screen" ]
75+ else :
76+ return
77+
78+ self .state_before = []
79+ for row in range (ROWS ):
80+ for col in range (COLS ):
81+ if self .tile_grid [row ][col ]:
82+ self .tiles_to_destroy .append ((row , col ))
83+
84+ break_sound .play ()
85+
86+ def combo_booster (self ):
87+ if self .score >= POWER_UPS ["combo_booster" ]:
88+ self .score -= POWER_UPS ["combo_booster" ]
89+ else :
90+ return
91+
92+ self .combo_booster_active = True
93+ self .combo_booster_moves_left = 6
94+
95+ def score_booster (self ):
96+ if self .score >= POWER_UPS ["score_booster" ]:
97+ self .score -= POWER_UPS ["score_booster" ]
98+ else :
99+ return
100+
101+ self .score_booster_active = True
102+ self .score_booster_moves_left = 6
103+
48104 def main_exit (self ):
49105 self .window .set_mouse_visible (True )
50106
@@ -67,6 +123,12 @@ def on_show_view(self):
67123 self .score_label = self .score_box .add (arcade .gui .UILabel (text = "Score: 0" , font_name = "Roboto" , font_size = 24 ))
68124 self .high_score_label = self .score_box .add (arcade .gui .UILabel (text = f"High Score: { self .high_score } " , font_name = "Roboto" , font_size = 24 ))
69125
126+ self .power_up_label = self .anchor .add (arcade .gui .UILabel (text = f'''{ POWER_UPS ["undo_move" ]} Score - Undo Move (1 to activate)
127+ { POWER_UPS ["combo_booster" ]} Score - Combo Booster (2 to activate)
128+ { POWER_UPS ["score_booster" ]} Score - Score Booster (3 to activate)
129+ { POWER_UPS ["clear_screen" ]} Score - Clear Screen (4 to activate)
130+ ''' , font_size = 14 , multiline = True ), anchor_x = "right" , anchor_y = "bottom" )
131+
70132 self .back_button = arcade .gui .UITextureButton (texture = button_texture , texture_hovered = button_hovered_texture , text = '<--' , style = button_style , width = 100 , height = 50 )
71133 self .back_button .on_click = lambda e : self .main_exit ()
72134 self .anchor .add (self .back_button , anchor_x = "left" , anchor_y = "top" , align_x = 5 , align_y = - 5 )
@@ -87,6 +149,9 @@ def on_button_press(self, controller, name):
87149 self .main_exit ()
88150
89151 def on_mouse_motion (self , x , y , dx , dy ):
152+ if self .is_game_over :
153+ return
154+
90155 grid_col = int ((x - self .start_x + (CELL_SIZE / 2 )) // (CELL_SIZE + OUTLINE_WIDTH ))
91156 grid_row = int ((y - self .start_y + (CELL_SIZE / 2 )) // (CELL_SIZE + OUTLINE_WIDTH ))
92157
@@ -184,9 +249,22 @@ def on_update(self, _):
184249 tile .color = arcade .color .GRAY
185250 tile .original_color = arcade .color .GRAY
186251 tile .scale = (1 , 1 )
252+
187253 self .tile_grid [row ][col ] = 0
188254 self .tiles_to_destroy .remove ((row , col ))
189255
256+ if self .combo_booster_active :
257+ combo_score = (25 * self .combo )
258+ else :
259+ combo_score = (10 * self .combo )
260+
261+ if self .score_booster_active :
262+ base_score = 50
263+ else :
264+ base_score = 25
265+
266+ self .score += (base_score + combo_score )
267+
190268 def check_game_over (self ):
191269 for grid_row in range (ROWS ):
192270 for grid_col in range (COLS ):
@@ -224,36 +302,62 @@ def check_game_over(self):
224302 def on_key_press (self , symbol : int , modifiers : int ) -> bool | None :
225303 if symbol == arcade .key .ESCAPE :
226304 self .main_exit ()
305+ elif symbol == arcade .key .KEY_1 :
306+ self .undo_move ()
307+ elif symbol == arcade .key .KEY_2 :
308+ self .combo_booster ()
309+ elif symbol == arcade .key .KEY_3 :
310+ self .score_booster ()
311+ elif symbol == arcade .key .KEY_4 :
312+ self .clear_screen ()
227313
228314 def on_mouse_press (self , x : int , y : int , button : int , modifiers : int ) -> bool | None :
315+ if self .is_game_over :
316+ return
317+
229318 grid_col = int ((x - self .start_x + (CELL_SIZE / 2 )) // (CELL_SIZE + OUTLINE_WIDTH ))
230319 grid_row = int ((y - self .start_y + (CELL_SIZE / 2 )) // (CELL_SIZE + OUTLINE_WIDTH ))
231320
232321 if self .can_place_shape :
233322 if self .settings_dict .get ("sfx" , True ):
234323 click_sound .play (volume = self .settings_dict .get ("sfx_volume" , 50 ) / 100 )
235324
325+ self .state_before .append ([copy .deepcopy (self .tile_grid ), self .shape_to_place , self .next_shape_to_place , self .shape_color , self .next_shape_color , self .score , self .combo , self .combo_moves_left ])
326+ if len (self .state_before ) > 3 :
327+ self .state_before .pop (0 )
328+
236329 for offset_col , offset_row in self .shape_data :
237330 tile_col = grid_col + offset_col
238331 tile_row = grid_row + offset_row
239332
240- self .tile_grid [tile_row ][tile_col ] = 1
333+ self .tile_grid [tile_row ][tile_col ] = self . shape_color
241334 self .sprite_grid [tile_row ][tile_col ].color = self .shape_color
242335 self .sprite_grid [tile_row ][tile_col ].original_color = self .shape_color
243-
244- self .score += 5
336+
337+ if self .score_booster_active :
338+ self .score += 10
339+ else :
340+ self .score += 5
245341
246342 for row , col in self .collided_tile_positions :
247343 self .tiles_to_destroy .append ((row , col ))
248344
249- self .score += 25 + (10 * self .combo )
250-
345+ if self .collided_tile_positions :
251346 break_sound .play ()
252347
348+ if self .score_booster_active :
349+ self .score_booster_moves_left -= 1
350+ if self .score_booster_moves_left <= 0 :
351+ self .score_booster_active = False
352+
353+ if self .combo_booster_active :
354+ self .combo_booster_moves_left -= 1
355+ if self .combo_booster_moves_left <= 0 :
356+ self .combo_booster_active = False
357+
253358 if self .collided_tile_positions :
254359 self .combo += 1
255360 self .combo_moves_left = COMBO_MOVES
256- self .last_combo = time .perf_counter ()
257361 else :
258362 self .combo_moves_left -= 1
259363
0 commit comments