class LoadingScreen(LoadableWindowView):

    def __init__(self,
                 loaded_view: Optional[LoadableWindowView] = None,
                 loading_text: str = 'Loading',
                 background_name: Optional[str] = None):
        super().__init__()
        self.sprite_list = SpriteList()
        self.loading_text = loading_text
        self.progress = 0
        self.progress_bar = self.create_progress_bar()
        self.loading_background = Sprite(background_name) if \
            background_name is not None else None
        self.sprite_list.extend(
            [e for e in (self.progress_bar, self.loading_background) if e]
        )
        self.set_updated_and_drawn_lists()
        self.loaded_view = loaded_view

    @staticmethod
    def create_progress_bar() -> SpriteSolidColor:
        bar_width = 1
        bar_height = int(SCREEN_HEIGHT * 0.025)
        bar = SpriteSolidColor(bar_width, bar_height, GREEN)
        bar.center_y = SCREEN_HEIGHT / 2
        return bar

    def on_show_view(self):
        super().on_show_view()
        self.window.toggle_mouse_and_keyboard(False)

    def on_update(self, delta_time: float):
        super().on_update(delta_time)
        try:
            progress = getattr(self.loaded_view, 'loading_progress') * 15
            self.update_progress(progress)
            self.loaded_view.on_update(delta_time)
        except AttributeError:
            self.update_progress(delta_time)
        self.update_progress_bar()

    def on_draw(self):
        super().on_draw()
        self.draw_loading_text()

    def draw_loading_text(self):
        text = ' '.join([self.loading_text, str(int(self.progress))])
        draw_text(text, SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2 + 10, WHITE, 20)

    def update_progress(self, update: float):
        self.progress += update
        if self.progress >= 100:
            self.window.show_view(self.loaded_view)

    def update_progress_bar(self):
        progress = self.progress
        self.progress_bar.center_x = center = progress * (SCREEN_WIDTH / 200)
        self.progress_bar.width = 0.01 + center * 2
