Pixel Art Maker For Melon Playground -
.sub text-align: center; font-size: 0.8rem; color: #bbccdd; margin-bottom: 1.2rem; border-bottom: 1px dashed #ffb34755; display: inline-block; width: 100%; font-family: monospace;
.color-well display: flex; align-items: center; gap: 10px; background: #171c26; padding: 5px 15px; border-radius: 40px;
// draw entire pixel matrix onto canvas function drawFullMatrix() if(!pixelMatrix.length) return; const size = currentGridSize; for(let row = 0; row < size; row++) for(let col = 0; col < size; col++) const color = pixelMatrix[row][col]; ctx.fillStyle = color; ctx.fillRect(col * cellW, row * cellH, cellW, cellH); // optional: draw subtle grid lines ctx.save(); ctx.beginPath(); ctx.strokeStyle = "#2c3e4e"; ctx.lineWidth = 0.5; for(let i = 0; i <= size; i++) ctx.beginPath(); ctx.moveTo(i * cellW, 0); ctx.lineTo(i * cellW, canvas.height); ctx.stroke(); ctx.moveTo(0, i * cellH); ctx.lineTo(canvas.width, i * cellH); ctx.stroke(); ctx.restore();
.melon-badge background: #00000055; border-radius: 28px; text-align: center; font-size: 0.7rem; padding: 6px 10px; color: #ffe1aa; margin-top: 12px; font-weight: bold; pixel art maker for melon playground
// ---- fill with current selected color (not only bg) but fill tool ---- function floodFillTool(targetRow, targetCol, newColor) // typical flood fill 4-direction if(pixelMatrix[targetRow][targetCol] === newColor) return; const targetColor = pixelMatrix[targetRow][targetCol]; const stack = [row: targetRow, col: targetCol]; const visited = Array(currentGridSize).fill().map(() => Array(currentGridSize).fill(false)); while(stack.length) col < 0
<!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 */
// ---------- state ---------- let currentGridSize = 32; // 32x32 default let cellW = 0, cellH = 0; let pixelMatrix = []; // 2D array storing hex colors let isDrawing = false; let eraseMode = false; // erase with background color (default dark bg) // Let's set canvas width/height = gridSize *
// update single cell in matrix & canvas function setPixel(row, col, color) row >= currentGridSize
// 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();
// ---------- Event listeners for drawing (mouse + touch) ---------- function handlePointerStart(e) // But user expects 32x32 cell size around
canvas display: block; margin: 0 auto; box-shadow: 0 0 0 3px #ffcf8a, 0 8px 20px rgba(0,0,0,0.5); border-radius: 12px; cursor: crosshair; background-color: #1a1e2a;
.size-control display: flex; align-items: center; gap: 12px; background: #171c26; padding: 5px 15px; border-radius: 40px; .size-control span color: #ffcf8a; font-weight: bold;
// get mouse / touch coordinates to grid cell function getGridCoordFromEvent(e) const rect = canvas.getBoundingClientRect(); const scaleX = canvas.width / rect.width; // canvas physical vs CSS const scaleY = canvas.height / rect.height; let clientX, clientY; if(e.touches) // touch event clientX = e.touches[0].clientX; clientY = e.touches[0].clientY; else clientX = e.clientX; clientY = e.clientY; let canvasX = (clientX - rect.left) * scaleX; let canvasY = (clientY - rect.top) * scaleY; canvasX = Math.min(Math.max(0, canvasX), canvas.width - 0.01); canvasY = Math.min(Math.max(0, canvasY), canvas.height - 0.01); const col = Math.floor(canvasX / cellW); const row = Math.floor(canvasY / cellH); return row, col ;
function handlePointerMove(e) if(!isDrawing) return; e.preventDefault(); // for mouse move, if right button held down, we treat as erase let forceErase = eraseMode; if(e.buttons === 2) // right button forceErase = true; else if(e.buttons === 1 && !eraseMode) forceErase = false; else if(e.buttons === 1 && eraseMode) forceErase = true; else forceErase = eraseMode; paintAtEvent(e, forceErase);
h1 margin: 0 0 0.3rem 0; font-size: 1.9rem; text-align: center; font-weight: 800; letter-spacing: 2px; background: linear-gradient(135deg, #FFE6B0, #FFB347); -webkit-background-clip: text; background-clip: text; color: transparent; text-shadow: 0 2px 3px rgba(0,0,0,0.2);
