中文 | English
Scrawl 提供了一个类 Godot 的可视化 IDE,让游戏开发更加直观便捷!
- 🎨 可视化场景编辑器 - 拖拽精灵、实时预览
- 📝 内置代码编辑器 - 语法高亮、即时编辑
- 🎮 一键运行 - 直接在 IDE 中测试游戏
- 🔧 属性检查器 - 可视化调整精灵和场景属性
- 🤖 AI 编程助手 - 配置 API Key 后,AI 可以帮你编写和修改游戏代码!
⚠️ 注意:Scrawl IDE 目前处于初步开发阶段,功能持续完善中,欢迎反馈建议!
为感谢大家的支持,我们为大家提供了免费的 AI API,无需自行配置即可体验 AI 编程助手!
- 🆓 开箱即用 - 默认选择免费模型,无需配置 API Key
- 🤖 多模型可选 - 提供 Gemini、GLM、Kimi、MiniMax 等多种免费模型
- ⏱️ 每日限额 - 每个模型每日 500 次调用(所有用户共享)
- ⚙️ 支持自定义 - 也可在设置中配置自己的 OpenAI 兼容 API
- 💬 智能对话 - 用自然语言描述需求,AI 自动生成代码
- ✏️ 代码修改 - AI 可以直接修改精灵和场景的代码
- 🎛️ 属性调整 - AI 可以修改精灵位置、大小等属性
- 📋 一键应用 - 点击"应用"按钮即可将 AI 生成的代码更新到项目中
第一次AI对话:
2026-01-23.212440.mp4
四次AI对话后成品:
2026-01-23.214005_2026.01.23-21.46.08.mp4
Scrawl 是一个基于 Pygame 的类 Scratch 游戏引擎,旨在为开发者提供类似 Scratch 的直观编程体验,同时利用 Python 的强大功能。
女巫游戏: https://github.com/streetartist/scrawl_demo_witch
- 🧩 类 Scratch 开发范式: 使用装饰器标记主协程、克隆协程和事件处理协程
- 🎮 内置游戏对象系统: 开箱即用的精灵、场景、粒子系统等
- ⚙️ 物理引擎集成: 支持速度、重力、弹性等物理属性
- 📻 广播消息系统: 组件间通信机制
- 🔧 调试工具: 实时显示 FPS、精灵数量等调试信息
- 🎨 绘图工具: 支持画笔绘制
- 🚀 协程任务系统: 协程机制支持直观的
while True循环
pip install scrawl-engine升级到最新版本:
pip install --upgrade scrawl-engine克隆代码库:
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 助手快速创建游戏!
以下代码演示了 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)2025-06-16.161101.mp4
示例 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()demo.mp4
- 处理事件循环
- 管理场景切换
- 控制帧率和调试信息
- 作为游戏容器
- 管理精灵和粒子系统
- 处理全局事件和广播消息
- 基本游戏实体
- 支持位置、方向、大小等属性
- 物理精灵支持速度、重力等物理属性
move(),goto(),turn_left(),turn_right()say(),clone(),delete_self()apply_impulse(),set_gravity()(物理精灵)
- 广播机制: 组件间通信
- 按键绑定: 全局和场景级别绑定
- 精灵事件: 支持碰撞检测
- 核心概念
- Game 类
- Scene 类
- Sprite 类
- 事件处理
- 按键事件
- 碰撞检测
- 广播事件
- 精灵克隆
- 创建克隆
- 克隆行为
- 资源管理
- 添加图片
- 使用字体
- 高级功能
- 物理精灵
- 粒子系统
- 画笔效果
- 调试工具
- 调试模式
- 性能监控
游戏主控制器,负责初始化和运行游戏循环:
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)游戏场景容器,管理精灵和粒子系统:
class MyScene(Scene):
def __init__(self):
super().__init__()
# 添加精灵
self.add_sprite(MySprite())
@as_main
def main1():
pass # 场景主函数
# 设置场景
game.set_scene(MyScene())游戏中的基本元素,具有位置、方向、大小等属性:
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



