Pixel Art Maker For Melon Playground Online
.color-label font-weight: bold; color: #ffdd99; font-size: 0.85rem;
/* Main card container */ .maker-container background: rgba(30, 40, 50, 0.75); backdrop-filter: blur(2px); border-radius: 2.5rem; padding: 1.5rem; box-shadow: 0 20px 35px rgba(0,0,0,0.5), inset 0 1px 0 rgba(255,255,255,0.1); border: 1px solid rgba(255,215,150,0.3);
body background: linear-gradient(145deg, #1a2a3a 0%, #0f1a24 100%); display: flex; justify-content: center; align-items: center; min-height: 100vh; font-family: 'Segoe UI', 'Courier New', 'Fira Code', monospace; margin: 0; padding: 20px;
/* tool panel */ .tools-panel display: flex; flex-wrap: wrap; justify-content: center; gap: 1rem; margin-bottom: 1.5rem; align-items: center; background: #202433cc; padding: 0.8rem 1.2rem; border-radius: 60px; backdrop-filter: blur(4px); pixel art maker for melon playground
// default background color (deep slate, melon playground style) const DEFAULT_BG = "#1e293b";
// resize canvas and redraw from matrix function resizeAndRedraw() const size = currentGridSize; // physical canvas resolution: 400x400 gives nice pixel blocks // We'll use 400x400 to have integer cell sizes: 400 / size must be integer. // But for 48x48, 400/48 = 8.33 not integer => we'll adjust canvas resolution dynamically to keep crisp pixels. // better approach: set canvas size to a multiple of grid size to avoid subpixel artifacts. // Let's set canvas width/height = gridSize * 10 (or gridSize * 12) .. but we need crisp squares. // I'll compute canvas size as gridSize * 12 -> max 48*12=576 still fine, min 16*12=192. // But user expects 32x32 cell size around 10px each => 320px. // For consistency, we set canvas.width = gridSize * 10 (max 480 for 48, still crisp). // But for 48, 480/48 = 10px exactly. For 24, 240px. Good. const pixelSize = 10; // each cell is exactly 10px const newCanvasWidth = size * pixelSize; const newCanvasHeight = size * pixelSize; canvas.width = newCanvasWidth; canvas.height = newCanvasHeight; canvas.style.width = `$newCanvasWidthpx`; canvas.style.height = `$newCanvasHeightpx`; cellW = pixelSize; cellH = pixelSize; // redraw full matrix drawFullMatrix();
<script> (function() // ---------- DOM elements ---------- const canvas = document.getElementById('pixelCanvas'); const ctx = canvas.getContext('2d'); const gridSizeSelect = document.getElementById('gridSizeSelect'); const clearBtn = document.getElementById('clearCanvasBtn'); const fillBgBtn = document.getElementById('fillCanvasBtn'); const exportPngBtn = document.getElementById('exportPNG'); const exportJsonBtn = document.getElementById('exportSpriteData'); const colorPicker = document.getElementById('activeColor'); const colorPreview = document.getElementById('currentColorPicker'); // Let's set canvas width/height = gridSize *
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no"> <title>Pixel Art Maker for Melon Playground</title> <style> * box-sizing: border-box; user-select: none; /* avoid accidental text selection while drawing */
// fill background (alias for clear with current bg but also set custom) function fillBackground() fillAllWithColor(DEFAULT_BG);
// painting logic (color or erase) function paintAtEvent(e, forceErase = false) // But user expects 32x32 cell size around
// fill bucket triggered by shift+click? but we add extra button: fill with active color. // Let's implement fill using double click OR special button? For simplicity, we add "Fill BG" and also "Flood Fill on double click canvas" function handleCanvasDoubleClick(e) e.preventDefault(); const row, col = getGridCoordFromEvent(e); if(row>=0 && row<currentGridSize && col>=0 && col<currentGridSize) floodFillTool(row, col, colorPicker.value);
function handlePointerEnd(e) isDrawing = false; // reset erase mode to default (based on next click, no persistent) eraseMode = false;
footer font-size: 0.7rem; text-align: center; color: #8aaec0; margin-top: 12px;
.btn background: #2e3b3e; border: none; font-family: monospace; font-weight: bold; font-size: 1rem; padding: 8px 18px; border-radius: 40px; color: #f5e7d9; cursor: pointer; transition: all 0.15s; box-shadow: 0 3px 0 #0f1219; letter-spacing: 0.5px; .btn-primary background: #ff8c42; color: #1e2a2f; box-shadow: 0 3px 0 #b45116; .btn-primary:active transform: translateY(2px); box-shadow: 0 1px 0 #b45116; .btn:active transform: translateY(2px); box-shadow: 0 1px 0 #0f1219; .btn-danger background: #a03e3e; box-shadow: 0 3px 0 #5e2626;