How to create a 2D game with Python and an arcade library

Hello, Habr! I present to you the translation of the article How to create a 2D game with Python and the Arcade library by Paul Vincent Craven







How to create a 2D game with Python and an arcade library



Learn how to get started with Arcade, an easy-to-use Python library for creating 2D video games.



image







Phython is a great language for people learning programming, and is ideal for those who want to "do something" and not spend a ton of time on boilerplate code. Arcade is a Python library for creating 2D video games that is easy to use and very effective when you gain experience. In this article, I will explain how to start using Python and Arcade to program video games.







I started development on Arcade after teaching students using the PyGame library. I taught personally using PyGame for almost 10 years, and I developed ProgramArcadeGames .com to teach online. PyGame is great, but in the end I felt like I was wasting time covering errors that were never fixed .

I was worried about teaching things like the event loop, which was no longer the way we code. I had a whole section in which I explained why the Y coordinates were flipped. Since PyGame was rarely updated, and it is based on the old SDL 1 library, and not on something like a more modern one, such as OpenGL , I did not have much hope for the future.







I wanted to create a library that was easier to use, more powerful, and used some of the new Python 3 features, such as decorators and type hints. This is an arcade. And here's how to get started.







Installation



Arcade, like many other packages, is available through PyPi , which means that you can install Arcade using the pip command (or pipenv command). If you already have Python installed, you can probably just open a command prompt on Windows and type:







pip install arcade
      
      





Or on MacOS and Linux type:







 pip3 install arcade
      
      





For more detailed installation instructions, you can refer to the Arcade installation documentation .







Simple drawing



You can open a window and create simple drawings with just a few lines of code. Let's create an example that draws a smiley, as shown in the image below:







image







The algorithm below shows how you can use Arcade drawing commands to do this. Note that you do not need to know how to use classes or even define functions. Programming with quick visual feedback is great for those who want to start learning programming.







 import arcade # Set constants for the screen size SCREEN_WIDTH = 600 SCREEN_HEIGHT = 600 # Open the window. Set the window title and dimensions (width and height) arcade.open_window(SCREEN_WIDTH, SCREEN_HEIGHT, "Drawing Example") # Set the background color to white. # For a list of named colors see: # http://arcade.academy/arcade.color.html # Colors can also be specified in (red, green, blue) format and # (red, green, blue, alpha) format. arcade.set_background_color( arcade.color.WHITE) # Start the render process. This must be done before any drawing commands. arcade.start_render() # 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 arcade.draw_arc_outline( x, y, width, height, arcade.color.BLACK, start_angle, end_angle, 10) # Finish drawing and display the result arcade.finish_render() # Keep the window open until the user hits the 'close' button arcade.run()
      
      





Function use



Of course, writing code in a global context is not a good form. Fortunately, improving your program with features is easy. Here we can see an example of drawing a pine tree in a specific (x, y) place using the function:







 def draw_pine_tree(x, y) : """ This function draws a pine tree at the specified location. """ # Draw the triangle on top of the trunk. # We need three x, y points for the triangle. arcade.draw_triangle_filled( x + 40, y, # Point 1 x, y - 100, # Point 2 x + 80, y - 100, # Point 3 arcade.color.DARK_GREEN) # Draw the trunk arcade.draw_lrtb_rectangle_filled( x + 30, x + 50, y - 100, y - 140 , arcade.color.DARK_BROWN)
      
      





For a complete example, see drawing with functions .







image







A more experienced programmer will know that modern graphics programs first upload graphic information to the video card, and then ask the video card to draw it later as a package. Arcade also supports this. Drawing 10,000 rectangles individually takes about .800 seconds. Drawing them as a package takes less than 0.001 seconds.







window class



Larger programs usually inherit from the Window class or use decorators . This allows the programmer to write code to handle drawing, updating, and processing user input. The template for launching the window program is shown below.







 import arcade SCREEN_WIDTH = 800 SCREEN_HEIGHT = 600 class MyGame( arcade.Window): """ Main application class. """ def __init__(self, width, height) : super( ) .__init__(width, height) arcade.set_background_color( arcade.color.AMAZON) def setup( self) : # Set up your game here pass def on_draw(self) : """ Render the screen. """ arcade.start_render() # Your drawing code goes here def update(self, delta_time) : """ All the logic to move, and the game logic goes here. """ pass def main( ) : game = MyGame( SCREEN_WIDTH, SCREEN_HEIGHT) game.setup( ) arcade.run() if __name__ = = "__main__": main()
      
      





The Window class has several methods that your programs can override to provide program functionality. Here are some of the most commonly used:







on_draw: all the code for drawing a screen goes here.

Update: all of the code to move your items and execute game logic is here. This is called about 60 times per second.

on_key_press: handle events when a key is pressed, for example, give the player speed.

on_key_release: processes when the key is released, here you can stop the player’s movement.

on_mouse_motion: Called every time the mouse moves.

