1

I'm trying to show a death screen when the player dies, so I have set up a new view in the GameOverView class. Whenever I try to run the game it crashes and says:

line 288, in on_update
self.window.show_view(GameOverView)
AttributeError: 'MyGame' object has no attribute 'window'
import arcade
import random
import math
from typing import Tuple

SPRITE_SCALING = 0.5
SPRITE_SCALING_LASER = 0.8

SCREEN_WIDTH = 1280
SCREEN_HEIGHT = 720
SCREEN_TITLE = "zombier shooter"
ENEMY_COUNT = 50

BULLET_SPEED = 30
MOVEMENT_SPEED = 5
SPRITE_SPEED = 2

INDICATOR_BAR_OFFSET = 32
ENEMY_ATTACK_COOLDOWN = 1
PLAYER_HEALTH = 5


class Player(arcade.Sprite):

    def update(self):
        """ moves the player """
        # move player.
        self.center_x += self.change_x
        self.center_y += self.change_y

        # check for out of bounds
        if self.left < 0:
            self.left = 0
        elif self.right > SCREEN_WIDTH - 1:
            self.right = SCREEN_WIDTH - 1

        if self.bottom < 0:
            self.bottom = 0
        elif self.top > SCREEN_HEIGHT - 1:
            self.top = SCREEN_HEIGHT - 1

class Enemy(arcade.Sprite):
    """
    This class represents the enemies on our screen. 
    """

    def follow_sprite(self, player_sprite):
        """
        This function will move the current sprite towards whatever
        other sprite is specified as a parameter.
        """

        if self.center_y < player_sprite.center_y:
            self.center_y += min(SPRITE_SPEED, player_sprite.center_y - self.center_y)
        elif self.center_y > player_sprite.center_y:
            self.center_y -= min(SPRITE_SPEED, self.center_y - player_sprite.center_y)

        if self.center_x < player_sprite.center_x:
            self.center_x += min(SPRITE_SPEED, player_sprite.center_x - self.center_x)
        elif self.center_x > player_sprite.center_x:
            self.center_x -= min(SPRITE_SPEED, self.center_x - player_sprite.center_x)

class GameOverView(arcade.View):
    def __init__(self):
        super().__init__()
        self.time_taken = 0

    def on_show_view(self):
        arcade.set_background_color(arcade.color.BLACK)

    def on_draw(self):
        self.clear()
        """
        death screen
        """
        arcade.draw_text("YOU DIED", 240, 400, arcade.color.RED, 54)
        arcade.draw_text("Click to restart", 310, 300, arcade.color.WHITE, 24)

        output_total = f"Score: {self.score}"
        arcade.draw_text(output_total, 10, 10, arcade.color.WHITE, 14)

