import os import pygame import pickle from pygame.locals import * pygame.init() # Updated window dimensions WINDOW_WIDTH, WINDOW_HEIGHT = 1600, 1000 MAP_WIDTH, MAP_HEIGHT = 1000, 1000 TILE_SIZE = 50 WHITE = (255, 255, 255) GREY = (200, 200, 200) BLACK = (0, 0, 0) RED = (255, 0, 0) GREEN = (0, 255, 0) BLUE = (0, 0, 255) # Load your images here background_image = pygame.image.load('Images/Background.png') background_image = pygame.transform.scale(background_image, (MAP_WIDTH, MAP_HEIGHT)) # Add your block images here block_images = { 'brick0': pygame.image.load('Images/Level/brick_dark0.png'), 'brick1': pygame.image.load('Images/Level/brick_dark1.png'), 'brick2': pygame.image.load('Images/Level/brick_dark2.png'), 'brick3': pygame.image.load('Images/Level/brick_dark3.png'), 'cobbweb': pygame.image.load('Images/Level/Cobbwebs.png'), 'grill': pygame.image.load('Images/Level/Grill.png'), 'skulls': pygame.image.load('Images/Level/skulls.png'), 'trog': pygame.image.load('Images/dngn_altar_trog.png') # Add more blocks as needed } # Resize block images to fit the tile size for key in block_images: block_images[key] = pygame.transform.scale(block_images[key], (TILE_SIZE, TILE_SIZE)) # Dictionary to hold the placed blocks for each level placed_blocks = {1: [], 2: [], 3: []} current_level = 1 # Start with level 1 undo_stack = [] # Stack to keep track of actions for undo functionality redo_stack = [] # Stack to keep track of actions for redo functionality screen = pygame.display.set_mode((WINDOW_WIDTH, WINDOW_HEIGHT)) pygame.display.set_caption('Level Editor') map_surface = pygame.Surface((MAP_WIDTH, MAP_HEIGHT)) font = pygame.font.SysFont(None, 36) def draw_grid(surface, width, height, tile_size): for x in range(0, width, tile_size): pygame.draw.line(surface, GREY, (x, 0), (x, height)) for y in range(0, height, tile_size): pygame.draw.line(surface, GREY, (0, y), (width, y)) def draw_menu(surface, save_button_color, load_button_color, reset_button_color, undo_button_color, current_level, selected_block): pygame.draw.rect(surface, WHITE, (0, 0, 600, WINDOW_HEIGHT)) # Updated width for the menu text = font.render('Menu', True, BLACK) surface.blit(text, (250, 20)) # Centered the menu title # Display block images in the menu y_offset = 70 x_offset = 50 for idx, (block_name, block_img) in enumerate(block_images.items()): if block_name == selected_block: pygame.draw.rect(surface, GREEN, (x_offset - 5, y_offset - 5, TILE_SIZE + 10, TILE_SIZE + 10), 2) surface.blit(block_img, (x_offset, y_offset)) x_offset += TILE_SIZE + 10 if x_offset > 500: # Move to the next row if out of bounds x_offset = 50 y_offset += TILE_SIZE + 10 # Save, Load, Reset, and Undo buttons y_offset = WINDOW_HEIGHT - 200 # Adjusted y_offset for buttons button_width = 250 # Set the width for each button button_height = 50 save_button = pygame.Rect(50, y_offset + 20, button_width, button_height) load_button = pygame.Rect(320, y_offset + 20, button_width, button_height) reset_button = pygame.Rect(50, y_offset + 80, button_width, button_height) undo_button = pygame.Rect(320, y_offset + 80, button_width, button_height) pygame.draw.rect(surface, save_button_color, save_button) pygame.draw.rect(surface, load_button_color, load_button) pygame.draw.rect(surface, reset_button_color, reset_button) pygame.draw.rect(surface, undo_button_color, undo_button) save_text = font.render('Save', True, BLACK) load_text = font.render('Load', True, BLACK) reset_text = font.render('Reset', True, BLACK) undo_text = font.render('Undo/Redo', True, BLACK) surface.blit(save_text, (save_button.x + 90, save_button.y + 15)) surface.blit(load_text, (load_button.x + 90, load_button.y + 15)) surface.blit(reset_text, (reset_button.x + 90, reset_button.y + 15)) surface.blit(undo_text, (undo_button.x + 60, undo_button.y + 15)) # Input boxes for save/load level_name_box = pygame.Rect(50, y_offset + 160, button_width, button_height) pygame.draw.rect(surface, WHITE, level_name_box, 2) # Display current level current_level_text = font.render(f'Current Level: {current_level}', True, BLACK) surface.blit(current_level_text, (200, WINDOW_HEIGHT - 50)) return save_button, load_button, reset_button, undo_button, level_name_box running = True selected_block = None # No block selected initially dragging_left = False # Track if the left mouse button is being dragged dragging_right = False # Track if the right mouse button is being dragged level_name = "" # Store the level name for saving/loading save_button_color = GREEN load_button_color = GREEN reset_button_color = RED undo_button_color = GREY save_button_clicked = False load_button_clicked = False reset_button_clicked = False undo_button_clicked = False undo_button_right_clicked = False # Ensure the level_data directory exists if not os.path.exists('level_data'): os.makedirs('level_data') while running: for event in pygame.event.get(): if event.type == QUIT: running = False elif event.type == MOUSEBUTTONDOWN: mouse_x, mouse_y = event.pos if event.button == 1: # Left mouse button if mouse_x <= 600: # Menu area y_offset = 70 x_offset = 50 for idx, block_name in enumerate(block_images.keys()): if x_offset <= mouse_x <= x_offset + TILE_SIZE and y_offset <= mouse_y <= y_offset + TILE_SIZE: selected_block = block_name break x_offset += TILE_SIZE + 10 if x_offset > 500: # Move to the next row if out of bounds x_offset = 50 y_offset += TILE_SIZE + 10 # Check for save, load, reset, and undo button clicks save_button, load_button, reset_button, undo_button, level_name_box = draw_menu(screen, save_button_color, load_button_color, reset_button_color, undo_button_color, current_level, selected_block) if save_button.collidepoint(mouse_x, mouse_y): save_button_color = GREEN save_button_clicked = True load_button_clicked = False reset_button_clicked = False undo_button_clicked = False undo_button_right_clicked = False elif load_button.collidepoint(mouse_x, mouse_y): load_button_color = GREEN load_button_clicked = True save_button_clicked = False reset_button_clicked = False undo_button_clicked = False undo_button_right_clicked = False elif reset_button.collidepoint(mouse_x, mouse_y): reset_button_color = GREEN reset_button_clicked = True save_button_clicked = False load_button_clicked = False undo_button_clicked = False undo_button_right_clicked = False elif undo_button.collidepoint(mouse_x, mouse_y): undo_button_color = GREEN undo_button_clicked = True save_button_clicked = False load_button_clicked = False reset_button_clicked = False undo_button_right_clicked = False else: # Map area dragging_left = True if selected_block: tile_x = ((mouse_x - 600) // TILE_SIZE) * TILE_SIZE tile_y = (mouse_y // TILE_SIZE) * TILE_SIZE placed_blocks[current_level].append((tile_x, tile_y, selected_block)) undo_stack.append(('add', (tile_x, tile_y, selected_block))) elif event.button == 3: # Right mouse button if mouse_x <= 600 and undo_button.collidepoint(mouse_x, mouse_y): undo_button_color = BLUE undo_button_right_clicked = True save_button_clicked = False load_button_clicked = False reset_button_clicked = False undo_button_clicked = False else: dragging_right = True if mouse_x > 600: # Ensure clicks are within the map area tile_x = ((mouse_x - 600) // TILE_SIZE) * TILE_SIZE tile_y = (mouse_y // TILE_SIZE) * TILE_SIZE # Remove the block at this position if it exists for block in placed_blocks[current_level]: if block[0] == tile_x and block[1] == tile_y: placed_blocks[current_level].remove(block) undo_stack.append(('remove', block)) break elif event.type == MOUSEBUTTONUP: if event.button == 1: dragging_left = False elif event.button == 3: dragging_right = False undo_button_right_clicked = False save_button_color = GREY load_button_color = GREY reset_button_color = RED undo_button_color = GREY elif event.type == MOUSEMOTION: mouse_x, mouse_y = event.pos if dragging_left and mouse_x > 600: # Ensure clicks are within the map area if selected_block: tile_x = ((mouse_x - 600) // TILE_SIZE) * TILE_SIZE tile_y = (mouse_y // TILE_SIZE) * TILE_SIZE placed_blocks[current_level].append((tile_x, tile_y, selected_block)) undo_stack.append(('add', (tile_x, tile_y, selected_block))) elif dragging_right and mouse_x > 600: # Ensure clicks are within the map area tile_x = ((mouse_x - 600) // TILE_SIZE) * TILE_SIZE tile_y = (mouse_y // TILE_SIZE) * TILE_SIZE # Remove the block at this position if it exists for block in placed_blocks[current_level]: if block[0] == tile_x and block[1] == tile_y: placed_blocks[current_level].remove(block) undo_stack.append(('remove', block)) break elif event.type == KEYDOWN: if event.key == K_BACKSPACE: level_name = level_name[:-1] elif event.key == K_RETURN: # Perform any action on pressing enter if needed pass elif event.key == K_LEFT: current_level = max(1, current_level - 1) elif event.key == K_RIGHT: current_level = min(3, current_level + 1) else: level_name += event.unicode screen.fill(WHITE) save_button, load_button, reset_button, undo_button, level_name_box = draw_menu(screen, save_button_color, load_button_color, reset_button_color, undo_button_color, current_level, selected_block) # Draw the level name in the input box level_name_text = font.render(level_name, True, BLACK) screen.blit(level_name_text, (level_name_box.x + 5, level_name_box.y + 5)) # Draw the background map_surface.blit(background_image, (0, 0)) # Draw placed blocks for block in placed_blocks[current_level]: tile_x, tile_y, block_type = block map_surface.blit(block_images[block_type], (tile_x, tile_y)) draw_grid(map_surface, MAP_WIDTH, MAP_HEIGHT, TILE_SIZE) screen.blit(map_surface, (600, 0)) pygame.display.flip() # Handle save button click if save_button_clicked: try: with open(f'level_data/level{current_level}_data', 'wb') as pickle_out: pickle.dump(placed_blocks[current_level], pickle_out) print(f"Level {current_level} saved successfully.") except Exception as e: print(f"Error saving level {current_level}: {e}") save_button_clicked = False # Handle load button click if load_button_clicked: try: with open(f'level_data/level{current_level}_data', 'rb') as pickle_in: placed_blocks[current_level] = pickle.load(pickle_in) print(f"Level {current_level} loaded successfully.") except FileNotFoundError: print(f"No save file found for level {current_level}. Starting with an empty level.") placed_blocks[current_level] = [] except Exception as e: print(f"Error loading level {current_level}: {e}") load_button_clicked = False # Handle reset button click if reset_button_clicked: placed_blocks[current_level] = [] undo_stack = [] # Clear undo stack redo_stack = [] # Clear redo stack print(f"Level {current_level} reset successfully.") reset_button_clicked = False # Handle undo button click if undo_button_clicked and undo_stack: action, block = undo_stack.pop() if action == 'add': placed_blocks[current_level].remove(block) redo_stack.append(('add', block)) elif action == 'remove': placed_blocks[current_level].append(block) redo_stack.append(('remove', block)) print(f"Undo performed for level {current_level}.") undo_button_clicked = False # Handle redo button click if undo_button_right_clicked and redo_stack: action, block = redo_stack.pop() if action == 'add': placed_blocks[current_level].append(block) undo_stack.append(('add', block)) elif action == 'remove': placed_blocks[current_level].remove(block) undo_stack.append(('remove', block)) print(f"Redo performed for level {current_level}.") undo_button_right_clicked = False pygame.quit()