scenario-side-view-game-kit

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Scenario Side-View Game Kit

Scenario 侧视角游戏套件

Overview

概述

A side-scroller needs two families of image assets no single generation gives: pixel sprites that animate cleanly on one feet line, and painted level layers that stack into parallax and repeat without seams. This route comes from a browser side-scroller made in one agent session (one hero, two ground enemies, five levels):
  1. Characters. A text-to-image still with two poses on flat magenta (hero: rest and jump; enemy: rest and attack wind-up), reframed with headroom, then one 3 second image-to-video clip per cycle, the character running or walking "like a treadmill" in a pure side profile facing right. A local script keys the magenta, cuts a loop or one-shot window, and pixelates every cycle of a character onto one shared canvas and palette. Fall, wall cling, plunge and dash come from one pose sheet. Make one facing; the game mirrors it.
  2. Levels. Per level, five renders in "richly detailed high-resolution pixel art" (background, midground, wall texture, platform strip, props), made into WebP layers locally.
The finish is local on purpose: keying, the loop search, the shared palette and the seamless cross-fade need pixels on disk, and the deliverables are game files. If the user wants the finished strips on the platform too,
upload_asset
them into a collection.
Connection, scope and the core loop: the
scenario
skill. Frame tools, GIF previews and engine slicing:
scenario-sprite-animation
. Pixel cleanup and other statics:
scenario-game-assets
. Clip model families:
scenario-video
. Music and sound effects are outside this image skill. If a sibling skill named here is missing from your available skills, ask the user to install it (
npx skills add scenario-labs/skills --skill <name>
); unattended, proceed from tool schemas and flag the gap.
The agent runs the scripts locally (Python 3, Pillow, NumPy;
side_sprites.py
also needs ffmpeg): reframe_stills.py makes the clip first frames, side_sprites.py builds the strips and imports sprite_cycles.py (never run directly), and process_env.py finishes the level layers. Prompts with slots: references/prompt-templates.md. Read references/processing-settings.md before changing a script flag or when
--report
flags a loop.
横版卷轴游戏需要两类无法通过单次生成得到的图像资产:能在同一脚位线上流畅动画的像素sprite,以及可堆叠为视差效果且无缝重复的手绘关卡图层。这套流程来自于一次agent会话中制作的浏览器横版游戏(1个主角、2个地面敌人、5个关卡):
  1. 角色 先生成一张纯洋红背景、包含两个姿势的文生图静态图(主角:休息和跳跃;敌人:休息和攻击蓄力),调整构图留出顶部空间,然后为每个动画循环生成一段3秒的图生视频片段,角色以纯右侧面朝向“像在跑步机上”一样奔跑或行走。本地脚本会进行洋红抠图,裁剪出循环或单次动画的窗口,并将角色的每个循环动画像素化到同一个共享画布和调色板上。下落、攀墙、俯冲和冲刺的姿势来自同一张姿势表。只需制作一个朝向的版本,游戏会自动镜像翻转。
  2. 关卡 每个关卡生成5张“细节丰富的高分辨率像素艺术”渲染图(背景、中景、墙壁纹理、平台条、道具),在本地处理为WebP图层。
后期处理特意放在本地是有原因的:抠图、循环查找、共享调色板和无缝交叉淡入淡出都需要本地磁盘上的像素数据,且最终交付的是游戏文件。如果用户也想在平台上保存成品sprite条,可以使用
upload_asset
将它们上传到集合中。
连接、范围与核心循环由
scenario
skill提供。帧工具、GIF预览和引擎切片由
scenario-sprite-animation
提供。像素清理和其他静态资源由
scenario-game-assets
提供。视频片段模型系列由
scenario-video
提供。音乐和音效不在这个图像skill的范围内。如果你的可用skill中缺少这里提到的兄弟skill,请让用户安装(命令:
npx skills add scenario-labs/skills --skill <name>
);如果是无人值守模式,则根据工具schema继续执行并标记缺失项。
Agent会在本地运行脚本(需要Python 3、Pillow、NumPy;
side_sprites.py
还需要ffmpeg):reframe_stills.py用于生成视频片段的首帧,side_sprites.py用于构建sprite条并导入sprite_cycles.py(请勿直接运行),process_env.py用于完成关卡图层的处理。带占位符的提示词模板见:references/prompt-templates.md。在修改脚本参数或
--report
标记出循环问题前,请先阅读references/processing-settings.md。

