pygame-web / pygbag

python and pygame wasm for everyone ( packager + test server + simulator )
https://github.com/pygame-web
MIT License
295 stars 34 forks source link

my pygame is displaying on localhost:8000 but the death menu doesnt appear, the screen is stuck and doesnt restart the game. #168

Closed brxeee closed 3 weeks ago

brxeee commented 1 month ago

the code runs fine on Pycharm, but i am having problems with trying to figure out why both menus dont appear.

my code:

import pygame
import os
import random
import asyncio

pygame.init()

# Global constants
SCREEN_WIDTH = 1000
SCREEN_HEIGHT = 500
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
GAME_SPEED = 14

RUNNING = [
    pygame.transform.scale(pygame.image.load(os.path.join("Assets/run", "run0.png")), (200, 200)),
    pygame.transform.scale(pygame.image.load(os.path.join("Assets/run", "run2.png")), (200, 200)),
    pygame.transform.scale(pygame.image.load(os.path.join("Assets/run", "run3.png")), (200, 200)),
    pygame.transform.scale(pygame.image.load(os.path.join("Assets/run", "run4.png")), (200, 200))
]
BG_img = pygame.image.load(os.path.join("Assets/background", "BGG.jpg"))
BG = pygame.transform.scale(BG_img, (SCREEN_WIDTH, SCREEN_HEIGHT))
CLOUD_IMG = [
    pygame.transform.scale(pygame.image.load(os.path.join("Assets/cloud", "cloud1.png")), (400, 600)),
    pygame.transform.scale(pygame.image.load(os.path.join("Assets/cloud", "cloud1.png")), (200, 400)),
    pygame.transform.scale(pygame.image.load(os.path.join("Assets/cloud", "cloud1.png")), (400, 200))
]

JUMPING = pygame.transform.scale(pygame.image.load(os.path.join("Assets/jump", "jump1.png")), (200, 200))

DUCKING = [
    pygame.transform.scale(pygame.image.load(os.path.join("Assets/duck", "duck1.png")), (300, 200)),
    pygame.transform.scale(pygame.image.load(os.path.join("Assets/duck", "duck1.png")), (300, 200)),
]

BLACKKITTY = [
    pygame.transform.scale(pygame.image.load(os.path.join("Assets/bad", "bad1.png")), (110, 90)),
    pygame.transform.scale(pygame.image.load(os.path.join("Assets/bad", "bad1.png")), (110, 90)),
]
SMALL_GATOR = [
    pygame.transform.scale(pygame.image.load(os.path.join("Assets/small", "obstacle1.png")), (150, 65)),
    pygame.transform.scale(pygame.image.load(os.path.join("Assets/small", "obstacle1.png")), (150, 65))
]

LARGE_GATOR = [
    pygame.transform.scale(pygame.image.load(os.path.join("Assets/large", "obstacle2.png")), (200, 75)),
    pygame.transform.scale(pygame.image.load(os.path.join("Assets/large", "obstacle2.png")), (200, 75)),
    pygame.transform.scale(pygame.image.load(os.path.join("Assets/large", "obstacle2.png")), (200, 75))
]

