Arcade - alternative Pygame

онлайн тренажер по питону
Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Complete Guide to the Arcade Library for Developing 2D Games in Python

Introduction to the Arcade Library

The Arcade library is a modern Python library for creating 2D games, designed as a powerful alternative to the outdated Pygame. Created by Dr. Paul Craven, Arcade offers a clean, intuitive API and leverages modern OpenGL for high performance.

Key benefits of Arcade include an object‑oriented approach, built‑in animation support, a modern rendering architecture, and ease of learning. The library is actively developed and community‑maintained, making it an excellent choice for both beginners and experienced programmers.

Key Features and Advantages

Modern Architecture

Arcade is built on top of OpenGL, providing hardware‑accelerated graphics and high performance. This is especially important for games with many sprites or complex visual effects.

Simple Syntax

The library offers an intuitive API that is easy for newcomers to learn while being powerful enough to create sophisticated games.

Built‑In Physics

Arcade includes several physics engines, including platformer physics and a PyMunk‑based engine, simplifying the creation of realistic game mechanics.

Support for Modern Formats

The library integrates with Tiled Map Editor, allowing you to build complex levels using the popular map editor.

Installation and Environment Setup

Basic Installation

pip install arcade

Installation with Extra Dependencies

pip install arcade[pymunk]  # For extended physics

Verify Installation

import arcade
print(f"Arcade version: {arcade.__version__}")
print(f"OpenGL version: {arcade.get_version()}")

Creating a Basic Application Window

Minimal Example

import arcade

SCREEN_WIDTH = 1024
SCREEN_HEIGHT = 768
SCREEN_TITLE = "My First Arcade Game"

class MyGame(arcade.Window):
    def __init__(self):
        super().__init__(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_TITLE)
        arcade.set_background_color(arcade.color.AMAZON)
        
    def setup(self):
        """Game setup"""
        pass
        
    def on_draw(self):
        """Render the frame"""
        self.clear()
        arcade.draw_text("Welcome to Arcade!", 
                        SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2,
                        arcade.color.WHITE, 36, 
                        anchor_x="center", anchor_y="center")
    
    def on_update(self, delta_time):
        """Update game logic"""
        pass

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

if __name__ == "__main__":
    main()

Sprite and Graphics System

Creating and Managing Sprites

class Player(arcade.Sprite):
    def __init__(self, filename, scale):
        super().__init__(filename, scale)
        self.speed = 5
        
    def update(self):
        self.center_x += self.change_x
        self.center_y += self.change_y
        
        # Keep within screen bounds
        if self.left < 0:
            self.left = 0
        elif self.right > SCREEN_WIDTH:
            self.right = SCREEN_WIDTH

Working with Sprite Lists

def setup(self):
    # Create sprite lists
    self.player_list = arcade.SpriteList()
    self.enemy_list = arcade.SpriteList()
    self.bullet_list = arcade.SpriteList()
    
    # Create player
    self.player = Player("images/player.png", 0.8)
    self.player.center_x = SCREEN_WIDTH // 2
    self.player.center_y = 50
    self.player_list.append(self.player)
    
    # Create enemies
    for i in range(5):
        enemy = arcade.Sprite("images/enemy.png", 0.6)
        enemy.center_x = random.randint(50, SCREEN_WIDTH - 50)
        enemy.center_y = random.randint(200, SCREEN_HEIGHT - 50)
        self.enemy_list.append(enemy)

User Input Handling

Keyboard

def on_key_press(self, key, modifiers):
    """Handle key press"""
    if key == arcade.key.LEFT or key == arcade.key.A:
        self.player.change_x = -self.player.speed
    elif key == arcade.key.RIGHT or key == arcade.key.D:
        self.player.change_x = self.player.speed
    elif key == arcade.key.UP or key == arcade.key.W:
        self.player.change_y = self.player.speed
    elif key == arcade.key.DOWN or key == arcade.key.S:
        self.player.change_y = -self.player.speed
    elif key == arcade.key.SPACE:
        self.shoot_bullet()

def on_key_release(self, key, modifiers):
    """Handle key release"""
    if key in [arcade.key.LEFT, arcade.key.RIGHT, arcade.key.A, arcade.key.D]:
        self.player.change_x = 0
    elif key in [arcade.key.UP, arcade.key.DOWN, arcade.key.W, arcade.key.S]:
        self.player.change_y = 0

Mouse

