From c2f1ed6a85c3895483d36af0f64e2829c3fa3263 Mon Sep 17 00:00:00 2001 From: RaindropsSys Date: Fri, 1 Sep 2023 14:54:08 +0200 Subject: Updated 11 files and added 2 files (automated) --- assets/source/texture_atlas.psd | Bin 195454 -> 194607 bytes assets/textures/texture_atlas.png | Bin 10496 -> 10552 bytes main.py | 12 ++- src/audio.py | 26 ++++- src/blocks.py | 6 +- src/constants.py | 2 +- src/display.py | 75 +++++++++------ src/game.py | 102 +++++++++++++------- src/helper.py | 33 +++++++ src/menu.py | 197 ++++++++++++++++++++++++++++++++++---- src/pause.py | 57 +++++++++++ src/save.py | 54 +++++++++++ src/zoom.py | 16 +++- 13 files changed, 487 insertions(+), 93 deletions(-) create mode 100644 src/pause.py create mode 100644 src/save.py diff --git a/assets/source/texture_atlas.psd b/assets/source/texture_atlas.psd index 8579250..e630156 100644 Binary files a/assets/source/texture_atlas.psd and b/assets/source/texture_atlas.psd differ diff --git a/assets/textures/texture_atlas.png b/assets/textures/texture_atlas.png index 170b075..156526e 100644 Binary files a/assets/textures/texture_atlas.png and b/assets/textures/texture_atlas.png differ diff --git a/main.py b/main.py index 6deda5a..2b06d03 100644 --- a/main.py +++ b/main.py @@ -2,6 +2,7 @@ from os import environ environ['PYGAME_HIDE_SUPPORT_PROMPT'] = '1' import traceback +import datetime import os os.chdir(os.path.dirname(os.path.realpath(__file__))) @@ -10,14 +11,15 @@ import pygame import sys sys.path.append("./src") -from src import audio, window, loader, menu +from src import audio, window, loader, menu, helper +helper.get_data_path() pygame.font.init() pygame.init() window.init() clock = pygame.time.Clock() -screen = pygame.display.set_mode((1280, 720), pygame.RESIZABLE) +screen = pygame.display.set_mode((1280, 720), pygame.RESIZABLE, vsync=True) running = True index = 0 @@ -79,6 +81,12 @@ while running: print(traceback.format_exc()) + try: + with open(helper.get_data_path() + "/crash_reports/" + datetime.datetime.now().isoformat().replace(":", "-") + ".txt", "w") as f: + f.write(traceback.format_exc()) + except Exception: + print(traceback.format_exc()) + while running: for event in pygame.event.get(): if event.type == pygame.QUIT: diff --git a/src/audio.py b/src/audio.py index 17ae5ef..baba6da 100644 --- a/src/audio.py +++ b/src/audio.py @@ -5,6 +5,8 @@ pygame.mixer.pre_init(48000, -16, 2, 2048) pygame.mixer.init() pygame.mixer.set_num_channels(3) +pygame.mixer.stop() + intro = pygame.mixer.Sound("./assets/sounds/intro.mp3") menu = pygame.mixer.Sound("./assets/music/menu.mp3") @@ -17,6 +19,10 @@ bgm = [ ] sfx = { + "action": [pygame.mixer.Sound("./assets/sounds/gui/action.ogg")], + "back": [pygame.mixer.Sound("./assets/sounds/gui/back.ogg")], + "menu": [pygame.mixer.Sound("./assets/sounds/gui/menu.ogg")], + "save": [pygame.mixer.Sound("./assets/sounds/gui/save.ogg")], "glass": [ pygame.mixer.Sound("./assets/sounds/game/block_glass_1.ogg"), pygame.mixer.Sound("./assets/sounds/game/block_glass_2.ogg"), @@ -49,20 +55,38 @@ sfx = { } def play_intro(): + return pygame.mixer.Channel(0).play(intro) def play_music(): + return if not pygame.mixer.Channel(1).get_busy(): pygame.mixer.Channel(1).set_volume(0.5) pygame.mixer.Channel(1).play(random.choice(bgm)) def play_menu(force=False): + return if not pygame.mixer.Channel(1).get_busy() or force: pygame.mixer.Channel(1).set_volume(0.5) pygame.mixer.Channel(1).play(menu) def stop(channel=1): + return pygame.mixer.Channel(channel).stop() +def pause_music(): + return + pygame.mixer.Channel(1).pause() + +def unpause_music(): + return + pygame.mixer.Channel(1).unpause() + def play_sfx(id): - pygame.mixer.Channel(2).play(random.choice(sfx[id])) \ No newline at end of file + return + pygame.mixer.Channel(2).play(random.choice(sfx[id])) + +def wait_for_sfx(): + return + while pygame.mixer.Channel(2).get_busy(): + pass \ No newline at end of file diff --git a/src/blocks.py b/src/blocks.py index ffdf461..769418b 100644 --- a/src/blocks.py +++ b/src/blocks.py @@ -1,6 +1,10 @@ blocks = { + "air": { + "texture": 4, + "sounds": ("stone", "stone") + }, "grass_block": { - "texture": 0, + "texture": 1, "sounds": ("grass", "grass") }, "stone": { diff --git a/src/constants.py b/src/constants.py index 5b11ca9..dc7a533 100644 --- a/src/constants.py +++ b/src/constants.py @@ -1 +1 @@ -VERSION = "0.1a" \ No newline at end of file +VERSION = "0.2a" \ No newline at end of file diff --git a/src/display.py b/src/display.py index 23722a5..4ba3c24 100644 --- a/src/display.py +++ b/src/display.py @@ -1,9 +1,12 @@ import pygame import helper +import pause +opacity = 0 -def draw(canvas, screen, need_update_world, world, mouse, blocks, zoom, offset, block_coordinates): +def draw(canvas, screen, need_update_world, world, mouse, blocks, zoom, offset, block_coordinates, paused, screen_blocks): + global opacity canvas.fill("red") width = screen.get_size()[0] @@ -16,75 +19,85 @@ def draw(canvas, screen, need_update_world, world, mouse, blocks, zoom, offset, world_display = pygame.Surface((1280, 720)) if need_update_world: + screen_blocks = [] world.fill("gray") - for block in blocks: - world.blit(helper.draw_texture(helper.get_block_texture(block[2])), (block[0], block[1])) + for layer in range(len(blocks)): + for height in range(len(blocks[layer]) - 1, -1, -1): + for width in range(len(blocks[layer][height]) - 1, -1, -1): + if blocks[layer][height][width] != "air": + x = offset[0] + 500 + (21 * width) - (21 * height) + y = offset[1] + 500 - (13 * layer) - (14 * width) - (12 * height) + world.blit(helper.draw_texture(helper.get_block_texture(blocks[layer][height][width])), (x, y)) + + for layer in range(len(blocks) - 1, -1, -1): + for height in range(len(blocks[layer]) - 1, -1, -1): + for width in range(len(blocks[layer][height]) - 1, -1, -1): + if blocks[layer][height][width] != "air": + x = offset[0] + 500 + (21 * width) - (21 * height) + y = offset[1] + 500 - (13 * layer) - (14 * width) - (12 * height) + screen_blocks.append((x, y, blocks[layer][height][width], layer, height, width)) need_update_world = False + print(offset) world_display.blit(world, (0, 0)) - if mouse[0] > -1 and mouse[1] > -1 and pygame.mouse.get_focused(): + if mouse[0] > -1 and mouse[1] > -1 and pygame.mouse.get_focused() and not paused: cursor_x = original_cursor_x = mouse[0] - 42 / 2 cursor_y = original_cursor_y = mouse[1] - 42 / 2 cursor_changed = False - for block in blocks: - if abs(block[0] - mouse[0] + 42 / 2) < 21 and abs(block[1] - mouse[1] + 42 / 2) < 21: + for block in screen_blocks: + if block[0] <= mouse[0] <= block[0] + 42 and block[1] <= mouse[1] <= block[1] + 42: cursor_x = block[0] cursor_y = block[1] cursor_changed = True break - if abs(block[0] - mouse[0] + 42 / 2) < 21 and abs(block[1] - mouse[1] + 42 / 2 + 15) < 21: - cursor_x = block[0] - cursor_y = block[1] + 15 - cursor_changed = True - break if cursor_changed: - has_block_below = False - - for i in range(len(blocks) - 1, -1, -1): - if blocks[i][0] == cursor_x and blocks[i][1] == cursor_y: - has_block_below = True - break - - if has_block_below: - world_display.blit(helper.draw_texture(5), (cursor_x, cursor_y)) - else: - world_display.blit(helper.draw_texture(1), (cursor_x, cursor_y)) - + world_display.blit(helper.draw_texture(5), (cursor_x, cursor_y)) block_coordinates = (cursor_x, cursor_y) else: block_coordinates = (-1, -1) world_display.blit(helper.draw_texture(2), (original_cursor_x + 42 / 2, original_cursor_y + 42 / 2)) - x = 1280 / 2 - zoom[0] / 2 + offset[0] - y = 720 / 2 - zoom[1] / 2 + offset[1] + x = 1280 / 2 - zoom[0] / 2 + y = 720 / 2 - zoom[1] / 2 if x < 0: x = 0 - offset = (offset[0] - 10, offset[1]) if y < 0: y = 0 - offset = (offset[0], offset[1]) if x + zoom[0] > 1280: x = 0 - offset = (offset[0] - 10, offset[1]) if y + zoom[1] > 720: y = 0 - offset = (offset[0], offset[1]) canvas.blit(pygame.transform.scale(world_display.subsurface(x, y, zoom[0], zoom[1]), (1280, 720)), (0, 0)) + if paused: + canvas.blit(pygame.Surface.convert_alpha(pause.show()), (0, 0)) + scaled_win = pygame.transform.scale(canvas, (width, height)) - screen.blit(scaled_win, (screen.get_size()[0] / 2 - width / 2, screen.get_size()[1] / 2 - height / 2)) + + if opacity >= 1: + result = scaled_win + else: + result = helper.transparent(scaled_win, opacity) + + screen.blit(result, (screen.get_size()[0] / 2 - width / 2, screen.get_size()[1] / 2 - height / 2)) pygame.display.flip() - return canvas, screen, need_update_world, world, mouse, blocks, zoom, offset, block_coordinates + if opacity < 1: + opacity += 1/30 + + if opacity >= 1: + opacity = 1 + + return canvas, screen, need_update_world, world, mouse, blocks, zoom, offset, block_coordinates, paused, screen_blocks diff --git a/src/game.py b/src/game.py index be1659e..952006d 100644 --- a/src/game.py +++ b/src/game.py @@ -4,8 +4,11 @@ from blocks import blocks as block_list import audio import zoom as zoom_util import display +import pause +import save -def run(screen, blocks): +def run(screen, blocks, save_data): + first = True canvas = pygame.Surface((1280, 720)) running = True zoom = (1280.0, 720.0) @@ -14,64 +17,99 @@ def run(screen, blocks): block_coordinates = (-1, -1) need_update_world = True world = pygame.Surface((1280, 720)) + paused = False + screen_blocks = [] + + display.opacity = 0 + + #for layer in blocks: + # print("-- Layer:") + + # for height in layer: + # print(" -", height) + + save.save_world(save_data, blocks) while running: - audio.play_music() - screen.fill("black") + if not first: + pygame.event.wait() + + first = True + + if not paused: + audio.play_music() for event in pygame.event.get(): if event.type == pygame.MOUSEMOTION: - pygame.mouse.set_visible(False) + pygame.mouse.set_visible(paused) mouse = pygame.mouse.get_pos() if event.type == pygame.MOUSEBUTTONDOWN: left, middle, right = pygame.mouse.get_pressed() - if left: - if block_coordinates[0] > -1: + if paused: + if left: + mouse, screen, paused, keep = pause.click(mouse, screen, paused, True, save_data, blocks) + if not keep: + return + else: + if left: block = "stone" - can_place = True - for i in range(len(blocks) - 1, -1, -1): - if blocks[i][0] == block_coordinates[0] and blocks[i][1] == block_coordinates[1]: - can_place = False + for i in range(len(screen_blocks)): + if screen_blocks[i][0] == block_coordinates[0] and screen_blocks[i][1] == block_coordinates[1]: + if block_list[screen_blocks[i][2]]: + audio.play_sfx(block_list[screen_blocks[i][2]]['sounds'][0]) + + if len(blocks) - 1 >= screen_blocks[i][3] + 1 and blocks[screen_blocks[i][3] + 1][screen_blocks[i][4]][screen_blocks[i][5]] == "air": + audio.play_sfx(block_list[block]['sounds'][0]) + blocks[screen_blocks[i][3] + 1][screen_blocks[i][4]][screen_blocks[i][5]] = "stone" + need_update_world = True + break + elif right: + for i in range(len(screen_blocks)): + if screen_blocks[i][0] == block_coordinates[0] and screen_blocks[i][1] == block_coordinates[1]: + if block_list[screen_blocks[i][2]]: + audio.play_sfx(block_list[screen_blocks[i][2]]['sounds'][0]) - if can_place: - audio.play_sfx(block_list[block]['sounds'][0]) - blocks.append((block_coordinates[0], block_coordinates[1], block)) - need_update_world = True - elif right: - for i in range(len(blocks) - 1, -1, -1): - if blocks[i][0] == block_coordinates[0] and blocks[i][1] == block_coordinates[1]: - if block_list[blocks[i][2]]: - audio.play_sfx(block_list[blocks[i][2]]['sounds'][0]) - - blocks.pop(i) - need_update_world = True - break - - if not need_update_world: - audio.play_sfx("none") + blocks[screen_blocks[i][3]][screen_blocks[i][4]][screen_blocks[i][5]] = "air" + need_update_world = True + break + + if not need_update_world: + audio.play_sfx("none") if event.type == pygame.KEYDOWN: if event.key == pygame.K_ESCAPE: - import menu - menu.show(screen) - return + paused = not paused + if paused: + audio.play_sfx("menu") + audio.pause_music() + else: + audio.play_sfx("back") + audio.unpause_music() + pygame.mouse.set_visible(paused) if event.key == pygame.K_w or event.key == pygame.K_z: offset = zoom_util.offset_up(offset) + need_update_world = True if event.key == pygame.K_s: offset = zoom_util.offset_down(offset) + need_update_world = True if event.key == pygame.K_q or event.key == pygame.K_a: offset = zoom_util.offset_left(offset) + need_update_world = True if event.key == pygame.K_d: offset = zoom_util.offset_right(offset) + need_update_world = True if event.key == pygame.K_o: zoom = zoom_util.zoom_in(zoom) + need_update_world = True if event.key == pygame.K_l: zoom = zoom_util.zoom_out(zoom) + need_update_world = True if event.key == pygame.K_p: - zoom, offset = zoom_util.zoom_reset(zoom, offset) + zoom, offset = zoom_util.zoom_reset() + need_update_world = True if event.type == pygame.QUIT: + pause.save_and_quit(screen, save_data, blocks) running = False - - canvas, screen, need_update_world, world, mouse, blocks, zoom, offset, block_coordinates = display.draw(canvas, screen, need_update_world, world, mouse, blocks, zoom, offset, block_coordinates) + canvas, screen, need_update_world, world, mouse, blocks, zoom, offset, block_coordinates, paused, screen_blocks = display.draw(canvas, screen, need_update_world, world, mouse, blocks, zoom, offset, block_coordinates, paused, screen_blocks) diff --git a/src/helper.py b/src/helper.py index 669ea1b..e391212 100644 --- a/src/helper.py +++ b/src/helper.py @@ -1,9 +1,42 @@ from blocks import blocks import pygame from math import floor +from sys import platform +from pathlib import Path +import os texture_map = pygame.image.load('./assets/textures/texture_atlas.png') +def get_data_path(): + path = str(Path.home()) + "/.blocks" + + if platform == "darwin": + path = str(Path.home()) + "/Library/Application Support/Blocks" + elif platform == "win32": + path = str(Path.home()).replace("\\", "/") + "/.blocks" + + if not os.path.exists(path): + os.mkdir(path) + + if not os.path.exists(path + "/saves"): + os.mkdir(path + "/saves") + + if not os.path.exists(path + "/crash_reports"): + os.mkdir(path + "/crash_reports") + + return path + +def transparent(surface, percentage): + screen = pygame.Surface((1280, 720)) + screen.fill("black") + screen.blit(surface, (0, 0)) + + surface2 = pygame.Surface((1280, 720)) + surface2.fill((0, 0, 0, 255*(1-percentage))) + screen.blit(pygame.Surface.convert_alpha(surface2), (0, 0)) + + return screen + def text(text, size, color): return pygame.font.Font("./assets/font/main.ttf", size).render(text, False, color) diff --git a/src/menu.py b/src/menu.py index d066f51..95147df 100644 --- a/src/menu.py +++ b/src/menu.py @@ -1,9 +1,14 @@ +import os.path + import pygame import helper import audio +import save +import constants def show(screen): running = True + opacity = 0 audio.play_menu(True) while running: @@ -17,6 +22,7 @@ def show(screen): if left: if 45 < mouse[0] < 195 and 40 < mouse[1] < 70: + audio.play_sfx("action") print("New game") screen.fill("black") canvas = pygame.Surface((1280, 720)) @@ -29,28 +35,166 @@ def show(screen): height = screen.get_size()[1] width = height * (16/9) - canvas.blit(helper.text("Generating world...", 20, (255, 255, 255)), (50, 50)) + run = True + done = False + text = "" + quit = False + + while run and not done: + canvas.fill("black") + + for event in pygame.event.get(): + if event.type == pygame.QUIT: + run = False + quit = True + elif event.type == pygame.KEYDOWN: + if event.key == pygame.K_ESCAPE: + run = False + elif event.key == pygame.K_RETURN: + for i in ["con", "prn", "aux", "nul", + "com1", "com2", "com3", "com4", "com5", "com6", "com7", "com8", "com9", + "lpt1", "lpt2", "lpt3", "lpt4", "lpt5", "lpt6", "lpt7", "lpt8", "lpt9"]: + if text.lower() == i or text.startswith(i + ".") or text.endswith("." + i): + text = "" + + if text.strip() != "" and not os.path.exists(helper.get_data_path() + "/saves/" + text): + done = True + elif os.path.exists(helper.get_data_path() + "/saves/" + text): + text = "" + else: + text = text.strip() + elif event.key == pygame.K_BACKSPACE: + text = text[:-1] + else: + if event.unicode not in ["/", "\\", "<", ">", ":", "\"", "'", "|", "?", "*"] and len(text) < 60: + text += event.unicode + + text_surf = helper.text(text + "|", 20, (255, 255, 255)) + canvas.blit(text_surf, (50, 75)) + canvas.blit(helper.text("Enter world name:", 20, (255, 255, 255)), (50, 50)) + + scaled_win = pygame.transform.scale(canvas, (width, height)) + screen.blit(scaled_win, (screen.get_size()[0] / 2 - width / 2, screen.get_size()[1] / 2 - height / 2)) + pygame.display.flip() + + if quit: + pygame.quit() + elif done: + audio.stop(1) + audio.play_sfx("menu") + + canvas.fill("black") + canvas.blit(helper.text("Generating world...", 20, (255, 255, 255)), (50, 50)) + + scaled_win = pygame.transform.scale(canvas, (width, height)) + screen.blit(scaled_win, (screen.get_size()[0] / 2 - width / 2, screen.get_size()[1] / 2 - height / 2)) + pygame.display.flip() + + world_map = [[["grass_block" for _ in range(20)] for _ in range(20)]] + + for _ in range(9): + world_map.append([["air" for _ in range(20)] for _ in range(20)]) + + audio.wait_for_sfx() + + import game + game.run(screen, world_map, helper.get_data_path() + "/saves/" + text) + + return + else: + audio.play_sfx("back") + elif 45 < mouse[0] < 205 and 40+25 < mouse[1] < 70+25: + audio.play_sfx("action") + print("Load game") + screen.fill("black") + canvas = pygame.Surface((1280, 720)) + canvas.fill("black") - scaled_win = pygame.transform.scale(canvas, (width, height)) - screen.blit(scaled_win, (screen.get_size()[0] / 2 - width / 2, screen.get_size()[1] / 2 - height / 2)) + width = screen.get_size()[0] + height = width / (16/9) - pygame.display.flip() + if width > screen.get_size()[0] or height > screen.get_size()[1]: + height = screen.get_size()[1] + width = height * (16/9) - blocks = [] + run = True + done = False + quit = False + world_name = "" - for i in range(20): - for j in range(20): - blocks.append((802 + j * 21 - i * 42, 202 + j * 13 + i, "grass_block")) + saves = list(filter(lambda x: not x.startswith(".") and os.path.exists(helper.get_data_path() + "/saves/" + x + "/level.dat"), os.listdir(helper.get_data_path() + "/saves"))) - import game - audio.stop(1) - game.run(screen, blocks) - return - elif 45 < mouse[0] < 205 and 40+25 < mouse[1] < 70+25: - print("Load game") + while run and not done: + canvas.fill("black") + + for event in pygame.event.get(): + if event.type == pygame.QUIT: + run = False + quit = True + elif event.type == pygame.MOUSEBUTTONDOWN: + cursor = pygame.mouse.get_pos() + + for i in range(len(saves)): + save_name = saves[i] + + if 45 < cursor[0] < 550 and 65+25*i < cursor[1] < 95+25*i: + print(save_name) + world_name = save_name + done = True + break + + elif event.type == pygame.KEYDOWN: + if event.key == pygame.K_ESCAPE: + run = False + + canvas.blit(helper.text("Select a world to load:", 20, (255, 255, 255)), (50, 50)) + + last_i = 0 + + for i in range(len(saves)): + save_name = saves[i] + canvas.blit(helper.text(save_name, 20, (255, 255, 255)), (75, 75 + (25 * i))) + last_i = i + + canvas.blit(helper.text("Notice:", 20, (255, 255, 255)), (50, 75 + (25 * (last_i + 2)))) + canvas.blit(helper.text("Worlds from Blocks 0.1a are not compatible and", 20, (255, 255, 255)), (75, 75 + (25 * (last_i + 3)))) + canvas.blit(helper.text("do not show up here.", 20, (255, 255, 255)), (75, 75 + (25 * (last_i + 4)))) + + scaled_win = pygame.transform.scale(canvas, (width, height)) + screen.blit(scaled_win, (screen.get_size()[0] / 2 - width / 2, screen.get_size()[1] / 2 - height / 2)) + pygame.display.flip() + if quit: + pygame.quit() + elif done: + audio.stop(1) + audio.play_sfx("menu") + + canvas.fill("black") + canvas.blit(helper.text("Loading world...", 20, (255, 255, 255)), (50, 50)) + + scaled_win = pygame.transform.scale(canvas, (width, height)) + screen.blit(scaled_win, (screen.get_size()[0] / 2 - width / 2, screen.get_size()[1] / 2 - height / 2)) + pygame.display.flip() + + loaded = save.load_world(helper.get_data_path() + "/saves/" + world_name) + + if loaded['version'] != constants.VERSION: + print("WARNING: World was last loaded in a different version.") + + audio.wait_for_sfx() + + import game + game.run(screen, loaded['blocks'], helper.get_data_path() + "/saves/" + world_name) + + return + else: + audio.play_sfx("back") elif 45 < mouse[0] < 125 and 40+25*2 < mouse[1] < 70+25*2: - print("Settings") - elif 45 < mouse[0] < 90 and 40+25*3 < mouse[1] < 70+25*3: + # audio.play_sfx("action") + # print("Settings") + #elif 45 < mouse[0] < 90 and 40+25*3 < mouse[1] < 70+25*3: + audio.play_sfx("action") + audio.wait_for_sfx() print("Exit") running = False @@ -70,11 +214,24 @@ def show(screen): canvas.blit(helper.text("Start new game", 20, (255, 255, 255)), (50, 50)) canvas.blit(helper.text("Load saved game", 20, (255, 255, 255)), (50, 75)) - canvas.blit(helper.text("Settings", 20, (255, 255, 255)), (50, 100)) - canvas.blit(helper.text("Exit", 20, (255, 255, 255)), (50, 125)) + #canvas.blit(helper.text("Settings", 20, (255, 255, 255)), (50, 100)) + #canvas.blit(helper.text("Exit", 20, (255, 255, 255)), (50, 125)) + canvas.blit(helper.text("Exit", 20, (255, 255, 255)), (50, 100)) scaled_win = pygame.transform.scale(canvas, (width, height)) - screen.blit(scaled_win, (screen.get_size()[0] / 2 - width / 2, screen.get_size()[1] / 2 - height / 2)) + + if opacity >= 1: + result = scaled_win + else: + result = helper.transparent(scaled_win, opacity) + + screen.blit(result, (screen.get_size()[0] / 2 - width / 2, screen.get_size()[1] / 2 - height / 2)) audio.play_menu() - pygame.display.flip() \ No newline at end of file + pygame.display.flip() + + if opacity < 1: + opacity += 1/30 + + if opacity >= 1: + opacity = 1 diff --git a/src/pause.py b/src/pause.py new file mode 100644 index 0000000..a68ea1f --- /dev/null +++ b/src/pause.py @@ -0,0 +1,57 @@ +import pygame + +import helper +import audio +import save + +def show(): + surface = pygame.Surface((1280, 720)) + surface.fill((0, 0, 0, 128)) + + surface.blit(helper.text("Back to game", 20, (255, 255, 255)), (50, 50)) + surface.blit(helper.text("Save and quit", 20, (255, 255, 255)), (50, 75)) + + return surface + +def click(mouse, screen, paused, keep, save_data, regions): + if 45 < mouse[0] < 195 and 40 < mouse[1] < 70: + audio.play_sfx("action") + print("Back") + audio.play_sfx("back") + audio.unpause_music() + pygame.mouse.set_visible(True) + paused = False + elif 45 < mouse[0] < 205 and 40+25 < mouse[1] < 70+25: + audio.play_sfx("action") + print("Save game") + save_and_quit(screen, save_data, regions) + keep = False + import menu + menu.show(screen) + + return mouse, screen, paused, keep + +def save_and_quit(screen, path, regions): + audio.play_sfx("save") + + canvas = pygame.Surface((1280, 720)) + canvas.fill("black") + + width = screen.get_size()[0] + height = width / (16/9) + + if width > screen.get_size()[0] or height > screen.get_size()[1]: + height = screen.get_size()[1] + width = height * (16/9) + + canvas.blit(helper.text("Saving world...", 20, (255, 255, 255)), (50, 50)) + + scaled_win = pygame.transform.scale(canvas, (width, height)) + screen.blit(scaled_win, (screen.get_size()[0] / 2 - width / 2, screen.get_size()[1] / 2 - height / 2)) + + pygame.display.flip() + audio.stop(1) + + audio.wait_for_sfx() + + save.save_world(path, regions) \ No newline at end of file diff --git a/src/save.py b/src/save.py new file mode 100644 index 0000000..0e8e3d2 --- /dev/null +++ b/src/save.py @@ -0,0 +1,54 @@ +import os +import zlib +import json + +import constants + +def save_world(path, regions): + checksums = {} + region_list = [] + + if not os.path.exists(path): + os.mkdir(path) + + if not os.path.exists(path + "/region"): + os.mkdir(path + "/region") + + if not os.path.exists(path + "/playerdata"): + os.mkdir(path + "/playerdata") + + for i in range(len(regions)): + with open(path + "/region/" + str(i) + ".bcr", "wb") as f: + checksums[str(i) + ".bcr"] = hex(zlib.crc32(str.encode(json.dumps(regions[i])))) + region_list.append(str(i) + ".bcr") + f.write(zlib.compress(str.encode(json.dumps(regions[i])))) + + with open(path + "/level.dat", "wb") as f: + f.write(zlib.compress(str.encode(json.dumps({ + "version": constants.VERSION, + "checksums": checksums, + "regions": region_list + })))) + +def load_world(path): + blocks = [] + + with open(path + "/level.dat", "rb") as f: + data = json.loads(zlib.decompress(f.read())) + + print(data) + + for region in data['regions']: + with open(path + "/region/" + region, "rb") as f: + raw = zlib.decompress(f.read()) + + if hex(zlib.crc32(raw)) != data['checksums'][region]: + raise Exception("Region file " + region + " is corrupted.") + + blocks.append(json.loads(raw)) + + + return { + "version": data['version'], + "blocks": blocks + } diff --git a/src/zoom.py b/src/zoom.py index 2f993a3..1e57d56 100644 --- a/src/zoom.py +++ b/src/zoom.py @@ -1,3 +1,5 @@ +offset_limit = 200 + def zoom_in(zoom): if zoom[0] > 128: zoom = (zoom[0] / 1.5, zoom[1] / 1.5) @@ -8,23 +10,27 @@ def zoom_out(zoom): zoom = (zoom[0] * 1.5, zoom[1] * 1.5) return zoom -def zoom_reset(zoom, offset): +def zoom_reset(): zoom = (1280.0, 720.0) offset = (0, 0) return zoom, offset def offset_up(offset): - offset = (offset[0], offset[1] - 10) + if offset[1] - 10 > -offset_limit: + offset = (offset[0], offset[1] - 10) return offset def offset_down(offset): - offset = (offset[0], offset[1] + 10) + if offset[1] + 10 < offset_limit: + offset = (offset[0], offset[1] + 10) return offset def offset_left(offset): - offset = (offset[0] - 10, offset[1]) + if offset[0] - 10 > -(offset_limit * 16/9): + offset = (offset[0] - 10, offset[1]) return offset def offset_right(offset): - offset = (offset[0] + 10, offset[1]) + if offset[0] + 10 < offset_limit * 16/9: + offset = (offset[0] + 10, offset[1]) return offset \ No newline at end of file -- cgit