class MyGame(arcade.Window):
    """
    main game class
    """

    def __init__(self, width, height, title):
        """
        initialises stuff
        """

        #call the parent class initializer
        super().__init__(width, height, title)

        #variables that will hold sprite lists
        self.player_list = None

        #set up the player info
        self.player_sprite = None


        #track the current state of what key is pressed

        self.left_pressed = False

        self.right_pressed = False

        self.up_pressed = False

        self.down_pressed = False

        


        #set the background color
        arcade.set_background_color(arcade.color.AMAZON)

    def setup(self):
        """ Set up the game and initialize the variables. """

        #sprite lists
        self.player_list = arcade.SpriteList()
        self.enemy_list = arcade.SpriteList()
        self.bullet_list = arcade.SpriteList()

        #setup score
        self.score = 0
        self.score_text = None

        #setup health info
        self.health = 5
        self.health_text = None
        self.dead = None


        #set up the player
        self.player_sprite = Player(":resources:images/animated_characters/female_person/femalePerson_idle.png", SPRITE_SCALING)
        self.player_sprite.center_x = 50
        self.player_sprite.center_y = 50
        self.player_list.append(self.player_sprite)

        

        for i in range(ENEMY_COUNT):
            
            #enemy texture
            enemy = arcade.Sprite(":resources:images/animated_characters/zombie/zombie_idle.png", SPRITE_SCALING)

            enemy.center_x = random.randrange(SCREEN_WIDTH)
            enemy.center_y = random.randrange(SCREEN_HEIGHT)

            self.enemy_list.append(enemy)

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

        #clear the screen
        self.clear()

        #draw all the sprites.
        self.player_list.draw()
        self.enemy_list.draw()
        self.bullet_list.draw()

        #put score text on the screen
        output = f"Score: {self.score}"
        arcade.draw_text(output, 10, 20, arcade.color.WHITE, 14)

            

        #put helth text on the screen
        output = f"Health: {self.health}"
        arcade.draw_text(output, 10, 40, arcade.color.WHITE, 14)



    def on_mouse_press(self, x, y, button, modifiers):
        """ Called whenever the mouse button is clicked. """

        #create a bullet
        bullet = arcade.Sprite(":resources:images/space_shooter/laserBlue01.png", SPRITE_SCALING_LASER)

        # Position the bullet at the player's current location
        start_x = self.player_sprite.center_x
        start_y = self.player_sprite.center_y
        bullet.center_x = start_x
        bullet.center_y = start_y

        # Get from the mouse the destination location for the bullet
        # IMPORTANT! If you have a scrolling screen, you will also need
        # to add in self.view_bottom and self.view_left.
        dest_x = x
        dest_y = y

        # Do math to calculate how to get the bullet to the destination.
        # Calculation the angle in radians between the start points
        # and end points. This is the angle the bullet will travel.
        x_diff = dest_x - start_x
        y_diff = dest_y - start_y
        angle = math.atan2(y_diff, x_diff)

        # Angle the bullet sprite so it doesn't look like it is flying
        # sideways.
        bullet.angle = math.degrees(angle)
        print(f"Bullet angle: {bullet.angle:.2f}")

        # Taking into account the angle, calculate our change_x
        # and change_y. Velocity is how fast the bullet travels.
        bullet.change_x = math.cos(angle) * BULLET_SPEED
        bullet.change_y = math.sin(angle) * BULLET_SPEED

        # Add the bullet to the appropriate lists
        self.bullet_list.append(bullet)


    def update_player_speed(self):



        #calculate speed based on the keys pressed

        self.player_sprite.change_x = 0

        self.player_sprite.change_y = 0



        if self.up_pressed and not self.down_pressed:

            self.player_sprite.change_y = MOVEMENT_SPEED

        elif self.down_pressed and not self.up_pressed:

            self.player_sprite.change_y = -MOVEMENT_SPEED

        if self.left_pressed and not self.right_pressed:

            self.player_sprite.change_x = -MOVEMENT_SPEED

        elif self.right_pressed and not self.left_pressed:

            self.player_sprite.change_x = MOVEMENT_SPEED


    def on_update(self, delta_time):
        """ updates values n stuff """

        #call update to move the sprite
        self.player_list.update()

         # Call update on all sprites
        self.bullet_list.update()

        # go through each bullet
        for bullet in self.bullet_list:

            #check each bullet to see if it hit a zombie
            hit_list = arcade.check_for_collision_with_list(bullet, self.enemy_list)

            #if it did, remove the bullet 
            if len(hit_list) > 0:
                bullet.remove_from_sprite_lists()

            # for each enemy we hit with a bullet, remove enemy and add to the score
            for enemy in hit_list:
                enemy.remove_from_sprite_lists()
                self.score += 1

            # if bullet goes off screen, then remove it
            if bullet.bottom > self.width or bullet.top < 0 or bullet.right < 0 or bullet.left > self.width:
                bullet.remove_from_sprite_lists()

        for enemy in self.enemy_list:
            Enemy.follow_sprite(enemy, self.player_sprite)

        # create a list of all sprites that had a collision with the player.
        hit_list = arcade.check_for_collision_with_list(self.player_sprite, self.enemy_list)

        # go through each sprite, if it got hit, then remove the sprite and lower score and health
        for enemy in hit_list:
            enemy.remove_from_sprite_lists()
            self.score -= 1
            self.health -= 1
        
        if self.health == 0:
            self.player_sprite.remove_from_sprite_lists()
            self.window.show_view(GameOverView)


    def on_key_press(self, key, modifiers):

        """called when user presses a key. """



        if key == arcade.key.UP:

            self.up_pressed = True

            self.update_player_speed()

        elif key == arcade.key.DOWN:

            self.down_pressed = True

            self.update_player_speed()

        elif key == arcade.key.LEFT:

            self.left_pressed = True

            self.update_player_speed()

        elif key == arcade.key.RIGHT:

            self.right_pressed = True

            self.update_player_speed()



    def on_key_release(self, key, modifiers):

        """called when user releases a key. """



        if key == arcade.key.UP:

            self.up_pressed = False

            self.update_player_speed()

        elif key == arcade.key.DOWN:

            self.down_pressed = False

            self.update_player_speed()

        elif key == arcade.key.LEFT:

            self.left_pressed = False

            self.update_player_speed()

        elif key == arcade.key.RIGHT:

            self.right_pressed = False

            self.update_player_speed()



def main():
    """ Main function """
    window = MyGame(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_TITLE)
    window.setup()
    arcade.run()


if __name__ == "__main__":
    main()
John Kugelman
  • 349,597
  • 67
  • 533
  • 578
riley
  • 53
  • 3

1 Answers1

0