def on_mouse_press(self, x, y, button, modifiers):
    """Handle mouse click"""
    if button == arcade.MOUSE_BUTTON_LEFT:
        bullet = arcade.Sprite("images/bullet.png", 0.5)
        bullet.center_x = self.player.center_x
        bullet.center_y = self.player.center_y
        
        # Calculate direction toward cursor
        dest_x = x
        dest_y = y
        x_diff = dest_x - bullet.center_x
        y_diff = dest_y - bullet.center_y
        angle = math.atan2(y_diff, x_diff)
        
        bullet.change_x = math.cos(angle) * 10
        bullet.change_y = math.sin(angle) * 10
        
        self.bullet_list.append(bullet)

Animation System

Animated Sprites

class AnimatedCharacter(arcade.Sprite):
    def __init__(self):
        super().__init__()
        
        # Load textures for animation
        self.idle_textures = []
        self.walk_textures = []
        
        for i in range(4):
            texture = arcade.load_texture(f"images/idle_{i}.png")
            self.idle_textures.append(texture)
            
        for i in range(6):
            texture = arcade.load_texture(f"images/walk_{i}.png")
            self.walk_textures.append(texture)
            
        self.current_texture = 0
        self.texture = self.idle_textures[0]
        
    def update_animation(self, delta_time: float = 1/60):
        if self.change_x == 0 and self.change_y == 0:
            # Idle animation
            self.current_texture += 1
            if self.current_texture >= len(self.idle_textures):
                self.current_texture = 0
            self.texture = self.idle_textures[self.current_texture]
        else:
            # Walking animation
            self.current_texture += 1
            if self.current_texture >= len(self.walk_textures):
                self.current_texture = 0
            self.texture = self.walk_textures[self.current_texture]

Collision System

Basic Collisions

def on_update(self, delta_time):
    self.player_list.update()
    self.enemy_list.update()
    self.bullet_list.update()
    
    # Bullet‑enemy collisions
    for bullet in self.bullet_list:
        hit_list = arcade.check_for_collision_with_list(bullet, self.enemy_list)
        if hit_list:
            bullet.remove_from_sprite_lists()
            for enemy in hit_list:
                enemy.remove_from_sprite_lists()
                self.score += 10
                
    # Player‑enemy collisions
    hit_list = arcade.check_for_collision_with_list(self.player, self.enemy_list)
    if hit_list:
        self.game_over = True

Advanced Collisions

def check_collision_with_walls(self, sprite, wall_list):
    """Check collision with walls considering movement direction"""
    collision_list = arcade.check_for_collision_with_list(sprite, wall_list)
    
    for wall in collision_list:
        if sprite.change_x > 0:  # Moving right
            sprite.right = wall.left
        elif sprite.change_x < 0:  # Moving left
            sprite.left = wall.right
            
        if sprite.change_y > 0:  # Moving up
            sprite.top = wall.bottom
        elif sprite.change_y < 0:  # Moving down
            sprite.bottom = wall.top

Physics Engines

Platformer Physics

def setup(self):
    # Create platformer physics engine
    self.physics_engine = arcade.PhysicsEnginePlatformer(
        self.player_sprite,
        gravity_constant=0.5,
        walls=self.wall_list
    )
    
def on_update(self, delta_time):
    # Update physics
    self.physics_engine.update()
    
    # Jump (only if player is on the ground)
    if self.physics_engine.can_jump():
        self.player_sprite.change_y = 15

PyMunk Physics

import arcade.pymunk_physics_engine

def setup(self):
    # Create PyMunk physics engine
    damping = 1.0
    gravity = (0, -900)
    self.physics_engine = arcade.pymunk_physics_engine.PymunkPhysicsEngine(
        damping=damping,
        gravity=gravity
    )
    
    # Add static objects
    self.physics_engine.add_sprite_list(
        self.wall_list,
        friction=0.6,
        collision_type="wall",
        body_type=arcade.pymunk_physics_engine.PymunkPhysicsEngine.STATIC
    )
    
    # Add dynamic objects
    self.physics_engine.add_sprite(
        self.player_sprite,
        friction=0.6,
        mass=1.0,
        collision_type="player"
    )

Camera and Viewport Management

Following the Player

def setup(self):
    self.camera = arcade.Camera(self.width, self.height)
    
