Python Arcade - Full Game Demonstration

in #python8 years ago (edited)

In this demo of the Python Arcade library, I demonstrate moving backgrounds, sprites, sound effects (now working with zero lag!), and scoring.

Our hero (the Raspberry) has to defeat his enemies (555 chips) by shooting fireballs. Ever hit counts as a point.

Obviously just having some randomly generated bad guys attack once is not enough to be a long entertainment, but it is enough to show how this module is awesome for developing playable games!

Gist here with full code

Code

import random
import arcade
import _thread


class Fireball(arcade.Sprite):
    def update(self):
        move_rate = 10
        self.center_y += move_rate


class Bad_Guy(arcade.Sprite):
    def update(self):

        drop_rate = random.randrange(-3, 2)
        lateral_rate = random.randrange(-2, 3)

        if lateral_rate > 1:
            rotation = random.randrange(0, 3)
        else:
            rotation = random.randrange(-3, 0)

        # do the moves
        self.center_y += drop_rate
        self.center_x += lateral_rate
        self.angle += rotation


class MyGame(arcade.Window):
    """ Main application class. """

    def sound(self, selected_sound):

        print(selected_sound)
        if selected_sound == "fart":
            arcade.sound.play_sound(self.fart_sound)
        else:
            arcade.sound.play_sound(self.boink_sound)

    def __init__(self):
        """ Initializer """
        # Call the parent class initializer
        super().__init__(800, 600, "Shooter")

        # Variables that will hold sprite lists
        self.player_list = None
        self.enemies_list = None
        self.fireball_list = None

        # Set up the player info
        self.player_sprite = None
        self.score = 0

        # Sounds
        self.fart_sound = None
        self.boink_sound = None

        # Don't show the mouse cursor
        self.set_mouse_visible(False)

        # BG
        self.line_start = -1

        # BG
        arcade.set_background_color(arcade.color.BLACK)

    def setup(self):

        """ Set up the game and initialize the variables. """

        # Sprite lists
        self.player_list = arcade.SpriteList()
        self.enemies_list = arcade.SpriteList()
        self.fireball_list = arcade.SpriteList()

        # Set up the player
        self.score = 0

        # Sound Effects
        self.fart_sound = arcade.sound.load_sound("raspberry.wav")
        self.boink_sound = arcade.sound.load_sound("boink.wav")

        # Our hero
        self.player_sprite = arcade.Sprite("raspberry.png", 1)
        self.player_sprite.center_x = 400
        self.player_sprite.center_y = 50
        self.player_list.append(self.player_sprite)

        # Create the enemies
        for i in range(60):

            # Create a bad_guy
            bad_guy = Bad_Guy("bug.png", 1)

            # Position the bad_guy
            bad_guy.center_x = random.randrange(800)
            bad_guy.center_y = random.randrange(500, 1500)

            # Add the bad_guy to the lists
            self.enemies_list.append(bad_guy)

        # Set the background color
        arcade.set_background_color(arcade.color.BLACK)

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

        # This command has to happen before we start drawing
        arcade.start_render()

        # move the background
        if self.line_start < 49:
            self.line_start += 1
        else:
            self.line_start = 0

        # Draw vertical lines every 50 pixels
        for x in range(0, 800, 50):
            arcade.draw_line(x + self.line_start, 0, x + self.line_start, 600, arcade.color.BLUE_GRAY, 2)

        # Draw horizontal lines every 50 pixels
        for y in range(0, 600, 50):
            arcade.draw_line(0, y + self.line_start, 800, y + self.line_start, arcade.color.BLUEBERRY, 2)

        # Draw all the sprites.
        self.enemies_list.draw()
        self.fireball_list.draw()
        self.player_sprite.draw()

        # Draw the score box
        arcade.draw_rectangle_filled(590, 520, 300, 80, (0, 0, 0, 150))

        # Draw the score text
        arcade.draw_text(f"Score: {self.score}", 498, 498, arcade.color.DARK_RED, 36)
        arcade.draw_text(f"Score: {self.score}", 500, 500, arcade.color.ORANGE_RED, 36)

    def on_mouse_motion(self, x, y, dx, dy):
        """
        Called whenever the mouse moves.
        """
        self.player_sprite.center_x = x

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

        # Create a fireball
        fireball = Fireball("fireball.png", 1)

        # play sound
        _thread.start_new_thread(self.sound, ("fart",))

        # rotate it.
        fireball.angle = random.randrange(-15, 15)

        # Position the fireball
        fireball.center_x = self.player_sprite.center_x
        fireball.bottom = self.player_sprite.top

        # Add the fireball to the appropriate lists
        self.fireball_list.append(fireball)

    def update(self, delta_time):
        """ Movement and game logic """

        # Call update on the enemies
        self.enemies_list.update()

        # Call update on fireball sprites
        self.fireball_list.update()

        # Loop through each fireball
        for fireball in self.fireball_list:

            # Check this fireball to see if it hit an enemy
            hit_list = arcade.check_for_collision_with_list(fireball, self.enemies_list)

            # If it did, get rid of the fireball
            if len(hit_list) > 0:
                # play sound
                _thread.start_new_thread(self.sound, ("boink",))

                # kill it
                fireball.kill()

            # For every enemy we hit, add to the score and remove the bad_guy
            for bad_guy in hit_list:
                bad_guy.kill()
                self.score += 1

            # If the fireball flies off-screen, remove it.
            if fireball.bottom > 600:
                fireball.kill()


def main():
    window = MyGame()
    window.setup()
    arcade.run()


if __name__ == "__main__":
    main()

You will notice I have branched out the sound effects into new threads - if we do not do this, currently the game halts while the sound plays. I got in touch with the Arcade Module developer over at Reddit and he is working on it, but I told him of my threading solution as an option.

Threading is really cool, I will likely return with a tutorial about just that.

Sort:  

Very cool 😎 Thank you for sharing the python scripts.

Coin Marketplace

STEEM 0.05
TRX 0.32
JST 0.078
BTC 66534.83
ETH 1775.30
USDT 1.00
SBD 0.42