Quick reference

快速参考

StepHowKeep when
Models
recommend
with
capability: "txt2img"
(stills, pose sheet, layers) or
"img2video"
plus
features: ["endImage"]
(clips), the user's words as
prompt
; then
model_schema_get
You know each schema's field names, enums and caps
Reframe and upload
reframe_stills.py
: figure 58% of a 960 square, feet at 82%;
upload_asset
+
upload_asset_complete
the rest frame, and the action frame for the hero's air spin
Headroom for a raised weapon or a somersault
Pose sheetText to image, chosen still as reference, 4 poses in a row on magentaSame design and palette as the strips
Price and wait
dry_run: true
per distinct payload, then
wait: false
for the batch and
jobs_wait
, re-called with
pending_job_ids
until done
The user heard the total before spending
Strips
side_sprites.py --report
, then without
--report
Loop seams (idle aside) under 0.6x baseline; no solid blocks
Level layersFive renders per level, level 1 firstDark lower middle, empty midground center, props apart
Level finish
process_env.py --env env --out assets --levels N
Texture tiles, ledge trims flat, prop count matches
DeliverStrips and pose images as lossless WebP plus
<name>_meta.json
(cell, feet anchor, fps); layers as lossy WebP
One anchor per character; nothing magenta at the edges
Payload names below (
startImage
,
endImage
,
referenceImages
,
background
,
quality
,
numOutputs
,
cfgScale
) are the build's schemas' examples: use the fields your pick's
model_schema_get
lists. The image pick needs strong layout adherence, a reference-image input, a transparent-background option and the template's 1536x1024; if its schema lacks one (a pixel-art specialty pick can cap far below that size), take the next ranked pick, even when
recommend
asks you to choose between such capped picks.
步骤操作方法保留条件
模型使用
recommend
接口,指定
capability: "txt2img"
(用于静态图、姿势表、图层)或
"img2video"
加上
features: ["endImage"]
(用于视频片段),将用户的描述作为
prompt
;然后调用
model_schema_get
你清楚每个schema的字段名、枚举值和能力上限
重设构图与上传
reframe_stills.py
:在960像素见方的画布中,人物占比58%,脚位在82%高度处;使用
upload_asset
+
upload_asset_complete
上传休息帧,以及主角空中旋转用的动作帧
需为举起的武器或空翻留出顶部空间
姿势表文生图,以选定的静态图为参考,在洋红背景上生成一排4个姿势需与sprite条保持相同的设计和调色板
费用与等待对每个不同的请求体先设置
dry_run: true
预估费用,然后批量提交时设置
wait: false
,调用
jobs_wait
,并用返回的
pending_job_ids
重复调用直到完成
需让用户在消费前知晓总费用
Sprite条先运行
side_sprites.py --report
检查,再去掉
--report
正式生成
循环接缝(待机除外)低于基线的0.6倍;无实心块
关卡图层每个关卡生成5张渲染图,先做第1关中下部偏暗、中景中心空旷、道具分散摆放
关卡最终处理运行
process_env.py --env env --out assets --levels N
纹理可平铺、平台边缘平整、道具数量符合要求
交付Sprite条和姿势图用无损WebP格式,附带
<name>_meta.json
(包含单元格、脚锚点、fps信息);图层用有损WebP格式
每个角色只有一个锚点;边缘无洋红色残留
下方的请求体参数名(
startImage
、
endImage
、
referenceImages
、
background
、
quality
、
numOutputs
、
cfgScale
)是构建版本schema的示例:请使用你所选模型的
model_schema_get
返回的字段列表。所选的图像模型需要具备强布局遵循能力、参考图输入功能、透明背景选项,且支持模板要求的1536x1024分辨率;如果其schema缺少其中一项(像素艺术专用模型的分辨率上限可能远低于该尺寸),则选择排名下一位的模型,即便
recommend
要求你在这类有上限的模型中做选择。

Worked example

实操示例

