master
			
			
		
		
							parent
							
								
									c61ccf2549
								
							
						
					
					
						commit
						dc3eed681b
					
				
							
								
								
									
										12
									
								
								TODO
								
								
								
								
							
							
						
						
									
										12
									
								
								TODO
								
								
								
								
							|  | @ -3,14 +3,14 @@ TODO main: | |||
| [x] fix image loading from last album | ||||
| [x] fix image choosing | ||||
| [x] add proper image loading from storage | ||||
| [ ] add setting - move pieses = slow/normal/fast/instant | ||||
| [ ] fix quick game window moving thing | ||||
| [ ] add popup when loading time - load previous or reset | ||||
| [meh] add setting - move pieses = slow/normal/fast/instant | ||||
| [meh] fix quick game window moving thing | ||||
| [meh] add popup when loading time - load previous or reset | ||||
| [ ] add small notes on button hover | ||||
| [ ] add functionality in select and menu mode | ||||
| [ ] add settings, info and stats with full functionality | ||||
| [ ] optimise code as possible | ||||
| [ ] add splash screen | ||||
| [sorta] add settings, info and stats with full functionality | ||||
| [meh] optimise code as possible | ||||
| [no] add splash screen | ||||
| [ ] add keybinds | ||||
| 
 | ||||
| TODO additional: | ||||
|  |  | |||
										
											Binary file not shown.
										
									
								
							| Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 4.5 KiB | 
										
											Binary file not shown.
										
									
								
							| Before Width: | Height: | Size: 5.7 KiB After Width: | Height: | Size: 5.8 KiB | 
							
								
								
									
										214
									
								
								main.py
								
								
								
								
							
							
						
						
									
										214
									
								
								main.py
								
								
								
								
							|  | @ -51,9 +51,9 @@ current_style = settings_data["style"] | |||
| SIZE_CHOICES = ["small", "medium", "big"] | ||||
| STYLE_CHOICES = ["classic", "original", "dark"] | ||||
| GRID_CHOICES = ["4x4", "3x3"] | ||||
| MUSIC_CHOICES = ["funky-leap", "serenity", "sunny-day"] | ||||
| SOUND_CHOICES = ["puzzle", "wood", "metal_pipe", "lego_breaking"] | ||||
| DISPLAY_CHOICES = ["time", "moves"] | ||||
| MUSIC_CHOICES = ["funky leap", "serenity", "sunny day"] | ||||
| SOUND_CHOICES = ["puzzle", "wood", "metal pipe", "lego breaking"] | ||||
| DISPLAY_CHOICES = ["time", "moves", "none"] | ||||
| LANGUAGE_CHOICES = ["english", "russian", "latvian"] | ||||
| FONTS = ["msreferencesansserif", "arial", "bahnschrift"] | ||||
| 
 | ||||
|  | @ -150,6 +150,11 @@ elif current_size == SIZE_CHOICES[1]: | |||
|     f_line = [135, 38, 100, 16] | ||||
|     s_line = [135, 58, 100, 16] | ||||
|     s_button = [238, 38, 12, 20] | ||||
|     arrow1 = (261, 0, 10, 13) | ||||
|     arrow2 = (274, 0, 10, 13) | ||||
|     spaces2 = [4, 5, 2, 5, 60, 42] | ||||
|     if current_style == STYLE_CHOICES[2]: | ||||
|         spaces2[1] = 2 | ||||
| 
 | ||||
