# 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()
```

**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\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"
}