Search code examples
pythontypeerrorarcadepositional-argument

TypeError: start_new_game() missing 1 required positional argument: 'max_health'


So I have been trying to figure out why I keep getting this error, even though everything is run from my game_view.py module. Everytime I press the 1 key to start a game and test to see if the players health bar and hit points works, I get this error message. TypeError: start_new_game() missing 1 required positional argument: 'max_health'

The sad part is, is that it reffers me to the start_view which doesn't have anything to do with anything else but running the start screen so players can choose to play solo or with another player. Below is the game_view and start_view so you guys can see where I'm going wrong. I wanted to test this out so this way I can add other enemies, bosses and power-ups later, but running into this error for the past several days is hindering progress. Anyway, code for both will be below. Thanks in advance for any and all help.

start_view:
import arcade
from game_view import GameView


class StartView(arcade.View):
    def on_show(self):
        # This is run once when we switch to this view
        arcade.set_background_color(arcade.csscolor.BLACK)
        # Reset the viewport, necessary if we have a scrolling game
        arcade.set_viewport(0, self.window.width, 0, self.window.height)

    def on_draw(self):
        # Draw this view
        arcade.start_render()
        line_height = 70
        line_location = self.window.height - line_height * 2
        arcade.draw_text("Space Defense Force",
                         self.window.width / 2,
                         line_location,
                         arcade.color.WHITE,
                         font_size=50,
                         anchor_x="center",
                         font_name="SF Atarian System")
        line_location -= line_height
        line_location -= line_height
        arcade.draw_text("1 - Start One Player Game",
                         self.window.width / 2,
                         line_location,
                         arcade.color.WHITE,
                         font_size=20,
                         anchor_x="center",
                         font_name="SF Atarian System")
#         if len(self.window.joysticks) > 1:
#             color = arcade.color.WHITE
#         else:
#             color = arcade.color.GRAY
        color = arcade.color.GRAY
        line_location -= line_height
        arcade.draw_text("2 - Start Two Player Game",
                         self.window.width / 2,
                         line_location,
                         color,
                         font_size=20,
                         anchor_x="center",
                         font_name="SF Atarian System")
        line_location -= line_height
        line_location -= line_height
        color = arcade.color.WHITE
        arcade.draw_text("Use joysticks to play, or arrow keys to move and number keys to fire.",
                         self.window.width / 2,
                         line_location,
                         color,
                         font_size=20,
                         anchor_x="center",
                         font_name="SF Atarian System")
    def on_key_press(self, symbol: int, modifiers: int):
        if symbol == arcade.key.KEY_1:
            game_view = GameView()
            game_view.start_new_game(1)
            self.window.show_view(game_view)
        elif symbol == arcade.key.KEY_2:
            game_view = GameView()
            game_view.start_new_game(2)
            self.window.show_view(game_view)

game_view:
import random
import math
import arcade

from health import Health
from game_over_view import GameOverView
from typing import cast
from arcade.experimental.shadertoy import Shadertoy
from constants import *
from asteroid_sprite import AsteroidSprite
from ship_sprite import ShipSprite
from bullet import Bullet
from glow_line import GlowLine
from glow_ball import GlowBall
from explosion import ExplosionMaker
from glow_image_sprite import GlowImageSprite
from window import Window as window

class GameView(arcade.View):
    # Main application class
    def __init__(self):
        super().__init__()
        
        # Sprite lists
        self.player_sprite_list = arcade.SpriteList()
        self.asteroid_list = arcade.SpriteList()
        self.bullet_list = arcade.SpriteList()
        self.ship_life_list = arcade.SpriteList()
        self.health_list = arcade.SpriteList()
        
        # Sounds
        self.laser_sound = arcade.load_sound(":resources:sounds/hurt5.wav")
        self.hit_sound1 = arcade.load_sound(":resources:sounds/explosion1.wav")
        self.hit_sound2 = arcade.load_sound(":resources:sounds/explosion2.wav")
        self.hit_sound3 = arcade.load_sound(":resources:sounds/hit1.wav")
        self.hit_sound4 = arcade.load_sound(":resources:sounds/hit2.wav")
        self.dead_sound = arcade.load_sound(":resources:sounds/gameover2.wav")
        self.glowball_shadertoy = Shadertoy.create_from_file(self.window.get_size(), "glow_ball.glsl")
        self.glowline_shadertoy = Shadertoy.create_from_file(self.window.get_size(), "glow_line.glsl")
        self.explosion_list = []
