Full Code of KilledByAPixel/ZzSprite for AI

master 6cb57e3b20ce cached
5 files
14.8 KB
4.2k tokens
1 symbols
1 requests
Download .txt
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 Image 1](/examples/example1.png)

## Example mutations...
![Example Image 2](/examples/example2.png)

## Example animations...
![Example Image 3](/examples/example3.png)

## So many possibilities!
![Example Image 4](/examples/example4.png)

![Favicon](/favicon.png)


================================================
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>
Download .txt
gitextract_qsbomy9q/

├── .gitattributes
├── LICENSE
├── README.md
├── ZzSprite.js
└── index.html
Download .txt
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.

Copied to clipboard!