Loading...
Loading...
Game asset engineer that creates pixel art sprites, animated characters, and visual entities for browser games. Use when a game needs better character art, enemy sprites, item visuals, or any upgrade from basic geometric shapes to recognizable pixel art.
npx skill4agent add opusgamelabs/game-creator game-assetsfillCircle()generateTexture()src/core/PixelRenderer.js/**
* Renders a 2D pixel matrix to a Phaser texture.
*
* @param {Phaser.Scene} scene - The scene to register the texture on
* @param {number[][]} pixels - 2D array of palette indices (0 = transparent)
* @param {(number|null)[]} palette - Array of hex colors indexed by pixel value
* @param {string} key - Texture key to register
* @param {number} scale - Pixel scale (2 = each pixel becomes 2x2)
*/
export function renderPixelArt(scene, pixels, palette, key, scale = 2) {
if (scene.textures.exists(key)) return;
const h = pixels.length;
const w = pixels[0].length;
const canvas = document.createElement('canvas');
canvas.width = w * scale;
canvas.height = h * scale;
const ctx = canvas.getContext('2d');
for (let y = 0; y < h; y++) {
for (let x = 0; x < w; x++) {
const idx = pixels[y][x];
if (idx === 0 || palette[idx] == null) continue;
const color = palette[idx];
const r = (color >> 16) & 0xff;
const g = (color >> 8) & 0xff;
const b = color & 0xff;
ctx.fillStyle = `rgb(${r},${g},${b})`;
ctx.fillRect(x * scale, y * scale, scale, scale);
}
}
scene.textures.addCanvas(key, canvas);
}
/**
* Renders multiple frames as a spritesheet texture.
* Frames are laid out horizontally in a single row.
*
* @param {Phaser.Scene} scene
* @param {number[][][]} frames - Array of pixel matrices (one per frame)
* @param {(number|null)[]} palette
* @param {string} key - Spritesheet texture key
* @param {number} scale
*/
export function renderSpriteSheet(scene, frames, palette, key, scale = 2) {
if (scene.textures.exists(key)) return;
const h = frames[0].length;
const w = frames[0][0].length;
const frameW = w * scale;
const frameH = h * scale;
const canvas = document.createElement('canvas');
canvas.width = frameW * frames.length;
canvas.height = frameH;
const ctx = canvas.getContext('2d');
frames.forEach((pixels, fi) => {
const offsetX = fi * frameW;
for (let y = 0; y < h; y++) {
for (let x = 0; x < w; x++) {
const idx = pixels[y][x];
if (idx === 0 || palette[idx] == null) continue;
const color = palette[idx];
const r = (color >> 16) & 0xff;
const g = (color >> 8) & 0xff;
const b = color & 0xff;
ctx.fillStyle = `rgb(${r},${g},${b})`;
ctx.fillRect(offsetX + x * scale, y * scale, scale, scale);
}
}
});
scene.textures.addSpriteSheet(key, scene.textures.addCanvas(`${key}-canvas`, canvas).source[0], {
frameWidth: frameW,
frameHeight: frameH,
});
}src/
core/
PixelRenderer.js # renderPixelArt() + renderSpriteSheet()
sprites/
palette.js # Shared color palette(s) for the game
player.js # Player sprite frames
enemies.js # Enemy sprite frames (one export per type)
items.js # Pickups, gems, weapons, etc.
projectiles.js # Bullets, fireballs, etc.src/sprites/palette.js// palette.js — all sprite colors live here
// Index 0 is ALWAYS transparent
export const PALETTE = {
// Gothic / dark fantasy (vampire survivors, roguelikes)
DARK: [
null, // 0: transparent
0x1a1a2e, // 1: dark outline
0x16213e, // 2: shadow
0xe94560, // 3: accent (blood red)
0xf5d742, // 4: highlight (gold)
0x8b5e3c, // 5: skin
0x4a4a6a, // 6: armor/cloth
0x2d2d4a, // 7: dark cloth
0xffffff, // 8: white (eyes, teeth)
0x6b3fa0, // 9: purple (magic)
0x3fa04b, // 10: green (poison/nature)
],
// Bright / arcade (platformers, casual)
BRIGHT: [
null,
0x222034, // 1: outline
0x45283c, // 2: shadow
0xd95763, // 3: red
0xfbf236, // 4: yellow
0xeec39a, // 5: skin
0x5fcde4, // 6: blue
0x639bff, // 7: light blue
0xffffff, // 8: white
0x76428a, // 9: purple
0x99e550, // 10: green
],
// Muted / retro (NES-inspired)
RETRO: [
null,
0x000000, // 1: black outline
0x7c7c7c, // 2: dark gray
0xbcbcbc, // 3: light gray
0xf83800, // 4: red
0xfcfc00, // 5: yellow
0xa4e4fc, // 6: sky blue
0x3cbcfc, // 7: blue
0xfcfcfc, // 8: white
0x0078f8, // 9: dark blue
0x00b800, // 10: green
],
};// sprites/player.js
import { PALETTE } from './palette.js';
export const PLAYER_PALETTE = PALETTE.DARK;
// Idle frame — standing, sword at side
export const PLAYER_IDLE = [
[0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0],
[0,0,0,0,0,1,4,4,4,4,1,0,0,0,0,0],
[0,0,0,0,0,1,4,4,4,4,1,0,0,0,0,0],
[0,0,0,0,1,5,5,5,5,5,5,1,0,0,0,0],
[0,0,0,0,1,5,1,5,5,1,5,1,0,0,0,0],
[0,0,0,0,1,5,5,5,5,5,5,1,0,0,0,0],
[0,0,0,0,0,1,5,3,5,5,1,0,0,0,0,0],
[0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0],
[0,0,0,0,1,6,6,6,6,6,6,1,0,0,0,0],
[0,0,0,1,6,6,6,6,6,6,6,6,1,0,0,0],
[0,0,0,1,6,6,6,6,6,6,6,6,1,0,0,0],
[0,0,0,1,5,6,6,6,6,6,6,5,1,0,0,0],
[0,0,0,0,1,6,6,6,6,6,6,1,0,0,0,0],
[0,0,0,0,1,7,7,1,1,7,7,1,0,0,0,0],
[0,0,0,0,1,7,7,1,1,7,7,1,0,0,0,0],
[0,0,0,0,1,1,1,0,0,1,1,1,0,0,0,0],
];
// Walk frame 1 — left leg forward
export const PLAYER_WALK1 = [
[0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0],
[0,0,0,0,0,1,4,4,4,4,1,0,0,0,0,0],
[0,0,0,0,0,1,4,4,4,4,1,0,0,0,0,0],
[0,0,0,0,1,5,5,5,5,5,5,1,0,0,0,0],
[0,0,0,0,1,5,1,5,5,1,5,1,0,0,0,0],
[0,0,0,0,1,5,5,5,5,5,5,1,0,0,0,0],
[0,0,0,0,0,1,5,3,5,5,1,0,0,0,0,0],
[0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0],
[0,0,0,0,1,6,6,6,6,6,6,1,0,0,0,0],
[0,0,0,1,6,6,6,6,6,6,6,6,1,0,0,0],
[0,0,0,1,6,6,6,6,6,6,6,6,1,0,0,0],
[0,0,0,1,5,6,6,6,6,6,6,5,1,0,0,0],
[0,0,0,0,1,6,6,6,6,6,6,1,0,0,0,0],
[0,0,0,1,7,7,1,0,0,1,7,7,1,0,0,0],
[0,0,1,7,7,1,0,0,0,0,1,7,1,0,0,0],
[0,0,1,1,1,0,0,0,0,0,1,1,1,0,0,0],
];
// Walk frame 2 — right leg forward (mirror of walk1)
export const PLAYER_WALK2 = [
[0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0],
[0,0,0,0,0,1,4,4,4,4,1,0,0,0,0,0],
[0,0,0,0,0,1,4,4,4,4,1,0,0,0,0,0],
[0,0,0,0,1,5,5,5,5,5,5,1,0,0,0,0],
[0,0,0,0,1,5,1,5,5,1,5,1,0,0,0,0],
[0,0,0,0,1,5,5,5,5,5,5,1,0,0,0,0],
[0,0,0,0,0,1,5,3,5,5,1,0,0,0,0,0],
[0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0],
[0,0,0,0,1,6,6,6,6,6,6,1,0,0,0,0],
[0,0,0,1,6,6,6,6,6,6,6,6,1,0,0,0],
[0,0,0,1,6,6,6,6,6,6,6,6,1,0,0,0],
[0,0,0,1,5,6,6,6,6,6,6,5,1,0,0,0],
[0,0,0,0,1,6,6,6,6,6,6,1,0,0,0,0],
[0,0,0,1,7,1,0,0,1,7,7,1,0,0,0,0],
[0,0,0,1,7,1,0,0,0,1,7,7,1,0,0,0],
[0,0,0,1,1,1,0,0,0,0,1,1,1,0,0,0],
];
export const PLAYER_FRAMES = [PLAYER_IDLE, PLAYER_WALK1, PLAYER_IDLE, PLAYER_WALK2];// In sprites/enemies.js
export const BAT_IDLE = [
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,1,1,0,0,0,0,0,0,0,1,1,0,0,0],
[0,1,9,9,1,0,0,0,0,0,1,9,9,1,0,0],
[1,9,9,9,9,1,0,0,0,1,9,9,9,9,1,0],
[1,9,9,9,9,9,1,1,1,9,9,9,9,9,1,0],
[0,1,9,9,9,9,9,9,9,9,9,9,9,1,0,0],
[0,0,1,9,9,3,9,9,9,3,9,9,1,0,0,0],
[0,0,0,1,9,9,9,9,9,9,9,1,0,0,0,0],
[0,0,0,0,1,9,9,8,9,9,1,0,0,0,0,0],
[0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0],
[0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
];
// Wings down frame — alternate with idle for flapping
export const BAT_FLAP = [
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0],
[0,0,0,0,1,9,9,9,9,9,1,0,0,0,0,0],
[0,0,0,1,9,9,3,9,3,9,9,1,0,0,0,0],
[0,0,1,9,9,9,9,9,9,9,9,9,1,0,0,0],
[0,1,9,9,9,9,9,8,9,9,9,9,9,1,0,0],
[1,9,9,9,9,9,1,1,1,9,9,9,9,9,1,0],
[1,9,9,9,9,1,0,0,0,1,9,9,9,9,1,0],
[0,1,9,9,1,0,0,0,0,0,1,9,9,1,0,0],
[0,0,1,1,0,0,0,0,0,0,0,1,1,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
];// Zombie — hunched, arms forward
export const ZOMBIE_IDLE = [
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0],
[0,0,0,0,1,10,10,10,10,10,1,0,0,0,0,0],
[0,0,0,0,1,10,3,10,3,10,1,0,0,0,0,0],
[0,0,0,0,1,10,10,10,10,10,1,0,0,0,0,0],
[0,0,0,0,0,1,10,1,10,1,0,0,0,0,0,0],
[0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0],
[0,0,0,0,1,7,7,7,7,7,1,0,0,0,0,0],
[0,0,0,1,7,7,7,7,7,7,7,1,0,0,0,0],
[0,0,1,10,7,7,7,7,7,7,10,10,1,0,0,0],
[0,1,10,1,7,7,7,7,7,7,1,10,10,1,0,0],
[0,0,0,0,1,7,7,7,7,7,1,0,0,0,0,0],
[0,0,0,0,1,7,7,1,7,7,1,0,0,0,0,0],
[0,0,0,0,1,7,1,0,1,7,1,0,0,0,0,0],
[0,0,0,0,1,10,1,0,1,10,1,0,0,0,0,0],
[0,0,0,0,1,1,1,0,1,1,1,0,0,0,0,0],
];// XP Gem — diamond shape, 8x8
export const XP_GEM = [
[0,0,0,4,4,0,0,0],
[0,0,4,4,4,4,0,0],
[0,4,4,8,4,4,4,0],
[4,4,8,4,4,4,4,4],
[4,4,4,4,4,8,4,4],
[0,4,4,4,4,4,4,0],
[0,0,4,4,4,4,0,0],
[0,0,0,4,4,0,0,0],
];
// Heart — 8x8
export const HEART = [
[0,0,3,3,0,3,3,0],
[0,3,3,3,3,3,3,3],
[0,3,8,3,3,3,3,3],
[0,3,3,3,3,3,3,3],
[0,0,3,3,3,3,3,0],
[0,0,0,3,3,3,0,0],
[0,0,0,0,3,0,0,0],
[0,0,0,0,0,0,0,0],
];// Fireball — 8x8
export const FIREBALL = [
[0,0,0,4,4,0,0,0],
[0,0,4,4,4,4,0,0],
[0,3,4,8,4,4,3,0],
[3,3,4,4,4,4,3,3],
[0,3,3,4,4,3,3,0],
[0,0,3,3,3,3,0,0],
[0,0,0,3,3,0,0,0],
[0,0,0,0,0,0,0,0],
];
// Magic bolt — 6x6
export const MAGIC_BOLT = [
[0,0,9,9,0,0],
[0,9,8,9,9,0],
[9,9,9,9,9,9],
[9,9,9,9,9,9],
[0,9,9,8,9,0],
[0,0,9,9,0,0],
];// sprites/tiles.js — background tile variants
// Ground tile — base terrain (dark earth / stone)
export const GROUND_BASE = [
[2,2,2,1,2,2,2,2,2,2,1,2,2,2,2,2],
[2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2],
[2,2,2,2,2,2,1,2,2,2,2,2,2,2,1,2],
[2,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2],
[2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,2],
[2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2],
[1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2],
[2,2,2,2,2,1,2,2,2,2,2,2,2,2,2,2],
[2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2],
[2,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2],
[2,2,1,2,2,2,2,2,2,2,2,2,2,1,2,2],
[2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2],
[2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2],
[2,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2],
[2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2],
[2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2],
];
// Variant tiles — alternate with GROUND_BASE for variety
export const GROUND_VAR1 = [ /* same size, different speckle pattern */ ];
export const GROUND_VAR2 = [ /* ... */ ];// Gravestone — 8x12
export const GRAVESTONE = [
[0,0,1,1,1,1,0,0],
[0,1,18,18,18,18,1,0],
[0,1,18,8,8,18,1,0],
[0,1,18,18,18,18,1,0],
[0,1,18,18,18,18,1,0],
[0,1,18,18,18,18,1,0],
[0,1,18,18,18,18,1,0],
[0,1,18,18,18,18,1,0],
[0,1,18,18,18,18,1,0],
[1,18,18,18,18,18,18,1],
[1,18,18,18,18,18,18,1],
[1,1,1,1,1,1,1,1],
];
// Bone pile — 8x6
export const BONE_PILE = [
[0,0,8,0,0,8,0,0],
[0,8,8,8,8,8,8,0],
[8,18,8,8,8,18,8,8],
[0,8,8,8,8,8,8,0],
[0,8,18,8,8,18,8,0],
[0,0,8,8,8,8,0,0],
];
// Torch — 6x12 (flickering tip animated via tween tint, not extra frame)
export const TORCH = [
[0,0,4,4,0,0],
[0,4,12,12,4,0],
[0,0,4,4,0,0],
[0,0,1,1,0,0],
[0,0,19,19,0,0],
[0,0,19,19,0,0],
[0,0,19,19,0,0],
[0,0,19,19,0,0],
[0,0,19,19,0,0],
[0,0,19,19,0,0],
[0,0,19,19,0,0],
[0,0,1,1,0,0],
];renderPixelArt()tileSprite// In the game scene's create():
import { renderPixelArt } from '../core/PixelRenderer.js';
import { GROUND_BASE, GROUND_VAR1, GROUND_VAR2 } from '../sprites/tiles.js';
import { PALETTE } from '../sprites/palette.js';
// Render tile textures
renderPixelArt(scene, GROUND_BASE, PALETTE, 'tile-ground-0', 2);
renderPixelArt(scene, GROUND_VAR1, PALETTE, 'tile-ground-1', 2);
renderPixelArt(scene, GROUND_VAR2, PALETTE, 'tile-ground-2', 2);
// Option A: TileSprite for infinite seamless ground
const bg = scene.add.tileSprite(0, 0, WORLD_WIDTH, WORLD_HEIGHT, 'tile-ground-0');
bg.setOrigin(0, 0);
bg.setDepth(-10);
// Option B: Random tile grid for variety (better visual result)
const tileSize = 32; // 16px * scale 2
for (let y = 0; y < WORLD_HEIGHT; y += tileSize) {
for (let x = 0; x < WORLD_WIDTH; x += tileSize) {
const variant = Math.random() < 0.7 ? 'tile-ground-0'
: Math.random() < 0.5 ? 'tile-ground-1'
: 'tile-ground-2';
scene.add.image(x + tileSize / 2, y + tileSize / 2, variant).setDepth(-10);
}
}
// Scatter decorative elements
const decorTypes = ['deco-gravestone', 'deco-bones', 'deco-torch'];
for (let i = 0; i < 40; i++) {
const dx = Phaser.Math.Between(100, WORLD_WIDTH - 100);
const dy = Phaser.Math.Between(100, WORLD_HEIGHT - 100);
const type = Phaser.Utils.Array.GetRandom(decorTypes);
const deco = scene.add.image(dx, dy, type);
deco.setDepth(-5);
deco.setAlpha(0.6 + Math.random() * 0.4);
}// OLD: in entity constructor
const gfx = scene.add.graphics();
gfx.fillStyle(cfg.color, 1);
gfx.fillCircle(cfg.size, cfg.size, cfg.size);
gfx.generateTexture(texKey, cfg.size * 2, cfg.size * 2);
gfx.destroy();
this.sprite = scene.physics.add.sprite(x, y, texKey);// NEW: in entity constructor
import { renderPixelArt } from '../core/PixelRenderer.js';
import { ZOMBIE_IDLE } from '../sprites/enemies.js';
import { PALETTE } from '../sprites/palette.js';
const texKey = `enemy-${typeKey}`;
renderPixelArt(scene, ZOMBIE_IDLE, PALETTE.DARK, texKey, 2);
this.sprite = scene.physics.add.sprite(x, y, texKey);import { renderSpriteSheet } from '../core/PixelRenderer.js';
import { PLAYER_FRAMES, PLAYER_PALETTE } from '../sprites/player.js';
// In entity constructor or BootScene
renderSpriteSheet(scene, PLAYER_FRAMES, PLAYER_PALETTE, 'player-sheet', 2);
// Create animation
scene.anims.create({
key: 'player-walk',
frames: scene.anims.generateFrameNumbers('player-sheet', { start: 0, end: 3 }),
frameRate: 8,
repeat: -1,
});
// Play animation
this.sprite = scene.physics.add.sprite(x, y, 'player-sheet', 0);
this.sprite.play('player-walk');
// Stop animation (idle)
this.sprite.stop();
this.sprite.setFrame(0);// sprites/enemies.js
import { PALETTE } from './palette.js';
export const ENEMY_SPRITES = {
BAT: { frames: [BAT_IDLE, BAT_FLAP], palette: PALETTE.DARK, animRate: 6 },
ZOMBIE: { frames: [ZOMBIE_IDLE, ZOMBIE_WALK], palette: PALETTE.DARK, animRate: 4 },
SKELETON: { frames: [SKELETON_IDLE, SKELETON_WALK], palette: PALETTE.DARK, animRate: 5 },
GHOST: { frames: [GHOST_IDLE, GHOST_FADE], palette: PALETTE.DARK, animRate: 3 },
DEMON: { frames: [DEMON_IDLE, DEMON_WALK], palette: PALETTE.DARK, animRate: 6 },
};
// In Enemy constructor:
const spriteData = ENEMY_SPRITES[typeKey];
const texKey = `enemy-${typeKey}`;
renderSpriteSheet(scene, spriteData.frames, spriteData.palette, texKey, 2);
this.sprite = scene.physics.add.sprite(x, y, texKey, 0);
scene.anims.create({
key: `${typeKey}-anim`,
frames: scene.anims.generateFrameNumbers(texKey, { start: 0, end: spriteData.frames.length - 1 }),
frameRate: spriteData.animRate,
repeat: -1,
});
this.sprite.play(`${typeKey}-anim`);| Entity Size | Grid | Scale | Rendered Size |
|---|---|---|---|
| Small (items, pickups) | 8x8 | 2 | 16x16px |
| Medium (player, enemies) | 16x16 | 2 | 32x32px |
| Large (boss, vehicle) | 24x24 or 32x32 | 2 | 48x48 or 64x64px |
| Source | License | Format | URL |
|---|---|---|---|
| Kenney.nl | CC0 (public domain) | PNG sprite sheets | kenney.nl/assets |
| OpenGameArt.org | Various (check each) | PNG, SVG | opengameart.org |
| itch.io (free assets) | Various (check each) | PNG | itch.io/game-assets/free |
curlwgetpublic/assets/sprites/public/// scenes/PreloaderScene.js
preload() {
this.load.spritesheet('player', 'assets/sprites/player.png', {
frameWidth: 32,
frameHeight: 32,
});
}renderPixelArt()// Check if external asset loaded, otherwise use pixel art
if (scene.textures.exists('player-external')) {
this.sprite = scene.physics.add.sprite(x, y, 'player-external');
} else {
renderPixelArt(scene, PLAYER_IDLE, PLAYER_PALETTE, 'player-fallback', 2);
this.sprite = scene.physics.add.sprite(x, y, 'player-fallback');
}package.jsonsrc/core/Constants.jsgenerateTexture()fillCircle| Entity | Type | Grid | Frames | Description |
|---|---|---|---|---|
| Player | Humanoid | 16x16 | 4 (idle + walk) | Cloaked warrior with golden hair |
| Bat | Flying | 16x16 | 2 (wings up/down) | Purple bat with red eyes |
| Zombie | Ground | 16x16 | 2 (shamble) | Green-skinned, arms forward |
| XP Gem | Item | 8x8 | 1 (static + bob tween) | Golden diamond |
| Ground | Tile | 16x16 | 3 variants | Dark earth with speckle variations |
| Gravestone | Decoration | 8x12 | 1 | Stone marker with cross |
| Bones | Decoration | 8x6 | 1 | Scattered bone pile |
src/core/PixelRenderer.jsrenderPixelArt()renderSpriteSheet()src/sprites/palette.jssrc/sprites/src/sprites/tiles.jsrenderPixelArt()renderSpriteSheet()fillCircle()generateTexture()setCircle()setSize()npm run build/game-creator:qa-gamePixelRenderer.jssrc/core/src/sprites/palette.jsrenderPixelArt()renderSpriteSheet()fillCircle()