Pygame resizable window when game is not active

Question:

How can I make the window in my game resizable only when the game is not active, when self.stats.game_active is False in my code.
This is how i’m setting the window in the init of the main class:

def __init__(self):
    """Initialize the game, and create game resources."""
    pygame.init()
    self.clock = pygame.time.Clock()
    self.settings = Settings()
    self.screen = pygame.display.set_mode((1250, 660), pygame.RESIZABLE)
    self.settings.screen_width = self.screen.get_rect().width
    self.settings.screen_height = self.screen.get_rect().height

And this is my run_game method:

def run_game(self):
    """Main loop for the game."""
    running = True
    i = 0
    while running:
        if not self.paused:  # check if the game is paused
            if self.stats.level <= 1:
                self.bg_img = self.reset_bg
            elif self.stats.level == 4:
                self.bg_img = self.second_bg
            elif self.stats.level >= 6:
                self.bg_img = self.third_bg
            self.screen.blit(self.bg_img, [0,i])
            self.screen.blit(self.bg_img, [0, i  - self.settings.screen_height])
            if i >= self.settings.screen_height:
                i = 0
            i += 1

            self.check_events()
            self._check_game_over()

            if self.stats.game_active:
                if self.stats.level >= 7:
                    self._create_asteroids()
                    self._update_asteroids()
                    self._check_asteroids_collisions()

                self._create_power_ups()
                self._update_power_ups()
                self._create_alien_bullets(3)
                self._update_alien_bullets()
                self._check_alien_bullets_collisions()
                self._check_power_ups_collisions()
                self._update_bullets()
                self._update_aliens()
                self.first_player_ship.update()
                self.second_player_ship.update()
                self._shield_collisions(self.ships, self.aliens,
                                         self.alien_bullet, self.asteroids)

            self._update_screen()
            self.clock.tick(60)

        self._check_for_pause()

When self.stats.game_active is True, I want the window to not be resizable.

Or it would be better to add a list of resolutions from which the player can choose instead of letting the window to be resizable.

Asked By: Ake

||

Answers:

def run_game(self):
  """Main loop for the game."""
  running = True
  i = 0
  while running:
      if not self.paused:  # check if the game is paused
          if self.stats.level <= 1:
              self.bg_img = self.reset_bg
          elif self.stats.level == 4:
              self.bg_img = self.second_bg
          elif self.stats.level >= 6:
              self.bg_img = self.third_bg
          self.screen.blit(self.bg_img, [0,i])
          self.screen.blit(self.bg_img, [0, i  - self.settings.screen_height])
          if i >= self.settings.screen_height:
              i = 0
          i += 1

          self.check_events()
          self._check_game_over()

          if self.stats.game_active:
              if self.stats.level >= 7:
                  self._create_asteroids()
                  self._update_asteroids()
                  self._check_asteroids_collisions()

              self._create_power_ups()
              self._update_power_ups()
              self._create_alien_bullets(3)
              self._update_alien_bullets()
              self._check_alien_bullets_collisions()
              self._check_power_ups_collisions()
              self._update_bullets()
              self._update_aliens()
              self.first_player_ship.update()
              self.second_player_ship.update()
              self._shield_collisions(self.ships, self.aliens,
                                          self.alien_bullet, self.asteroids)

          self._update_screen()

          # set the resizable flag only when the game is not active
          if not self.stats.game_active and not self.resizable:
              pygame.display.set_mode((1250, 660), pygame.RESIZABLE)
              self.resizable = True
          elif self.stats.game_active and self.resizable:
              pygame.display.set_mode((1250, 660))
              self.resizable = False

          self.clock.tick(60)

      self._check_for_pause()
Answered By: NoobCoder

A window can be either RESIZABLE, or not resizable, but it can’t be both at once. You have 2 options:

  1. You can resize the window back to its original size if you don’t want it to be resized.

  2. You can create a new window, every time the state of self.stats.game_active changes:

    self.screen = pygame.display.set_mode(
                      self.screen.get_size(),
                      pygame.RESIZABLE if self.stats.game_active else 0)
    

In the first solution, the window is always resizable, but jumps back to its original size if resizing is not allowed. With the 2nd solution, the window alternates between resizable and not resizable. This causes flickering when the new window is created.


Minimal example for option 1:

import pygame

pygame.init()
window = pygame.display.set_mode((400, 400), pygame.RESIZABLE)
clock = pygame.time.Clock()

window_size = window.get_size()
allow_resize = False

run = True
while run:
    clock.tick(100)
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False 

        if event.type == pygame.KEYDOWN:
            allow_resize = not allow_resize

        if event.type == pygame.VIDEORESIZE:
            new_window_size = event.size if allow_resize else window_size
            window = pygame.display.set_mode(new_window_size, pygame.RESIZABLE)
            window_size = window.get_size()

    window.fill(0)
    pygame.draw.circle(window, (255, 0, 0), window.get_rect().center, 100)
    pygame.display.flip()

pygame.quit()
exit()

Minimal example for option 2:

import pygame

pygame.init()
window = pygame.display.set_mode((400, 400))
clock = pygame.time.Clock()

allow_resize = False

run = True
while run:
    clock.tick(100)
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False 

        if event.type == pygame.KEYDOWN:
            allow_resize = not allow_resize
            pygame.display.set_mode(window.get_size(), pygame.RESIZABLE if allow_resize else 0)

    window.fill(0)
    pygame.draw.circle(window, (255, 0, 0), window.get_rect().center, 100)
    pygame.display.flip()

pygame.quit()
exit()
Answered By: Rabbid76

I solved it by creating this method and calling it before checking if self.stats.game_active in the run_game method:

def _check_for_resize(self):
    info = pygame.display.Info()
    if not self.stats.game_active and not self.resizable:
        pygame.display.set_mode((info.current_w, info.current_h), pygame.RESIZABLE)
        self.resizable = True
    elif self.stats.game_active and self.resizable:
        pygame.display.set_mode((info.current_w, info.current_h))
        self.resizable = False
Answered By: Ake
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.