From 65dac764b605ee2315dcb9002a0e13ceb4b830da Mon Sep 17 00:00:00 2001 From: elukjanovica Date: Thu, 29 Feb 2024 15:08:33 +0200 Subject: [PATCH] --- main.py | 152 +++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 102 insertions(+), 50 deletions(-) diff --git a/main.py b/main.py index c56392b..7f076fb 100644 --- a/main.py +++ b/main.py @@ -12,7 +12,7 @@ pygame.init() FPS = 60 MAIN_PATH = "C:/Users/User/Documents/Coding/Picture_Puzzle/" -#School: MAIN_PATH = "C:/Users/RVKG/Documents/My Palettes/Picture Puzzle/" +# School: MAIN_PATH = "C:/Users/RVKG/Documents/My Palettes/Picture Puzzle/" IMAGES_PATH = "images/albums/" SIZE_PATH = "images/assets/" @@ -22,6 +22,8 @@ SETTINGS_FILE = "main_settings.json" STATS_FILE = "main_stats.json" # Data loading and saving + + def load_data(data): try: with open(data, "r") as file: @@ -29,7 +31,8 @@ def load_data(data): except (FileNotFoundError, json.JSONDecodeError): print("Something went wrong with file loading") return current_data - + + storage = load_data(DATA_FILE) puzzle_data = load_data(PUZZLE_FILE) settings_data = load_data(SETTINGS_FILE) @@ -77,8 +80,8 @@ if settings_data["size"] == SIZE_CHOICES[0]: size = [20, 25, 100, 15] cons = [15, 195, 12, 3, 9] scaled_size = (18, 21, 108, 108) - area = (72 , 142) - + area = (72, 142) + elif settings_data["size"] == SIZE_CHOICES[1]: WIDTH, HEIGHT = 202, 216 INT = 1 @@ -116,7 +119,7 @@ else: area = (197, 390) puzzle_version = settings_data["grid"] - + # Seting screen and other stuff programIcon = pygame.image.load('icon.png') pygame.display.set_icon(programIcon) @@ -128,6 +131,8 @@ clock = pygame.time.Clock() hwnd = pygame.display.get_wm_info()["window"] # Sprites generation + + class SpriteSheet: def __init__(self, sheet_path): self.sheet = pygame.image.load(sheet_path).convert_alpha() @@ -155,9 +160,11 @@ class SpriteSheet: new_color.hsva = (h, s, v, a) self.sheet.set_at((x, y), new_color) - + + sprite_sheet = SpriteSheet(SIZE_PATH + str(INT) + STYLE_PATH + "sprites.png") - + + class Image: def __init__(self, sprite_position, window_position, size): self.sprite_sheet = sprite_sheet @@ -173,6 +180,7 @@ class Image: def draw(self, screen): screen.blit(self.img, self.rect) + class Slider: def __init__(self, line_size, button_size, position): self.line_size = line_size @@ -202,6 +210,7 @@ class Slider: self.value = int(((mouse_x - self.position[0]) / (self.line_size[0] - self.button_size[0])) * 360) self.update() + class Button: def __init__(self, sprite_position, window_position, size): self.sprite_sheet = sprite_sheet @@ -226,14 +235,14 @@ class Button: def is_hovered(self, mouse_pos): return self.rect.collidepoint(mouse_pos) and self.mask.get_at( (mouse_pos[0] - self.rect.x, mouse_pos[1] - self.rect.y) - ) - + ) + def disable(self): self.disabled = True - + def enable(self): self.disabled = False - + def update(self, mouse_pos): self.hovered = self.is_hovered(mouse_pos) @@ -244,6 +253,8 @@ class Button: screen.blit(self.img, self.rect) # Ability to move window + + def move_win(coordinates): hwnd = pygame.display.get_wm_info()["window"] w, h = pygame.display.get_surface().get_size() @@ -251,6 +262,8 @@ def move_win(coordinates): set_shadow_style(hwnd) # Generating shadow + + def set_shadow_style(hwnd): try: DWMWA_NCRENDERING_POLICY = 2 @@ -267,8 +280,10 @@ def set_shadow_style(hwnd): except Exception as e: print(e) - + # Text render + + def render_text(text, position, screen, color=text_color, centered=False): font = pygame.font.SysFont(FONT, FONT_SIZE) text_render = font.render(text, True, color) @@ -280,6 +295,8 @@ def render_text(text, position, screen, color=text_color, centered=False): screen.blit(text_render, position) # MENU MODE + + def browse(): root = Tk() root.withdraw() @@ -287,9 +304,11 @@ def browse(): root.destroy() return file_path + quick_game_activated = False selected_file = None + def quick_game(): global selected_file, puzzle_image, puzzle_pieces, shuffled_pieces, empty_position, quick_game_activated, original_image quick_game_activated = True @@ -305,6 +324,7 @@ def quick_game(): except FileNotFoundError: print("No file selected") + def render_albums(): global current_mode, album_name current_hovered_index = -1 @@ -325,41 +345,45 @@ def render_albums(): album_name = album if album_name != album: album_name = None - + if album_name is not None: current_mode = "select" - + return album - + if current_hovered_index == -1: current_hovered_index = 0 arrow_image = Image((cons[1], 0), (cons[2], size[1] + cons[0] * current_hovered_index + cons[3]), (cons[4], cons[4])) arrow_image.draw(screen) - + + def album_deletion(): # Not finished yet pass + def album_creation(): # Not finished yet pass - + # SELECT MODE + + class ImageRender: def __init__(self, album_name, initial_index=0): self.album_name = album_name self.index = initial_index self.image_load() - + def image_load(self): global current_img, current_album self.scaled_size = scaled_size image_list = storage["albums"][self.album_name] image_names = list(image_list.keys()) - + if not image_names: return - + self.current = image_names[self.index] selected_image = pygame.image.load(MAIN_PATH + IMAGES_PATH + self.album_name + "/" + self.current) self.scaled_image = pygame.transform.scale(selected_image, (self.scaled_size[2], self.scaled_size[3])) @@ -368,20 +392,19 @@ class ImageRender: self.num_images = len(storage["albums"][self.album_name]) self.current_text = f"{self.index+1} of {self.num_images}" - def render(self, screen): screen.blit(self.scaled_image, (self.scaled_size[0], self.scaled_size[1])) render_text(self.current_text, (area[0], area[1]), screen, oposite_color, True) pygame.display.flip() - + def update_index(self, increment): self.index += increment if self.index >= self.num_images: self.index = 0 elif self.index < 0: - self.index = self.num_images - 1 + self.index = self.num_images - 1 self.image_load() - + @staticmethod def image_save(selected_album, current_img): for album in storage["albums"].values(): @@ -399,7 +422,7 @@ class ImageRender: puzzle_file.write(json.dumps(puzzle_data)) load_puzzle() return image_rect - + def image_deletion(self): # Not finished yet pass @@ -407,7 +430,8 @@ class ImageRender: def image_creation(self): # Not finished yet pass - + + def reload_chosen(): for album in storage["albums"].values(): for image in album.values(): @@ -416,6 +440,8 @@ def reload_chosen(): data_file.write(json.dumps(storage, indent=3)) # GAME MODE + + def timer(elapsed_time): hours = elapsed_time // 3600 minutes = (elapsed_time % 3600) // 60 @@ -424,6 +450,8 @@ def timer(elapsed_time): return timer_text # Puzzle loading and running logic + + def cut_image(image): piece_width = puzzle_size[0] // len(puzzle_matrix[0]) piece_height = puzzle_size[1] // len(puzzle_matrix) @@ -435,7 +463,7 @@ def cut_image(image): piece_image = image.subsurface(piece_rect) piece_layer = pygame.Surface((piece_width, piece_height), pygame.SRCALPHA) - + if puzzle_version == GRID_CHOICES[0]: layer_path = pygame.image.load("images/assets/piece32.png").convert_alpha() else: @@ -450,6 +478,7 @@ def cut_image(image): return pieces + def load_puzzle(): global puzzle_matrix, original_matrix, empty_position, puzzle_pieces, shuffled_pieces, puzzle_size, directions, cell_size, number_of_rows, original_image @@ -474,8 +503,10 @@ def load_puzzle(): shuffled_pieces = shuffle_pieces(puzzle_pieces) empty_position = (len(puzzle_matrix) - 1, len(puzzle_matrix[0]) - 1) + load_puzzle() + def shuffle_pieces(puzzle_pieces): global puzzle_matrix numbers = list(range(len(puzzle_pieces))) @@ -490,6 +521,7 @@ def shuffle_pieces(puzzle_pieces): return puzzle_pieces + def move_pieces(clicked_row, clicked_col): global puzzle_matrix @@ -513,7 +545,7 @@ def move_pieces(clicked_row, clicked_col): pieces_to_move = puzzle_matrix[min(clicked_row, zero_row):max(clicked_row, zero_row) + 1, clicked_col] else: pieces_to_move = puzzle_matrix[clicked_row, min(clicked_col, zero_col):max(clicked_col, zero_col) + 1] - + if direction == "right": puzzle_matrix[clicked_row, clicked_col:zero_col + 1] = np.roll(puzzle_matrix[clicked_row, clicked_col:zero_col + 1], 1) elif direction == "left": @@ -526,6 +558,7 @@ def move_pieces(clicked_row, clicked_col): save_puzzle_state() update_directions() + def update_directions(): global directions, puzzle_matrix zero_positions = np.nonzero(puzzle_matrix == 0) @@ -537,15 +570,18 @@ def update_directions(): "left": puzzle_matrix[zero_row, zero_col + 1:].flatten().tolist() if zero_col < number_of_rows - 1 else [], "right": puzzle_matrix[zero_row, :zero_col].flatten().tolist() if zero_col > 0 else [], } - + + update_directions() + def save_puzzle_state(): puzzle_matrix_list = puzzle_matrix.tolist() puzzle_data[f'current {puzzle_version}']['matrix'] = puzzle_matrix_list with open(PUZZLE_FILE, 'w') as puzzle_file: json.dump(puzzle_data, puzzle_file) - + + def update_puzzle_data(completed, sorted, current_time, current_moves, real_time): path_components = puzzle_data[f'current {puzzle_version}']['selected_image'].split('/')[2:] current_data = storage[path_components[0]] @@ -555,36 +591,40 @@ def update_puzzle_data(completed, sorted, current_time, current_moves, real_time else: print("Something went wrong while updating puzzle data") return - + print(current_data) initial_chosen, initial_completed, initial_sorted, initial_moves, initial_time, _, _ = current_data initial_completed = int(completed) initial_sorted = int(sorted) initial_moves += current_moves - + initial_time_seconds = sum(int(x) * 60**i for i, x in enumerate(reversed(initial_time.split(":")))) total_time_seconds = initial_time_seconds + real_time hours, remainder = divmod(total_time_seconds, 3600) minutes, seconds = divmod(remainder, 60) formatted_time = f"{hours:02d}:{minutes:02d}:{seconds:02d}" - + current_data = [initial_chosen, initial_completed, initial_sorted, initial_moves, formatted_time, current_time, current_moves] print(current_data) storage[path_components[0]][path_components[1]][path_components[2]] = current_data with open(DATA_FILE, 'w') as data_file: data_file.write(json.dumps(storage, indent=3)) - + # SETTINGS MODE + + def play_music(): music_file = settings_data["music"]["version"] volume = settings_data["music"]["volume"] pygame.mixer.music.load("misc/" + music_file + ".mp3") pygame.mixer.music.set_volume(volume) pygame.mixer.music.play(-1) - + + if settings_data["music"]["on"] is True: play_music() + def play_sound(): sound_file = settings_data["sound"]["version"] volume = settings_data["sound"]["volume"] @@ -592,13 +632,14 @@ def play_sound(): sound.set_volume(volume) pygame.mixer.Sound.play(sound) + def set_hue(): global hue_value if settings_data["style"] == STYLE_CHOICES[0]: x = 0 elif settings_data["style"] == STYLE_CHOICES[2]: x = 1 - + hue_value = settings_data["gui color"][x] keys = pygame.key.get_pressed() if keys[pygame.K_LEFT]: @@ -614,6 +655,7 @@ def set_hue(): with open(SETTINGS_FILE, "w") as settings_file: json.dump(settings_data, settings_file) + def change_hue(image, hue): new_image = image.copy() @@ -629,24 +671,29 @@ def change_hue(image, hue): new_image.set_at((x, y), new_color) return new_image - + + def export(): # Export data function, not finished yet pass + def reset(): # Reset all data function, not finished yet pass + def info(): # Not finished yet pass + # Stats def stats(): # Not finished yet pass + # Buttons if settings_data["size"] == SIZE_CHOICES[0]: px12 = (12, 12) @@ -741,6 +788,7 @@ settings_buttons = [info_button, menu_button, stats_button, continue_button, clo do_not_save = False + def button_check(pressed_button, run, current_mode, timer_running): global completed, not_shuffled, current_timer_text, current_moves, real_time do_not_save = False @@ -781,13 +829,15 @@ def button_check(pressed_button, run, current_mode, timer_running): return run, current_mode, timer_running, do_not_save + win32gui.SetWindowLong(hwnd, win32con.GWL_EXSTYLE, win32gui.GetWindowLong(hwnd, win32con.GWL_EXSTYLE) | win32con.WS_EX_LAYERED) win32gui.SetLayeredWindowAttributes(hwnd, win32api.RGB(*(255, 0, 128)), 0, win32con.LWA_COLORKEY) set_shadow_style(hwnd) -def data_check(current_mode): + +def data_check(current_mode): if current_mode == "select": background_image = ver2_layer current_buttons = select_buttons @@ -807,6 +857,8 @@ def data_check(current_mode): return background_image, current_buttons # Game state + + run = True current_mode = "menu" # Dragging and mouse interaction @@ -832,11 +884,11 @@ timer_button.disable() while run: background_image, current_buttons = data_check(current_mode) current_time = pygame.time.get_ticks() - + screen.fill((255,0,128)) screen.blit(BACKGROUND_IMAGE.img, (0, 0)) screen.blit(background_image, (0, 0)) - + mouse_pos = pygame.mouse.get_pos() for button in current_buttons: @@ -846,17 +898,17 @@ while run: button.draw(screen) clock.tick(FPS) - + if current_mode == "menu": selected_album = render_albums() - + if current_mode == "select": if image_display is None or current_album != selected_album: selected_image = ImageRender(selected_album) image_display = True selected_image.render(screen) - + for event in pygame.event.get(): if event.type == pygame.QUIT or event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE: if current_mode == "game": #is this needed? @@ -874,7 +926,7 @@ while run: current_mode = "game" shuffle_pieces(puzzle_pieces) last_click_time = pygame.time.get_ticks() - + if to_left_button.is_hovered(event.pos): selected_image.update_index(-1) last_image_switch_time = current_time @@ -882,7 +934,7 @@ while run: if to_right_button.is_hovered(event.pos): selected_image.update_index(1) last_image_switch_time = current_time - + elif current_mode == "game": if non_movable_area.collidepoint(event.pos) and not timer_running: timer_running = True @@ -892,7 +944,7 @@ while run: timer_running = False timer_button.disable() total_paused_time += pygame.time.get_ticks() - timer_start_time - + if event.button == 1: dragging = True start_pos = pygame.mouse.get_pos() @@ -910,7 +962,7 @@ while run: window_coords[0] += offset_x window_coords[1] += offset_y move_win(window_coords) - + elif event.type == pygame.MOUSEBUTTONUP: dragging = False pressed_button = None @@ -939,7 +991,7 @@ while run: save_puzzle_state() update_directions() last_shuffle_time = current_time - + for row in range(len(puzzle_matrix)): for col in range(len(puzzle_matrix[0])): if puzzle_matrix[row][col] != 0: @@ -999,7 +1051,7 @@ while run: text_alpha = max(0, text_alpha) pygame.display.flip() pygame.time.delay(16) - + pygame.display.flip() -pygame.quit() \ No newline at end of file +pygame.quit()