A user asks: "Make the art for my side-scroller: a fox knight hero with a rapier, a mole miner enemy with a pickaxe, and two levels, a mushroom forest and a crystal mine." Pass
team_id
and
project_id
on every call (the
scenario
skill covers picking them).
  1. Hero still.
    recommend { "capability": "txt2img", "prompt": "<the user's request>; needs reference image input, transparent output" }
    ,
    model_schema_get
    the pick, price the two-pose template (left: standing ready facing right; right: mid-jump facing right) with
    model_run { "model_id": "<pick>", "dry_run": true, "parameters": { "prompt": "...", "width": 1536, "height": 1024, "quality": "high", "background": "opaque", "numOutputs": 2 } }
    . Tell the user the price, run (
    jobs_wait
    with its
    job_id
    if it returns in progress),
    asset_display
    both takes; keep one with both poses on model, in a pure side profile (every clip inherits a three-quarter body), and nothing pink or purple,
    asset_download
    it and
    curl -L
    it to
    fox_two_pose.png
    .
  2. First frames.
    python3 scripts/reframe_stills.py fox_two_pose.png --name fox --out frames
    writes
    frames/fox_rest.png
    (left pose, the first frame of every ground clip) and
    frames/fox_action.png
    (the jump). Check both, then
    upload_asset { "file_name": "fox_rest.png", "content_type": "image/png", "kind": "image", "file_size": <bytes> }
    , PUT the parts,
    upload_asset_complete { "upload_id": "<id>" }
    ; same for the action frame, which only the air spin uses.
  3. Hero clips.
    recommend { "capability": "img2video", "features": ["endImage"], "prompt": "<the user's request>; square clip, no audio" }
    , then
    model_schema_get
    . One payload per cycle from the motion templates. With the build's schema:
    run:  { "prompt": "<run sentence> <facing and tail>", "negativePrompt": "<negative>, slowing down, stopping, standing still",
            "startImage": "<fox_rest id>", "duration": "3", "aspectRatio": "1:1", "generateAudio": false }
    atk1: { "prompt": "<attack: a fast rapier thrust ... returns to the starting ready pose> <facing and tail>", "negativePrompt": "<negative>",
            "startImage": "<fox_rest id>", "endImage": "<fox_rest id>", "duration": "3", "aspectRatio": "1:1", "generateAudio": false }
    Idle and hurt pin like the attack; the air spin uses the action id as both frames. Price each distinct payload with
    dry_run: true
    (first frame only, pinned, changed guidance), give the user the total, launch every clip with
    "wait": false
    , and collect them with one
    jobs_wait { "job_ids": [...] }
    , re-called with the returned
    pending_job_ids
    as
    job_ids
    while any is in progress (never poll
    job_get
    ).
    asset_download
    each (omit
    format
    on video) and save as
    clips/fox_<cycle>.mp4
    ,
    <cycle>
    being exactly the step 5
    --cycles
    name (
    run
    ,
    idle
    ,
    atk1
    ,
    spin
    ,
    hurt
    ). Review each as a local contact sheet (
    ffmpeg -i clips/fox_run.mp4 -vf "fps=6,scale=240:-1,tile=6x3" fox_run_sheet.png
    ), since
    asset_display
    shows no frames of a video; re-run only one that turns toward or away from the camera or travels.
  4. Pose sheet. Text to image with
    referenceImages: ["<chosen still id>"]
    and the pose-sheet template (fall, wall cling, plunge, dash). Price, tell the user, run, download as
    fox_poses.png
    .
  5. Strips.
    python3 scripts/side_sprites.py --clips clips --name fox --cycles run:loop:8,idle:loop:8,atk1:attack:7,spin:attack:8,hurt:attack:5 --report
    python3 scripts/side_sprites.py --clips clips --name fox --height 56 --palette 28 \
        --cycles run:loop:8,idle:loop:8,atk1:attack:7,spin:attack:8,hurt:attack:5 \
        --poses fox_poses.png --jump frames/fox_action.png --webp --out sprites
    View the strips at 4x, nearest-neighbor. If the slash trail keyed into a white block, re-run with
    --drop atk1=<index>
    (0-based) and
    --force
    .
  6. Enemy. Same route: two-pose still (rest, and an attack wind-up that keeps the design consistent), reframe, upload only
    mole_rest.png
    ; walk with the first frame only, the armed-enemy walk wording and a lower guidance such as
    cfgScale: 0.7
    if the schema has one; attack and hurt pinned.
    side_sprites.py --clips clips --name mole --height 72 --cycles walk:loop:8,attack:attack:8,hurt:attack:5 --report
    ; a walk flagged as a weak loop gets
    --range walk=12:48
    before any re-run.
  7. Level layers. Fill the five environment templates for the mushroom forest (opaque background and texture, the rest transparent).
    dry_run
    each distinct setting, tell the user the total, run, download as
    env/bg1.png
    ,
    env/mid1.png
    ,
    env/tex1.png
    ,
    env/ledge1.png
    ,
    env/props1.png
    , then
    python3 scripts/process_env.py --env env --out assets --levels 1
    . Put level 1 in the game with the fox on it before generating the crystal mine; process that one alone with
    --levels 2,
    (a bare
    2
    is a count and redoes level 1),
    --force
    after a re-render.
  8. Check. Play each strip at its fps from
    <name>_meta.json
    , tile the texture across a wall, and draw a long and a short platform.