| else: | ||||
|     WIDTH, HEIGHT = 396, 425 | ||||
|  | @ -168,15 +173,18 @@ else: | |||
|     timer_area = pygame.Rect(49, 5, 86, 32) | ||||
|     win_area = pygame.Rect(200, 214, 360, 360) | ||||
|     size = [50, 58, 328, 35] | ||||
|     cons = [35, 455, 26, 8, 26] | ||||
|     cons = [35, 455, 26, 10, 26] | ||||
|     scaled_size = (43, 48, 310, 310) | ||||
|     area = (197, 390) | ||||
|     spaces = [24, 34, 50, 84, 8] | ||||
|     f_line = [276, 70, 200, 32] | ||||
|     s_line = [276, 105, 200, 32] | ||||
|     s_button = [479, 70, 24, 40] | ||||
|     if current_style == STYLE_CHOICES[0]: | ||||
|         cons[3] = 10 | ||||
|     arrow1 = (261, 0, 10, 13) | ||||
|     arrow2 = (274, 0, 10, 13) | ||||
|     spaces2 = (4, 5, 2, 5, 60, 42) | ||||
|     if current_style == STYLE_CHOICES[2]: | ||||
|         cons[3] = 8 | ||||
| 
 | ||||
| puzzle_version = settings_data["grid"] | ||||
| 
 | ||||
|  | @ -318,7 +326,7 @@ def render_text(text, position, screen, color=text_color, centered=False): | |||
|         screen.blit(text_render, position) | ||||
| 
 | ||||
| def render_settings_text(text, position, screen, value=None,color=text_color): | ||||
|     font = pygame.font.SysFont(FONT, FONT_SIZE2-1) | ||||
|     font = pygame.font.SysFont(FONT, FONT_SIZE2-1, italic=True) | ||||
|     if value is not None: | ||||
|         text_render = font.render(f"{text}: {value}", True, color) | ||||
|     else: | ||||
|  | @ -643,14 +651,10 @@ def slider(position, value_range, value, active_slider, setting): | |||
|     value_pos = second_x - s_button[2] / 2 | ||||
|     first_line = Image((f_line[0], f_line[1]), (position[0], position[1]), (f_line[2], f_line[3])) | ||||
|     second_line = Image((s_line[0], s_line[1]), (position[0], position[1]), (second_x, s_line[3])) | ||||
|     slider_button = Image((s_button[0], s_button[1]), (position[0] + value_pos, position[1] + gap), (s_button[2], s_button[3])) | ||||
|     mouse_buttons = pygame.mouse.get_pressed() | ||||
|     if active_slider[setting] and mouse_buttons[0]: | ||||
|          | ||||
|     slider_button = Button((s_button[0], s_button[1]), (position[0] + value_pos, position[1] + gap), (s_button[2], s_button[3])) | ||||
|     if active_slider[setting] and pygame.mouse.get_pressed()[0]: | ||||
|         mouse_pos = pygame.mouse.get_pos() | ||||
| 
 | ||||
|         if mouse_buttons[0] and slider_button.rect.inflate(100, 25).collidepoint(mouse_pos): | ||||
|             mouse_pos = pygame.mouse.get_pos() | ||||
|         if slider_button.rect.inflate(100, 25).collidepoint(mouse_pos): | ||||
|             mouse_x = mouse_pos[0] | ||||
|             min_x = position[0] - s_button[2] / 2 | ||||
|             max_x = position[0] + s_line[2] - s_button[2] / 2 | ||||
|  | @ -663,15 +667,63 @@ def slider(position, value_range, value, active_slider, setting): | |||
| 
 | ||||
|     return first_line, second_line, slider_button | ||||
| 
 | ||||
| 
 | ||||
| active_selects = {"size": False, "style": False, "grid": False, "music_version": False, "sound_version": False} | ||||
| def arrows(position, setting, value, choices, event_list): | ||||
|     index = choices.index(value) | ||||
|     arrow_width = arrow1[2] | ||||
| 
 | ||||
|     font = pygame.font.SysFont(FONT, FONT_SIZE) | ||||
|     text_render = font.render(value, True, text_color) | ||||
|     text_rect = text_render.get_rect() | ||||
|     text_x = position[0] + (arrow_width + spaces2[0]) / 2 - text_rect.width / 2 + spaces2[5] | ||||
|     text_y = position[1] - spaces2[1] | ||||
| 
 | ||||
|     value_text = screen.blit(text_render, (text_x, text_y)) | ||||
| 
 | ||||
