Write game like Scratch
Project description
Scrawl - 类 Scratch 的 Python 游戏引擎
中文 | English
热烈邀请大家到QQ群:1001578435交流!!!
✨ 交互式可视化 IDE
Scrawl 提供了一个类 Godot 的可视化 IDE,让游戏开发更加直观便捷!
- 🎨 可视化场景编辑器 - 拖拽精灵、实时预览
- 📝 内置代码编辑器 - 语法高亮、即时编辑
- 🎮 一键运行 - 直接在 IDE 中测试游戏
- 🔧 属性检查器 - 可视化调整精灵和场景属性
- 🤖 AI 编程助手 - 配置 API Key 后,AI 可以帮你编写和修改游戏代码!
🤖 AI 助手功能(新功能!)
⚠️ 注意:Scrawl IDE 目前处于初步开发阶段,功能持续完善中,欢迎反馈建议!
🎁 免费 AI API 试玩
为感谢大家的支持,我们为大家提供了免费的 AI API,无需自行配置即可体验 AI 编程助手!
- 🆓 开箱即用 - 默认选择免费模型,无需配置 API Key
- 🤖 多模型可选 - 提供 Gemini、GLM、Kimi、MiniMax 等多种免费模型
- ⏱️ 每日限额 - 每个模型每日 500 次调用(所有用户共享)
- ⚙️ 支持自定义 - 也可在设置中配置自己的 OpenAI 兼容 API
功能特性
- 💬 智能对话 - 用自然语言描述需求,AI 自动生成代码
- ✏️ 代码修改 - AI 可以直接修改精灵和场景的代码
- 🎛️ 属性调整 - AI 可以修改精灵位置、大小等属性
- 📋 一键应用 - 点击"应用"按钮即可将 AI 生成的代码更新到项目中
第一次AI对话:
https://github.com/user-attachments/assets/f58c2f57-b0d3-4aa7-a38b-742ec3046761
四次AI对话后成品:
https://github.com/user-attachments/assets/9d1c0071-3832-4b30-aa36-729c271c6749
简介
Scrawl 是一个基于 Pygame 的类 Scratch 游戏引擎,旨在为开发者提供类似 Scratch 的直观编程体验,同时利用 Python 的强大功能。
最佳示例
女巫游戏: https://github.com/streetartist/scrawl_demo_witch
核心特性
- 🧩 类 Scratch 开发范式: 使用装饰器标记主协程、克隆协程和事件处理协程
- 🎮 内置游戏对象系统: 开箱即用的精灵、场景、粒子系统等
- ⚙️ 物理引擎集成: 支持速度、重力、弹性等物理属性
- 📻 广播消息系统: 组件间通信机制
- 🔧 调试工具: 实时显示 FPS、精灵数量等调试信息
- 🎨 绘图工具: 支持画笔绘制
- 🚀 协程任务系统: 协程机制支持直观的
while True循环
快速开始
1. 安装 Scrawl 引擎
pip install scrawl-engine
升级到最新版本:
pip install --upgrade scrawl-engine
2. 使用可视化 IDE(推荐)
克隆代码库:
git clone https://github.com/streetartist/scrawl
cd scrawl
安装 IDE 依赖:
pip install -r scrawl_ide/requirements.txt
运行 IDE:
python scrawl_ide/main.py
即可启动可视化 IDE,通过拖拽和 AI 助手快速创建游戏!
3. 代码示例
以下代码演示了 Scrawl 的基本用法:
示例 1:
from scrawl import *
import pygame
# svg files from https://scratch.mit.edu/projects/239626199/editor/
# 创建游戏实例
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
# 添加蝙蝠
self.clone()
@on_edge_collision()
def finish(self):
self.delete_self()
@on_sprite_collision("FireBall")
def hit_fireball(self, other):
self.delete_self()
@on_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
@on_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)
# 定义场景
class MyScene(Scene):
def __init__(self):
super().__init__()
bat = Bat()
self.add_sprite(bat)
witch = Witch()
self.add_sprite(witch)
# 运行游戏
game.set_scene(MyScene())
game.run(fps=60)
https://github.com/user-attachments/assets/7398ac8f-689e-4088-9d78-414272c99438
示例 2:
from scrawl import Game, Scene, Sprite, Cat, as_main
# 创建游戏实例
game = Game()
class MyCat(Cat):
def __init__(self):
super().__init__()
@as_main
def main1(self):
while True:
self.walk()
yield 500
# 定义场景
class MyScene(Scene):
def __init__(self):
super().__init__()
# 添加精灵
cat = MyCat()
self.add_sprite(cat)
# 运行游戏
game.set_scene(MyScene())
game.run()
示例 3:
from scrawl import *
import time
# 创建游戏实例
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
@on_broadcast("event")
def event1(self):
self.say("hello")
# 定义场景
class MyScene(Scene):
def __init__(self):
super().__init__()
# 添加精灵
ball = Ball()
self.add_sprite(ball)
@as_main
def main1(self):
while True:
# 添加粒子系统
explosion = ParticleSystem(400, 300)
self.add_particles(explosion)
self.broadcast("event")
yield 3000
# 运行游戏
game.set_scene(MyScene())
game.run()
https://github.com/user-attachments/assets/ef1a03d8-28b6-4bff-acf7-5f96be02f35a
核心概念
1. 游戏主循环(Game 类)
- 处理事件循环
- 管理场景切换
- 控制帧率和调试信息
2. 场景(Scene 类)
- 作为游戏容器
- 管理精灵和粒子系统
- 处理全局事件和广播消息
3. 精灵(Sprite 和 PhysicsSprite 类)
- 基本游戏实体
- 支持位置、方向、大小等属性
- 物理精灵支持速度、重力等物理属性
常用方法:
move(),goto(),turn_left(),turn_right()say(),clone(),delete_self()apply_impulse(),set_gravity()(物理精灵)
4. 事件系统
- 广播机制: 组件间通信
- 按键绑定: 全局和场景级别绑定
- 精灵事件: 支持碰撞检测
开发文档
目录
- 核心概念
- Game 类
- Scene 类
- Sprite 类
- 事件处理
- 按键事件
- 碰撞检测
- 广播事件
- 精灵克隆
- 创建克隆
- 克隆行为
- 资源管理
- 添加图片
- 使用字体
- 高级功能
- 物理精灵
- 粒子系统
- 画笔效果
- 调试工具
- 调试模式
- 性能监控
核心概念
Game 类
游戏主控制器,负责初始化和运行游戏循环:
game = Game(
width=800,
height=600,
title="游戏标题",
font_path="font.ttf",
font_size=20,
fullscreen=False
)
game.set_scene(MyScene()) # 设置场景
game.run(fps=60, debug=True)
Scene 类
游戏场景容器,管理精灵和粒子系统:
class MyScene(Scene):
def __init__(self):
super().__init__()
# 添加精灵
self.add_sprite(MySprite())
@as_main
def main1():
pass # 场景主函数
# 设置场景
game.set_scene(MyScene())
Sprite 类
游戏中的基本元素,具有位置、方向、大小等属性:
class MySprite(Sprite):
def __init__(self):
super().__init__()
self.name = "精灵名称"
self.pos = pygame.Vector2(100, 100)
self.direction = 90 # 0=右, 90=上
self.size = 1.0
self.visible = True
@as_main
def main1(self):
while True:
# 精灵主函数
self.move(5)
yield 2000 # 延迟 2000ms
事件处理
按键事件
使用装饰器处理按键事件:
@on_key(pygame.K_SPACE, "pressed") # 按下时触发
def space_pressed(self):
print("空格键被按下")
@on_key(pygame.K_LEFT, "held") # 按住时持续触发
def left_held(self):
self.turn_left(2)
鼠标事件
处理鼠标点击事件:
@on_mouse("clicked", 1) # 鼠标左键点击
def on_click(self):
print("鼠标点击")
@on_sprite_clicked # 精灵被点击时触发
def on_self_clicked(self):
self.say("你点击了我!")
碰撞检测
处理精灵之间和边界的碰撞:
# 设置碰撞类型(rect/circle/mask)
self.set_collision_type("circle")
# 检测是否与其他精灵碰撞
if self.is_colliding_with(other_sprite):
print("碰撞了!")
# 检测是否触碰指定颜色
if self.is_touching_color((255, 0, 0)):
print("碰到红色了!")
# 边缘碰撞检测(装饰器)
@on_edge_collision("left") # 可选:left/right/top/bottom/any
def hit_left(self):
self.say("碰到左墙")
# 精灵碰撞检测(装饰器)
@on_sprite_collision("Enemy") # 与名为 "Enemy" 的精灵碰撞
def hit_enemy(self, other):
self.delete_self()
广播事件
精灵和场景之间的通信机制:
# 广播事件
self.broadcast("gameover")
# 处理广播事件
@on_broadcast("gameover")
def on_gameover(self):
self.visible = True
精灵克隆
创建克隆
克隆现有精灵:
# 克隆自身
self.clone()
# 克隆其他精灵
self.clone(other_sprite)
克隆行为
定义克隆体特有的逻辑:
class Bat(Sprite):
@as_clones # 标记为克隆任务
def clones_behavior(self):
self.visible = True
while True:
self.move(5)
yield 200 # 每 200ms 移动一次
资源管理
添加图片
为精灵添加多个造型:
self.add_costume("costume1", pygame.image.load("cat1.svg"))
self.add_costume("costume2", pygame.image.load("cat2.svg"))
self.switch_costume("costume1") # 切换造型
self.next_costume() # 切换到下一个造型
使用字体
游戏字体设置:
game = Game(
font_path="Simhei.ttf", # 支持中文字体
font_size=20
)
高级功能
物理精灵
具有物理属性(速度、重力、摩擦力)的精灵:
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 # 弹性系数
self.friction = 0.02 # 摩擦力
@as_main
def main(self):
# 设置物理属性
self.set_gravity(0, 0.5)
self.set_elasticity(0.9)
self.set_friction(0.1)
while True:
# 施加力
self.apply_force(1, 0)
# 施加冲量
self.apply_impulse(0, -10)
yield 0
粒子系统
创建粒子效果:
# 在指定位置创建粒子系统
self.scene.add_particles(
ParticleSystem(
x=100,
y=100,
count=50,
life_range=(500, 1500)
)
)
画笔效果
实现绘图功能:
# 启用画笔
self.put_pen_down()
self.set_pen_color((255, 0, 0))
self.set_pen_size(3)
# 移动时自动记录路径
self.move(100)
# 抬起画笔
self.put_pen_up()
# 清除画笔轨迹
self.clear_pen()
声音系统
播放音效和背景音乐:
# 在场景中加载音效和音乐
self.game.load_sound("jump", "sounds/jump.ogg")
self.game.load_music("bgm", "sounds/background.mp3")
# 播放音效
self.play_sound("jump")
# 播放背景音乐(循环)
self.play_music("bgm", loops=-1)
# 播放音符(C4-C5)
self.play_note("C4", 500)
# 播放鼓声(bass/snare/hihat/cymbal)
self.play_drum("snare", 100)
# 停止音乐
self.stop_music()
云变量
支持多人游戏的云变量同步:
from scrawl import CloudVariablesClient
# 方式1:自动注册新项目(获取新的project_id)
cloud = CloudVariablesClient()
print(f"项目ID: {cloud.project_id}") # 保存此ID以便下次使用
# 方式2:使用已有的项目ID
cloud = CloudVariablesClient(project_id="your-project-uuid")
# 设置变量
cloud.set_variable("score", 100)
# 获取变量
score = cloud.get_variable("score", default=0)
# 获取所有变量
all_vars = cloud.get_all_variables()
# 关闭连接
cloud.close()
注意:首次使用会自动注册项目并返回project_id,请保存此ID以便后续使用同一项目。
调试工具
调试模式
启用调试信息显示:
game.run(debug=True) # 启用调试模式
# 记录调试信息
game.log_debug("精灵已创建")
性能监控
屏幕上显示的关键性能指标:
- 实时 FPS
- 场景中精灵数量
- 当前场景名称
- 自定义调试信息
贡献指南
欢迎通过 GitHub 提交 issue 和 pull request: https://github.com/streetartist/scrawl
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file scrawl_engine-0.13.3.tar.gz.
File metadata
- Download URL: scrawl_engine-0.13.3.tar.gz
- Upload date:
- Size: 31.9 MB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b1e5abc2f1e8222a31d1f26f56dd2dc34fb2e2fddec24f522f8d545a7590e0a8
|
|
| MD5 |
fd3b7c4969a57788cb2cd289eae32d9f
|
|
| BLAKE2b-256 |
f46d5cee8575217d05888c67b68c70f3e51af09bfdf96a8caf1bc23d76d1a65d
|
File details
Details for the file scrawl_engine-0.13.3-py3-none-any.whl.
File metadata
- Download URL: scrawl_engine-0.13.3-py3-none-any.whl
- Upload date:
- Size: 19.4 MB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
96219d42899f7a972be9d2fc9d27bafa3134b432a30e71700a0a71f675d1311f
|
|
| MD5 |
170682302c80b34031f3e48eff798d9b
|
|
| BLAKE2b-256 |
733dfa7285f29e379bbfeccf5ba91a6c8f9869ae111e5125affd8bd185c164ba
|