def on_update(self, delta_time):
    # Center camera on player
    self.camera.move_to(
        (self.player_sprite.center_x - self.width // 2,
         self.player_sprite.center_y - self.height // 2),
        speed=0.1
    )
    
def on_draw(self):
    self.camera.use()
    
    # Draw game objects
    self.wall_list.draw()
    self.player_list.draw()
    self.enemy_list.draw()

Loading and Working with Tile Maps

Using Tiled Map Editor

def setup(self):
    # Load TMX map file
    map_name = "maps/level_1.tmx"
    my_map = arcade.tilemap.read_tmx(map_name)
    
    # Create scene from map
    self.scene = arcade.Scene.from_tilemap(my_map)
    
    # Retrieve layers
    self.wall_list = self.scene.get_sprite_list("Walls")
    self.coin_list = self.scene.get_sprite_list("Coins")
    self.background_list = self.scene.get_sprite_list("Background")
    
    # Add player to scene
    self.scene.add_sprite("Player", self.player_sprite)

Sound System

Loading and Playing Sounds

def setup(self):
    # Load sound files
    self.jump_sound = arcade.load_sound("sounds/jump.wav")
    self.coin_sound = arcade.load_sound("sounds/coin.wav")
    self.background_music = arcade.load_sound("sounds/background.mp3")
    
    # Play background music
    arcade.play_sound(self.background_music, volume=0.5, looping=True)
    
def collect_coin(self):
    # Play sound when collecting a coin
    arcade.play_sound(self.coin_sound, volume=0.7)

Particle Systems and Effects

Creating a Particle System

class ParticleSystem:
    def __init__(self):
        self.particles = []
        
    def add_explosion(self, x, y):
        for _ in range(20):
            particle = {
                'x': x,
                'y': y,
                'velocity_x': random.uniform(-5, 5),
                'velocity_y': random.uniform(-5, 5),
                'life': 60,
                'color': random.choice([arcade.color.RED, arcade.color.ORANGE, arcade.color.YELLOW])
            }
            self.particles.append(particle)
            
    def update(self):
        for particle in self.particles[:]:
            particle['x'] += particle['velocity_x']
            particle['y'] += particle['velocity_y']
            particle['life'] -= 1
            
            if particle['life'] <= 0:
                self.particles.remove(particle)
                
    def draw(self):
        for particle in self.particles:
            arcade.draw_circle_filled(
                particle['x'], particle['y'], 3, particle['color']
            )

Table of Core Arcade Methods and Functions

Category Method / Function Description Example Usage
Window & Rendering arcade.Window() Create a game window class Game(arcade.Window):
  arcade.run() Start the game loop arcade.run()
  arcade.start_render() Begin frame rendering arcade.start_render()
  self.clear() Clear the screen self.clear()
  arcade.set_background_color() Set background color arcade.set_background_color(arcade.color.BLUE)
Sprites arcade.Sprite() Create a sprite sprite = arcade.Sprite("image.png", 0.5)
  arcade.SpriteList() Create a sprite list sprite_list = arcade.SpriteList()
  sprite_list.draw() Draw a sprite list self.player_list.draw()
  sprite_list.update() Update a sprite list self.enemy_list.update()
  sprite.remove_from_sprite_lists() Remove sprite from all lists enemy.remove_from_sprite_lists()
Textures arcade.load_texture() Load a texture texture = arcade.load_texture("image.png")
  arcade.load_texture_pair() Load a pair of textures (e.g., left/right) textures = arcade.load_texture_pair("sprite.png")
Collisions arcade.check_for_collision() Check collision between two sprites if arcade.check_for_collision(player, enemy):
  arcade.check_for_collision_with_list() Check collision against a sprite list hits = arcade.check_for_collision_with_list(bullet, enemies)
  arcade.get_sprites_at_point() Get sprites at a specific point sprites = arcade.get_sprites_at_point((x, y), sprite_list)
Primitives arcade.draw_circle_filled() Draw a filled circle arcade.draw_circle_filled(x, y, radius, color)
  arcade.draw_rectangle_filled() Draw a filled rectangle arcade.draw_rectangle_filled(x, y, width, height, color)
  arcade.draw_line() Draw a line arcade.draw_line(x1, y1, x2, y2, color, width)
  arcade.draw_text() Draw text on screen arcade.draw_text("Hello", x, y, color, size)
Physics arcade.PhysicsEnginePlatformer() Create a platformer physics engine physics = arcade.PhysicsEnginePlatformer(player, walls)
  arcade.PhysicsEngineSimple() Create a simple physics engine physics = arcade.PhysicsEngineSimple(player, walls)
  physics_engine.update() Update the physics engine self.physics_engine.update()
Sound arcade.load_sound() Load a sound file sound = arcade.load_sound("sound.wav")
  arcade.play_sound() Play a sound arcade.play_sound(sound, volume=0.5)
Maps arcade.tilemap.read_tmx() Read a TMX map file my_map = arcade.tilemap.read_tmx("level.tmx")
  arcade.Scene.from_tilemap() Create a scene from a tile map scene = arcade.Scene.from_tilemap(my_map)
Camera arcade.Camera() Create a camera camera = arcade.Camera(width, height)
  camera.move_to() Move the camera camera.move_to((x, y), speed=0.1)
  camera.use() Activate the camera for rendering self.camera.use()
Events on_draw() Frame rendering method def on_draw(self):
  on_update() Logic update method def on_update(self, delta_time):
  on_key_press() Handle key press events def on_key_press(self, key, modifiers):
  on_mouse_press() Handle mouse click events def on_mouse_press(self, x, y, button, modifiers):
Math arcade.get_distance() Calculate distance between two points distance = arcade.get_distance(x1, y1, x2, y2)
  arcade.get_angle_degrees() Calculate angle in degrees angle = arcade.get_angle_degrees(x1, y1, x2, y2)

Frequently Asked Questions

How can I optimize game performance in Arcade?

Use SpriteList with use_spatial_hash=True for large numbers of sprites, employ texture atlases to reduce OpenGL calls, and avoid creating new objects inside the update loop.

Can Arcade be used for mobile platforms?

Currently Arcade is optimized for desktop platforms. For mobile development, consider specialized frameworks such as Kivy or pygame‑based solutions.

How do I add gamepad support in Arcade?

Arcade provides built‑in gamepad support via on_joybutton_press(), on_joybutton_release(), and on_joyaxis_motion(). Use the arcade.joysticks module to work with controllers.

What is the main difference between Arcade and Pygame?

Arcade uses modern OpenGL for rendering, offers a cleaner object‑oriented API, includes built‑in animation and physics support, and delivers better performance with large sprite counts.

Project Examples for Learning

Simple Platformer

Create a game where a character can jump across platforms, collect items, and avoid obstacles. Use PhysicsEnginePlatformer for realistic physics.

Space Shooter

Develop an arcade‑style space shooter where a ship fires at asteroids and enemy vessels. Add a particle system for explosions and sound effects.

Top‑Down Puzzle

Build a top‑down maze game where the player collects keys and opens doors. Use tiled maps to design levels.

RPG with Dialogues

Develop a simple role‑playing game featuring dialogue systems, inventory, and combat. Explore state management and UI design.

Integration with External Libraries

Working with Databases

import sqlite3

class GameData:
    def __init__(self):
        self.conn = sqlite3.connect('gamedata.db')
        self.create_tables()
        
    def save_score(self, player_name, score):
        cursor = self.conn.cursor()
        cursor.execute("INSERT INTO scores (name, score) VALUES (?, ?)", 
                      (player_name, score))
        self.conn.commit()

Network Interaction

import socket
import threading

class NetworkManager:
    def __init__(self):
        self.socket = socket.socket(socket.AF_INET, socket.SOCK_TCP)
        self.connected = False
        
    def connect_to_server(self, host, port):
        try:
            self.socket.connect((host, port))
            self.connected = True
            threading.Thread(target=self.listen_for_messages).start()
        except Exception as e:
            print(f"Connection error: {e}")

Best Development Practices

Code Organization

Separate code into modules: distinct files for sprites, scenes, physics, and utilities. Use inheritance to create specialized sprite classes.

Resource Management

Load resources once during initialization and reuse them. Use arcade.load_texture() with caching to conserve memory.

Debugging and Testing

Take advantage of Arcade’s built‑in debugging tools, such as FPS display and sprite statistics. Add logging to track game state.

Conclusion

Arcade is a powerful, modern tool for developing 2D games in Python. With its clean API, high performance, and extensive feature set, the library is suitable both for learning game development fundamentals and for building full‑scale commercial projects.

A vibrant ecosystem, active community, and continuous development make Arcade an excellent choice for developers who want to create high‑quality 2D games using modern technologies. Start with simple projects and gradually explore the library’s advanced capabilities to craft unique gaming experiences.

News