def handle_debug_commands(self): if inputs.get_instance().was_pressed(keybinds.get_instance().get_keys( const.TOGGLE_PLAYER_TYPE)): self._do_debug_player_type_toggle() if inputs.get_instance().was_pressed(keybinds.get_instance().get_keys( const.TOGGLE_SHOW_LIGHTING)): showing = gs.get_instance().get_settings().get( gs.Settings.SHOW_LIGHTING) gs.get_instance().get_settings().set(gs.Settings.SHOW_LIGHTING, not showing)
def get_user_friendly_misc_keys(self): """ returns: reset_key, hard_reset_key, pause_key, mute_key, fullscreen_key""" keysets = [ keybinds.get_instance().get_keys( const.SOFT_RESET).get_pretty_names(), keybinds.get_instance().get_keys(const.RESET).get_pretty_names(), keybinds.get_instance().get_keys( const.MENU_CANCEL).get_pretty_names(), keybinds.get_instance().get_keys( const.TOGGLE_MUTE).get_pretty_names(), ["F4"], # XXX this one is kinda weird... ] return [(s[0] if len(s) > 0 else "") for s in keysets]
def update(self): if len(self.options) == 0: return # probably not initialized yet if self.is_focused(): if inputs.get_instance().was_pressed( keybinds.get_instance().get_keys(const.MENU_UP)): self.set_selected_idx( (self.selected_idx - 1) % len(self.options)) if inputs.get_instance().was_pressed( keybinds.get_instance().get_keys(const.MENU_DOWN)): self.set_selected_idx( (self.selected_idx + 1) % len(self.options)) opt_idx_at_mouse_xy = None if inputs.get_instance().mouse_in_window(): mouse_xy = inputs.get_instance().mouse_pos() opt_idx_at_mouse_xy = self.get_option_idx_at(mouse_xy, absolute=True) if opt_idx_at_mouse_xy is not None and ( inputs.get_instance().mouse_moved() or self.ticks_alive <= 1): self.set_selected_idx(opt_idx_at_mouse_xy) did_activation = False if inputs.get_instance().was_pressed( keybinds.get_instance().get_keys(const.MENU_CANCEL)): if self._esc_option is not None: did_activation = self._try_to_activate_option( self._esc_option) if inputs.get_instance().was_pressed( keybinds.get_instance().get_keys(const.MENU_ACCEPT)): if not did_activation and 0 <= self.selected_idx < len( self.options): did_activation = self._try_to_activate_option( self.options[self.selected_idx]) if inputs.get_instance().mouse_was_pressed(button=1): if not did_activation and opt_idx_at_mouse_xy is not None and self.ticks_alive >= 5: did_activation = self._try_to_activate_option( self.options[opt_idx_at_mouse_xy]) self.update_sprites()
def get_user_friendly_movement_keys(self): """ returns: [wasd_keys, arrow_keys, alt_jump_key]""" jump_keys = keybinds.get_instance().get_keys( const.JUMP).get_pretty_names() left_keys = keybinds.get_instance().get_keys( const.MOVE_LEFT).get_pretty_names() down_keys = keybinds.get_instance().get_keys( const.CROUCH).get_pretty_names() right_keys = keybinds.get_instance().get_keys( const.MOVE_RIGHT).get_pretty_names() # XXX this relies on keybindings not using modifiers or keys with long names, but whatever res = ["", "", ""] for i, s in enumerate(res): for keyset in [jump_keys, left_keys, down_keys, right_keys]: if i < len(keyset): res[i] = res[i] + keyset[i] return res
def is_held(self, key): """:param key - Binding, single key, or list of keys""" if isinstance(key, list) or isinstance(key, tuple): return any(map(lambda k: self.is_held(k), key)) elif isinstance(key, keybinds.Binding): return key.is_held(self) elif isinstance(key, int): return key in self._held_keys elif isinstance(key, str): binding = keybinds.get_instance().get_binding_or_none(key) return binding is not None and binding.is_held(self) else: raise ValueError("Unrecognized key type: {}".format(key))
def time_held(self, key): """:param key - Binding, single key, or list of keys""" if isinstance(key, list) or isinstance(key, tuple): return max(map(lambda k: self.time_held(k), key)) elif isinstance(key, keybinds.Binding): return key.time_held(self) elif isinstance(key, int) or (isinstance(key, str) and key.startswith("MOUSE_BUTTON")): if key not in self._held_keys: return -1 else: return self._current_time - self._held_keys[key] elif isinstance(key, str): binding = keybinds.get_instance().get_binding_or_none(key) return binding is not None and binding.time_held(self) else: raise ValueError("Unrecognized key type: {}".format(key))
def was_pressed(self, key): """:param key - Binding, single key, the id of a binding, or a list/tuple of any of these""" if isinstance(key, list) or isinstance(key, tuple): for k in key: if self.was_pressed(k): return True return False elif isinstance(key, keybinds.Binding): return key.was_pressed(self) elif isinstance(key, int) or (isinstance(key, str) and key.startswith("MOUSE_BUTTON")): # it's a single key, hopefully return key in self._pressed_this_frame and self._pressed_this_frame[ key] > 0 elif isinstance(key, str): binding = keybinds.get_instance().get_binding_or_none(key) return binding is not None and binding.was_pressed(self) else: raise ValueError("Unrecognized key type: {}".format(key))
id_resolver=lookup), DialogFragment( "Deep down, you know what must be done. The choice is yours, A, B, C, and D.", speaker=Speaker.NONE, id_resolver=lookup)) else: return DialogFragment("I have nothing to say.", speaker=Speaker.OTHER, id_resolver=lookup) REPLACEMENTS = { "{MOVEMENT_KEYS}": lambda: gs.get_instance().get_user_friendly_movement_keys(), "{INTERACT_KEYS}": lambda: keybinds.get_instance().get_keys(const.ACTION).get_pretty_names(), "{JUMP_KEYS}": lambda: keybinds.get_instance().get_keys(const.JUMP).get_pretty_names(), "{PLAYER_A}": lambda: playertypes.PlayerTypes.FAST.get_name(), "{PLAYER_B}": lambda: playertypes.PlayerTypes.SMALL.get_name(), "{PLAYER_C}": lambda: playertypes.PlayerTypes.HEAVY.get_name(), "{PLAYER_D}": lambda: playertypes.PlayerTypes.FLYING.get_name() } def replace_placeholders(raw_text: str) -> sprites.TextBuilder: raw_colors = [None] * len(raw_text)
def __init__(self, game): self._game = game self._clock = pygame.time.Clock() self._requested_fullscreen_toggle_this_tick = False self._slo_mo_timer = 0 print("INFO: pygame version: " + pygame.version.ver) print("INFO: initializing sounds...") pygame.mixer.pre_init(44100, -16, 1, 2048) pygame.mixer.init() pygame.init() window_icon = pygame.image.load( util.resource_path("assets/icons/icon_16x16.png")) window_icon.set_colorkey((255, 0, 0)) print("INFO: creating window...") window.create_instance(window_size=configs.default_window_size, min_size=configs.minimum_window_size, opengl_mode=not configs.start_in_compat_mode) window.get_instance().set_caption(configs.name_of_game) window.get_instance().set_icon(window_icon) window.get_instance().show() glsl_version_to_use = None if window.get_instance().is_opengl_mode(): # make sure we can actually support OpenGL glsl_version_to_use = renderengine.check_system_glsl_version( or_else_throw=False) if glsl_version_to_use is None: window.get_instance().set_opengl_mode(False) print("INFO: creating render engine...") render_eng = renderengine.create_instance(glsl_version_to_use) render_eng.init(*configs.default_window_size) render_eng.set_min_size(*configs.minimum_window_size) inputs.create_instance() keybinds.create_instance() sprite_atlas = spritesheets.create_instance() for sheet in self._game.get_sheets(): sprite_atlas.add_sheet(sheet) atlas_surface = sprite_atlas.create_atlas_surface() # uncomment for fun # import src.utils.artutils as artutils # artutils.rainbowfill(atlas_surface) # uncomment to save out the full texture atlas # pygame.image.save(atlas_surface, "texture_atlas.png") render_eng.set_texture_atlas(atlas_surface) for layer in self._game.get_layers(): renderengine.get_instance().add_layer(layer) px_scale = window.calc_pixel_scale( window.get_instance().get_display_size()) render_eng.set_pixel_scale(px_scale) self._game.initialize() if configs.is_dev: keybinds.get_instance().set_global_action( pygame.K_F1, "toggle profiling", lambda: self._toggle_profiling()) if configs.allow_fullscreen: keybinds.get_instance().set_global_action( pygame.K_F4, "fullscreen", lambda: self._request_fullscreen_toggle())
def run(self): running = True ignore_resize_events_next_tick = False while running: # processing user input events all_resize_events = [] input_state = inputs.get_instance() input_state.pre_update() for py_event in pygame.event.get(): if py_event.type == pygame.QUIT: running = False continue elif py_event.type == pygame.KEYDOWN: input_state.set_key(py_event.key, True, ascii_val=py_event.unicode) keybinds.get_instance().do_global_action_if_necessary( py_event.key) elif py_event.type == pygame.KEYUP: input_state.set_key(py_event.key, False) elif py_event.type in (pygame.MOUSEMOTION, pygame.MOUSEBUTTONDOWN, pygame.MOUSEBUTTONUP): scr_pos = window.get_instance().window_to_screen_pos( py_event.pos) game_pos = util.round_vec( util.mult( scr_pos, 1 / renderengine.get_instance().get_pixel_scale())) input_state.set_mouse_pos(game_pos) if py_event.type == pygame.MOUSEBUTTONDOWN: input_state.set_mouse_down(True, button=py_event.button) elif py_event.type == pygame.MOUSEBUTTONUP: input_state.set_mouse_down(False, button=py_event.button) elif py_event.type == pygame.VIDEORESIZE: all_resize_events.append(py_event) if not pygame.mouse.get_focused(): input_state.set_mouse_pos(None) ignore_resize_events_this_tick = ignore_resize_events_next_tick ignore_resize_events_next_tick = False if self._requested_fullscreen_toggle_this_tick: # TODO I have no idea if this **** is still necessary in pygame 2+ win = window.get_instance() win.set_fullscreen(not win.is_fullscreen()) new_size = win.get_display_size() new_pixel_scale = window.calc_pixel_scale(new_size) if new_pixel_scale != renderengine.get_instance( ).get_pixel_scale(): renderengine.get_instance().set_pixel_scale( new_pixel_scale) renderengine.get_instance().resize(new_size[0], new_size[1], px_scale=new_pixel_scale) # when it goes from fullscreen to windowed mode, pygame sends a VIDEORESIZE event # on the next frame that claims the window has been resized to the maximum resolution. # this is annoying so we ignore it. we want the window to remain the same size it was # before the fullscreen happened. ignore_resize_events_next_tick = True self._requested_fullscreen_toggle_this_tick = False if not ignore_resize_events_this_tick and len( all_resize_events) > 0: last_resize_event = all_resize_events[-1] window.get_instance().set_window_size(last_resize_event.w, last_resize_event.h) display_w, display_h = window.get_instance().get_display_size() new_pixel_scale = window.calc_pixel_scale( (last_resize_event.w, last_resize_event.h)) renderengine.get_instance().resize(display_w, display_h, px_scale=new_pixel_scale) input_state.update() sounds.update() # updates the actual game state still_running = self._game.update() if still_running is False: running = False # draws the actual game state for spr in self._game.all_sprites(): if spr is not None: renderengine.get_instance().update(spr) renderengine.get_instance().set_clear_color( self._game.get_clear_color()) renderengine.get_instance().render_layers() pygame.display.flip() slo_mo_mode = configs.is_dev and input_state.is_held(pygame.K_TAB) target_fps = configs.target_fps if not slo_mo_mode else configs.target_fps // 4 self._wait_until_next_frame(target_fps) globaltimer.inc_tick_count() if globaltimer.get_show_fps(): if globaltimer.tick_count() % 20 == 0: window.get_instance().set_caption_info( "FPS", "{:.1f}".format(globaltimer.get_fps())) elif globaltimer.tick_count() % configs.target_fps == 0: if globaltimer.get_fps( ) < 0.9 * configs.target_fps and configs.is_dev and not slo_mo_mode: print("WARN: fps drop: {} ({} sprites)".format( round(globaltimer.get_fps() * 10) / 10.0, renderengine.get_instance().count_sprites())) if slo_mo_mode: self._slo_mo_timer += 1 elif self._slo_mo_timer > 0: # useful for timing things in the game print("INFO: slow-mo mode ended after {} tick(s)".format( self._slo_mo_timer)) self._slo_mo_timer = 0 self._game.cleanup() print("INFO: quitting game") pygame.quit()
def initialize(self): if configs.is_dev: _update_readme() util.set_info_for_user_data_path(configs.userdata_subdir, "Ghast") keybinds.get_instance().set_binding(const.MOVE_LEFT, [pygame.K_LEFT, pygame.K_a]) keybinds.get_instance().set_binding(const.MOVE_RIGHT, [pygame.K_RIGHT, pygame.K_d]) keybinds.get_instance().set_binding( const.JUMP, [pygame.K_UP, pygame.K_w, pygame.K_SPACE]) keybinds.get_instance().set_binding(const.CROUCH, [pygame.K_DOWN, pygame.K_s]) keybinds.get_instance().set_binding( const.ACTION, [pygame.K_f, pygame.K_j, pygame.K_RETURN]) keybinds.get_instance().set_binding(const.MENU_UP, [pygame.K_UP, pygame.K_w]) keybinds.get_instance().set_binding(const.MENU_DOWN, [pygame.K_DOWN, pygame.K_s]) keybinds.get_instance().set_binding(const.MENU_LEFT, [pygame.K_LEFT, pygame.K_a]) keybinds.get_instance().set_binding(const.MENU_RIGHT, [pygame.K_RIGHT, pygame.K_d]) keybinds.get_instance().set_binding(const.MENU_ACCEPT, [pygame.K_RETURN]) keybinds.get_instance().set_binding(const.MENU_CANCEL, [pygame.K_ESCAPE]) keybinds.get_instance().set_binding( const.RESET, keybinds.Binding(pygame.K_r, mods=pygame.KMOD_SHIFT)) keybinds.get_instance().set_binding(const.SOFT_RESET, [pygame.K_r]) keybinds.get_instance().set_binding(const.TOGGLE_MUTE, [pygame.K_m]) # debug commands keybinds.get_instance().set_binding(const.TOGGLE_SPRITE_MODE_DEBUG, [pygame.K_h]) keybinds.get_instance().set_binding(const.TOGGLE_PLAYER_TYPE, [pygame.K_p]) keybinds.get_instance().set_binding( const.TEST_KEY_1, keybinds.Binding(pygame.K_1, mods=pygame.KMOD_SHIFT)) keybinds.get_instance().set_binding( const.TEST_KEY_2, keybinds.Binding(pygame.K_2, mods=pygame.KMOD_SHIFT)) keybinds.get_instance().set_binding( const.TEST_KEY_3, keybinds.Binding(pygame.K_3, mods=pygame.KMOD_SHIFT)) keybinds.get_instance().set_binding(const.TOGGLE_SHOW_LIGHTING, keybinds.Binding(pygame.K_l)) keybinds.get_instance().set_binding( const.UNLOCK_ALL_DEBUG, keybinds.Binding(pygame.K_u, mods=pygame.KMOD_CTRL)) keybinds.get_instance().set_binding( const.SAVE, keybinds.Binding(pygame.K_s, mods=[pygame.KMOD_CTRL, pygame.KMOD_NONE])) keybinds.get_instance().set_binding( const.SAVE_AS, keybinds.Binding( pygame.K_s, mods=[pygame.KMOD_CTRL, pygame.KMOD_SHIFT, pygame.KMOD_NONE])) # level editor commands keybinds.get_instance().set_binding(const.TOGGLE_SHOW_CAPTION_INFO, [pygame.K_F3]) keybinds.get_instance().set_binding(const.TOGGLE_EDIT_MODE, [pygame.K_F5]) keybinds.get_instance().set_binding(const.TOGGLE_COMPAT_MODE, [pygame.K_F6]) keybinds.get_instance().set_binding( const.MOVE_SELECTION_UP, keybinds.Binding(pygame.K_w, mods=pygame.KMOD_NONE)) keybinds.get_instance().set_binding( const.MOVE_SELECTION_LEFT, keybinds.Binding(pygame.K_a, mods=pygame.KMOD_NONE)) keybinds.get_instance().set_binding( const.MOVE_SELECTION_DOWN, keybinds.Binding(pygame.K_s, mods=pygame.KMOD_NONE)) keybinds.get_instance().set_binding( const.MOVE_SELECTION_RIGHT, keybinds.Binding(pygame.K_d, mods=pygame.KMOD_NONE)) keybinds.get_instance().set_binding(const.MOVE_CAMERA_UP, [pygame.K_UP]) keybinds.get_instance().set_binding(const.MOVE_CAMERA_LEFT, [pygame.K_LEFT]) keybinds.get_instance().set_binding(const.MOVE_CAMERA_DOWN, [pygame.K_DOWN]) keybinds.get_instance().set_binding(const.MOVE_CAMERA_RIGHT, [pygame.K_RIGHT]) keybinds.get_instance().set_binding( const.SHRINK_SELECTION_VERT, keybinds.Binding(pygame.K_w, mods=[pygame.KMOD_SHIFT, pygame.KMOD_NONE])) keybinds.get_instance().set_binding( const.SHRINK_SELECTION_HORZ, keybinds.Binding(pygame.K_a, mods=[pygame.KMOD_SHIFT, pygame.KMOD_NONE])) keybinds.get_instance().set_binding( const.GROW_SELECTION_VERT, keybinds.Binding(pygame.K_s, mods=[pygame.KMOD_SHIFT, pygame.KMOD_NONE])) keybinds.get_instance().set_binding( const.GROW_SELECTION_HORZ, keybinds.Binding(pygame.K_d, mods=[pygame.KMOD_SHIFT, pygame.KMOD_NONE])) keybinds.get_instance().set_binding( const.CYCLE_SELECTION_SUBTYPE_FORWARD, keybinds.Binding(pygame.K_t, mods=pygame.KMOD_NONE)) keybinds.get_instance().set_binding( const.CYCLE_SELECTION_SUBTYPE_BACKWARD, keybinds.Binding(pygame.K_t, mods=[pygame.KMOD_SHIFT, pygame.KMOD_NONE])) keybinds.get_instance().set_binding( const.CYCLE_SELECTION_COLOR_FORWARD, keybinds.Binding(pygame.K_c, mods=pygame.KMOD_NONE)) keybinds.get_instance().set_binding( const.CYCLE_SELECTION_COLOR_BACKWARD, keybinds.Binding(pygame.K_c, mods=[pygame.KMOD_SHIFT, pygame.KMOD_NONE])) keybinds.get_instance().set_binding( const.CYCLE_SELECTION_ART_FORWARD, keybinds.Binding(pygame.K_e, mods=pygame.KMOD_NONE)) keybinds.get_instance().set_binding( const.CYCLE_SELECTION_ART_BACKWARD, keybinds.Binding(pygame.K_e, mods=[pygame.KMOD_SHIFT, pygame.KMOD_NONE])) keybinds.get_instance().set_binding( const.TOGGLE_SELECTION_INVERTED, keybinds.Binding(pygame.K_i, mods=pygame.KMOD_NONE)) keybinds.get_instance().set_binding( const.ADVANCED_EDIT, keybinds.Binding(pygame.K_o, mods=pygame.KMOD_NONE)) keybinds.get_instance().set_binding( const.ADD_POINT, keybinds.Binding(pygame.K_p, mods=pygame.KMOD_NONE)) keybinds.get_instance().set_binding( const.REMOVE_POINT, keybinds.Binding(pygame.K_p, mods=[pygame.KMOD_SHIFT, pygame.KMOD_NONE])) keybinds.get_instance().set_binding( const.CLEAR_POINTS, keybinds.Binding( pygame.K_p, mods=[pygame.KMOD_SHIFT, pygame.KMOD_CTRL, pygame.KMOD_NONE])) keybinds.get_instance().set_binding( const.ROTATE_POINTS_FORWARD, keybinds.Binding(pygame.K_p, mods=[pygame.KMOD_ALT, pygame.KMOD_NONE])) keybinds.get_instance().set_binding( const.ROTATE_POINTS_BACKWARD, keybinds.Binding( pygame.K_p, mods=[pygame.KMOD_ALT, pygame.KMOD_SHIFT, pygame.KMOD_NONE])) keybinds.get_instance().set_binding(const.DECREASE_EDIT_RESOLUTION, [pygame.K_LEFTBRACKET]) keybinds.get_instance().set_binding(const.INCREASE_EDIT_RESOLUTION, [pygame.K_RIGHTBRACKET]) keybinds.get_instance().set_binding(const.OPTION_0, [pygame.K_1]) keybinds.get_instance().set_binding(const.OPTION_1, [pygame.K_2]) keybinds.get_instance().set_binding(const.OPTION_2, [pygame.K_3]) keybinds.get_instance().set_binding(const.OPTION_3, [pygame.K_4]) keybinds.get_instance().set_binding(const.OPTION_4, [pygame.K_5]) keybinds.get_instance().set_binding(const.OPTION_5, [pygame.K_6]) keybinds.get_instance().set_binding(const.OPTION_6, [pygame.K_7]) keybinds.get_instance().set_binding(const.OPTION_7, [pygame.K_8]) keybinds.get_instance().set_binding(const.OPTION_8, [pygame.K_9]) keybinds.get_instance().set_binding(const.OPTION_9, [pygame.K_0]) keybinds.get_instance().set_binding( const.UNDO, keybinds.Binding(pygame.K_z, mods=pygame.KMOD_CTRL)) keybinds.get_instance().set_binding( const.REDO, keybinds.Binding(pygame.K_y, mods=pygame.KMOD_CTRL)) keybinds.get_instance().set_binding( const.DELETE, [pygame.K_DELETE, pygame.K_BACKSPACE]) keybinds.get_instance().set_binding( const.COPY, keybinds.Binding(pygame.K_c, mods=pygame.KMOD_CTRL)) keybinds.get_instance().set_binding( const.PASTE, keybinds.Binding(pygame.K_v, mods=pygame.KMOD_CTRL)) keybinds.get_instance().set_binding( const.CUT, keybinds.Binding(pygame.K_x, mods=pygame.KMOD_CTRL)) keybinds.get_instance().set_binding( const.SELECT_ALL, keybinds.Binding(pygame.K_a, mods=[pygame.KMOD_CTRL, pygame.KMOD_NONE])) keybinds.get_instance().set_binding( const.SELECT_ALL_ONSCREEN, keybinds.Binding( pygame.K_a, mods=[pygame.KMOD_SHIFT, pygame.KMOD_CTRL, pygame.KMOD_NONE])) path_to_cursors = util.resource_path("assets/cursors.png") cursors.init_cursors(path_to_cursors, [(const.CURSOR_DEFAULT, [0, 0, 16, 16], (0, 0)), (const.CURSOR_HAND, [16, 0, 16, 16], (5, 3)), (const.CURSOR_INVIS, [32, 0, 16, 16], (0, 0))]) cursors.set_cursor(const.CURSOR_DEFAULT) globaltimer.set_show_fps(True) gs.get_instance().load_data_from_disk() scenes.set_instance(menus.CircuitsSceneManager(menus.MainMenuScene()))
def get_user_friendly_action_keys(self): """ returns: right_action_key, left_action_key, alt_action_key""" keys = keybinds.get_instance().get_keys( const.ACTION).get_pretty_names() return util.extend_or_empty_list_to_length(keys, 3, lambda: "")