用户请求:“为我的横版游戏制作美术资源:一个持细剑的狐狸骑士主角,一个持镐的鼹鼠矿工敌人,以及两个关卡:蘑菇森林和水晶矿。” 每次调用都需传递
team_id
和
project_id
(
scenario
skill会负责选择这些参数)。
  1. 主角静态图 调用
    recommend { "capability": "txt2img", "prompt": "<用户的请求>; needs reference image input, transparent output" }
    ,用
    model_schema_get
    获取所选模型的schema,然后使用
    model_run
    预估双姿势模板(左:朝右站立待命;右:朝右跳跃中途)的费用:
    model_run { "model_id": "<所选模型ID>", "dry_run": true, "parameters": { "prompt": "...", "width": 1536, "height": 1024, "quality": "high", "background": "opaque", "numOutputs": 2 } }
    。告知用户费用后执行任务(如果返回进行中状态,用
    job_id
    调用
    jobs_wait
    等待),用
    asset_display
    展示两个生成结果;保留一张同时包含两个姿势、纯侧面朝向(所有视频片段都会继承四分之三身体的视角)、且无任何粉色或紫色的结果,用
    asset_download
    下载,再通过
    curl -L
    保存为
    fox_two_pose.png
    。
  2. 首帧生成 运行
    python3 scripts/reframe_stills.py fox_two_pose.png --name fox --out frames
    ,会生成
    frames/fox_rest.png
    (左侧姿势,所有地面动画片段的首帧)和
    frames/fox_action.png
    (跳跃姿势)。检查两张图后,调用
    upload_asset { "file_name": "fox_rest.png", "content_type": "image/png", "kind": "image", "file_size": <字节数> }
    上传分片,再调用
    upload_asset_complete { "upload_id": "<上传ID>" }
    完成上传;动作帧也按同样步骤上传,它仅用于空中旋转动画。
  3. 主角视频片段 调用
    recommend { "capability": "img2video", "features": ["endImage"], "prompt": "<用户的请求>; square clip, no audio" }
    ,然后调用
    model_schema_get
    。每个动画循环对应一个请求体,模板来自动作模板。以下是构建版本schema的示例:
run:  { "prompt": "<run sentence> <facing and tail>", "negativePrompt": "<negative>, slowing down, stopping, standing still",
        "startImage": "<fox_rest id>", "duration": "3", "aspectRatio": "1:1", "generateAudio": false }
atk1: { "prompt": "<attack: a fast rapier thrust ... returns to the starting ready pose> <facing and tail>", "negativePrompt": "<negative>",
        "startImage": "<fox_rest id>", "endImage": "<fox_rest id>", "duration": "3", "aspectRatio": "1:1", "generateAudio": false }