|     first_arrow = Button((arrow1[0], arrow1[1]), (text_x - arrow_width - spaces2[0], position[1]), (arrow_width, arrow1[3])) | ||||
|     second_arrow_x = text_x + text_rect.width + spaces2[2] | ||||
|     second_arrow = Button((arrow2[0], arrow2[1]), (second_arrow_x , position[1]), (arrow2[2], arrow2[3])) | ||||
| 
 | ||||
|     for event in event_list: | ||||
|         if event.type == pygame.MOUSEBUTTONDOWN: | ||||
|             if first_arrow.rect.collidepoint(event.pos): | ||||
|                 index -= 1 | ||||
|                 if index < 0: | ||||
|                     index = len(choices) - 1 | ||||
|                 value = choices[index] | ||||
|                 data_set(setting, value) | ||||
|             elif second_arrow.rect.collidepoint(event.pos): | ||||
|                 index += 1 | ||||
|                 if index >= len(choices): | ||||
|                     index = 0 | ||||
|                 value = choices[index] | ||||
|                 data_set(setting, value) | ||||
| 
 | ||||
|     return first_arrow, value_text, second_arrow | ||||
| 
 | ||||
| 
 | ||||
| def data_set(setting, value): | ||||
|     if setting == gui: | ||||
|     if setting == "size": | ||||
|         settings_data["size"] = value | ||||
|     elif setting == "style": | ||||
|         settings_data["style"] = value | ||||
|     elif setting == "grid": | ||||
|         settings_data["grid"] = value | ||||
|     elif setting == gui: | ||||
|         settings_data[gui] = value | ||||
|     elif setting == music: | ||||
|         settings_data[music]["volume"] = value | ||||
|         update_music_volume() | ||||
|         if isinstance(value, str): | ||||
|             settings_data[sound]["version"] = value | ||||
|         else: | ||||
|             settings_data[music]["volume"] = value | ||||
|             update_music_volume() | ||||
|     elif setting == sound: | ||||
|         settings_data[sound]["volume"] = value | ||||
|         update_sound_volume() | ||||
|         if isinstance(value, str): | ||||
|             settings_data[sound]["version"] = value | ||||
|         else: | ||||
|             settings_data[sound]["volume"] = value | ||||
|             update_sound_volume() | ||||
|          | ||||
|     with open(SETTINGS_FILE, "w") as settings_file: | ||||
|         json.dump(settings_data, settings_file, indent=2) | ||||
|  | @ -750,16 +802,49 @@ def reset(): | |||
|     # Reset all data function, not finished yet | ||||
|     pass | ||||
| 
 | ||||
| 
 | ||||
| def info(): | ||||
|     # Not finished yet | ||||
|     pass | ||||
| # STATS MODE | ||||
| 
 | ||||
| 
 | ||||
| # Stats | ||||
| def stats(): | ||||
|     # Not finished yet | ||||
|     pass | ||||
| #INFO MODE | ||||
| text_size = [3, 5] | ||||
| 
 | ||||
| def render_text_in_rect(long_text, rect_area): | ||||
|     font = pygame.font.SysFont(FONT, FONT_SIZE-text_size[0]) | ||||
|     lines = [] | ||||
|     words = long_text.split() | ||||
|     current_line = "" | ||||
|     for word in words: | ||||
|         test_line = current_line + word + " " | ||||
|         if font.size(test_line)[0] <= rect_area.width: | ||||
|             current_line = test_line | ||||
|         else: | ||||
|             lines.append(current_line.strip()) | ||||
|             current_line = word + " " | ||||
|     lines.append(current_line.strip()) | ||||
| 
 | ||||
|     line_height = font.get_linesize() | ||||
|     text_surfaces = [] | ||||
|     text_rects = [] | ||||
|     for i, line in enumerate(lines): | ||||
|         text_render = font.render(line, True, pygame.Color(*text_color)) | ||||
|         text_rect = text_render.get_rect(topleft=(rect_area.x, rect_area.y + i * line_height)) | ||||
|         text_surfaces.append(text_render) | ||||
|         text_rects.append(text_rect) | ||||
| 
 | ||||
|     return text_surfaces, text_rects | ||||
| 
 | ||||