#         for joystick in self.window.joysticks:
#             joystick.push_handlers(self)

    def start_new_game(self, player_count, max_health):
        #Set up the game and initialize the variables
        self.game_over = False
        arcade.set_background_color(arcade.csscolor.BLACK)
        # Sprite lists
        self.player_sprite_list = arcade.SpriteList()
        self.asteroid_list = arcade.SpriteList()
        self.bullet_list = arcade.SpriteList()
        self.ship_life_list = arcade.SpriteList()
        self.health_list = arcade.SpriteList()
#         if len(self.window.joysticks) > 0:
#             joystick = self.window.joysticks[0]
#         else:
#             joystick = None
        joystick = None
        player_sprite = ShipSprite(":resources:images/space_shooter/playerShip1_orange.png",
                                   SCALE,
                                   joystick,
                                   player_no=1,
                                   player_count=player_count,
                                   max_health=5)
        self.player_sprite_list.append(player_sprite)
        self.health_list.append(max_health)
        if player_count > 1:
            joystick = None
#             if len(self.window.joysticks) > 1:
#                 joystick = self.window.joysticks[1]
#             else:
#                 joystick = None
            player_sprite = ShipSprite(":resources:images/space_shooter/playerShip1_green.png",
                                       SCALE,
                                       joystick,
                                       player_no=2,
                                       player_count=player_count,
                                       max_health=5
                                       )
            self.player_sprite_list.append(player_sprite)
            self.health_list.append(max_health)
        # Set up the player
        for player in self.player_sprite_list:
            player.score = 0
            player.lives = 3
            
        # Set up the little icons that represent the player lives.
        cur_pos = 10
        for i in range(self.player_sprite_list[0].lives):
            life = arcade.Sprite(":resources:images/space_shooter/playerLife1_orange.png", SCALE)
            life.center_x = cur_pos + life.width
            life.center_y = life.height
            cur_pos += life.width
            self.ship_life_list.append(life)
        if len(self.player_sprite_list) > 1:
            cur_pos = 100
            for i in range(self.player_sprite_list[1].lives):
                life = arcade.Sprite(":resources:images/space_shooter/playerLife1_green.png", SCALE)
                life.center_x = cur_pos + life.width
                life.center_y = life.height
                cur_pos += life.width
                self.ship_life_list.append(life)
                
        # Make the asteroids
        image_list = (":resources:images/space_shooter/meteorGrey_big1.png",
                      ":resources:images/space_shooter/meteorGrey_big2.png",
                      ":resources:images/space_shooter/meteorGrey_big3.png",
                      ":resources:images/space_shooter/meteorGrey_big4.png")
        for i in range(STARTING_ASTEROID_COUNT):
            image_no = random.randrange(4)
            enemy_sprite = AsteroidSprite(image_list[image_no], SCALE)
            enemy_sprite.guid = "Asteroid"
            enemy_sprite.center_y = random.randrange(BOTTOM_LIMIT, TOP_LIMIT)
            enemy_sprite.center_x = random.randrange(LEFT_LIMIT, RIGHT_LIMIT)
            enemy_sprite.change_x = random.random() * 2 - 1
            enemy_sprite.change_y = random.random() * 2 - 1
            enemy_sprite.change_angle = (random.random() - 0.5) * 2
            enemy_sprite.size = 4
            self.asteroid_list.append(enemy_sprite)
            
    def on_draw(self):
        # Render the screen.
        # This command has to happen before we start drawing
        arcade.start_render()
        # Draw all the sprites.
        self.asteroid_list.draw()
        self.ship_life_list.draw()
        for bullet in self.bullet_list:
            bullet.draw()
        self.bullet_list.draw()
        for explosion in self.explosion_list:
            explosion.render()
        self.player_sprite_list.draw()
        self.health_list.draw()
        # Put the text on the screen.
        output = f"Player 1 Score: {self.player_sprite_list[0].score}"
        arcade.draw_text(output, 10, 40, arcade.color.AMBER,
                         font_size=15,
                         font_name="Arcade")
        if len(self.player_sprite_list) > 1:
            output = f"Player 2 Score: {self.player_sprite_list[1].score}"
            arcade.draw_text(output, 500, 40, arcade.color.AMBER,
                             font_size=15,
                             font_name="Arcade")
        output = f"Asteroid Count: {len(self.asteroid_list)}"
        arcade.draw_text(output, 10, 80, arcade.color.AMBER,
                         font_size=15,
                         font_name="Arcade")
        for player in health_list:
            player.draw_health_number()
            player.draw_health_bar()
