Easy 2D Game Creation

With Python And Arcade

Paul Vincent Craven

Explore On-Line!

Installation

pip install arcade

Requires

  • Python 3.6+
  • OpenGL Capable Hardware

For detailed installation instructions on Windows, MacOS, and Linux, see:

http://arcade.academy/installation.html

import arcade

# Set constants for the screen size
SCREEN_WIDTH = 600
SCREEN_HEIGHT = 600

# Open the window. Set the window title and dimensions
arcade.open_window(SCREEN_WIDTH, SCREEN_HEIGHT, "Drawing Example")

# --- Drawing Code Will Go Here ---

# Keep the window open until the user hits the 'close' button
arcade.run()

1

2

3

Open a Window

import arcade

SCREEN_WIDTH = 600
SCREEN_HEIGHT = 600

# Open the window. Set the window title and dimensions
arcade.open_window(SCREEN_WIDTH, SCREEN_HEIGHT, "Drawing Example")

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

# Clear screen and start render process
arcade.start_render()

# --- Drawing Commands Will Go Here ---

# Finish drawing and display the result
arcade.finish_render()

# Keep the window open until the user hits the 'close' button
arcade.run()

1

2

Drawing Setup

3

# Draw the face
x = 300; y = 300; radius = 200
arcade.draw_circle_filled(x, y, radius, arcade.color.YELLOW)

# Draw the right eye
x = 370; y = 350; radius = 20
arcade.draw_circle_filled(x, y, radius, arcade.color.BLACK)

# Draw the left eye
x = 230; y = 350; radius = 20
arcade.draw_circle_filled(x, y, radius, arcade.color.BLACK)

# Draw the smile
x = 300; y = 280; width = 120; height = 100
start_angle = 190; end_angle = 350; line_width = 10
arcade.draw_arc_outline(x, y, width, height, arcade.color.BLACK,
                        start_angle, end_angle, line_width)

Drawing

1

2

3

4

draw_arc_filled()
draw_arc_outline()

draw_circle_filled()
draw_circle_outline()

draw_ellipse_filled()
draw_ellipse_outline()

draw_line()
draw_line_strip()
draw_lines()

draw_parabola_filled()
draw_parabola_outline()

draw_point()
draw_points()

Drawing Commands

draw_rectangle_filled()
draw_rectangle_outline()
draw_lrtb_rectangle_filled()
draw_lrtb_rectangle_outline()
draw_xywh_rectangle_filled()
draw_xywh_rectangle_outline()

draw_polygon_filled()
draw_polygon_outline()

draw_text()

load_texture()
draw_texture_rectangle()
draw_xywh_rectangle_textured()

draw_triangle_filled()
draw_triangle_outline()

Sample Images

Wait!

Put code in functions!

def draw_pine_tree(x, y):
    """
    This function draws a pine tree at the specified location.
    """
    # Draw the triangle on top of the trunk
    arcade.draw_triangle_filled(x + 40, y,
                                x, y - 100,
                                x + 80, y - 100,
                                arcade.color.DARK_GREEN)

    # Draw the trunk
    arcade.draw_lrtb_rectangle_filled(x + 30, x + 50, 
                                      y - 100, y - 140,
                                      arcade.color.DARK_BROWN)

Draw With Functions

1

2

3

def main():

    arcade.open_window(SCREEN_WIDTH, SCREEN_HEIGHT, 
                       "Drawing With Functions")
    arcade.start_render()

    # Call our drawing functions.
    draw_background()
    draw_pine_tree(50, 250)
    draw_pine_tree(350, 320)
    draw_bird(70, 500)
    draw_bird(470, 550)

    arcade.finish_render()
    arcade.run()


if __name__ == "__main__":
    main()

The Main Function

1

2

3

Wait!

That's not fast...

Explore using buffered shapes

class MyGame(arcade.Window):

    def __init__(self, width, height, title):
        """ Initialize everything """

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

        arcade.set_background_color(arcade.color.AMAZON)

    def setup(self):
        """ Create the sprites and set up the game """
        pass

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

        arcade.start_render()

        # TODO: Drawing code goes here

Use Classes

2

3

4

1

    def update(self, delta_time):
        """ All the logic to move, and the game logic goes here. """
        pass

    def on_key_press(self, key, key_modifiers):
        """ Called whenever a key on the keyboard is pressed. """
        pass

    def on_mouse_motion(self, x, y, delta_x, delta_y):
        """ Called whenever the mouse moves. """
        pass

    def on_mouse_press(self, x, y, button, key_modifiers):
        """ Called when the user presses a mouse button. """
        pass