| # Example usage | ||||
| rect_area = non_movable_area | ||||
| rect_area.x += text_size[1] | ||||
| rect_area.width -= text_size[1] | ||||
| long_text = ( | ||||
|     "Picture Puzzle, once a feature in Windows Vista and 7's 'Desktop Gadgets,' " | ||||
|     "faced an end in 2012 due to security concerns. This game is a remake of original " | ||||
|     "Picture Puzzle with modified and upgraded functionality. Music autor is SmugBurger, " | ||||
|     "sounds taken from open sources." | ||||
| ) | ||||
| 
 | ||||
| text_surfaces, text_rects = render_text_in_rect(long_text, rect_area) | ||||
| 
 | ||||
| 
 | ||||
| # Buttons (maybe optimise?) | ||||
|  | @ -896,9 +981,9 @@ def button_check(pressed_button, run, current_mode, timer_running): | |||
|         # Not finished yet | ||||
|         pass | ||||
|     elif pressed_button == info_button: | ||||
|         info() | ||||
|         current_mode = "info" | ||||
|     elif pressed_button == stats_button: | ||||
|         stats() | ||||
|         current_mode = "stats" | ||||
| 
 | ||||
|     return run, current_mode, timer_running, do_not_save | ||||
| 
 | ||||
|  | @ -935,11 +1020,12 @@ run = True | |||
| current_mode = "menu" | ||||
| # Dragging and mouse interaction | ||||
| dragging = False | ||||
| slider_moving = False | ||||
| setting = None | ||||
| can_move = False | ||||
| start_pos = (0, 0) | ||||
| pressed_button = None | ||||
| slider_moving = False | ||||
| setting = None | ||||
| arrow = None | ||||
| # Select mode | ||||
| clicked_image = False | ||||
| image_display = None | ||||
|  | @ -987,7 +1073,9 @@ while run: | |||
| 
 | ||||
|         selected_image.render(screen) | ||||
| 
 | ||||
|     for event in pygame.event.get(): | ||||
|     event_list = pygame.event.get() | ||||
|      | ||||
|     for event in event_list: | ||||
|         if event.type == pygame.QUIT or event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE: | ||||
|             save_puzzle_state() | ||||
|             update_puzzle_data(completed, not_shuffled, current_timer_text, current_moves, real_time) | ||||
|  | @ -1058,7 +1146,7 @@ while run: | |||
|             pressed_button = None | ||||
|             can_move = False | ||||
|             setting = None | ||||
|              | ||||
|                   | ||||
|         elif event.type == pygame.MOUSEBUTTONDOWN and current_mode == "settings": | ||||
|             if event.button == 4: | ||||
|                 scroll_offset -= 20 | ||||
|  | @ -1107,7 +1195,7 @@ while run: | |||
|                 if 0 <= clicked_row < len(puzzle_matrix) and 0 <= clicked_col < len(puzzle_matrix[0]): | ||||
|                     if puzzle_matrix[clicked_row, clicked_col] and clicked is None: | ||||
|                         moved = move_pieces(clicked_row, clicked_col) | ||||
|                         if settings_data[sound]["on"] is True and moved is not None: | ||||
|                         if settings_data[sound]["on"] and moved is not None: | ||||
|                             current_moves += 1 | ||||
|                             user_win = True | ||||
|                             print("clicked:", current_moves) | ||||
|  | @ -1160,18 +1248,39 @@ while run: | |||
| 
 | ||||
