Repository: KilledByAPixel/ZzSprite
Branch: master
Commit: 6cb57e3b20ce
Files: 5
Total size: 14.8 KB
Directory structure:
gitextract_qsbomy9q/
├── .gitattributes
├── LICENSE
├── README.md
├── ZzSprite.js
└── index.html
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitattributes
================================================
*.html linguist-language=Javascript
================================================
FILE: LICENSE
================================================
MIT License
Copyright (c) 2020 Frank Force
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: README.md
================================================
# ZzSprite
A Tiny Sprite Generator by Frank Force
[Based on a Dweet](https://www.dwitter.net/d/3078) by Firey Fly
# [Live Demo](https://killedbyapixel.github.io/ZzSprite/)
## Features
- Generates a wide variety of symetric pixel art sprites
- Click on a sprite to set that as the current seed
- Sprite can be mutated in shape or color
- Sprite sheets can be saved as pngs
- Sprites can be coppied to the clipboard for easy pasting
- Supports 4 color and monochrome color modes
- ZzSprite function can be used to generate sprites at run time
## Example sprites...

## Example mutations...

## Example animations...

## So many possibilities!


================================================
FILE: ZzSprite.js
================================================
// ZzSprite - Tiny Sprite Generator - Frank Force 2020 - MIT License
'use strict';
// ==ClosureCompiler==
// @compilation_level ADVANCED_OPTIMIZATIONS
// @language_out ECMASCRIPT_2019
// @js_externs ZzSprite
// ==/ClosureCompiler==
function ZzSprite(context, x=0, y=0, seed=1, size=16, mode=0, mutateSeed=0, colorSeed=0)
{
function Random(max=1, min=0)
{
randomSeed ^= randomSeed << 13;
randomSeed ^= randomSeed >>> 17;
return (Math.abs(randomSeed ^= randomSeed << 5) % 1e9 / 1e9)*(max-min) + min;
}
// random chance to flip drawing axis
let randomSeed = seed;
const flipAxis = Random() < .5;
const w = flipAxis ? size-3 : size/2 - 1 |0;
const h = !flipAxis ? size-3 : size/2 - 1 |0;
// apply mutations
randomSeed += mutateSeed + 1e8;
const spriteSize = size * Random(.9, .6);
const density = Random(1, .9);
const doubleCenter = Random() < .5;
const yBias = Random(.1, -.1);
const colorRand = (mode==1 ? .08 : .04);
// recenter
x += size/2 | 0;
y += 2 | 0;
function DrawSpriteInternal(x, y, outline)
{
// draw each pixel
randomSeed = seed;
const passCount = mode == 3 ? 3: 1
for(let pass=0; pass < passCount; ++pass)
for(let k=0; k < w*h; ++k)
{
const i = flipAxis ? k/w|0 : k%w;
const j = !flipAxis ? k/w|0 : k%w;
// pick new random color using color seed
const saveSeed = randomSeed;
randomSeed += colorSeed + 1e9;
const r = Random(360)|0;
let newColor = `hsl(${ r },${ Random(200,0)|0 }%,${ Random(100,20)|0 }%)`;
if (outline || mode == 3)
newColor = '#000';
else if (mode == 1)
newColor = r%3? r%3==1 ? '#444' : '#999' : '#fff';
else if (mode == 2)
newColor = `#fff`;
if (!k || Random() < colorRand)
context.fillStyle = newColor;
randomSeed = saveSeed;
// check if pixel should be drawn
const isHole = Random() > density;
if (Random(spriteSize/2)**2 > i*i + (j-(1-2*yBias)*h/2)**2 && !isHole)
{
const o = !!outline;
context.fillRect(x+i-o-doubleCenter, y+j-o, 1+2*o, 1+2*o);
context.fillRect(x-i-o, y+j-o, 1+2*o, 1+2*o);
}
}
}
// outline then fill
if (mode != 3)
DrawSpriteInternal(x, y, 1);
DrawSpriteInternal(x, y);
}
================================================
FILE: index.html
================================================
<style>
*
{
font-size:20px;
font-family:Arial;
}
body
{
background:#111;
color:#fff;
user-select:none;
}
.settingsContainer
{
display:grid;
grid-template-columns: 130px 130px 130px 130px;
grid-gap:10px;
padding:10px;
}
canvas
{
background:#ccc;
image-rendering:-moz-crisp-edges;
image-rendering:pixelated;
}
details
{
padding:10px;
}
.programTitle
{
font-size:20px;
font-style:italic;
padding:4px;
text-align:center;
}
</style>
<link rel="shortcut icon" type="image/x-icon" href="favicon.png"/>
<div style=display:flex;height:180px>
<div id=settingsContainer class=settingsContainer></div>
<div>
<div id=programTitleDiv class=programTitle></div>
<canvas id=previewCanvas style='flex-shrink:0;width:128px;height:128px;border:3px solid #000'></canvas>
</div>
<details style=display:none>
<summary>Advanced</summary>
<div class=settingsContainer id=advancedSettingsContainer>
</div>
</details>
</div>
<canvas id=canvas style=width:100%></canvas>
<a id=link display:none></a>
<script src=ZzSprite.js?1></script>
<script>'use strict';
/////////////////////////////////////////////////////////////////////////////
let randomSeed = 0;
function Random(max=1, min=0)
{
randomSeed ^= randomSeed << 13;
randomSeed ^= randomSeed >>> 17;
return (Math.abs(randomSeed ^= randomSeed << 5) % 1e9 / 1e9)*(max-min) + min;
}
function GenerateRandomSeed() { return Math.random()*1e9|0; }
function Update()
{
// init canvas
const tileSize = settings.tileSize.Get();
const rows = settings.rows.Get();
const columns = settings.columns.Get();
canvas.height = rows*tileSize;
canvas.width = columns*tileSize;
// render sprites
const displayMode = settings.displayMode.Get();
let seed = settings.seed.Get();
let colorSeed = settings.colorSeed.Get();
let mutateSeed = settings.mutateSeed.Get();
let animationSeed = GenerateRandomSeed();
let sheetSeed = settings.sheetSeed.Get();
for(let y = 0; y<rows; ++y)
for(let x = 0; x<columns; ++x)
{
if (x || y)
{
// randomize parameters
randomSeed = sheetSeed;
if (displayMode == 0)
{
seed = Random(1e9)|0;
}
else if (displayMode == 1)
{
mutateSeed = Random(1e9)|0;
colorSeed = Random(1e9)|0;
}
else if (displayMode == 2)
{
mutateSeed = Random(1e9)|0;
}
sheetSeed = randomSeed;
}
savedParameters[x+y*columns] = {seed, mutateSeed, colorSeed};
ZzSprite(context, x*tileSize, y*tileSize, seed, settings.tileSize.Get(), settings.colorMode.Get(), mutateSeed, colorSeed);
}
// draw preview sprite
const previewContext = previewCanvas.getContext('2d');
previewCanvas.width = tileSize;
previewCanvas.height = tileSize;
previewContext.fillStyle = '#fff';
previewContext.fillRect(0,0,2e3,2e3);
previewContext.drawImage(canvas, 0, 0);
}
class Setting
{
constructor(name, value, max=1, min=0, step=1, advanced=0)
{
const container = advanced ? advancedSettingsContainer : settingsContainer;
const nameElement = document.createElement('span');
nameElement.innerText = name;
container.appendChild(nameElement);
const e = this.element = document.createElement('input');
container.appendChild(e);
e.type = 'number';
e.value = this.default = value;
e.max = this.max = max;
e.min = this.min = min;
e.step = step;
this.element.onchange= e=>
{
this.Set(step==1?this.element.value|0:this.element.value);
Update();
}
}
SetDefault() { this.Set(this.default); }
Set(value)
{
value = value||0;
if (value < this.min)
value = this.min;
else if (value > this.max)
value = this.max;
this.element.value = value;
}
Get() { return parseFloat(this.element.value); }
}
class SettingDropDown
{
constructor(name, options, advanced = 0)
{
const container = advanced ? advancedSettingsContainer : settingsContainer;
const nameElement = document.createElement('span');
nameElement.innerText = name;
container.appendChild(nameElement);
this.element = document.createElement('select');
container.appendChild(this.element);
options.map((o,i)=>
{
let e = document.createElement('option');
e.innerHTML = o;
e.value = i;
this.element.appendChild(e);
});
this.element.onchange= e=> Update();
}
SetDefault() { this.Set(0); }
Set(value) { this.element.selectedIndex = value; }
Get() { return this.element.options[this.element.selectedIndex].value; }
}
function BuildHTML()
{
document.title = programTitle + ' - ' + programDescription;
programTitleDiv.innerHTML = programTitle + ' v' + programVersion;
canvas.title = 'Click to select seed';
settings.seed = new Setting('Seed', GenerateRandomSeed(), 1e9);
settings.tileSize = new Setting('Tile Size', 16, 32, 8, 1);
settings.displayMode = new SettingDropDown('Display Mode',
['Seeds','Mutations','Animations']);
settings.colorMode = new SettingDropDown('Color Mode',
['Full Color','4 Colors','2 Colors','1 Color']);
settings.rows = new Setting('Rows', 8, 128, 1);
settings.columns = new Setting('Columns', 16, 128, 1);
// advanced
settings.colorSeed = new Setting('Color Seed', 0, 1e9, 0, 1, 1);
settings.mutateSeed = new Setting('Mutate Seed', 0, 1e9, 0, 1, 1);
settings.sheetSeed = new Setting('Sheet Seed', GenerateRandomSeed(), 1e9, 0, 1, 1);
let e;
/*e = settingsContainer.appendChild(document.createElement('button'));
e.innerHTML = 'Reset';
e.title = 'Reset all parameters.';
e.onclick = e =>
{
// reset defaults
for(const setting in settings)
{
const s = settings[setting];
s.SetDefault && s.SetDefault();
}
settings.seed.Set(GenerateRandomSeed());
settings.sheetSeed.Set(GenerateRandomSeed());
Update();
};*/
e = settingsContainer.appendChild(document.createElement('button'));
e.innerHTML = 'Randomize';
e.title = 'Randomize sprite sheet.';
e.onclick = e =>
{
settings.sheetSeed.Set(GenerateRandomSeed());
if (settings.displayMode.Get()==0)
settings.seed.Set(GenerateRandomSeed());
Update();
};
e = settingsContainer.appendChild(document.createElement('button'));
e.innerHTML = 'Save Sheet';
e.title = 'Save png of entire sheet.';
e.onclick = e => link.click(
link.href = canvas.toDataURL('image/png'),
link.download = 'sprite_sheet');
e = settingsContainer.appendChild(document.createElement('button'));
e.innerHTML = 'Save Sprite';
e.title = 'Save png of sprite.';
e.onclick = e => link.click(
link.href = previewCanvas.toDataURL('image/png'),
link.download = 'sprite');
e = settingsContainer.appendChild(document.createElement('button'));
e.innerHTML = 'Copy Sprite';
previewCanvas.title = e.title = 'Copy sprite to clipboard.';
previewCanvas.onclick =
e.onclick = e =>
{
try {
previewCanvas.toBlob(blob =>
navigator.clipboard.write([new ClipboardItem({'image/png': blob})]));
} catch (e) {
alert('Could not copy!');
}
}
}
canvas.onmousedown=e=>
{
// get click tile
const rect = canvas.getBoundingClientRect();
const scaleX = canvas.width / rect.width;
const scaleY = canvas.height / rect.height;
const tileSize = settings.tileSize.Get();
const X = (e.x - rect.left)*scaleX/tileSize|0;
const Y = (e.y - rect.top)*scaleY/tileSize|0;
// update settings
const columns = settings.columns.Get();
const parameters = savedParameters[X+Y*columns];
settings.seed.Set(parameters.seed,0);
settings.colorSeed.Set(parameters.colorSeed,0);
settings.mutateSeed.Set(parameters.mutateSeed,0);
Update();
}
const programTitle = 'ZzSprite';
const programDescription = 'Tiny Sprite Generator';
const programVersion = '1.0';
const savedParameters = [];
const settings = {};
const context = canvas.getContext('2d');
BuildHTML();
Update();
</script>
<a href="https://github.com/KilledByAPixel/ZzSprite" target="_blank" class="github-corner" aria-label="View source on GitHub"><svg width="80" height="80" viewBox="0 0 250 250" style="fill:#5AF; color:#222; position: absolute; top: 0; border: 0; right: 0;" aria-hidden="true"><path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"></path><path d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2" fill="currentColor" style="transform-origin: 130px 106px;" class="octo-arm"></path><path d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z" fill="currentColor" class="octo-body"></path></svg></a><style>.github-corner:hover .octo-arm{animation:octocat-wave 560ms ease-in-out}@keyframes octocat-wave{0%,100%{transform:rotate(0)}20%,60%{transform:rotate(-25deg)}40%,80%{transform:rotate(10deg)}}@media (max-width:500px){.github-corner:hover .octo-arm{animation:none}.github-corner .octo-arm{animation:octocat-wave 560ms ease-in-out}}</style>
gitextract_qsbomy9q/ ├── .gitattributes ├── LICENSE ├── README.md ├── ZzSprite.js └── index.html
SYMBOL INDEX (1 symbols across 1 files) FILE: ZzSprite.js function ZzSprite (line 11) | function ZzSprite(context, x=0, y=0, seed=1, size=16, mode=0, mutateSeed...
Condensed preview — 5 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (16K chars).
[
{
"path": ".gitattributes",
"chars": 36,
"preview": "*.html linguist-language=Javascript\n"
},
{
"path": "LICENSE",
"chars": 1068,
"preview": "MIT License\n\nCopyright (c) 2020 Frank Force\n\nPermission is hereby granted, free of charge, to any person obtaining a cop"
},
{
"path": "README.md",
"chars": 845,
"preview": "# ZzSprite\n\nA Tiny Sprite Generator by Frank Force\n\n[Based on a Dweet](https://www.dwitter.net/d/3078) by Firey Fly\n\n# ["
},
{
"path": "ZzSprite.js",
"chars": 2621,
"preview": "// ZzSprite - Tiny Sprite Generator - Frank Force 2020 - MIT License\r\n\r\n'use strict';\r\n\r\n// ==ClosureCompiler==\r\n// @com"
},
{
"path": "index.html",
"chars": 10542,
"preview": "<style>\r\n*\r\n{\r\n font-size:20px;\r\n font-family:Arial;\r\n}\r\nbody\r\n{\r\n background:#111;\r\n color:#fff;\r\n user-"
}
]
About this extraction
This page contains the full source code of the KilledByAPixel/ZzSprite GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 5 files (14.8 KB), approximately 4.2k tokens, and a symbol index with 1 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.