class WesternMaker: def __init__(self, screen, global_config): self.screen = screen self.global_config = global_config self.running = False self.debug = False self.selected_object = Tile(["assets", "dirt.png"], interactable=True) self.selected_layer = "BASE" self.GameMap = GameMap() self.x_offset = 0 self.gui_image = pygame.image.load( os.path.join(ASSETS_DIRECTORY, GUI_DIRECTORY, "gui.png")) self.save_button_image = pygame.image.load( os.path.join(ASSETS_DIRECTORY, GUI_DIRECTORY, "save-button.png")) self.play_button_image = pygame.image.load( os.path.join(ASSETS_DIRECTORY, GUI_DIRECTORY, "play-button.png")) self.load_button_image = pygame.image.load( os.path.join(ASSETS_DIRECTORY, GUI_DIRECTORY, "load-button.png")) self.newl_button_image = pygame.image.load( os.path.join(ASSETS_DIRECTORY, GUI_DIRECTORY, "new-button.png")) self.screen = None # TODO unhardcode this self.buttons = [] self.filename_input = TextInput(16, 24 * 16, "filename") self.save_button = ImageButton((19 * 16, 24 * 16), self.save_button_image, on_click=self.save_map) self.buttons.append(self.save_button) self.play_button = ImageButton((24 * 16, 24 * 16), self.play_button_image, on_click=self.quickplay) self.buttons.append(self.play_button) self.load_button = ImageButton((24 * 16, 22 * 16), self.load_button_image, on_click=self.load_map) self.buttons.append(self.load_button) self.newlayer_button = ImageButton((24 * 16, 22 * 16), self.newl_button_image, on_click=self.new_layer) self.buttons.append(self.newlayer_button) self.grass_button = ImageButton( (16, 19 * 16), TILE_GRASS, image_path=[ASSETS_DIRECTORY, "grass.png"]) self.buttons.append(self.grass_button) self.dirt_variant_button = ImageButton( (16, 20 * 16), TILE_DIRT_VARIANT, image_path=[ASSETS_DIRECTORY, "dirt-variant.png"]) self.buttons.append(self.dirt_variant_button) self.dirt_button = ImageButton( (16, 21 * 16), TILE_DIRT, image_path=[ASSETS_DIRECTORY, "dirt.png"]) self.buttons.append(self.dirt_button) self.barrel_button = ImageButton( (32, 19 * 16), TILE_BARREL, image_path=[ASSETS_DIRECTORY, "barrel.png"]) self.buttons.append(self.barrel_button) self.crate_button = ImageButton( (32, 20 * 16), TILE_CRATE, image_path=[ASSETS_DIRECTORY, "crate.png"]) self.buttons.append(self.crate_button) self.general_store = Interacter((4 * 16, 3 * 16), (7 * 16, 19 * 16), on_interact=self.building_select, name="general-shop.png") self.gun_store = Interacter((4 * 16, 3 * 16), (11 * 16, 19 * 16), on_interact=self.building_select, name="gun-shop.png") self.saloon = Interacter((3 * 16, 3 * 16), (15 * 16, 19 * 16), on_interact=self.building_select, name="saloon.png") self.side_store = Interacter((4 * 16, 3 * 16), (18 * 16, 19 * 16), on_interact=self.building_select, name="side-shop.png") self.interactors = [ self.general_store, self.gun_store, self.saloon, self.side_store ] def resume(self): self.screen = pygame.display.set_mode((800, 432)) self.running = True self.mainloop() return self.global_config def pause(self): pygame.mixer.pause() self.screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT)) self.running = False def place_object(self): pos = pygame.mouse.get_pos() tile_x = (pos[0] + self.x_offset) // 16 tile_y = pos[1] // 16 print(f"{tile_x}, {tile_y}") try: # TODO rewrite to handle this in gamemap self.GameMap.tile_map[tile_x][tile_y] = self.selected_object except IndexError: self.GameMap.extend_map([tile_x, tile_y]) self.GameMap.tile_map[tile_x][tile_y] = self.selected_object def load_map(self): filename = file_loader(self.screen) self.GameMap = GameMap(filename) self.filename_input.text = filename self.filename_input.refresh() def save_map(self): name = self.filename_input.text self.GameMap.save_map(name) self.global_config.default_world = name def new_layer(self): pass def quickplay(self): self.GameMap.save_map("tempmap.json") WorldRunner(self.screen, self.global_config).resume(gamemap="tempmap.json") self.screen = pygame.display.set_mode((800, 432)) pygame.mixer.pause() def building_select(self, name): fp = [ASSETS_DIRECTORY, BUILDINGS_DIRECTORY, name] self.selected_object = Tile(fp, category="building") def mainloop(self): while self.running: self.screen.fill((0, 255, 255)) self.GameMap.render(self.screen, (self.x_offset, 0), debug=self.debug) # gui stuff self.screen.blit(self.gui_image, (0, 18 * 16)) for button in self.buttons: self.screen.blit(button.surf, button.rect) self.screen.blit(self.filename_input.text_surface, self.filename_input.rect) curs_posx, curs_posy = pygame.mouse.get_pos() curs_pos = (curs_posx, curs_posy) # self.screen.blit(self.title_font.render("West of Here", 1, (255, 255, 255)), (46, 60)) # render in where the selected tile would be placed if curs_pos[1] < 288: # don't want it interefering with the gui tile_x = ((curs_posx + self.x_offset) // 16) self.screen.blit(self.selected_object.image, ((tile_x * 16) - self.x_offset, (curs_pos[1] // 16) * 16)) # render a cursor pygame.mouse.set_visible(False) self.screen.blit( CURSOR_IMG, (curs_pos[0] - 3, curs_pos[1] - 3)) # offset to make mouse pointer line up with cursor centre # EVENT HANDLING for event in pygame.event.get(): if event.type == KEYDOWN: self.filename_input.update(event) if event.key == K_ESCAPE: self.global_config.next_game = "mainmenu" self.pause() if event.key == K_UP: self.debug = False if self.debug else True # this will become "interact" key for entering doors if event.key == K_6: self.selected_object = Tile( ["assets", "buildings", "general-shop.png"], category="building") if event.key == K_7: self.GameMap.player_location = curs_posx + self.x_offset else: obj_num = num_from_keypress(event.key) if obj_num: if obj_num == 1: name = self.filename_input.text self.GameMap.save_map(name) self.global_config.default_world = name elif obj_num == 2: pygame.image.save(self.screen, "testsc.png") elif event.type == QUIT: self.global_config.game_running = False self.pause() keys = pygame.key.get_pressed() if keys[K_LEFT]: self.x_offset -= 4 if keys[K_RIGHT]: self.x_offset += 4 if pygame.mouse.get_pressed()[0] or pygame.mouse.get_pressed()[2]: if curs_pos[1] < 288: self.place_object() else: if self.filename_input.rect.collidepoint(curs_pos): self.filename_input.active = True else: self.filename_input.active = False for button in self.buttons: if button.rect.collidepoint(curs_pos): if button.image_path: if pygame.mouse.get_pressed()[0]: self.selected_object = Tile( button.image_path, surf=button.surf, category="none") print("not interactable block") else: self.selected_object = Tile( button.image_path, surf=button.surf, category="none", interactable=True) print("making blockinteractable") else: button.on_click() for interacter in self.interactors: if interacter.rect.collidepoint(curs_pos): interacter.on_interact() pygame.display.flip()
class MainMenu: def __init__(self, screen, global_config): self.screen = screen self.global_config = global_config self.running = True self.first_start = True self.buttons = [] self.start_button = Button("play", self.start_game) self.buttons.append(self.start_button) self.settings_button = Button("create", self.start_maker) self.buttons.append(self.settings_button) self.selected_button = None self.GameMap = GameMap("menu_town.json") def resume(self): self.running = True self.mainloop() return self.global_config def pause(self): pygame.mixer.pause() self.running = False def start_maker(self): self.global_config.next_game = "westernmaker" self.pause() def start_game(self): self.global_config.next_game = "gameselect" self.pause() def handle_event(self, event): if event.type == KEYDOWN: if event.key == K_ESCAPE: self.running = False elif event.type == QUIT: self.global_config.game_running = False self.running = False elif event.type == pygame.MOUSEBUTTONUP: if event.button == 1: if self.selected_button: self.selected_button.on_hit() def mainloop(self): while self.running: self.GameMap.render(self.screen) pygame.mouse.set_visible(False) curs_pos = pygame.mouse.get_pos() self.screen.blit( CURSOR_IMG, (curs_pos[0] - 3, curs_pos[1] - 3)) # offset to make mouse pointer line up with cursor centre for button in self.buttons: if button.rect.collidepoint(curs_pos): button.update_highlight("on") self.selected_button = button break else: button.update_highlight("off") self.selected_button = None # menu rendering self.screen.blit( FONT_TITLE.render("West of Here", 1, (255, 255, 255)), (46, 60)) self.start_button.rect.center = (SCREEN_WIDTH * 0.75, SCREEN_HEIGHT - (SCREEN_HEIGHT * 0.08)) self.screen.blit(self.start_button.button_surface, self.start_button.rect) self.settings_button.rect.center = (SCREEN_WIDTH * 0.25, SCREEN_HEIGHT - (SCREEN_HEIGHT * 0.08)) self.screen.blit(self.settings_button.button_surface, self.settings_button.rect) # EVENT HANDLING for event in pygame.event.get(): self.handle_event(event) pygame.display.flip()
class GameModeSelect: def __init__(self, screen, global_config): self.screen = screen self.global_config = global_config self.running = True self.GameMap = GameMap("menu_town.json") self.button_spacing = 5 self.buttons = [] self.settings_button = Button("World Runner", self.start_game) self.buttons.append(self.settings_button) self.play_treasure = Button("Treasure Protect", self.start_treasure) self.buttons.append(self.play_treasure) self.play_typeduel = Button("Type Duel!", self.start_typeduel) self.buttons.append(self.play_typeduel) self.selected_button = None self.setup_buttons() def setup_buttons(self): total_height = 0 if self.buttons: total_height += len( self.buttons) * self.buttons[0].button_surface.get_height( ) # this only works if all buttons same height total_height += (len(self.buttons) - 1) * self.button_spacing start_height = ((SCREEN_HEIGHT - total_height) // 2) for i in range(0, len(self.buttons)): y_val = start_height + ( i * (self.buttons[i].button_surface.get_height() + 5)) x_val = (SCREEN_WIDTH - self.buttons[i].button_surface.get_width()) // 2 self.buttons[i].rect.midleft = (x_val, y_val) def resume(self): self.global_config.next_game = "mainmenu" self.running = True self.mainloop() return self.global_config def pause(self): pygame.mixer.pause() self.running = False def start_game(self): self.global_config.next_game = "worldrunner" self.pause() def start_treasure(self): self.global_config.next_game = "treasureprotect" self.pause() def start_typeduel(self): self.global_config.next_game = "typeduel" self.pause() def handle_event(self, event): if event.type == KEYDOWN: if event.key == K_ESCAPE: self.running = False elif event.type == QUIT: self.global_config.game_running = False self.running = False elif event.type == pygame.MOUSEBUTTONUP: if event.button == 1: if self.selected_button: self.selected_button.on_hit() def mainloop(self): while self.running: self.GameMap.render(self.screen) pygame.mouse.set_visible(False) curs_pos = pygame.mouse.get_pos() self.screen.blit( CURSOR_IMG, (curs_pos[0] - 3, curs_pos[1] - 3)) # offset to make mouse pointer line up with cursor centre for button in self.buttons: if button.rect.collidepoint(curs_pos): button.update_highlight("on") self.selected_button = button break else: button.update_highlight("off") self.selected_button = None for button in self.buttons: self.screen.blit(button.button_surface, button.rect) # EVENT HANDLING for event in pygame.event.get(): self.handle_event(event) pygame.display.flip()
class WesternMaker(WesternMakerGUI): def __init__(self, screen, global_config): super(WesternMaker, self).__init__() self.screen = None self.global_config = global_config self.running = False self.offset = [0, 0] self.GameMap = GameMap() @staticmethod def get_tile_positions(coords): """ Returns the X and Y tile coordinates are inside of """ return coords[0] // 16, coords[1] // 16 def get_adjusted_mouse_pos(self): """ Returns the mouse position adjusted for the offset of the screen """ real_pos = pygame.mouse.get_pos() adjusted = (real_pos[0] + self.offset[0], real_pos[1] + self.offset[1]) return adjusted def resume(self): self.screen = pygame.display.set_mode((800, 432)) self.running = True self.mainloop() return self.global_config def pause(self): self.screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT)) self.running = False def handle_event(self, event): if event.type == pygame.KEYDOWN: self.filename_input.update(event) if event.key == pygame.K_ESCAPE: self.global_config.next_game = "mainmenu" self.pause() elif event.type == pygame.QUIT: self.global_config.game_running = False self.running = False def on_click_screen(self): curs_pos = self.get_adjusted_mouse_pos() tilepos = self.get_tile_positions(curs_pos) if "TILE" in self.selected_object.id: self.GameMap.place_tile( tilepos, self.selected_object, "BASE") # replace this with layer selection later else: self.GameMap.add_entity(self.selected_object.name, self.get_adjusted_mouse_pos() ) # give more options to pass stuff here def save_map(self): name = self.filename_input.text self.GameMap.save_map(name) self.global_config.default_world = name def quickplay(self): self.GameMap.save_map("tempmap.json") WorldRunner(self.screen, self.global_config).resume(gamemap="tempmap.json") self.screen = pygame.display.set_mode((800, 432)) pygame.mixer.pause() def mainloop(self): while self.running: self.screen.fill((0, 255, 255)) self.GameMap.render(self.screen, self.offset) gui_surf = self.get_gui_surf() self.screen.blit(gui_surf, (0, SCREEN_HEIGHT)) curs_pos = pygame.mouse.get_pos() if curs_pos[ 1] < 288 and "TILE" in self.selected_object.id and self.selected_object.image: # render where the tile would go if placed tile_x = ((curs_pos[0] + self.offset[0]) // 16) self.screen.blit(self.selected_object.image, ((tile_x * 16) - self.offset[0], (curs_pos[1] // 16) * 16)) pygame.mouse.set_visible(False) self.screen.blit(CURSOR_IMG, (curs_pos[0] - 3, curs_pos[1] - 3)) for event in pygame.event.get(): self.handle_event(event) # Handle offset keys = pygame.key.get_pressed() if keys[pygame.K_LEFT]: self.offset[0] -= 4 elif keys[pygame.K_RIGHT]: self.offset[0] += 4 mouse_state = pygame.mouse.get_pressed() if mouse_state[0]: if curs_pos[1] < SCREEN_HEIGHT: self.on_click_screen() else: self.on_click_gui() pygame.display.flip()