|         for index, setting_name in enumerate(settings_data): | ||||
|             if setting_name != "keybinds": | ||||
|                 y = f_line[3] - scroll_offset + index * (cons[0] + spaces[2]) - spaces[1] | ||||
|                 y = f_line[3] - scroll_offset + index * (cons[0] + spaces[2]) + spaces[1] | ||||
|                 value = settings_data[setting_name] | ||||
|                 if setting_name in [gui, music, sound]: | ||||
|                     if setting_name in [music, sound]: | ||||
|                         value = value["volume"] | ||||
|                     render_settings_text(setting_name.upper(), | ||||
|                                         (settings_x_position // 2 + spaces[4], y), screen, value) | ||||
|                 else: | ||||
|                    render_settings_text(setting_name.upper(), | ||||
|                                         (settings_x_position // 2 + spaces[4], y), screen) | ||||
|                         value =  settings_data[setting_name]["volume"] | ||||
|                         value2 =  settings_data[setting_name]["version"] | ||||
| 
 | ||||
|                 if setting_name == gui: | ||||
|                 if setting_name == "size": | ||||
|                     render_settings_text(setting_name.upper(),(settings_x_position // 2 + spaces[4], y), screen) | ||||
|                     size_choosing = arrows((settings_x_position // 2 - spaces[3], y + spaces[0]), setting_name, value, SIZE_CHOICES, event_list) | ||||
|                     size_choosing[0].update(mouse_pos) | ||||
|                     size_choosing[2].update(mouse_pos) | ||||
|                     size_choosing[0].draw(screen) | ||||
|                     size_choosing[2].draw(screen) | ||||
|                     active_selects["size"] = True | ||||
|                 elif setting_name == "style": | ||||
|                     render_settings_text(setting_name.upper(),(settings_x_position // 2 + spaces[4], y), screen) | ||||
|                     style_choosing = arrows((settings_x_position // 2 - spaces[3], y + spaces[0]), setting_name, value, STYLE_CHOICES, event_list) | ||||
|                     style_choosing[0].update(mouse_pos) | ||||
|                     style_choosing[2].update(mouse_pos) | ||||
|                     style_choosing[0].draw(screen) | ||||
|                     style_choosing[2].draw(screen) | ||||
|                     active_selects["style"] = True | ||||
|                 elif setting_name == "grid": | ||||
|                     render_settings_text(setting_name.upper(),(settings_x_position // 2 + spaces[4], y), screen) | ||||
|                     grid_choosing = arrows((settings_x_position // 2 - spaces[3], y + spaces[0]), setting_name, value, GRID_CHOICES, event_list) | ||||
|                     grid_choosing[0].update(mouse_pos) | ||||
|                     grid_choosing[2].update(mouse_pos) | ||||
|                     grid_choosing[0].draw(screen) | ||||
|                     grid_choosing[2].draw(screen) | ||||
|                     active_selects["grid"] = True | ||||
|                 elif setting_name == gui: | ||||
|                     render_settings_text(setting_name.upper(),(settings_x_position // 2 + spaces[4], y), screen, value) | ||||
|                     gui_color_slider = slider((settings_x_position // 2 - spaces[3], y + spaces[0]), 360, value, active_sliders, setting_name) | ||||
|                     for slider_part in gui_color_slider: | ||||
|                         slider_part.draw(screen) | ||||
|  | @ -1181,6 +1290,7 @@ while run: | |||
|                         elif not dragging: | ||||
|                             active_sliders[gui] = False | ||||
|                 elif setting_name == music: | ||||
|                     render_settings_text(setting_name.upper(),(settings_x_position // 2 + spaces[4], y), screen, value) | ||||
|                     music_volume_slider = slider((settings_x_position // 2 - spaces[3], y + spaces[0]), 100, value, active_sliders, setting_name) | ||||
|                     for slider_part in music_volume_slider: | ||||
|                         slider_part.draw(screen) | ||||
|  | @ -1189,8 +1299,16 @@ while run: | |||
|                             setting = setting_name | ||||
|                         elif not dragging: | ||||
|                             active_sliders[music] = False | ||||
|                     music_choosing = arrows((settings_x_position // 2 - spaces[3], y + spaces[0]+24), setting_name, value2, MUSIC_CHOICES, event_list) | ||||
|                     music_choosing[0].update(mouse_pos) | ||||
|                     music_choosing[2].update(mouse_pos) | ||||
|                     music_choosing[0].draw(screen) | ||||
|                     music_choosing[2].draw(screen) | ||||
|                     active_selects["music_version"] = True | ||||
|                 elif setting_name == sound: | ||||
|                     sound_volume_slider = slider((settings_x_position // 2 - spaces[3], y + spaces[0]), 100, value, active_sliders, setting_name) | ||||
|                     render_settings_text(setting_name.upper(),(settings_x_position // 2 + spaces[4], y+20), screen, value) | ||||
|                     y += spaces2[5] | ||||
|                     sound_volume_slider = slider((settings_x_position // 2 - spaces[3], y-10), 100, value, active_sliders, setting_name) | ||||
|                     for slider_part in sound_volume_slider: | ||||
|                         slider_part.draw(screen) | ||||
|                         if dragging and sound_volume_slider[2].rect.collidepoint(mouse_pos): | ||||
|  | @ -1198,8 +1316,18 @@ while run: | |||
|                             setting = setting_name | ||||
|                         elif not dragging: | ||||
|                             active_sliders[sound] = False | ||||
|                     sound_choosing = arrows((settings_x_position // 2 - spaces[3], y + spaces[0]), setting_name, value2, SOUND_CHOICES, event_list) | ||||
|                     sound_choosing[0].update(mouse_pos) | ||||
|                     sound_choosing[2].update(mouse_pos) | ||||
|                     sound_choosing[0].draw(screen) | ||||
|                     sound_choosing[2].draw(screen) | ||||
|                     active_selects["sound_version"] = True | ||||
| 
 | ||||
|         screen.set_clip(None) | ||||
|      | ||||
|     if current_mode == "info": | ||||
|         for text_surface, text_rect in zip(text_surfaces, text_rects): | ||||
|             screen.blit(text_surface, text_rect) | ||||
| 
 | ||||
|     pygame.display.flip() | ||||
| 
 | ||||
|  |  | |||
|  | @ -5,19 +5,19 @@ | |||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             93, | ||||
|             "00:01:05", | ||||
|             "00:00:40", | ||||
|             0 | ||||
|             99, | ||||
|             "00:01:11", | ||||
|             "00:00:46", | ||||
|             6 | ||||
|          ], | ||||
|          "2.png": [ | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             57, | ||||
|             "00:00:23", | ||||
|             "00:00:23", | ||||
|             1 | ||||
|             85, | ||||
|             "00:00:40", | ||||
|             "00:00:40", | ||||
|             0 | ||||
|          ], | ||||
|          "3.png": [ | ||||
|             0, | ||||
|  |  | |||
|  | @ -1 +1 @@ | |||
| {"puzzle 4x4": [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 0]], "puzzle 3x3": [[1, 2, 3], [4, 5, 6], [7, 8, 0]], "current 4x4": {"matrix": [[13, 2, 9, 12], [4, 1, 6, 8], [5, 3, 10, 15], [14, 7, 11, 0]], "selected_image": "images/albums/Original images/1.png"}, "current 3x3": {"matrix": [[3, 6, 7], [5, 4, 1], [0, 8, 2]], "selected_image": "/images/albums/Birds/1.png"}} | ||||
| {"puzzle 4x4": [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 0]], "puzzle 3x3": [[1, 2, 3], [4, 5, 6], [7, 8, 0]], "current 4x4": {"matrix": [[10, 2, 5, 12], [13, 4, 3, 15], [6, 14, 8, 0], [11, 1, 7, 9]], "selected_image": "images/albums/Original images/2.png"}, "current 3x3": {"matrix": [[3, 6, 7], [5, 4, 1], [0, 8, 2]], "selected_image": "/images/albums/Birds/1.png"}} | ||||
|  | @ -1,5 +1,5 @@ | |||
| { | ||||
|   "size": "big", | ||||
|   "size": "medium", | ||||
|   "style": "classic", | ||||
|   "grid": "4x4", | ||||
|   "gui color": 0, | ||||
|  | @ -10,7 +10,7 @@ | |||
|   }, | ||||
|   "sound": { | ||||
|     "on": true, | ||||
|     "volume": 16, | ||||
|     "volume": 12, | ||||
|     "version": "wood" | ||||
|   }, | ||||
|   "display": "time", | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue