scrawl-engine


Namescrawl-engine JSON
Version 0.12.12 PyPI version JSON
download
home_pagehttp://github.com/streetartist/scrawl
SummaryWrite game like Scratch
upload_time2025-09-03 11:14:17
maintainerNone
docs_urlNone
authorStreetartist
requires_python>=3
licenseNone
keywords game engine
VCS
bugtrack_url
requirements pygame-ce requests numpy
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # Scrawl - A Scratch-like Python Game Engine

[中文](README_zh.md) | English

For Chinese documentation, click **中文**. Scrawl QQ 交流群: **1001578435**

<img src="https://github.com/user-attachments/assets/f3e9e30b-7132-47e6-abd5-c39332a920be" width="200" />

Scrawl is a Scratch-like game engine based on Pygame, designed to provide developers with an intuitive programming experience similar to Scratch, while leveraging Python's powerful capabilities.

## Best Demo

Witch Game: https://github.com/streetartist/scrawl_demo_witch

## Core Features

-   🧩 **Scratch-like Development Paradigm**: Use decorators to mark main coroutines, clone coroutines, and event handler coroutines
-   🎮 **Built-in Game Object System**: Ready-to-use sprites, scenes, particle systems, and more
-   ⚙️ **Physics Engine Integration**: Supports physical properties like velocity, gravity, elasticity, etc.
-   📻 **Broadcast Messaging System**: Component communication mechanism
-   🔧 **Debugging Tools**: Real-time display of FPS, sprite count, and other debug information
-   🎨 **Drawing Tools**: Supports pen drawing
-   🚀 **Coroutine Task System**: Coroutine mechanism supports intuitive `while True` loops

## Quick Start

The following code demonstrates the basic usage of Scrawl:

**Example 1:**

```python
from scrawl import *
import pygame

# svg files from https://scratch.mit.edu/projects/239626199/editor/

# Create game instance
game = Game()

class Bat(Sprite):
    def __init__(self):
        super().__init__()
        self.name = "Bat"
        self.add_costume("costume1", pygame.image.load("bat2-b.svg").convert_alpha())
        self.add_costume("costume2", pygame.image.load("bat2-a.svg").convert_alpha())
        self.visible = False
        self.set_size(0.5)

    @as_clones
    def clones1(self):
        self.pos = pygame.Vector2(400, 300)
        self.face_random_direction()
        self.move(400)
        self.face_towards("Witch")
        self.visible = True
        while True:
            self.next_costume()
            yield 300

    @as_clones
    def clones2(self):
        while True:
            self.move(5)
            yield 200

    @as_main
    def main1(self):
        while True:
            yield 3000
            # Add bat
            self.clone()

    @handle_edge_collision()
    def finish(self):
        self.delete_self()

    @handle_sprite_collision("FireBall")
    def hit_fireball(self, other):
        self.delete_self()

    @handle_sprite_collision("Witch")
    def hit_witch(self, other):
        self.delete_self()

class FireBall(Sprite):
    def __init__(self):
        super().__init__()
        self.name = "FireBall"
        self.add_costume("costume1", pygame.image.load("ball-a.svg").convert_alpha())
        self.visible = False
        self.set_size(0.2)

    @as_clones
    def clones1(self):
        self.visible = True
        while True:
            self.move(10)
            yield 100

    @handle_edge_collision()
    def finish(self):
        self.delete_self()

class Witch(Sprite):
    def __init__(self):
        super().__init__()
        self.name = "Witch"
        self.add_costume("costume1", pygame.image.load("witch.svg").convert_alpha())
        self.fireball = FireBall()

    @on_key(pygame.K_s, "held")
    def right_held(self):
        self.turn_right(2)

    @on_key(pygame.K_d, "held")
    def left_held(self):
        self.turn_left(2)

    @on_key(pygame.K_SPACE, "held")
    def space_pressed(self):
        self.fireball.direction = self.direction
        self.clone(self.fireball)

# Define scene
class MyScene(Scene):
    def __init__(self):
        super().__init__()
        bat = Bat()
        self.add_sprite(bat)
        witch = Witch()
        self.add_sprite(witch)

# Run game
game.set_scene(MyScene())
game.run(fps=60)
```

*The video appears slow due to VNC recording. Runs quite smoothly when sprite count is below 200.*

https://github.com/user-attachments/assets/7398ac8f-689e-4088-9d78-414272c99438

**Example 2:**

```python
from scrawl import Game, Scene, Sprite, Cat, as_main

# Create game instance
game = Game()

class MyCat(Cat):
    def __init__(self):
        super().__init__()

    @as_main
    def main1(self):
        while True:
            self.walk()
            yield 500

# Define scene
class MyScene(Scene):
    def __init__(self):
        super().__init__()
        # Add sprite
        cat = MyCat()
        self.add_sprite(cat)

# Run game
game.set_scene(MyScene())
game.run()
```

![Screen Capture 2025-06-15 090207](https://github.com/user-attachments/assets/2842db4a-147a-466e-ad69-4d74c24ba4b4)

**Example 3:**

```python
from scrawl import *
import time

# Create game instance
game = Game()

class Ball(Sprite):
    def __init__(self):
        super().__init__()

    @as_main
    def main1(self):
        while True:
            self.turn_left(10)
            self.move(10)
            yield 100
            self.clone()

    @as_clones
    def clones1(self):
        while True:
            self.turn_right(10)
            self.move(100)
            self.change_color_random()
            yield 1000

    @handle_broadcast("event")
    def event1(self):
        self.say("hello")

# Define scene
class MyScene(Scene):
    def __init__(self):
        super().__init__()
        # Add sprite
        ball = Ball()
        self.add_sprite(ball)

    @as_main
    def main1(self):
        while True:
            # Add particle system
            explosion = ParticleSystem(400, 300)
            self.add_particles(explosion)  # Add particle system to scene
            self.broadcast("event")
            yield 3000

# Run game
game.set_scene(MyScene())
game.run()
```

https://github.com/user-attachments/assets/ef1a03d8-28b6-4bff-acf7-5f96be02f35a

## Core Concepts

### 1. Game Main Loop (`Game` Class)
-   Handles event loop
-   Manages scene switching
-   Controls frame rate and debug information

### 2. Scene (`Scene` Class)
-   Serves as game container
-   Manages sprites and particle systems
-   Handles global events and broadcast messages

### 3. Sprite (`Sprite` and `PhysicsSprite` Classes)
-   Basic game entities
-   Support properties like position, direction, size
-   Physics sprites support velocity, gravity, and other physical properties

#### Common Methods:
-   `move()`, `goto()`, `turn_left()`, `turn_right()`
-   `say()`, `clone()`, `delete_self()`
-   `apply_impulse()`, `set_gravity()` (for physics sprites)

### 4. Event System
-   **Broadcast Mechanism**: Component communication
-   **Key Binding**: Global and scene-level bindings
-   **Sprite Events**: Supports collision detection

## Documentation Index

1.  **Core Class Reference**
    -   Game - Game Controller
    -   Scene - Game Scene
    -   Sprite - Base Sprite Class
    -   PhysicsSprite - Physics Sprite Class
2.  **Decorator System**
    -   `@as_main` - Marks main behavior coroutine
    -   `@as_clones` - Marks clone behavior
    -   `@handle_broadcast` - Broadcast handler
3.  **Advanced Features**
    -   Particle Systems
    -   Drawing Tools
    -   Collision Detection
    -   Physics System

## Installation

```bash
pip install scrawl-engine
```

Upgrade

```bash
pip install --upgrade scrawl-engine
```

## Development Documentation (Tentative Version)

# Scrawl Library Usage Documentation

## Table of Contents

- Core Concepts
  - Game Class
  - Scene Class
  - Sprite Class
- Event Handling
  - Key Events
  - Collision Detection
  - Broadcast Events
- Sprite Cloning
  - Creating Clones
  - Clone Behavior
- Resource Management
  - Adding Images
  - Using Fonts
- Advanced Features
  - Physics Sprites
  - Particle Systems
  - Pen Effects
- Debugging Tools
  - Debug Mode
  - Performance Monitoring

---

## Core Concepts
### Game Class
Main game controller responsible for initialization and running game loop:
```python
game = Game(
    width=800, 
    height=600, 
    title="Game Title",
    font_path="font.ttf",
    font_size=20,
    fullscreen=False
)
game.set_scene(MyScene()) # Set scene
game.run(fps=60, debug=True)
```

### Scene Class
Game scene container for managing sprites and particle systems:
```python
class MyScene(Scene):
    def __init__(self):
        super().__init__()
        # Add sprite
        self.add_sprite(MySprite())
    
    @as_main    
    def main1():
        pass # Scene main function
# Set scene
game.set_scene(MyScene())
```

### Sprite Class
Basic elements in the game with properties like position, direction, size:
```python
class MySprite(Sprite):
    def __init__(self):
        super().__init__()
        self.name = "Sprite Name"
        self.pos = pygame.Vector2(100, 100)
        self.direction = 90  # 0=right, 90=up
        self.size = 1.0
        self.visible = True

    @as_main   
    def main1(self):
        while True:
            # Sprite main function
            self.move(5)
            yield 2000 # Delay 2000ms
```
---
## Event Handling
### Key Events
Handle key events using decorators:
```python
@on_key(pygame.K_SPACE, "pressed")  # Triggered on press
def space_pressed(self):
    print("Space pressed")
@on_key(pygame.K_LEFT, "held")  # Continuously triggered while held
def left_held(self):
    self.turn_left(2)
```

### Collision Detection
Handle collisions between sprites and with boundaries:
```python
# Edge collision detection
@handle_edge_collision("left")  # Collide with left edge
def hit_left(self):
    self.say("Hit left wall")
# Sprite collision detection
@handle_sprite_collision("Enemy")  # Collide with sprite named "Enemy"
def hit_enemy(self, other):
    self.delete_self()
```

### Broadcast Events
Communication mechanism between sprites and scenes:
```python
# Broadcast event
self.broadcast("gameover")
# Handle broadcast event
@handle_broadcast("gameover")
def on_gameover(self):
    self.visible = True
```
---
## Sprite Cloning
### Creating Clones
Clone existing sprites:
```python
# Clone self
self.clone()
# Clone other sprite
self.clone(other_sprite)
```

### Clone Behavior
Define logic specific to clones:
```python
class Bat(Sprite):
    @as_clones  # Mark as clone task
    def clones_behavior(self):
        self.visible = True
        while True:
            self.move(5)
            yield 200  # Move every 200ms
```
---
## Resource Management
### Adding Images
Add multiple costumes for sprites:
```python
self.add_costume("costume1", pygame.image.load("cat1.svg"))
self.add_costume("costume2", pygame.image.load("cat2.svg"))
self.switch_costume("costume1")  # Switch costume
self.next_costume()  # Switch to next costume
```

### Using Fonts
Game font settings:
```python
game = Game(
    font_path="Simhei.ttf",  # Supports Chinese fonts
    font_size=20
)
```
---
## Advanced Features
### Physics Sprites
Sprites with physical properties (velocity, gravity, friction):
```python
class PhysicsBall(PhysicsSprite):
    def __init__(self):
        super().__init__()
        self.velocity = pygame.Vector2(0, 5)
        self.gravity = pygame.Vector2(0, 0.2)
        self.elasticity = 0.8  # Elasticity coefficient
```

### Particle Systems
Create particle effects:
```python
# Create particle system at specified position
self.scene.add_particles(
    ParticleSystem(
        x=100, 
        y=100, 
        count=50,
        life_range=(500, 1500)
    )
)
```

### Pen Effects
Implement drawing functionality:
```python
# Enable pen
self.pen_down = True
self.pen_color = (255, 0, 0)
self.pen_size = 3
# Automatically record path when moving
self.move(100)
# Clear pen trails
self.clear_pen()
```
---
## Debugging Tools
### Debug Mode
Enable debug information display:
```python
game.run(debug=True)  # Enable debug mode
# Log debug information
game.log_debug("Sprite created")
```

### Performance Monitoring
Key performance metrics displayed on screen:
1. Real-time FPS
2. Number of sprites in scene
3. Current scene name
4. Custom debug information

## Contribution Guidelines

Welcome to submit issues and pull requests via GitHub:
https://github.com/streetartist/scrawl

---

            

Raw data

            {
    "_id": null,
    "home_page": "http://github.com/streetartist/scrawl",
    "name": "scrawl-engine",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3",
    "maintainer_email": null,
    "keywords": "game, engine",
    "author": "Streetartist",
    "author_email": "207148178@qq.com",
    "download_url": "https://files.pythonhosted.org/packages/5c/e2/ef215d2538f03587f93f5028178d33039215c54e6a34e58393c7484b9888/scrawl_engine-0.12.12.tar.gz",
    "platform": null,
    "description": "# Scrawl - A Scratch-like Python Game Engine\n\n[\u4e2d\u6587](README_zh.md) | English\n\nFor Chinese documentation, click **\u4e2d\u6587**. Scrawl QQ \u4ea4\u6d41\u7fa4: **1001578435**\n\n<img src=\"https://github.com/user-attachments/assets/f3e9e30b-7132-47e6-abd5-c39332a920be\" width=\"200\" />\n\nScrawl is a Scratch-like game engine based on Pygame, designed to provide developers with an intuitive programming experience similar to Scratch, while leveraging Python's powerful capabilities.\n\n## Best Demo\n\nWitch Game: https://github.com/streetartist/scrawl_demo_witch\n\n## Core Features\n\n-   \ud83e\udde9 **Scratch-like Development Paradigm**: Use decorators to mark main coroutines, clone coroutines, and event handler coroutines\n-   \ud83c\udfae **Built-in Game Object System**: Ready-to-use sprites, scenes, particle systems, and more\n-   \u2699\ufe0f **Physics Engine Integration**: Supports physical properties like velocity, gravity, elasticity, etc.\n-   \ud83d\udcfb **Broadcast Messaging System**: Component communication mechanism\n-   \ud83d\udd27 **Debugging Tools**: Real-time display of FPS, sprite count, and other debug information\n-   \ud83c\udfa8 **Drawing Tools**: Supports pen drawing\n-   \ud83d\ude80 **Coroutine Task System**: Coroutine mechanism supports intuitive `while True` loops\n\n## Quick Start\n\nThe following code demonstrates the basic usage of Scrawl:\n\n**Example 1:**\n\n```python\nfrom scrawl import *\nimport pygame\n\n# svg files from https://scratch.mit.edu/projects/239626199/editor/\n\n# Create game instance\ngame = Game()\n\nclass Bat(Sprite):\n    def __init__(self):\n        super().__init__()\n        self.name = \"Bat\"\n        self.add_costume(\"costume1\", pygame.image.load(\"bat2-b.svg\").convert_alpha())\n        self.add_costume(\"costume2\", pygame.image.load(\"bat2-a.svg\").convert_alpha())\n        self.visible = False\n        self.set_size(0.5)\n\n    @as_clones\n    def clones1(self):\n        self.pos = pygame.Vector2(400, 300)\n        self.face_random_direction()\n        self.move(400)\n        self.face_towards(\"Witch\")\n        self.visible = True\n        while True:\n            self.next_costume()\n            yield 300\n\n    @as_clones\n    def clones2(self):\n        while True:\n            self.move(5)\n            yield 200\n\n    @as_main\n    def main1(self):\n        while True:\n            yield 3000\n            # Add bat\n            self.clone()\n\n    @handle_edge_collision()\n    def finish(self):\n        self.delete_self()\n\n    @handle_sprite_collision(\"FireBall\")\n    def hit_fireball(self, other):\n        self.delete_self()\n\n    @handle_sprite_collision(\"Witch\")\n    def hit_witch(self, other):\n        self.delete_self()\n\nclass FireBall(Sprite):\n    def __init__(self):\n        super().__init__()\n        self.name = \"FireBall\"\n        self.add_costume(\"costume1\", pygame.image.load(\"ball-a.svg\").convert_alpha())\n        self.visible = False\n        self.set_size(0.2)\n\n    @as_clones\n    def clones1(self):\n        self.visible = True\n        while True:\n            self.move(10)\n            yield 100\n\n    @handle_edge_collision()\n    def finish(self):\n        self.delete_self()\n\nclass Witch(Sprite):\n    def __init__(self):\n        super().__init__()\n        self.name = \"Witch\"\n        self.add_costume(\"costume1\", pygame.image.load(\"witch.svg\").convert_alpha())\n        self.fireball = FireBall()\n\n    @on_key(pygame.K_s, \"held\")\n    def right_held(self):\n        self.turn_right(2)\n\n    @on_key(pygame.K_d, \"held\")\n    def left_held(self):\n        self.turn_left(2)\n\n    @on_key(pygame.K_SPACE, \"held\")\n    def space_pressed(self):\n        self.fireball.direction = self.direction\n        self.clone(self.fireball)\n\n# Define scene\nclass MyScene(Scene):\n    def __init__(self):\n        super().__init__()\n        bat = Bat()\n        self.add_sprite(bat)\n        witch = Witch()\n        self.add_sprite(witch)\n\n# Run game\ngame.set_scene(MyScene())\ngame.run(fps=60)\n```\n\n*The video appears slow due to VNC recording. Runs quite smoothly when sprite count is below 200.*\n\nhttps://github.com/user-attachments/assets/7398ac8f-689e-4088-9d78-414272c99438\n\n**Example 2:**\n\n```python\nfrom scrawl import Game, Scene, Sprite, Cat, as_main\n\n# Create game instance\ngame = Game()\n\nclass MyCat(Cat):\n    def __init__(self):\n        super().__init__()\n\n    @as_main\n    def main1(self):\n        while True:\n            self.walk()\n            yield 500\n\n# Define scene\nclass MyScene(Scene):\n    def __init__(self):\n        super().__init__()\n        # Add sprite\n        cat = MyCat()\n        self.add_sprite(cat)\n\n# Run game\ngame.set_scene(MyScene())\ngame.run()\n```\n\n![Screen Capture 2025-06-15 090207](https://github.com/user-attachments/assets/2842db4a-147a-466e-ad69-4d74c24ba4b4)\n\n**Example 3:**\n\n```python\nfrom scrawl import *\nimport time\n\n# Create game instance\ngame = Game()\n\nclass Ball(Sprite):\n    def __init__(self):\n        super().__init__()\n\n    @as_main\n    def main1(self):\n        while True:\n            self.turn_left(10)\n            self.move(10)\n            yield 100\n            self.clone()\n\n    @as_clones\n    def clones1(self):\n        while True:\n            self.turn_right(10)\n            self.move(100)\n            self.change_color_random()\n            yield 1000\n\n    @handle_broadcast(\"event\")\n    def event1(self):\n        self.say(\"hello\")\n\n# Define scene\nclass MyScene(Scene):\n    def __init__(self):\n        super().__init__()\n        # Add sprite\n        ball = Ball()\n        self.add_sprite(ball)\n\n    @as_main\n    def main1(self):\n        while True:\n            # Add particle system\n            explosion = ParticleSystem(400, 300)\n            self.add_particles(explosion)  # Add particle system to scene\n            self.broadcast(\"event\")\n            yield 3000\n\n# Run game\ngame.set_scene(MyScene())\ngame.run()\n```\n\nhttps://github.com/user-attachments/assets/ef1a03d8-28b6-4bff-acf7-5f96be02f35a\n\n## Core Concepts\n\n### 1. Game Main Loop (`Game` Class)\n-   Handles event loop\n-   Manages scene switching\n-   Controls frame rate and debug information\n\n### 2. Scene (`Scene` Class)\n-   Serves as game container\n-   Manages sprites and particle systems\n-   Handles global events and broadcast messages\n\n### 3. Sprite (`Sprite` and `PhysicsSprite` Classes)\n-   Basic game entities\n-   Support properties like position, direction, size\n-   Physics sprites support velocity, gravity, and other physical properties\n\n#### Common Methods:\n-   `move()`, `goto()`, `turn_left()`, `turn_right()`\n-   `say()`, `clone()`, `delete_self()`\n-   `apply_impulse()`, `set_gravity()` (for physics sprites)\n\n### 4. Event System\n-   **Broadcast Mechanism**: Component communication\n-   **Key Binding**: Global and scene-level bindings\n-   **Sprite Events**: Supports collision detection\n\n## Documentation Index\n\n1.  **Core Class Reference**\n    -   Game - Game Controller\n    -   Scene - Game Scene\n    -   Sprite - Base Sprite Class\n    -   PhysicsSprite - Physics Sprite Class\n2.  **Decorator System**\n    -   `@as_main` - Marks main behavior coroutine\n    -   `@as_clones` - Marks clone behavior\n    -   `@handle_broadcast` - Broadcast handler\n3.  **Advanced Features**\n    -   Particle Systems\n    -   Drawing Tools\n    -   Collision Detection\n    -   Physics System\n\n## Installation\n\n```bash\npip install scrawl-engine\n```\n\nUpgrade\n\n```bash\npip install --upgrade scrawl-engine\n```\n\n## Development Documentation (Tentative Version)\n\n# Scrawl Library Usage Documentation\n\n## Table of Contents\n\n- Core Concepts\n  - Game Class\n  - Scene Class\n  - Sprite Class\n- Event Handling\n  - Key Events\n  - Collision Detection\n  - Broadcast Events\n- Sprite Cloning\n  - Creating Clones\n  - Clone Behavior\n- Resource Management\n  - Adding Images\n  - Using Fonts\n- Advanced Features\n  - Physics Sprites\n  - Particle Systems\n  - Pen Effects\n- Debugging Tools\n  - Debug Mode\n  - Performance Monitoring\n\n---\n\n## Core Concepts\n### Game Class\nMain game controller responsible for initialization and running game loop:\n```python\ngame = Game(\n    width=800, \n    height=600, \n    title=\"Game Title\",\n    font_path=\"font.ttf\",\n    font_size=20,\n    fullscreen=False\n)\ngame.set_scene(MyScene()) # Set scene\ngame.run(fps=60, debug=True)\n```\n\n### Scene Class\nGame scene container for managing sprites and particle systems:\n```python\nclass MyScene(Scene):\n    def __init__(self):\n        super().__init__()\n        # Add sprite\n        self.add_sprite(MySprite())\n    \n    @as_main    \n    def main1():\n        pass # Scene main function\n# Set scene\ngame.set_scene(MyScene())\n```\n\n### Sprite Class\nBasic elements in the game with properties like position, direction, size:\n```python\nclass MySprite(Sprite):\n    def __init__(self):\n        super().__init__()\n        self.name = \"Sprite Name\"\n        self.pos = pygame.Vector2(100, 100)\n        self.direction = 90  # 0=right, 90=up\n        self.size = 1.0\n        self.visible = True\n\n    @as_main   \n    def main1(self):\n        while True:\n            # Sprite main function\n            self.move(5)\n            yield 2000 # Delay 2000ms\n```\n---\n## Event Handling\n### Key Events\nHandle key events using decorators:\n```python\n@on_key(pygame.K_SPACE, \"pressed\")  # Triggered on press\ndef space_pressed(self):\n    print(\"Space pressed\")\n@on_key(pygame.K_LEFT, \"held\")  # Continuously triggered while held\ndef left_held(self):\n    self.turn_left(2)\n```\n\n### Collision Detection\nHandle collisions between sprites and with boundaries:\n```python\n# Edge collision detection\n@handle_edge_collision(\"left\")  # Collide with left edge\ndef hit_left(self):\n    self.say(\"Hit left wall\")\n# Sprite collision detection\n@handle_sprite_collision(\"Enemy\")  # Collide with sprite named \"Enemy\"\ndef hit_enemy(self, other):\n    self.delete_self()\n```\n\n### Broadcast Events\nCommunication mechanism between sprites and scenes:\n```python\n# Broadcast event\nself.broadcast(\"gameover\")\n# Handle broadcast event\n@handle_broadcast(\"gameover\")\ndef on_gameover(self):\n    self.visible = True\n```\n---\n## Sprite Cloning\n### Creating Clones\nClone existing sprites:\n```python\n# Clone self\nself.clone()\n# Clone other sprite\nself.clone(other_sprite)\n```\n\n### Clone Behavior\nDefine logic specific to clones:\n```python\nclass Bat(Sprite):\n    @as_clones  # Mark as clone task\n    def clones_behavior(self):\n        self.visible = True\n        while True:\n            self.move(5)\n            yield 200  # Move every 200ms\n```\n---\n## Resource Management\n### Adding Images\nAdd multiple costumes for sprites:\n```python\nself.add_costume(\"costume1\", pygame.image.load(\"cat1.svg\"))\nself.add_costume(\"costume2\", pygame.image.load(\"cat2.svg\"))\nself.switch_costume(\"costume1\")  # Switch costume\nself.next_costume()  # Switch to next costume\n```\n\n### Using Fonts\nGame font settings:\n```python\ngame = Game(\n    font_path=\"Simhei.ttf\",  # Supports Chinese fonts\n    font_size=20\n)\n```\n---\n## Advanced Features\n### Physics Sprites\nSprites with physical properties (velocity, gravity, friction):\n```python\nclass PhysicsBall(PhysicsSprite):\n    def __init__(self):\n        super().__init__()\n        self.velocity = pygame.Vector2(0, 5)\n        self.gravity = pygame.Vector2(0, 0.2)\n        self.elasticity = 0.8  # Elasticity coefficient\n```\n\n### Particle Systems\nCreate particle effects:\n```python\n# Create particle system at specified position\nself.scene.add_particles(\n    ParticleSystem(\n        x=100, \n        y=100, \n        count=50,\n        life_range=(500, 1500)\n    )\n)\n```\n\n### Pen Effects\nImplement drawing functionality:\n```python\n# Enable pen\nself.pen_down = True\nself.pen_color = (255, 0, 0)\nself.pen_size = 3\n# Automatically record path when moving\nself.move(100)\n# Clear pen trails\nself.clear_pen()\n```\n---\n## Debugging Tools\n### Debug Mode\nEnable debug information display:\n```python\ngame.run(debug=True)  # Enable debug mode\n# Log debug information\ngame.log_debug(\"Sprite created\")\n```\n\n### Performance Monitoring\nKey performance metrics displayed on screen:\n1. Real-time FPS\n2. Number of sprites in scene\n3. Current scene name\n4. Custom debug information\n\n## Contribution Guidelines\n\nWelcome to submit issues and pull requests via GitHub:\nhttps://github.com/streetartist/scrawl\n\n---\n",
    "bugtrack_url": null,
    "license": null,
    "summary": "Write game like Scratch",
    "version": "0.12.12",
    "project_urls": {
        "Homepage": "http://github.com/streetartist/scrawl"
    },
    "split_keywords": [
        "game",
        " engine"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "1dec831b8e4b9041c52a135337311d52313b730825c71210bba3ef55fa12eeda",
                "md5": "4ebcd041bcb4404d71c7bf27e48793b0",
                "sha256": "36e3155a7f07aee7fb56774bbe3338bdc37788f2f01f11f3f715d2f293a1add9"
            },
            "downloads": -1,
            "filename": "scrawl_engine-0.12.12-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "4ebcd041bcb4404d71c7bf27e48793b0",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3",
            "size": 19393925,
            "upload_time": "2025-09-03T11:14:15",
            "upload_time_iso_8601": "2025-09-03T11:14:15.264922Z",
            "url": "https://files.pythonhosted.org/packages/1d/ec/831b8e4b9041c52a135337311d52313b730825c71210bba3ef55fa12eeda/scrawl_engine-0.12.12-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "5ce2ef215d2538f03587f93f5028178d33039215c54e6a34e58393c7484b9888",
                "md5": "0c349ba35274e686eb91e7269abce3ff",
                "sha256": "1aff7a3ab07d4bda2c4a98994890faa6a2cf74eb5bee524955a307115c4ab36e"
            },
            "downloads": -1,
            "filename": "scrawl_engine-0.12.12.tar.gz",
            "has_sig": false,
            "md5_digest": "0c349ba35274e686eb91e7269abce3ff",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3",
            "size": 19348224,
            "upload_time": "2025-09-03T11:14:17",
            "upload_time_iso_8601": "2025-09-03T11:14:17.522644Z",
            "url": "https://files.pythonhosted.org/packages/5c/e2/ef215d2538f03587f93f5028178d33039215c54e6a34e58393c7484b9888/scrawl_engine-0.12.12.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-09-03 11:14:17",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "streetartist",
    "github_project": "scrawl",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "requirements": [
        {
            "name": "pygame-ce",
            "specs": []
        },
        {
            "name": "requests",
            "specs": []
        },
        {
            "name": "numpy",
            "specs": []
        }
    ],
    "lcname": "scrawl-engine"
}
        
Elapsed time: 2.10558s