You can't mix arcade.View and arcade.Window classes in one project. Replace MyGame(arcade.Window) with GameView(arcade.View) and initialize Arcade window like this: window = arcade.Window(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_TITLE)

Full example:

import arcade
import random
import math

SPRITE_SCALING = 0.5
SPRITE_SCALING_LASER = 0.8

SCREEN_WIDTH = 600
SCREEN_HEIGHT = 400
SCREEN_TITLE = "zombier shooter"
ENEMY_COUNT = 5

BULLET_SPEED = 30
MOVEMENT_SPEED = 5
SPRITE_SPEED = 2

INDICATOR_BAR_OFFSET = 32
ENEMY_ATTACK_COOLDOWN = 1
PLAYER_HEALTH = 5

SCORE = 0


class Player(arcade.Sprite):

    def update(self):
        """ moves the player """
        # move player.
        self.center_x += self.change_x
        self.center_y += self.change_y

        # check for out of bounds
        if self.left < 0:
            self.left = 0
        elif self.right > SCREEN_WIDTH - 1:
            self.right = SCREEN_WIDTH - 1

        if self.bottom < 0:
            self.bottom = 0
        elif self.top > SCREEN_HEIGHT - 1:
            self.top = SCREEN_HEIGHT - 1


class Enemy(arcade.Sprite):
    """
    This class represents the enemies on our screen.
    """

    def follow_sprite(self, player_sprite):
        """
        This function will move the current sprite towards whatever
        other sprite is specified as a parameter.
        """

        if self.center_y < player_sprite.center_y:
            self.center_y += min(SPRITE_SPEED, player_sprite.center_y - self.center_y)
        elif self.center_y > player_sprite.center_y:
            self.center_y -= min(SPRITE_SPEED, self.center_y - player_sprite.center_y)

        if self.center_x < player_sprite.center_x:
            self.center_x += min(SPRITE_SPEED, player_sprite.center_x - self.center_x)
        elif self.center_x > player_sprite.center_x:
            self.center_x -= min(SPRITE_SPEED, self.center_x - player_sprite.center_x)


class GameOverView(arcade.View):
    def __init__(self):
        super().__init__()
        self.time_taken = 0

    def on_show_view(self):
        arcade.set_background_color(arcade.color.BLACK)

    def on_draw(self):
        self.clear()
        """
        death screen
        """
        arcade.draw_text("YOU DIED", SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2, arcade.color.RED, 54, anchor_x='center')
        arcade.draw_text("Click to restart", SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2 - 100, arcade.color.WHITE, 24,
                         anchor_x='center')

        output_total = f"Score: {SCORE}"
        arcade.draw_text(output_total, 10, 10, arcade.color.WHITE, 14)