Use Classes

1

2

3

4

def main():
    """ Main method """
    game = MyGame(SCREEN_WIDTH, SCREEN_HEIGHT, "My Game Title")
    game.setup()
    arcade.run()


if __name__ == "__main__":
    main()

Use Classes

1

2

3

Use Sprites

Images from Kenney.nl

# This code goes in the setup() method of our MyGame class

# Set up the player
self.player_sprite = arcade.Sprite("images/character.png")

self.player_sprite.center_x = 50
self.player_sprite.center_y = 50

# Add player to a sprite list
self.player_list = arcade.SpriteList()
self.player_list.append(self.player_sprite)

Create Sprites

1

2

3

The SpriteList Class

  • Optimizes drawing by using vertex buffers and more
  • Optimizes collision detection by using spatial hashing
  • Allows you to control drawing order
  • Easier management of your game logic
# This code goes in the setup() method of our MyGame class

COIN_COUNT = 50
self.coin_list = arcade.SpriteList()

# Create the coins
for i in range(COIN_COUNT):

    # Create the coin instance
    coin = arcade.Sprite("images/coin_01.png")

    # Position the coin
    coin.center_x = random.randrange(SCREEN_WIDTH)
    coin.center_y = random.randrange(SCREEN_HEIGHT)

    # Add the coin to the lists
    self.coin_list.append(coin)

Create Sprites

1

2

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

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

        # Draw all the sprites.
        self.wall_list.draw()
        self.coin_list.draw()
        self.player_sprite_list.draw()

Drawing Sprites

1

2

def update(self, delta_time):
    # Generate a list of all coin sprites that collided with the player.
    coins_hit_list = arcade.check_for_collision_with_list(self.player_sprite, 
                                                          self.coin_list)

    # Loop through each colliding sprite, remove it, and add to the score.
    for coin in coins_hit_list:
        coin.kill()
        self.score += 1

Sprite Collisions

1

2

Moving Sprites

Moving Coins Down

0

599

620

700

799

0

Y

X

On-Screen

Where Coins Respawn

    def on_mouse_motion(self, x, y, dx, dy):
        """ Handle Mouse Motion """

        # Move the center of the player sprite to match the mouse x, y
        self.player_sprite.center_x = x
        self.player_sprite.center_y = y

Moving The Player

1

2

class Coin(arcade.Sprite):

    def reset_pos(self):

        # Reset the coin to a random spot above the screen
        self.center_y = random.randrange(SCREEN_HEIGHT + 20,
                                         SCREEN_HEIGHT + 100)
        self.center_x = random.randrange(SCREEN_WIDTH)

    def update(self):

        # Move the coin
        self.center_y -= 1

        # See if the coin has fallen off the bottom of the screen.
        # If so, reset it.
        if self.top < 0:
            self.reset_pos()

Moving Coins Down

1

2

4

3

5

6

# This code goes in the setup() method of our MyGame class

COIN_COUNT = 50
self.coin_list = arcade.SpriteList()

# Create the coins
for i in range(COIN_COUNT):

    # Create the coin instance
    coin = arcade.Sprite("images/coin_01.png")

    # Position the coin
    coin.center_x = random.randrange(SCREEN_WIDTH)
    coin.center_y = random.randrange(SCREEN_HEIGHT)

    # Add the coin to the lists
    self.coin_list.append(coin)

Moving Coins Down

1

2

Coin

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

    # Call update on all sprites (The sprites don't do much in this
    # example though.)
    self.coin_sprite_list.update()

    # Generate a list of all sprites that collided with the player.
    hit_list = arcade.check_for_collision_with_list(self.player_sprite,
                                                    self.coin_sprite_list)

    # Loop through each colliding sprite, remove it, and add to the score.
    for coin in hit_list:
        coin.kill()
        self.score += 1

Moving a Sprite

1

2

Learn By Example

Learn By Example

Learn By Example

What's Next?

  • Immediate:
    • Isometric map examples and support
    • Better support for the Tiled Map Editor
  • Soon:
    • Better decorator support
    • Particle support
    • Lighting / shader support

How Does It Compare To PyGame?

  • Easier
  • Arcade is based on OpenGL, PyGame SDL1
  • Uses modern design, Python features like type hinting

Want To Contribute?

  • Use GitHub!
  • Code and documentation open for pull requests.
  • There's also an open-source book on learning to program with Arcade and Python.

Contact Me:

Paul Vincent Craven

paul@cravenfamily.com

@professorcraven

Learn More:

http://arcade.academy

Support:

www.reddit.com://r/pythonarcade

Made with Slides.com