class HelloKitty:
    X_POSITION = 80
    Y_POSITION = 307
    Y_POS_DUCK = 340
    JUMP_VELOCITY = 10

    def __init__(self):
        self.run_img = RUNNING
        self.jump_img = JUMPING
        self.duck_img = DUCKING
        self.duck_duck = False
        self.run_run = True
        self.jump_jump = False
        self.step_index = 0
        self.jump_vel = self.JUMP_VELOCITY
        self.image = self.run_img[0]
        self.run_rect = self.image.get_rect()
        self.run_rect.x = self.X_POSITION
        self.run_rect.y = self.Y_POSITION

    def update(self, userInput):
        if self.duck_duck:
            self.duck()
        elif self.run_run:
            self.run()
        elif self.jump_jump:
            self.jump()

        if self.step_index >= len(self.run_img) * 5:
            self.step_index = 0

        if (userInput[pygame.K_UP] or userInput[pygame.K_SPACE]) and not self.jump_jump:
            self.duck_duck = False
            self.jump_jump = True
            self.run_run = False

        if (userInput[pygame.K_DOWN] or userInput[pygame.K_s]) and not self.jump_jump:
            self.duck_duck = True
            self.jump_jump = False
            self.run_run = False
        elif not (userInput[pygame.K_s] or userInput[pygame.K_DOWN]) and not self.jump_jump:
            self.duck_duck = False
            self.run_run = True
            self.jump_jump = False

    def duck(self):
        index = self.step_index // 5
        if index >= len(self.duck_img):
            index = 0
        self.image = self.duck_img[index]
        self.run_rect = self.image.get_rect()
        self.run_rect.x = self.X_POSITION
        self.run_rect.y = self.Y_POS_DUCK
        self.step_index += 1

    def run(self):
        self.image = self.run_img[self.step_index // 5]
        self.run_rect = self.image.get_rect()
        self.run_rect.x = self.X_POSITION
        self.run_rect.y = self.Y_POSITION
        self.step_index += 1

    def jump(self):
        self.image = self.jump_img
        if self.jump_jump:
            self.run_rect.y -= self.jump_vel * 4
            self.jump_vel -= 0.6
            if self.jump_vel < -self.JUMP_VELOCITY:
                self.jump_jump = False
                self.jump_vel = self.JUMP_VELOCITY
                self.run_rect.y = self.Y_POSITION

    def draw(self, screen):
        screen.blit(self.image, (self.run_rect.x, self.run_rect.y))

class Cloud:
    def __init__(self):
        self.x = SCREEN_WIDTH + random.randint(800, 1000)
        self.y = random.randint(50, 100)
        self.image = random.choice(CLOUD_IMG)
        self.width = self.image.get_width()

    def update(self):
        global game_speed
        self.x -= game_speed
        if self.x < -self.width:
            self.x = SCREEN_WIDTH + random.randint(2500, 3000)
            self.y = random.randint(50, 100)

    def draw(self, screen):
        screen.blit(self.image, (self.x, self.y))

class Obstacle:
    def __init__(self, image, type):
        self.image = image
        self.type = type
        self.rect = self.image[self.type].get_rect()
        self.rect.x = SCREEN_WIDTH

    def update(self):
        global obstacles
        self.rect.x -= game_speed
        if self.rect.x < -self.rect.width:
            obstacles.pop(0)

        if isinstance(self, Evil) and self.rect.y > 150:
            self.rect.y -= 1

    def draw(self, screen):
        screen.blit(self.image[self.type], self.rect)

class SmallGator(Obstacle):
    def __init__(self, image):
        if image:
            self.type = random.randint(0, len(image) - 1)
            super().__init__(image, self.type)
            self.rect.y = SCREEN_HEIGHT - self.rect.height - 10

class LargeGator(Obstacle):
    def __init__(self, image):
        if image:
            self.type = random.randint(0, len(image) - 1)
            super().__init__(image, self.type)
            self.rect.y = SCREEN_HEIGHT - self.rect.height - 10

class Evil(Obstacle):
    def __init__(self, image):
        self.type = 0
        super().__init__(image, self.type)
        self.rect.y = 255
        self.index = 0

    def draw(self, screen):
        if self.index >= 9:
            self.index = 0
        screen.blit(self.image[self.index // 5], self.rect)
        self.index += 1

async def main():
    global game_speed, x_pos_bg, y_pos_bg, points, obstacles
    run = True
    clock = pygame.time.Clock()
    player = HelloKitty()
    cloud = Cloud()
    game_speed = 14
    x_pos_bg = 0
    y_pos_bg = 380
    points = 0
    font = pygame.font.Font('freesansbold.ttf', 30)
    obstacles = []
    death_count = 0

    def score():
        global points, game_speed
        points += 1
        if points % 100 == 0:
            game_speed += 1
        text = font.render("Points: " + str(points), True, (0, 0, 0))
        textRect = text.get_rect()
        textRect.center = (SCREEN_WIDTH - 100, 40)
        screen.blit(text, textRect)

    i = 0
    width = 1000

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

        screen.fill((0, 0, 0))
        screen.blit(BG, (i, 0))
        screen.blit(BG, (width + i, 0))
        if i == -width:
            screen.blit(BG, (width + i, 0))
            i = 0
        i -= 1

        userInput = pygame.key.get_pressed()

        player.update(userInput)
        player.draw(screen)

        if len(obstacles) == 0:
            if random.randint(0, 2) == 0:
                obstacles.append(SmallGator(SMALL_GATOR))
            elif random.randint(0, 2) == 1:
                obstacles.append(LargeGator(LARGE_GATOR))
            elif random.randint(0, 2) == 2:
                obstacles.append(Evil(BLACKKITTY))

        for obstacle in obstacles:
            obstacle.draw(screen)
            obstacle.update()
            if player.run_rect.colliderect(obstacle.rect):
                death_count += 1
                run = False
                await menu(death_count)

        cloud.draw(screen)
        cloud.update()

        score()

        clock.tick(50)
        pygame.display.update()

        await asyncio.sleep(0)

async def menu(death_count):
    global points
    run = True

    while run:
        screen.fill((255, 255, 255))
        font = pygame.font.Font('freesansbold.ttf', 30)

        if death_count == 0:
            text = font.render("Press any key to Start", True, (0, 0, 0))
            textRect = text.get_rect()
            textRect.center = (SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2)
            screen.blit(text, textRect)
        elif death_count > 0:
            text = font.render("Press any key to Restart", True, (0, 0, 0))
            score_text = font.render("Your score: " + str(points), True, (0, 0, 0))
            scoreRect = score_text.get_rect()
            scoreRect.center = (SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2 + 50)
            textRect = text.get_rect()
            textRect.center = (SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2)
            screen.blit(text, textRect)
            screen.blit(score_text, scoreRect)

        pygame.display.update()

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                run = False
            if event.type == pygame.KEYDOWN:
                await asyncio.sleep(0)
                await main()

asyncio.run(menu(death_count=0))
pmp-p commented 1 month ago

you should not nest update/sleep loops and use game states instead see https://github.com/pmp-p/pygame-breakout-wasm/ for an example

            if event.type == pygame.KEYDOWN:
                await asyncio.sleep(0)
                await main()

is wrong, the await asyncio.sleep(0) is a critical call that must be made on each frame.

brxeee commented 1 month ago

you should not nest update/sleep loops and use game states instead see https://github.com/pmp-p/pygame-breakout-wasm/ for an example

            if event.type == pygame.KEYDOWN:
                await asyncio.sleep(0)
                await main()

is wrong, the await asyncio.sleep(0) is a critical call that must be made on each frame.

How do i fix it? I’m a beginner with everything.