待机动画和受击动画像攻击动画一样固定首尾帧;空中旋转动画的首尾帧都使用动作帧的ID。对每个不同的请求体用
dry_run: true
预估费用(仅首帧、固定首尾、调整引导强度),告知用户总费用后,用
"wait": false
提交所有视频片段任务,然后用一次
jobs_wait { "job_ids": [...] }
收集结果,只要还有任务在进行中,就用返回的
pending_job_ids
作为
job_ids
重复调用(切勿轮询
job_get
)。用
asset_download
下载每个视频(视频下载时省略
format
参数),保存为
clips/fox_<循环名>.mp4
,其中
<循环名>
必须与第5步
--cycles
参数中的名称完全一致(
run
、
idle
、
atk1
、
spin
、
hurt
)。由于
asset_display
无法显示视频帧,需要在本地生成联系表来检查每个视频(命令:
ffmpeg -i clips/fox_run.mp4 -vf "fps=6,scale=240:-1,tile=6x3" fox_run_sheet.png
);只有当角色朝向镜头转动、背向镜头或发生位移时,才重新生成对应的视频。
  1. 姿势表 使用文生图接口,传入
    referenceImages: ["<选定静态图的ID>"]
    和姿势表模板(下落、攀墙、俯冲、冲刺)。预估费用、告知用户后执行任务,下载保存为
    fox_poses.png
    。
  2. Sprite条生成
python3 scripts/side_sprites.py --clips clips --name fox --cycles run:loop:8,idle:loop:8,atk1:attack:7,spin:attack:8,hurt:attack:5 --report
python3 scripts/side_sprites.py --clips clips --name fox --height 56 --palette 28 \
    --cycles run:loop:8,idle:loop:8,atk1:attack:7,spin:attack:8,hurt:attack:5 \
    --poses fox_poses.png --jump frames/fox_action.png --webp --out sprites
用4倍最近邻缩放查看sprite条。如果斩击轨迹抠出了白色块,使用
--drop atk1=<索引>
(从0开始)和
--force
参数重新运行。
  1. 敌人 流程相同:生成双姿势静态图(休息姿势,以及保持设计一致的攻击蓄力姿势),重设构图后仅上传
    mole_rest.png
    ;行走动画仅使用首帧,使用武装敌人行走提示词,如果schema支持的话,使用较低的引导强度如
    cfgScale: 0.7
    ;攻击和受击动画固定首尾帧。运行
    side_sprites.py --clips clips --name mole --height 72 --cycles walk:loop:8,attack:attack:8,hurt:attack:5 --report
    ;如果行走循环被标记为弱循环,在重新运行前添加
    --range walk=12:48
    参数。
  2. 关卡图层 为蘑菇森林关卡填写5个环境模板(背景和纹理为不透明,其余为透明)。对每个不同的设置用
    dry_run
    预估费用,告知用户总费用后执行任务,下载保存为
    env/bg1.png
    、
    env/mid1.png
    、
    env/tex1.png
    、
    env/ledge1.png
    、
    env/props1.png
    ,然后运行
    python3 scripts/process_env.py --env env --out assets --levels 1
    。在生成水晶矿关卡前,先将第1关和狐狸主角放入游戏中测试;处理第2关时使用
    --levels 2,
    参数(单独的
    2
    表示关卡数量,会重新处理第1关),重新渲染后添加
    --force
    参数。
  3. 检查 按照
    <name>_meta.json
    中的fps播放每个sprite条,将纹理平铺在墙上,再绘制一长一短两个平台进行测试。

Common mistakes