#     def on_joybutton_press(self, joystick, button):
#         # What player is this?
#         if joystick == self.window.joysticks[0]:
#             player_sprite = self.player_sprite_list[0]
#         else:
#             player_sprite = self.player_sprite_list[1]
#         if player_sprite.player_no == 1:
#             color = 255, 128, 128
#         else:
#             color = 128, 255, 128
#         if button == 0:
#             self.fire_circle(color, player_sprite, player_no=player_sprite.player_no)
#         elif button == 1:
#             self.fire_line(color, player_sprite, player_no=player_sprite.player_no)
#         elif button == 2:
#             bullet_sprite = GlowImageSprite(":resources:images/space_shooter/laserBlue01.png",
#                                             SCALE,
#                                             glowcolor=arcade.color.WHITE,
#                                             shadertoy=self.glowball_shadertoy,
#                                             player_no=player_sprite.player_no)
#             self.set_bullet_vector(bullet_sprite, 10, player_sprite)
#             arcade.play_sound(self.laser_sound)

    def on_key_press(self, symbol, modifiers):
        # Shoot if the player hit the space bar and we aren't respawning.
        if symbol == arcade.key.LEFT:
            self.player_sprite_list[0].change_angle = 3
        elif symbol == arcade.key.RIGHT:
            self.player_sprite_list[0].change_angle = -3
        elif symbol == arcade.key.UP:
            self.player_sprite_list[0].thrust = 0.15
        elif symbol == arcade.key.DOWN:
            self.player_sprite_list[0].thrust = -.2
        elif symbol == arcade.key.KEY_1:
            color = (255, 128, 128)
            self.fire_circle(color, self.player_sprite_list[0], player_no=0)
        elif symbol == arcade.key.KEY_2:
            color = (128, 255, 128)
            self.fire_circle(color, self.player_sprite_list[0], player_no=0)
        elif symbol == arcade.key.KEY_3:
            color = (128, 128, 255)
            self.fire_circle(color, self.player_sprite_list[0], player_no=0)
        elif symbol == arcade.key.KEY_4:
            color = (255, 128, 255)
            self.fire_circle(color, self.player_sprite_list[0], player_no=0)
        elif symbol == arcade.key.KEY_5:
            color = (255, 255, 255)
            self.fire_line(color, self.player_sprite_list[0], player_no=0)
        elif symbol == arcade.key.KEY_6:
            color = (64, 255, 64)
            self.fire_line(color, self.player_sprite_list[0], player_no=0)
        elif symbol == arcade.key.KEY_7:
            bullet_sprite = GlowImageSprite(":resources:images/space_shooter/laserBlue01.png",
                                            SCALE,
                                            glowcolor=arcade.color.WHITE,
                                            shadertoy=self.glowball_shadertoy,
                                            player_no=0)
            self.set_bullet_vector(bullet_sprite, 13, self.player_sprite_list[0])
            arcade.play_sound(self.laser_sound)
            
    def fire_circle(self, bullet_color, player_sprite, player_no):
        bullet_sprite = GlowBall(glowcolor=bullet_color,
                                 radius=5,
                                 shadertoy=self.glowball_shadertoy,
                                 player_no=player_no)
        self.set_bullet_vector(bullet_sprite, 5, player_sprite)
        arcade.play_sound(self.laser_sound)
        
    def fire_line(self, bullet_color, player_sprite, player_no):
        bullet_sprite = GlowLine(glowcolor=bullet_color,
                                 shadertoy=self.glowline_shadertoy,
                                 player=player_sprite,
                                 player_no=player_no)
        self.set_bullet_vector(bullet_sprite, 13, player_sprite)
        arcade.play_sound(self.laser_sound)
        
    def set_bullet_vector(self, bullet_sprite, bullet_speed, player_sprite):
        bullet_sprite.change_y = \
            math.cos(math.radians(player_sprite.angle)) * bullet_speed
        bullet_sprite.change_x = \
            -math.sin(math.radians(player_sprite.angle)) \
            * bullet_speed
        bullet_sprite.center_x = player_sprite.center_x
        bullet_sprite.center_y = player_sprite.center_y
        self.bullet_list.append(bullet_sprite)
        
    def on_key_release(self, symbol, modifiers):
        # Called whenever a key is released
        if symbol == arcade.key.LEFT:
            self.player_sprite_list[0].change_angle = 0
        elif symbol == arcade.key.RIGHT:
            self.player_sprite_list[0].change_angle = 0
        elif symbol == arcade.key.UP:
            self.player_sprite_list[0].thrust = 0
        elif symbol == arcade.key.DOWN:
            self.player_sprite_list[0].thrust = 0
            
    def split_asteroid(self, asteroid: AsteroidSprite):
        # Split an asteroid into chunks
        x = asteroid.center_x
        y = asteroid.center_y
        if asteroid.size == 4:
            for i in range(3):
                image_no = random.randrange(2)
                image_list = [":resources:images/space_shooter/meteorGrey_med1.png",
                              ":resources:images/space_shooter/meteorGrey_med2.png"]
                enemy_sprite = AsteroidSprite(image_list[image_no],
                                              SCALE * 1.5)
                enemy_sprite.center_y = y
                enemy_sprite.center_x = x
                enemy_sprite.change_x = random.random() * 2.5 - 1.25
                enemy_sprite.change_y = random.random() * 2.5 - 1.25
                enemy_sprite.change_angle = (random.random() - 0.5) * 2
                enemy_sprite.size = 3
                self.asteroid_list.append(enemy_sprite)
                self.hit_sound1.play()
        elif asteroid.size == 3:
            for i in range(3):
                image_no = random.randrange(2)
                image_list = [":resources:images/space_shooter/meteorGrey_small1.png",
                              ":resources:images/space_shooter/meteorGrey_small2.png"]
                enemy_sprite = AsteroidSprite(image_list[image_no],
                                              SCALE * 1.5)
                enemy_sprite.center_y = y
                enemy_sprite.center_x = x
                enemy_sprite.change_x = random.random() * 3 - 1.5
                enemy_sprite.change_y = random.random() * 3 - 1.5
                enemy_sprite.change_angle = (random.random() - 0.5) * 2
                enemy_sprite.size = 2
                self.asteroid_list.append(enemy_sprite)
                self.hit_sound2.play()
        elif asteroid.size == 2:
            for i in range(3):
                image_no = random.randrange(2)
                image_list = [":resources:images/space_shooter/meteorGrey_tiny1.png",
                              ":resources:images/space_shooter/meteorGrey_tiny2.png"]
                enemy_sprite = AsteroidSprite(image_list[image_no],
                                              SCALE * 1.5)
                enemy_sprite.center_y = y
                enemy_sprite.center_x = x
                enemy_sprite.change_x = random.random() * 3.5 - 1.75
                enemy_sprite.change_y = random.random() * 3.5 - 1.75
                enemy_sprite.change_angle = (random.random() - 0.5) * 2
                enemy_sprite.size = 1
                self.asteroid_list.append(enemy_sprite)
                self.hit_sound3.play()
        elif asteroid.size == 1:
            self.hit_sound4.play()
            
    def on_update(self, x, delta_time):
        # Move everything
        self.asteroid_list.update()
        self.bullet_list.update()
        self.player_sprite_list.update()
        self.health_list.update()
        explosion_list_copy = self.explosion_list.copy()
        for explosion in explosion_list_copy:
            explosion.update(x)
            if explosion.time > .9:
                self.explosion_list.remove(explosion)
                
        for bullet in self.bullet_list:
            hit_list = arcade.check_for_collision_with_list(bullet, self.player_sprite_list)
            # If it did hit, get rid of sprite
            if len(hit_list) > 0:
                bullet.remove_from_lists()
                
            for player in hit_list:
                if not isinstance(player, ShipSprite):
                    raise TypeError("List contents must be all ints")
                # Remove one health point
                player.cur_health -= 1
                # Check Health
                if player.cur_health <= 0:
                    arcade.play_sound(self.dead_sound)
                    view=GameOverView
                    self.window.show_view(view)
                else:
                    # Not Dead
                    arcade.play_sound(self.hit_sound1)
                    
            assert isinstance(bullet, Bullet)
            asteroids = arcade.check_for_collision_with_list(bullet, self.asteroid_list)
            if len(asteroids) > 0:
                explosion = ExplosionMaker(self.window.get_size(), bullet.position)
                self.explosion_list.append(explosion)
            for asteroid in asteroids:
                assert isinstance(asteroid, AsteroidSprite)
                self.player_sprite_list[bullet.player_no - 1].score += 1
                self.split_asteroid(cast(AsteroidSprite, asteroid))  # expected AsteroidSprite, got Sprite instead
                asteroid.remove_from_sprite_lists()
                bullet.remove_from_sprite_lists()
                
            # Remove bullet if it goes off-screen
            size = max(bullet.width, bullet.height)
            if bullet.center_x < 0 - size:
                bullet.remove_from_sprite_lists()
            if bullet.center_x > SCREEN_WIDTH + size:
                bullet.remove_from_sprite_lists()
            if bullet.center_y < 0 - size:
                bullet.remove_from_sprite_lists()
            if bullet.center_y > SCREEN_HEIGHT + size:
                bullet.remove_from_sprite_lists()
                
        for player in self.player_sprite_list:
            assert isinstance(player, ShipSprite, max_health)
            if not player.respawning:
                asteroids = arcade.check_for_collision_with_list(player, self.asteroid_list)
                if len(asteroids) > 0:
                    if player.lives > 0:
                        player.lives -= 1
                        player.respawn()
                        self.split_asteroid(cast(AsteroidSprite, asteroids[0]))
                        asteroids[0].remove_from_sprite_lists()
                        self.ship_life_list.pop().remove_from_sprite_lists()
                elif len(asteroids) > 0:
                    if player.health > 0:
                        player.health -=1
                        player.respawn()
                        self.split_asteroid(cast(AsteroidSprite, asteroids[0]))
                        asteroids[0].remove_from_sprite_lists()
                        self.ship_list_list.pop().remove_from_sprite_lists()
                    else:
                        arcade.play_sound(self.dead_sound)
                        view = GameOverView()
                        self.window.show_view(view)

Sorry in advance if I have tons of code to go through. But like I said I am adding some features that wasn't in the Arcade Repository from github. I even set a separte module for the health bar and hit points so this way I can see what conflicts. But the error above has been a royal pain.Thanks again.

P.S. Remarked out joysticks because it was conflicting with another module I built.


Solution

  • As your title says, your start game function requires 2 arguments: player_count and max_healh. And in your code, when using start_new_game, you aren't supplying the max_health argument, thus raising an error.

    (function) start_new_game(self, player_count, max_health)