Ajan API'si
Nibble, AI ajanlar tarafından kullanılmak üzere tasarlandı. Editörü aç ve window.nibble.help() çağır — bu çağrı el sıkışmadır.
Altın kurallar
- Pikselleri tek tek gönderme. Bir sprite'ı tek drawFromText çağrısında çiz — 32×32 tuvalde piksel piksel tıklamak 1024 eylem demektir.
- Çok adımlı işi beginBatch("etiket") / endBatch() arasına al ki kullanıcı yaptığın her şeyi tek Ctrl+Z ile geri alabilsin.
- Ne çizdiğini görmek için readCanvas() kullan. Yazma formatının aynısını döndürür; ekran görüntüsü gerekmez.
- Her dönüş değerindeki hint alanını oku — site seni aktif olarak yönlendiriyor.
Tipik akış
// 1 — el sıkışma / handshake
await nibble.help()
// 2 — palet / palette
nibble.usePalette("sweetie-16")
// 3 — tek çağrıda bir sprite / a whole sprite in one call
nibble.drawFromText({
rows: [
"..AAAA..",
".AABBAA.",
"AABBBBAA",
"AABBBBAA",
".AABBAA.",
"..AAAA..",
],
legend: { A: 3, B: 4 },
x: 12, y: 12,
})
// 4 — animasyon / animation
nibble.addFrame({ copyFrom: 0 })
nibble.setPixels([{ x: 12, y: 11, c: 3 }])
nibble.setFps(10)
// 5 — ne çizdiğini oku / read back what you drew
nibble.readCanvas()İskelet — parça adıyla konuş
Bir sprite'ı kare kare yeniden çizmek bir ajan için en pahalı yol. Bunun yerine parçalara bir kez isim ver: bundan sonra “sol bacağı iki piksel yukarı al” tek çağrı. Tutamakları poz olarak anahtarlarsan aradaki kareleri Nibble üretir.
// bir parçaya isim ver / name a part: tutamak + piksel kutusu
nibble.definePart({
name: "left_leg",
x: 12, y: 24, // tutamak / handle
box: { x: 10, y: 22, w: 5, h: 8 }, // taşınacak pikseller / pixels it carries
})
// artık piksel değil PARÇA konuşuyorsun / now you speak in parts
nibble.movePart("left_leg", 0, -2) // tutamak + pikseller
nibble.flipPart("left_leg", "x") // kayıpsız / lossless
nibble.recolorPart("left_leg", { to: "#b13e53" })
// poz anahtarla, aradakileri Nibble üretsin / key the poses, let Nibble fill in
nibble.addFrame({ copyFrom: 0 })
nibble.movePart("left_leg", 0, -3)
nibble.setActiveFrame(0)
nibble.tween({ count: 2 })
nibble.describeRig() // hangi parçanın kutusu/tutamağı eksik, söylerSadece öteleme — ezme veya bükme yok. Pixel art deforme edilince çamura döner.
Ajan izinleri
Ajan yalnızca burada işaretli olanları yapabilir. Değişiklik anında geçerli olur.
Çizim — varsayılan: açıkPiksel boyama, kova ile doldurma, aktif kareyi temizleme.
Animasyon — varsayılan: açıkKare ekleme, FPS değiştirme, oynatma/duraklatma.
Katmanlar — varsayılan: açıkKatman ekleme, gizleme/gösterme, kilitleme, adlandırma.
Palet — varsayılan: açıkProjenin renk paletini değiştirme.
Yıkıcı işlemler — varsayılan: kapalıBoyut değiştirme, yeni proje açma, kare veya katman silme. Varsayılan kapalı.
Dosya ve ağ — varsayılan: kapalıDışa aktarım indirme ve URL'den görsel yükleme. Varsayılan kapalı.
Karşılaşacağın sınırlar
- İzinler kullanıcınındır. Yıkıcı çağrılar (resize, newProject, deleteFrame, deleteLayer) ve dosya/ağ çağrıları kullanıcı açana kadar reddedilir — reddedilme istisna değil, içinde kapsam adı geçen ok:false döner.
- Çağrılar hız sınırlıdır. Piksel başına bir çağrı döngüsü yerine işini toplu gönder.
- Kayıtlı taslaklar, depolama ve ayarlar API'nin parçası değil. Kullanıcının diğer projelerini okumanın veya silmenin yolu bilinçli olarak yok.
- Yük sınırları: 4096 satır, satır başına 4096 karakter, setPixels başına 250.000 piksel, parça kutusu başına 2048×2048.
- Uzak görseller "files" izni istiyor ve denetim ÇÖZÜLMÜŞ adres üstünden yapılıyor — şemayı gizlemek adresi yine uzak kökene çözdüğü için uzak sayılıyor.
rate limit: 120 / 10s · rows ≤ 4096 · setPixels ≤ 250000 · canvas ≤ 512px · part box ≤ 2048px
Referans
help(topic?)API + canvas state + a hint for what to do nextgetState() · describe()Canvas, frames, layers, palette, parts, permissionsgetPermissions()What you are currently allowed to doreadCanvas(frame?)Reads back rows + legend — same format you writedrawFromText({rows, legend, x, y})Draw a whole sprite in one callsetPixels([{x, y, c}])Bulk pixel writesfill(x, y, c, opts?)Flood fillclearFrame(frame?)Clears unlocked layers of a frameaddFrame({copyFrom?}) · duplicateFrame(i)New frame (blank, or a copy)setActiveFrame(i) · setFrameDuration(i, cs)Navigate / time framessetFps(n) · play() · pause()Playback (fps must divide 100)addLayer(name?) · setLayer(id, props)Layer create / visibility / lock / renamegetPalette() · setPalette([]) · usePalette(id)Colour palettedefinePart({name, x, y, box?})Name a part: a handle plus the pixels it carriessetPartBox(name, box) · clearPartBox(name)Attach or detach the pixel boxsetPartHandle(name, x, y)Move the handle only — this is how you key a posemovePart(name, dx, dy, opts?)Move handle AND pixels — one undo stepflipPart(name, axis) · rotatePart(name, deg)90° multiples lossless, other angles are notrecolorPart(name, {to, from?, tolerance?})Repaint just that partrenamePart(a, b) · deletePart(name)Edit the part listdefineBone({name, from, to}) · deleteBone(name)Named link between two partsgetRig() · describeRig()The skeleton, and what is still missing from ittween({from?, count})In-between frames from the handle positionsimportImage(src, opts?)Image → pixel art (data:/blob: free, http(s) needs files)beginBatch(label) · endBatch()Group everything into one undo stepundo() · redo()HistoryexportGif() · exportPng()Downloads — needs the files permissionexportApng()Lossless animation: full RGBA alpha, no 256-colour limitexportSpriteSheet()PNG + Aseprite JSON — rig parts become Aseprite "slices"resize(w, h) · newProject() · deleteFrame(i) · deleteLayer(id)Destructive — off by defaultAJAN NE YAPABİLİR, NE YAPAMAZ
- Her çizim eylemi tek bir geri alma adımıdır — bir Ctrl+Z hepsini siler.
- Kayıtlı taslakların ajana kapalı. API onları listeleyemez, açamaz, silemez.
- Yıkıcı işler — boyut değiştirme, projeyi sıfırlama, kare veya katman silme — sen izin verene kadar kapalı.
- Dosya indirme ve internetten görsel yükleme varsayılan olarak kapalı.
- Çağrılar hız sınırlı, yani kontrolden çıkan bir ajan tuvali spamlayamaz.
- İstediğin an Bağlantıyı kes diyebilirsin; window.nibble anında ortadan kalkar.