Beispiel #2
0
class MyGame(arcade.View):
    """
    Main application class.
    """
    def __init__(self, level: int = 1):
        super().__init__()
        self.score: int = 0
        self.level = level
        # These are 'lists' that keep track of our sprites. Each sprite should
        # go into a list.
        self.wall_list = None
        self.wall_counter = 0

        self.bg_list = None
        self.answer_sprites = None
        self.sky_scraper_sprites = None

        # Separate variable that holds the player sprite
        self.player_sprite = None

        self.ui_manager = UIManager()

        # Our physics engine
        self.physics_engine = None

        # Used to keep track of our scrolling
        self.view_bottom = 0
        self.view_left = 0

        self.is_dead = False
        self.won = False
        self.sound = arcade.Sound("sound_files/dying2.mp3", True)
        # keeps track of the player sprite's location from previous frame
        self.player_last_x = 0

        # Initialize equations
        self.equations: List[Equation] = None  # First is current

        # Load sounds
        self.collect_coin_sound = arcade.load_sound(
            ":resources:sounds/coin1.wav")
        self.jump_sound = arcade.load_sound(":resources:sounds/jump1.wav")
        self.courage_sound = arcade.load_sound(
            "sound_files/courage screech.mp3")
        self.dying_sound_1 = arcade.load_sound("sound_files/dying1.mp3")
        self.dying_sound_2 = arcade.load_sound("sound_files/dying2.mp3")
        self.music1 = arcade.load_sound("sound_files/music1.mp3")

        arcade.set_background_color(arcade.csscolor.CORNFLOWER_BLUE)
        self.setup()

    def setup(self):
        self.is_dead = False
        """ Set up the game here. Call this function to restart the game. """
        self.sky_scraper_sprites = SpriteList()
        self.answer_sprites = SpriteList()

        self.equations = []
        for i in range(3):
            self.equations.append(Equation(self.level))

        # Used to keep track of our scrolling
        self.view_bottom = 0
        self.view_left = 0

        # Create the Sprite lists
        self.wall_list = arcade.SpriteList()
        self.bg_list = Background(PLAYER_MOVEMENT_SPEED, self.level)

        # Set up the player, specifically placing it at these coordinates.
        image_source = "assets-target/pixelbird2/"
        self.player_sprite = Bird(image_source, CHARACTER_SCALING)
        self.player_sprite.center_x = 250
        self.player_sprite.center_y = SCREEN_HEIGHT // 2
        self.player_sprite.change_x = PLAYER_MOVEMENT_SPEED

        # Load in walls (invisible)
        self.wall_list = SpriteList()
        wall_offset = STARTING_X_OFFSET + 830
        create_wall_list = lambda x_offset=0: [
            Sprite("stoneMid.png",
                   scale=TILE_SCALING,
                   center_x=wall_offset + x_offset,
                   center_y=SCREEN_HEIGHT // 2 - 100),
            Sprite("stoneMid.png",
                   scale=TILE_SCALING,
                   center_x=wall_offset + x_offset,
                   center_y=SCREEN_HEIGHT // 2 + 100),
        ]
        self.wall_list.extend(create_wall_list())
        self.wall_list.extend(create_wall_list(1250))

        ys = [116, 316, 516]
        values = self.equations[0].answers
        for i in range(3):
            answer = Answer(COIN_SCALING)
            answer.center_x = 920 + STARTING_X_OFFSET
            answer.center_y = ys[i]
            answer.set_number(values[i])
            self.answer_sprites.append(answer)

        # create the sky scrapers
        center_x = STARTING_X_OFFSET + 920 - 1250 * 2
        center_y = SCREEN_HEIGHT // 2
        print([e.answers for e in self.equations])
        for i in range(3):
            values = self.equations[(i - 1) % len(self.equations)].answers
            sky_scraper = SkyScraper(values, id=self.wall_counter)
            self.wall_counter += 1
            sky_scraper.center_x = center_x
            sky_scraper.center_y = center_y
            center_x = sky_scraper.move_forward()
            print("hello!")
            self.sky_scraper_sprites.append(sky_scraper)
            print("sky_scraper_sprites", len(self.sky_scraper_sprites))
            if i == 0:
                # make the first invisible temporarily so it doesn't get in the way
                sky_scraper.scale = 0

        # Create the 'physics engine'
        self.physics_engine = arcade.PhysicsEnginePlatformer(
            self.player_sprite, self.wall_list, 0)

    def on_draw(self):
        """ Render the screen. """

        # Clear the screen to the background color
        arcade.start_render()

        # Draw our sprites
        # self.wall_list.draw()  # invisible
        # self.answer_sprites.draw()  # invisible
        self.bg_list.draw()
        self.sky_scraper_sprites.draw()
        self.player_sprite.draw()
        self.draw_stats()
        w = 200
        h = 60
        arcade.draw_xywh_rectangle_filled(SCREEN_WIDTH // 2 - w // 2 +
                                          self.view_left,
                                          SCREEN_HEIGHT - h,
                                          width=w,
                                          height=h,
                                          color=arcade.color.BLACK)
        arcade.draw_text(self.equations[0].equationUnsolved(),
                         self.view_left + SCREEN_WIDTH // 2,
                         600 + self.view_bottom,
                         arcade.csscolor.WHITE,
                         18,
                         anchor_x="center")

    def on_key_press(self, key, modifiers):
        """Called whenever a key is pressed. """

        if key == arcade.key.UP or key == arcade.key.W:
            self.player_sprite.change_y = PLAYER_MOVEMENT_SPEED
        elif key == arcade.key.DOWN or key == arcade.key.S:
            self.player_sprite.change_y = -PLAYER_MOVEMENT_SPEED
        # elif key == arcade.key.LEFT:
        #     self.player_sprite.change_x = -PLAYER_MOVEMENT_SPEED
        # elif key == arcade.key.RIGHT:
        #     self.player_sprite.change_x = PLAYER_MOVEMENT_SPEED

    def on_key_release(self, key, modifiers):
        """Called when the user releases a key. """

        if key == arcade.key.UP or key == arcade.key.W:
            self.player_sprite.change_y = 0
        elif key == arcade.key.DOWN or key == arcade.key.S:
            self.player_sprite.change_y = 0
        # elif key == arcade.key.LEFT:
        #     self.player_sprite.change_x = 0
        # elif key == arcade.key.RIGHT:
        #     self.player_sprite.change_x = 0

    def on_update(self, delta_time: float):

        # --- Manage Animations ---
        self.player_sprite.on_update(delta_time)

    def update(self, delta_time):
        if self.is_dead:
            print("CANCEELED")
            return
        """ Movement and game logic """
        # Stop the player from leaving the screen
        if self.player_sprite.center_y > 600:
            self.player_sprite.change_y = 0
            self.player_sprite.center_y = 599
        elif self.player_sprite.center_y < 25:
            self.player_sprite.change_y = 0
            self.player_sprite.center_y = 26

        # record the player's last location to get their true speed
        self.player_last_x = self.player_sprite.center_x

        # Move the player with the physics engine
        self.physics_engine.update()

        # get player's speed and update backgrounds
        player_speed = self.player_sprite.center_x - self.player_last_x
        self.bg_list.update(player_speed, self.player_sprite.center_x)

        # --- Manage Scrolling ---

        changed = False

        # Scroll left
        left_boundary = self.view_left + LEFT_VIEWPORT_MARGIN
        if self.player_sprite.left < left_boundary:
            self.view_left -= left_boundary - self.player_sprite.left
            changed = True

        # Scroll right
        right_boundary = self.view_left + SCREEN_WIDTH - RIGHT_VIEWPORT_MARGIN
        if self.player_sprite.right > right_boundary:
            self.view_left += self.player_sprite.right - right_boundary
            changed = True

        if changed:
            # Only scroll to integers. Otherwise we end up with pixels that
            # don't line up on the screen
            self.view_bottom = int(self.view_bottom)
            self.view_left = int(self.view_left)

            # Do the scrolling
            arcade.set_viewport(self.view_left, SCREEN_WIDTH + self.view_left,
                                self.view_bottom,
                                SCREEN_HEIGHT + self.view_bottom)

        for wall in self.wall_list:
            if wall.center_x < self.player_sprite.center_x - 500:
                wall.center_x += 1250

        # if self.won:
        #     arcade.play_sound(self.courage_sound)
        #     time.sleep(1)
        #     new_view = game_won.GameWon()
        #     self.window.show_view(new_view)
        #     if wall.center_x < self.player_sprite.center_x - 500:
        #         wall.center_x += 2500

        # manage threads
        for i in range(len(self.sky_scraper_sprites)):
            ss: SkyScraper = self.sky_scraper_sprites[i]
            if not ss.thread.is_alive() and not ss.loaded:
                ss.load_image()
        current_equation = self.equations[0]
        closest_sprite: Sprite = arcade.get_closest_sprite(
            self.player_sprite, self.answer_sprites)[0]
        if type(closest_sprite
                ) == Answer and self.player_sprite.left > closest_sprite.left:
            answer: Answer = closest_sprite

            # player hit the correct answer
            if answer.get_number() == current_equation.answer:
                self.score += 1
                # Reset the equation and answers
                self.get_new_equation()
                current_equation = self.equations[0]
            else:
                self.kill_bird()

            # move answers
            values = current_equation.answers
            for i in range(len(self.answer_sprites)):
                a: Answer = self.answer_sprites[i]
                a.center_x += 1250
                value = values[i]
                a.set_number(value)
                a.is_correct = current_equation.answer == value
            if len(self.sky_scraper_sprites) == 3:
                sprite: SkyScraper = self.sky_scraper_sprites.pop(0)
                center = (sprite.center_x, sprite.center_y)
                print("reloading", [e.answers for e in self.equations])
                new_sprite = SkyScraper(self.equations[1].answers,
                                        id=self.wall_counter)
                self.wall_counter += 1
                new_sprite.center_x = center[0]
                new_sprite.center_y = center[1]
                new_sprite.move_forward(how_many=3)
                self.sky_scraper_sprites.append(new_sprite)

        # bird death detection
        if player_speed == 0:
            print("Bird hit the wall")
            self.kill_bird()

    def kill_bird(self):
        self.is_dead = True
        print("Bird died")
        arcade.play_sound(self.dying_sound_2)
        self.tear_down(self.sky_scraper_sprites)
        self.tear_down(self.answer_sprites)
        self.tear_down(self.wall_list)
        new_view = game_over.GameOver(self, self.score)
        self.window.show_view(new_view)

    def tear_down(self, sprite_list: SpriteList):
        for i in range(len(sprite_list)):
            sprite = sprite_list.pop()
            sprite.scale = 0

    def draw_stats(self):
        start_x = SCREEN_WIDTH + self.view_left
        start_y = SCREEN_HEIGHT
        font_size = 20
        if self.score > 0:
            number_width = math.floor(math.log10(self.score) + 1) * font_size
        else:
            number_width = 1 * font_size
        arcade.draw_xywh_rectangle_filled(start_x - number_width,
                                          start_y - 100,
                                          width=100,
                                          height=100,
                                          color=arcade.color.BLACK)
        arcade.draw_text(str(self.score),
                         start_x,
                         start_y,
                         arcade.color.WHITE,
                         font_size,
                         anchor_x="right",
                         anchor_y="top")

    def get_new_equation(self):
        self.equations.pop(0)
        self.equations.append(Equation(self.level))
        print("get_new_equation", [e.answers for e in self.equations])