class GameView(arcade.View):
    """
    main game class
    """

    def __init__(self):
        """
        initialises stuff
        """

        # call the parent class initializer
        super().__init__()

        # variables that will hold sprite lists
        self.player_list = None

        # set up the player info
        self.player_sprite = None

        # track the current state of what key is pressed

        self.left_pressed = False

        self.right_pressed = False

        self.up_pressed = False

        self.down_pressed = False

        # set the background color
        arcade.set_background_color(arcade.color.AMAZON)

    def setup(self):
        """ Set up the game and initialize the variables. """

        # sprite lists
        self.player_list = arcade.SpriteList()
        self.enemy_list = arcade.SpriteList()
        self.bullet_list = arcade.SpriteList()

        # setup score
        global SCORE
        SCORE = 0
        self.score_text = None

        # setup health info
        self.health = 5
        self.health_text = None
        self.dead = None

        # set up the player
        self.player_sprite = Player(":resources:images/animated_characters/female_person/femalePerson_idle.png",
                                    SPRITE_SCALING)
        self.player_sprite.center_x = 50
        self.player_sprite.center_y = 50
        self.player_list.append(self.player_sprite)

        for i in range(ENEMY_COUNT):
            # enemy texture
            enemy = arcade.Sprite(":resources:images/animated_characters/zombie/zombie_idle.png", SPRITE_SCALING)

            enemy.center_x = random.randrange(SCREEN_WIDTH)
            enemy.center_y = random.randrange(SCREEN_HEIGHT)

            self.enemy_list.append(enemy)

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

        # clear the screen
        self.clear()

        # draw all the sprites.
        self.player_list.draw()
        self.enemy_list.draw()
        self.bullet_list.draw()

        # put score text on the screen
        output = f"Score: {SCORE}"
        arcade.draw_text(output, 10, 20, arcade.color.WHITE, 14)

        # put helth text on the screen
        output = f"Health: {self.health}"
        arcade.draw_text(output, 10, 40, arcade.color.WHITE, 14)

    def on_mouse_press(self, x, y, button, modifiers):
        """ Called whenever the mouse button is clicked. """

        # create a bullet
        bullet = arcade.Sprite(":resources:images/space_shooter/laserBlue01.png", SPRITE_SCALING_LASER)

        # Position the bullet at the player's current location
        start_x = self.player_sprite.center_x
        start_y = self.player_sprite.center_y
        bullet.center_x = start_x
        bullet.center_y = start_y

        # Get from the mouse the destination location for the bullet
        # IMPORTANT! If you have a scrolling screen, you will also need
        # to add in self.view_bottom and self.view_left.
        dest_x = x
        dest_y = y

        # Do math to calculate how to get the bullet to the destination.
        # Calculation the angle in radians between the start points
        # and end points. This is the angle the bullet will travel.
        x_diff = dest_x - start_x
        y_diff = dest_y - start_y
        angle = math.atan2(y_diff, x_diff)

        # Angle the bullet sprite so it doesn't look like it is flying
        # sideways.
        bullet.angle = math.degrees(angle)
        print(f"Bullet angle: {bullet.angle:.2f}")

        # Taking into account the angle, calculate our change_x
        # and change_y. Velocity is how fast the bullet travels.
        bullet.change_x = math.cos(angle) * BULLET_SPEED
        bullet.change_y = math.sin(angle) * BULLET_SPEED

        # Add the bullet to the appropriate lists
        self.bullet_list.append(bullet)

    def update_player_speed(self):

        global SCORE

        # calculate speed based on the keys pressed

        self.player_sprite.change_x = 0

        self.player_sprite.change_y = 0

        if self.up_pressed and not self.down_pressed:

            self.player_sprite.change_y = MOVEMENT_SPEED

        elif self.down_pressed and not self.up_pressed:

            self.player_sprite.change_y = -MOVEMENT_SPEED

        if self.left_pressed and not self.right_pressed:

            self.player_sprite.change_x = -MOVEMENT_SPEED

        elif self.right_pressed and not self.left_pressed:

            self.player_sprite.change_x = MOVEMENT_SPEED

    def on_update(self, delta_time):
        """ updates values n stuff """

        global SCORE

        # call update to move the sprite
        self.player_list.update()

        # Call update on all sprites
        self.bullet_list.update()

        # go through each bullet
        for bullet in self.bullet_list:

            # check each bullet to see if it hit a zombie
            hit_list = arcade.check_for_collision_with_list(bullet, self.enemy_list)

            # if it did, remove the bullet
            if len(hit_list) > 0:
                bullet.remove_from_sprite_lists()

            # for each enemy we hit with a bullet, remove enemy and add to the score
            for enemy in hit_list:
                enemy.remove_from_sprite_lists()
                SCORE += 1

            # if bullet goes off screen, then remove it
            if bullet.bottom > SCREEN_WIDTH or bullet.top < 0 or bullet.right < 0 or bullet.left > SCREEN_WIDTH:
                bullet.remove_from_sprite_lists()

        for enemy in self.enemy_list:
            Enemy.follow_sprite(enemy, self.player_sprite)

        # create a list of all sprites that had a collision with the player.
        hit_list = arcade.check_for_collision_with_list(self.player_sprite, self.enemy_list)

        # go through each sprite, if it got hit, then remove the sprite and lower score and health
        for enemy in hit_list:
            enemy.remove_from_sprite_lists()
            SCORE -= 1
            self.health -= 1

        if self.health == 0:
            self.player_sprite.remove_from_sprite_lists()
            # self.window.show_view(GameOverView)
            game_over_view = GameOverView()
            self.window.show_view(game_over_view)

    def on_key_press(self, key, modifiers):

        """called when user presses a key. """

        if key == arcade.key.UP:

            self.up_pressed = True

            self.update_player_speed()

        elif key == arcade.key.DOWN:

            self.down_pressed = True

            self.update_player_speed()

        elif key == arcade.key.LEFT:

            self.left_pressed = True

            self.update_player_speed()

        elif key == arcade.key.RIGHT:

            self.right_pressed = True

            self.update_player_speed()

    def on_key_release(self, key, modifiers):

        """called when user releases a key. """

        if key == arcade.key.UP:

            self.up_pressed = False

            self.update_player_speed()

        elif key == arcade.key.DOWN:

            self.down_pressed = False

            self.update_player_speed()

        elif key == arcade.key.LEFT:

            self.left_pressed = False

            self.update_player_speed()

        elif key == arcade.key.RIGHT:

            self.right_pressed = False

            self.update_player_speed()


def main():
    """ Main function """
    window = arcade.Window(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_TITLE)
    game_view = GameView()
    window.show_view(game_view)
    game_view.setup()
    arcade.run()


if __name__ == "__main__":
    main()

Result:

Death screen

Alderven
  • 7,569
  • 5
  • 26
  • 38