常见错误

  • An end frame on run or walk. Pinning the still at both ends of short locomotion spends the clip speeding up and slowing down. First frame only for run and walk; pin first = last for idle and every one-shot so they return to rest.
  • An armed enemy's walk using its weapon. The build's first armed walk swung its weapon mid-stride and closed at 1.44x baseline. "His arms stay still ... never lifts, swings or twirls it", the weapon terms in the negative and a guidance of 0.7 closed it at 0.42x.
  • Keeping a frame where an effect keyed into a block. A white slash trail and an impact dust cloud came out of the key as solid blobs;
    --drop
    removes the sampled frame without changing the shared canvas or palette.
  • Paying to regenerate every weak loop. A heavy walk closed at 1.03x, a wider range found the same window, and it shipped after review. Widen the range, look at the loop, and pay only when it visibly hitches.
  • Splitting a pose sheet by columns. Poses overlap horizontally; split by connected components (
    --poses
    does) and ask for wide gaps.
  • Trusting "seamless tileable" in a texture prompt. The renders do not tile reliably;
    process_env.py
    cross-fades opposite edges instead of a re-render.
  • Stretching a platform strip. Draw left cap + repeated middle + right cap so every length keeps the carved ends.
  • Retro-scale level art. Small retro paintings failed the first playtest; 1920x1152 detailed layers drawn at 2x replaced them while sprites kept nearest-neighbor scaling. Validate level 1 in the game before the rest.
  • Pink or purple on a character. Everything strongly magenta is keyed away; say "no pink, no purple, no magenta anywhere on the character" and reject takes that show any. A fast weapon swing can pick up a purple motion-blur tint and key away mid-strike, which
    --drop
    cannot fix since it would remove the strike itself: reject that take, or re-run with "no motion blur, the weapon keeps its colors" in the prompt and "purple or magenta tint on the weapon" in the negative (in one validation run this cleared the tint, and one impact frame still needed
    --drop
    ).
  • Rewording a blocked combat clip. A thrust or pickaxe swing can come back
    moderation_blocked
    , and the filter is the provider's: read the error, then run the unchanged payload on a pick from another provider (same
    recommend
    ,
    endImage
    feature kept) per
    scenario-moderation
    before softening the beat.
  • Lossy sprite strips. Lossy WebP shifts the shared palette; only the HD layers ship lossy.
  • 奔跑或行走动画设置了结束帧。 在短距离移动动画的两端都固定静态图,会导致视频片段在加速和减速上浪费时间。奔跑和行走动画仅设置首帧;待机动画和所有单次动画设置首帧=尾帧,这样它们会回到休息姿势。
  • 武装敌人的行走动画中武器会动。 本构建的第一个武装行走动画在步幅中间会挥舞武器,循环闭合差为基线的1.44倍。在提示词中加入“他的手臂保持不动……绝不举起、挥舞或转动武器”,在负向提示词中加入武器相关术语,并将引导强度设为0.7,可将闭合差降至0.42倍。
  • 保留了特效抠成块的帧。 白色斩击轨迹和冲击尘云在抠图后会变成实心块;
    --drop
    参数可以移除采样帧,且不会改变共享画布或调色板。
  • 花钱重新生成所有弱循环。 一个沉重的行走动画闭合差为1.03倍,扩大查找范围后找到了相同的循环窗口,经审核后直接交付。先扩大范围、查看循环效果,只有在明显卡顿的时候才花钱重新生成。
  • 按列拆分姿势表。 姿势在水平方向上会有重叠;应按连通组件拆分(
    --poses
    参数就是这么做的),并要求生成时留出较大间距。
  • 轻信纹理提示词中的“可无缝平铺”。 生成的渲染图无法可靠平铺;
    process_env.py
    会对边缘做交叉淡入淡出处理,而不是重新渲染。
  • 拉伸平台条。 应绘制左端帽+重复中间段+右端帽,这样任何长度的平台都能保持两端的雕刻效果。
  • 关卡美术使用复古分辨率。 小尺寸复古画在第一次玩法测试中不合格;替换为2倍绘制的1920x1152分辨率细节图层,同时sprite仍保持最近邻缩放。在生成其他关卡前,先在游戏中验证第1关的效果。
  • 角色上有粉色或紫色。 所有深洋红色都会被抠掉;要在提示词中说明“角色身上任何地方都不能有粉色、紫色、洋红色”,并拒绝出现这些颜色的生成结果。快速挥舞的武器可能会带有紫色运动模糊色调,导致攻击中途被抠掉,这无法用
    --drop
    修复,因为会把攻击动作本身删掉:要么拒绝该结果,要么重新运行时在提示词中加入“无运动模糊,武器保持原有颜色”,在负向提示词中加入“武器上有紫色或洋红色调”(在一次验证运行中,这种方法清除了色调,仍有一帧冲击效果需要用
    --drop
    移除)。
  • 修改被拦截的战斗动画片段的措辞。 刺击或镐子挥舞可能会返回
    moderation_blocked
    (内容审核拦截),而过滤器是服务商提供的:先阅读错误信息,然后根据
    scenario-moderation
    的指引,在另一个服务商的模型上运行未修改的请求体(使用相同的
    recommend
    条件,保留
    endImage
    特性),之后再考虑弱化动作幅度。
  • Sprite条使用有损压缩。 有损WebP会改变共享调色板;只有高清图层才使用有损格式交付。