androidpythonpygamepysdl2

Python - Black screen afther re-opening pygame application


I created a simple tile based game with python pygame and the android subset. When I exit the app on my android device and I re-open it I see a black screen, if I close the program form the 'tabs' then the game will work again, does anybody know what's the problem? Do I have to add some code in the program?

from pygame.locals import *
from settings import *
from sprites import *
import pygame
import time
import sys
import os

try:
    import pygame_sdl2
    pygame_sdl2.import_as_pygame()
except ImportError:
    pass

pygame.init()
pygame.display.set_caption(TITLE)

class Game:

    def __init__(self):
        self.clock = pygame.time.Clock()
        self.screen = pygame.display.set_mode((WIDTH, HEIGHT))

        self.up_button = pygame.Rect(1000, 400, 100, 100)
        self.down_button = pygame.Rect(1000, 600, 100, 100)
        self.right_button = pygame.Rect(1100, 500, 100, 100)
        self.left_button = pygame.Rect(900, 500, 100, 100)

        self.all_sprites = pygame.sprite.Group()
        self.walls = pygame.sprite.Group()
        self.player = Player(self, 2, 2)

        for x in range(5, 10):
            Wall(self, x, 3)
        for x in range(5, 10):
            Wall(self, x, 7)
        for y in range(3, 8):
            Wall(self, 10, y)

        self.buttons = pygame.sprite.Group()
        self.game_over = False

    def update(self):
        self.all_sprites.update()

    def draw(self):
        self.screen.fill(BLACK)
        self.draw_grid()
        self.all_sprites.draw(self.screen)
        pygame.draw.rect(self.screen, GREEN, self.up_button)
        pygame.draw.rect(self.screen, RED, self.down_button)
        pygame.draw.rect(self.screen, BLUE, self.right_button)
        pygame.draw.rect(self.screen, YELLOW, self.left_button)
        pygame.display.update()

    def events(self):
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()
            elif event.type == KEYDOWN:
                if event.key == K_ESCAPE:
                    pygame.quit()
                    sys.exit()
            elif event.type == MOUSEBUTTONDOWN:
                mouse_pos = pygame.mouse.get_pos()
                if self.up_button.collidepoint(mouse_pos):
                    self.player.move(dy = -1)
                elif self.down_button.collidepoint(mouse_pos):
                    self.player.move(dy = 1)
                elif self.right_button.collidepoint(mouse_pos):
                    self.player.move(dx = 1)
                elif self.left_button.collidepoint(mouse_pos):
                    self.player.move(dx = -1)

    def run(self):
        self.title_menu()
        while not self.game_over:
            self.clock.tick(FPS)
            self.events()
            self.update()
            self.draw()

    def draw_grid(self):
        for x in range(0, WIDTH, TILESIZE):
            pygame.draw.line(self.screen, LIGHTGRAY, (x, 0), (x, HEIGHT))
        for y in range(0, HEIGHT, TILESIZE):
            pygame.draw.line(self.screen, LIGHTGRAY, (0, y), (WIDTH, y))

    def title_menu(self):
        pass

if __name__ == '__main__':
    game = Game()
    game.run()

Solution

  • For some reasons that I don't really understand, it looks like the reference to the screen (that you stored in the screen property of your Game object) is lost after the Android main Activity loses the focus. One possible reason might be related to the EGL Context Lost, although I don't have significant elements to confirm this hypothesis.

    Despite the reasons causing this issue, I think I've found a solution to it. First, you need to catch the event when the app is coming back to foreground (check this answer for more details about how to do this by means of specific SDL2 events), and then restore the screen reference.

    Here is what worked for me, applied to your events method:

    def events(self):
        for event in pygame.event.get():
            if event.type == 261:
                # 261 is SDL_APP_WILLENTERFOREGROUND event code
                self.screen = pygame.display.set_mode((WIDTH, HEIGHT))
    
            # ...