def _handle_global_keybinds(self): if inputs.get_instance().was_pressed(const.TOGGLE_MUTE): is_muted = (gs.get_instance().get_settings().get( gs.Settings.MUTE_MUSIC) and gs.get_instance().get_settings().get( gs.Settings.EFFECTS_VOLUME)) print(f"INFO: {'unmuting' if is_muted else 'muting'} audio") gs.get_instance().get_settings().set(gs.Settings.MUTE_MUSIC, not is_muted) gs.get_instance().get_settings().set(gs.Settings.MUTE_EFFECTS, not is_muted) if inputs.get_instance().was_pressed(const.TOGGLE_SHOW_CAPTION_INFO): win = window.get_instance() print( f"INFO: toggling caption info to {not win.is_showing_caption_info()}" ) win.set_show_caption_info(not win.is_showing_caption_info()) if inputs.get_instance().was_pressed(const.TOGGLE_COMPAT_MODE): win = window.get_instance() if win.is_fullscreen(): win.set_fullscreen(False) print(f"INFO: setting compat mode to {win.is_opengl_mode()}") win.set_opengl_mode(not win.is_opengl_mode())
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 update(self): if self._ui is not None: if inputs.get_instance().mouse_in_window() and inputs.get_instance( ).mouse_was_pressed(button=1): mouse_xy = inputs.get_instance().mouse_pos() self._ui.send_click_to_self_and_kids(mouse_xy, absolute=True, button=1) self._ui.update_self_and_kids() if self._ui is not None and self._ui.current_dialog is None: self._ui = None
def _handle_inputs(self): edits = inputs.get_instance().all_pressed_ascii_keys() text = self.text cursor_pos = self.cursor_pos jump_cursor = inputs.get_instance().was_pressed_two_way( pygame.K_HOME, pygame.K_END) if jump_cursor < 0: cursor_pos = 0 elif jump_cursor > 0: cursor_pos = len(text) move_cursor = 0 if inputs.get_instance().was_pressed_or_held_and_repeated( pygame.K_LEFT) and not inputs.get_instance().is_held( pygame.K_RIGHT): move_cursor = -1 if inputs.get_instance().was_pressed_or_held_and_repeated( pygame.K_RIGHT) and not inputs.get_instance().is_held( pygame.K_LEFT): move_cursor = 1 if move_cursor != 0: cursor_pos = util.bound(cursor_pos + move_cursor, 0, len(text)) if inputs.get_instance().was_pressed_or_held_and_repeated( pygame.K_DELETE): text, cursor_pos = util.apply_ascii_edits_to_text( text, ["~delete~"], cursor_pos=cursor_pos) if not inputs.get_instance().was_pressed( pygame.K_BACKSPACE) and inputs.get_instance( ).was_pressed_or_held_and_repeated(pygame.K_BACKSPACE): # backspace is an ascii character, so if it was pressed this frame it'll be in edits text, cursor_pos = util.apply_ascii_edits_to_text( text, ["\b"], cursor_pos=cursor_pos) # TODO can't hold regular keys to make them repeat if len(edits) > 0: text, cursor_pos = util.apply_ascii_edits_to_text( text, edits, cursor_pos=cursor_pos, max_len=self.char_limit, allowlist=self.allowed_chars) self.text = text self.cursor_pos = cursor_pos
def update(self): if self._next_scene is not None: if self._next_scene_delay <= 0: self._active_scene.about_to_become_inactive() self._active_scene = self._next_scene self._next_scene.became_active() self._next_scene = None self._next_scene_delay = 0 else: self._next_scene_delay -= 1 self._active_scene.update() self._active_scene.update_sprites() if self._active_scene.should_do_cursor_updates( ) and inputs.get_instance().mouse_in_window(): mouse_xy = inputs.get_instance().mouse_pos() cursor_key = self._active_scene.get_cursor_id_at(mouse_xy) cursors.set_cursor(cursor_key)
def _handle_debug_inputs(self): zoom_change = 0 if inputs.get_instance().was_pressed(pygame.K_MINUS): zoom_change -= 1 if inputs.get_instance().was_pressed(pygame.K_EQUALS): zoom_change += 1 if zoom_change != 0: self.adjust_base_zoom(zoom_change) if inputs.get_instance().was_pressed(pygame.K_f): self._free_camera = not self._free_camera print("INFO: toggled free camera to: {}".format(self._free_camera)) if inputs.get_instance().was_pressed(pygame.K_g): self._show_grid = not self._show_grid print("INFO: toggled grid to: {}".format(self._show_grid)) if inputs.get_instance().was_pressed(pygame.K_h): gs.get_instance().debug_render = not gs.get_instance().debug_render print("INFO: toggled debug sprites to: {}".format( gs.get_instance().debug_render))
def update(self): if not self._has_played_sound: self._has_played_sound = True sound_to_play = self.current_dialog.get_sound() sounds.play_sound(sound_to_play) if self._was_clicked_this_frame or inputs.get_instance().was_pressed( (const.ACTION, const.MENU_ACCEPT, const.MENU_CANCEL)): self.handle_dialog_interact() if self.current_dialog is None: sounds.play_sound(soundref.DIALOG_EXIT) self._was_clicked_this_frame = False self.current_dialog_ticks += 1
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 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 update(self): if len(self.entity_sprites) == 0: self.entity_sprites.append( sprites.ImageSprite.new_sprite(DemoGame.ENTITY_LAYER, scale=1)) # player self.entity_sprites.append( sprites.ImageSprite.new_sprite(DemoGame.ENTITY_LAYER, scale=1)) # tv if len(self.wall_sprites) == 0: for pos in self.wall_positions: new_sprite = sprites.ImageSprite( DemoGame.demo_sheet.wall_model, pos[0] * DemoGame.cell_size, pos[1] * DemoGame.cell_size, DemoGame.WALL_LAYER, scale=2) self.wall_sprites.append(new_sprite) if len(self.floor_sprites) == 0: for pos in self.floor_positions: new_sprite = sprites.ImageSprite( DemoGame.demo_sheet.floor_model, pos[0] * DemoGame.cell_size, pos[1] * DemoGame.cell_size, DemoGame.FLOOR_LAYER, scale=2) self.floor_sprites.append(new_sprite) if len(self.shadow_sprites) == 0: for _ in self.entity_sprites: self.shadow_sprites.append( sprites.ImageSprite(DemoGame.demo_sheet.shadow_model, 0, 0, DemoGame.SHADOW_LAYER, scale=1)) if self.triangle_sprite is None: self.triangle_sprite = sprites.TriangleSprite( DemoGame.POLYGON_LAYER, color=(0, 0, 0)) while len(self.cube_line_sprites) < 12: self.cube_line_sprites.append( sprites.LineSprite(DemoGame.POLYGON_LAYER, thickness=self.cube_line_thickness)) anim_tick = globaltimer.tick_count() // 16 speed = 2 dx = 0 new_xflip = None if inputs.get_instance().is_held([pygame.K_a, pygame.K_LEFT]): dx -= speed new_xflip = False elif inputs.get_instance().is_held([pygame.K_d, pygame.K_RIGHT]): dx += speed new_xflip = True dy = 0 if inputs.get_instance().is_held([pygame.K_w, pygame.K_UP]): dy -= speed elif inputs.get_instance().is_held([pygame.K_s, pygame.K_DOWN]): dy += speed player_x = self.entity_positions[0][0] + dx new_y = self.entity_positions[0][1] + dy player_y = max(new_y, int(1.1 * DemoGame.cell_size)) # collision with walls~ self.entity_positions[0] = (player_x, player_y) new_model = DemoGame.demo_sheet.player_models[anim_tick % len( DemoGame.demo_sheet.player_models)] player_sprite = self.entity_sprites[0] player_scale = player_sprite.scale() self.entity_sprites[0] = player_sprite.update( new_model=new_model, new_x=player_x - new_model.width() * player_scale // 2, new_y=player_y - new_model.height() * player_scale, new_xflip=new_xflip, new_depth=-player_y) tv_model = DemoGame.demo_sheet.tv_models[(anim_tick // 2) % len( DemoGame.demo_sheet.tv_models)] tv_x = self.entity_positions[1][0] tv_y = self.entity_positions[1][1] tv_xflip = player_x > tv_x # turn to face player tv_sprite = self.entity_sprites[1] tv_scale = tv_sprite.scale() self.entity_sprites[1] = tv_sprite.update( new_model=tv_model, new_x=tv_x - tv_model.width() * tv_scale // 2, new_y=tv_y - tv_model.height() * tv_scale, new_xflip=tv_xflip, new_depth=-tv_y) for i in range(0, len(self.entity_positions)): xy = self.entity_positions[i] shadow_sprite = self.shadow_sprites[i] shadow_model = self.demo_sheet.shadow_model shadow_x = xy[0] - shadow_sprite.scale() * shadow_model.width() // 2 shadow_y = xy[1] - shadow_sprite.scale() * shadow_model.height( ) // 2 self.shadow_sprites[i] = shadow_sprite.update( new_model=shadow_model, new_x=shadow_x, new_y=shadow_y) min_rot_speed = 0.3 max_rot_speed = 4 if self.triangle_sprite is not None: tri_center = self.triangle_center tri_angle = self.triangle_angle * 2 * 3.141529 / 360 tri_length = self.triangle_length p1 = Utils.add(tri_center, Utils.rotate((tri_length, 0), tri_angle)) p2 = Utils.add( tri_center, Utils.rotate((tri_length, 0), tri_angle + 3.141529 * 2 / 3)) p3 = Utils.add( tri_center, Utils.rotate((tri_length, 0), tri_angle + 3.141529 * 4 / 3)) self.triangle_sprite = self.triangle_sprite.update(new_points=(p1, p2, p3)) player_dist = Utils.dist(self.entity_positions[0], tri_center) if player_dist > 100: rot_speed = min_rot_speed else: rot_speed = Utils.linear_interp(min_rot_speed, max_rot_speed, (100 - player_dist) / 100) self.triangle_angle += rot_speed text_inset = 4 title_text = "Demo Scene" if self.title_text_sprite is None: self.title_text_sprite = sprites.TextSprite( DemoGame.UI_FG_LAYER, 0, text_inset, title_text) title_text_width = self.title_text_sprite.get_size()[0] title_text_x = renderengine.get_instance().get_game_size( )[0] - title_text_width - text_inset self.title_text_sprite = self.title_text_sprite.update( new_x=title_text_x) if self.fps_text_sprite is None: self.fps_text_sprite = sprites.TextSprite(DemoGame.UI_FG_LAYER, text_inset, text_inset, "FPS: 0") fps_text = "FPS: {}".format(int(globaltimer.get_fps())) self.fps_text_sprite = self.fps_text_sprite.update(new_x=text_inset, new_y=text_inset, new_text=fps_text) player_to_tv_dist = Utils.dist(self.entity_positions[0], self.entity_positions[1]) info_text = "There's something wrong with the TV. Maybe it's better this way." if player_to_tv_dist < 32 else None info_text_w = 400 - 32 info_text_h = 48 info_text_rect = [ renderengine.get_instance().get_game_size()[0] // 2 - info_text_w // 2, renderengine.get_instance().get_game_size()[1] - info_text_h - 16, info_text_w, info_text_h ] if info_text is None: self.text_box_text_sprite = None self.text_box_sprite = None else: wrapped_text = "\n".join( sprites.TextSprite.wrap_text_to_fit(info_text, info_text_rect[2])) if self.text_box_text_sprite is None: self.text_box_text_sprite = sprites.TextSprite( DemoGame.UI_FG_LAYER, 0, 0, wrapped_text) self.text_box_text_sprite = self.text_box_text_sprite.update( new_x=info_text_rect[0], new_y=info_text_rect[1], new_text=wrapped_text) if self.text_box_sprite is None: self.text_box_sprite = sprites.BorderBoxSprite( DemoGame.UI_BG_LAYER, info_text_rect, all_borders=DemoGame.demo_sheet.border_models) self.text_box_sprite = self.text_box_sprite.update( new_rect=info_text_rect, new_scale=2) if len(self.cube_line_sprites) == 12: cube_center = self.cube_center cube_angle = self.cube_angle * 2 * 3.141529 / 360 cube_length = self.cube_length cube_color = self.cube_color cube_top_pts = [] cube_btm_pts = [] for i in range(0, 4): dx = cube_length / 2 * math.cos(cube_angle + i * 3.141529 / 2) dy = cube_length / 2 * math.sin( cube_angle + i * 3.141529 / 2) / 2 # foreshortened in the y-axis cube_btm_pts.append(Utils.add(cube_center, (dx, dy))) cube_top_pts.append( Utils.add(cube_center, (dx, dy - cube_length))) for i in range(0, 12): if i < 4: # bottom lines p1 = cube_btm_pts[i % 4] p2 = cube_btm_pts[(i + 1) % 4] elif i < 8: # top lines p1 = cube_top_pts[i % 4] p2 = cube_top_pts[(i + 1) % 4] else: # bottom to top lines p1 = cube_btm_pts[i % 4] p2 = cube_top_pts[i % 4] self.cube_line_sprites[i].update(new_p1=p1, new_p2=p2, new_color=cube_color) player_dist = Utils.dist(self.entity_positions[0], cube_center) if player_dist > 100: rotation_speed = min_rot_speed else: rotation_speed = Utils.linear_interp(min_rot_speed, max_rot_speed, (100 - player_dist) / 100) self.cube_angle += rotation_speed # setting layer positions camera_x = player_x - renderengine.get_instance().get_game_size( )[0] // 2 camera_y = player_y - renderengine.get_instance().get_game_size( )[1] // 2 for layer_id in DemoGame.world_layer_ids: renderengine.get_instance().set_layer_offset( layer_id, camera_x, camera_y)
def run(): clock = pygame.time.Clock() running = True ignore_resize_events_next_tick = False while running: # processing user input events all_resize_events = [] toggled_fullscreen = False input_state = inputs.get_instance() 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) 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 = Utils.round( Utils.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 py_event.type == pygame.KEYDOWN and py_event.key == pygame.K_F4: toggled_fullscreen = True 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 toggled_fullscreen: # print("INFO {}: toggled fullscreen".format(gs.get_instance().tick_counter)) win = window.get_instance() win.set_fullscreen(not win.is_fullscreen()) new_size = win.get_display_size() new_pixel_scale = _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 if not ignore_resize_events_this_tick and len(all_resize_events) > 0: last_resize_event = all_resize_events[-1] print("INFO: resizing to {}, {}".format(last_resize_event.w, last_resize_event.h)) 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 = _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(gs.get_instance().tick_count) sounds.update() if gs.get_instance().is_dev() and input_state.was_pressed(pygame.K_F1): # used to help find performance bottlenecks import src.utils.profiling as profiling profiling.get_instance().toggle() if input_state.was_pressed(pygame.K_F5): current_scale = gs.get_instance().px_scale options = gs.get_instance().px_scale_options if current_scale in options: new_scale = (options.index(current_scale) + 1) % len(options) else: print("WARN: illegal pixel scale={}, reverting to default". format(current_scale)) new_scale = options[0] gs.get_instance().px_scale = new_scale display_size = window.get_instance().get_display_size() new_pixel_scale = _calc_pixel_scale(display_size, px_scale_opt=new_scale) renderengine.get_instance().set_pixel_scale(new_pixel_scale) if input_state.was_pressed(pygame.K_r): print("INFO: restarting game") renderengine.get_instance().clear_all_sprites() # full nuke gs.get_instance().set_game_state(gamestate.GameState()) renderengine.get_instance().set_clear_color((0, 0, 0)) gs.get_instance().update_all() renderengine.get_instance().render_layers() pygame.display.flip() slo_mo_mode = gs.get_instance().is_dev() and input_state.is_held( pygame.K_TAB) if slo_mo_mode: clock.tick(15) else: clock.tick(60) gs.get_instance().tick_count += 1 if gs.get_instance().tick_count % 60 == 0: if clock.get_fps() < 55 and gs.get_instance().is_dev( ) and not slo_mo_mode: print("WARN: fps drop: {} ({} sprites)".format( round(clock.get_fps() * 10) / 10.0, renderengine.get_instance().count_sprites())) print("INFO: quitting game") pygame.quit()
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() 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) 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 = Utils.round( Utils.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 input_state.was_pressed( pygame.K_F4) and configs.allow_fullscreen: win = window.get_instance() win.set_fullscreen(not win.is_fullscreen()) new_size = win.get_display_size() new_pixel_scale = self._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 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 = self._calc_pixel_scale( (last_resize_event.w, last_resize_event.h)) renderengine.get_instance().resize(display_w, display_h, px_scale=new_pixel_scale) if configs.is_dev and input_state.was_pressed(pygame.K_F1): # used to help find performance bottlenecks import src.utils.profiling as profiling profiling.get_instance().toggle() input_state.update() sounds.update() # updates the actual game state self._game.update() # 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(configs.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.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())) print("INFO: quitting game") pygame.quit()