on_mouse_press: called when the mouse button is clicked.

set_viewport: this function is used in scrolling games when your world is much larger than what you can see on one screen. The set_viewport call allows the programmer to set which part of this world is currently visible.







Sprites



Sprites are an easy way to create a two-dimensional raster object in Arcade. Arcade has methods that make drawing, moving, and animating sprites easier. You can also easily use sprites to detect collisions between objects.







Sprite creation



Creating an instance of the Sprite Arcade class from graphics is easy. The programmer only needs the name of the image file in order for the sprite to be based, and, optionally, a number to scale the image up or down. For example:







 SPRITE_SCALING_COIN = 0,2 coin = arcade.Sprite("coin_01.png", SPRITE_SCALING_COIN)
      
      





This code will create a sprite using the image stored in coin_01.png. The image will be reduced to 20% of its original height and width.

image







Sprite lists



Sprites are usually organized into lists. These lists facilitate the management of sprites. The sprites in the list will use OpenGL to batch draw sprites as a group. The code below sets up a game with a player and a bunch of coins that the player collects. We use two lists, one for the player and one for the coins.







 def setup(self): """ Set up the game and initialize the variables. """ # Create the sprite lists self.player_list = arcade.SpriteList() self.coin_list = arcade.SpriteList() # Score self.score = 0 # Set up the player # Character image from kenney.nl self. player_sprite = arcade.Sprite("images/character.png", SPRITE_SCALING_PLAYER) self.player_sprite.center_x = 50 # Starting position self.player_sprite.center_y = 50 self.player_list.append(self.player_sprite) # Create the coins for i in range( COIN_COUNT): # Create the coin instance # Coin image from kenney.nl coin = arcade.Sprite("images/coin_01.png", SPRITE_SCALING_COIN) # 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)
      
      





We can easily draw all the coins in the coin lists:







 def on_draw(self): """ Draw everything """ arcade.start_render() self.coin_list.draw() self.player_list.draw()
      
      





Sprite collision detection



Sprite collision detection

The check_for_collision_with_list function allows us to see if a sprite meets another sprite in the list. We can use this to see all the coins that the player’s sprite is in contact with. Using a simple for loop, we can get rid of the coin from the game and increase our score.







 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
      
      





For a complete example, see collect_coins.py .







Game physics



Many games include some kind of physics. The simplest are downstream programs that prevent the player from going through walls. Platformers add more gravity to moving platforms. Some games use a full-fledged 2D physics engine with mass, friction, springs, and more.







Top down games



image







For simple top-down games, the arcade program needs a list of walls through which the player (or anything else) cannot pass. I usually call it wall_list. Then the physics engine is created in the installation code of the Window class using:







 self.physics_engine = arcade.PhysicsEngineSimple(self.player_sprite, self.wall_list)
      
      





Player_sprite receives a motion vector with two attributes: change_x and change_y. A simple example of this is moving a player using the keyboard. For example, this could be in a custom child of the Window class:







 MOVEMENT_SPEED = 5 def on_key_press(self, key, modifiers) : """Called whenever a key is pressed. """ if key = = arcade.key.UP: self.player_sprite.change_y = MOVEMENT_SPEED elif key = = arcade.key.DOWN: self.player_sprite.change_y = -MOVEMENT_SPEED elif key = = arcade.key.LEFT: self.player_sprite.change_x = -MOVEMENT_SPEED elif key = = arcade.key.RIGHT: self.player_sprite.change_x = 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.DOWN: self.player_sprite.change_y = 0 elif key = = arcade.key.LEFT or key = = arcade.key.RIGHT: selfplayer_sprite.change_x = 0
      
      





Although this code sets the speed of the player, it does not move the player. In the method of updating the Window class, when calling Physics_engine.update (), the player will move, but not through the walls.







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





For a complete example, see sprite_move_walls.py .







Platformers



image







Switching to a platformer with a side view is quite simple. The programmer just needs to switch the physics engine to PhysicsEnginePlatformer and add the gravitational constant.







 self.physics_engine = arcade.PhysicsEnginePlatformer(self.player_sprite, self.wall_list, gravity_constant= GRAVITY)
      
      





You can use a program like Tiled to lay the tiles / blocks that make up your level.







For an example, see sprite_tiled_map.py .







For full 2D physics, you can integrate the PyMunk library.







Learn from an example



One of the best ways to learn is an example. The Arcade Library has a long list of examples of programs that people can use to create games. Each of these examples shows the concept of a game that students have asked in my lessons or on the Internet over the years.







Running any of these demos is easy after installing Arcade. Each of the examples has a comment at the beginning of the program with a command that you can enter on the command line to run the example, for example:







 python -m arcade.examples.sprite_moving_platforms
      
      





Brief information



Arcade lets you start programming graphics and games with easy-to-understand code. Many new programmers created great games shortly after the start. Give it a try!








All Articles