You can edit the below JavaScript code to customize the image tool.
Apply Changes
function processImage(originalImg, playerName = "STAR", playerHP = 100, playerMP = 100, partnerName = "MARCO") {
// Ensure numeric bounds for bars
const hp = Math.max(0, Math.min(100, Number(playerHP)));
const mp = Math.max(0, Math.min(100, Number(playerMP)));
const canvas = document.createElement('canvas');
const w = originalImg.width;
const h = originalImg.height;
canvas.width = w;
canvas.height = h;
const ctx = canvas.getContext('2d');
// Draw the gameplay background image
ctx.drawImage(originalImg, 0, 0, w, h);
// Calculate a dynamic scale based on the image size so the UI always looks appropriate
const s = Math.min(w / 1280, h / 720);
// --- 1. Draw KH-style SVTFOE Target Lock-On ---
const targetX = w / 2;
const targetY = h / 2 - (50 * s);
const rScale = 45 * s;
// Glowing reticle ring
ctx.shadowBlur = 10 * s;
ctx.shadowColor = "magenta";
ctx.beginPath();
ctx.arc(targetX, targetY, rScale, 0, Math.PI * 2);
ctx.strokeStyle = "rgba(255, 235, 59, 0.8)"; // SVTFOE Bright Yellow
ctx.lineWidth = 4 * s;
ctx.stroke();
// Reset shadow
ctx.shadowBlur = 0;
// Lock-on inner triangles
for (let i = 0; i < 4; i++) {
const angle = i * (Math.PI / 2) + (Math.PI / 4); // Diagonals
ctx.save();
ctx.translate(targetX, targetY);
ctx.rotate(angle);
ctx.beginPath();
ctx.moveTo(rScale - 10 * s, 0); // Pointing inwards
ctx.lineTo(rScale + 12 * s, -8 * s);
ctx.lineTo(rScale + 12 * s, 8 * s);
ctx.closePath();
ctx.fillStyle = "rgba(255, 105, 180, 0.9)"; // Hot Pink
ctx.fill();
ctx.restore();
}
// --- 2. Draw Command Menu (Bottom Left) ---
const menuX = 50 * s;
const menuY = h - (260 * s);
// Command Menu Header
ctx.fillStyle = "rgba(0, 0, 0, 0.7)";
ctx.beginPath();
ctx.moveTo(menuX + 5 * s, menuY - 45 * s);
ctx.lineTo(menuX + 135 * s, menuY - 45 * s);
ctx.lineTo(menuX + 120 * s, menuY - 10 * s);
ctx.lineTo(menuX - 5 * s, menuY - 10 * s);
ctx.fill();
ctx.fillStyle = "#FF69B4"; // Pink header text
ctx.font = `italic bold ${20 * s}px Arial, sans-serif`;
ctx.fillText("COMMAND", menuX + 15 * s, menuY - 22 * s);
// Command Options
const commands = ["ATTACK", "MAGIC", "ITEMS", "DIMENSIONAL"];
for (let i = 0; i < commands.length; i++) {
const itemY = menuY + (i * 45 * s);
// Command background (SVTFOE themed colors, highlight first item)
ctx.fillStyle = i === 0 ? "rgba(255, 105, 180, 0.85)" : "rgba(0, 0, 0, 0.6)";
ctx.beginPath();
ctx.moveTo(menuX + 15 * s, itemY);
ctx.lineTo(menuX + 160 * s, itemY);
ctx.lineTo(menuX + 145 * s, itemY + 36 * s);
ctx.lineTo(menuX, itemY + 36 * s);
ctx.fill();
// Arrow indicator for selected
if (i === 0) {
ctx.fillStyle = "yellow";
ctx.beginPath();
ctx.moveTo(menuX - 10 * s, itemY + 10 * s);
ctx.lineTo(menuX + 5 * s, itemY + 18 * s);
ctx.lineTo(menuX - 10 * s, itemY + 26 * s);
ctx.fill();
}
// Command Text
ctx.fillStyle = i === 0 ? "white" : "#DDD";
ctx.font = `bold ${19 * s}px Arial, sans-serif`;
ctx.fillText(commands[i], menuX + 30 * s, itemY + 25 * s);
}
// --- 3. Draw Player Party UI (Marco, Top of Player) ---
const portX = w - (200 * s);
const portY = h - (170 * s);
const portRadius = 75 * s;
// Party Member Box
const partyY = portY - (120 * s);
const partyX = portX + (20 * s);
// Background plate
ctx.fillStyle = "rgba(0,0,0,0.6)";
ctx.beginPath();
ctx.moveTo(partyX - 130 * s, partyY);
ctx.lineTo(partyX + 20 * s, partyY);
ctx.lineTo(partyX, partyY + 45 * s);
ctx.lineTo(partyX - 150 * s, partyY + 45 * s);
ctx.fill();
// Text
ctx.fillStyle = "white";
ctx.font = `bold ${16 * s}px 'Georgia', serif`;
ctx.fillText(partnerName, partyX - 120 * s, partyY + 18 * s);
// Marco's HP bar
ctx.fillStyle = "rgba(0,0,0,0.8)";
ctx.fillRect(partyX - 120 * s, partyY + 25 * s, 100 * s, 8 * s);
ctx.fillStyle = "#00FF00"; // Green HP
ctx.fillRect(partyX - 120 * s, partyY + 25 * s, 80 * s, 8 * s); // always 80% for visual flavor
// --- 4. Main Character Portrait (Star Butterfly / User defined) ---
// Portrait Background Circle
ctx.fillStyle = "rgba(20, 20, 20, 0.8)";
ctx.beginPath();
ctx.arc(portX, portY, portRadius, 0, Math.PI * 2);
ctx.fill();
// Draw a stylized Star inside the portrait area to denote SVTFOE Main Character
function drawStar(cx, cy, spikes, outerRadius, innerRadius) {
let rot = (Math.PI / 2) * 3;
let x = cx;
let y = cy;
let step = Math.PI / spikes;
ctx.beginPath();
ctx.moveTo(cx, cy - outerRadius);
for (let i = 0; i < spikes; i++) {
x = cx + Math.cos(rot) * outerRadius;
y = cy + Math.sin(rot) * outerRadius;
ctx.lineTo(x, y);
rot += step;
x = cx + Math.cos(rot) * innerRadius;
y = cy + Math.sin(rot) * innerRadius;
ctx.lineTo(x, y);
rot += step;
}
ctx.lineTo(cx, cy - outerRadius);
ctx.closePath();
ctx.lineWidth = 4 * s;
ctx.strokeStyle = '#FFE066'; // Yellow Gold
ctx.stroke();
ctx.fillStyle = '#FF4DA6'; // SVTFOE Pink
ctx.fill();
}
// Emulate character portrait icon
drawStar(portX, portY, 5, 45 * s, 22 * s);
// --- 5. Draw Player HUD Bars ---
// HP Bar Ring
// Background black arc
ctx.beginPath();
ctx.arc(portX, portY, portRadius + 14 * s, 0.7 * Math.PI, 2.75 * Math.PI);
ctx.lineWidth = 14 * s;
ctx.lineCap = "round";
ctx.strokeStyle = "rgba(0, 0, 0, 0.7)";
ctx.stroke();
// Foreground green arc (dynamic to HP)
if (hp > 0) {
const hpEndAngle = 0.7 * Math.PI + (2.05 * Math.PI * (hp / 100));
ctx.beginPath();
ctx.arc(portX, portY, portRadius + 14 * s, 0.7 * Math.PI, hpEndAngle);
ctx.lineWidth = 10 * s;
// Gradient for SVTFOE style HP
let hpGradient = ctx.createLinearGradient(0, portY - portRadius, 0, portY + portRadius);
hpGradient.addColorStop(0, "#00FF40");
hpGradient.addColorStop(1, "#00AA00");
ctx.strokeStyle = hpGradient;
ctx.stroke();
}
// MP Bar Ring (Outside HP ring)
const mpRadius = portRadius + 30 * s;
ctx.beginPath();
ctx.arc(portX, portY, mpRadius, 1.1 * Math.PI, 2.65 * Math.PI);
ctx.lineWidth = 10 * s;
ctx.strokeStyle = "rgba(0, 0, 0, 0.7)";
ctx.stroke();
if (mp > 0) {
const mpEndAngle = 1.1 * Math.PI + (1.55 * Math.PI * (mp / 100));
ctx.beginPath();
ctx.arc(portX, portY, mpRadius, 1.1 * Math.PI, mpEndAngle);
ctx.lineWidth = 6 * s;
ctx.strokeStyle = "#00FFFF"; // Cyan Magic
ctx.stroke();
}
// KH Style Crown on the Portrait (adds to the Kingdom Hearts vibe)
function drawCrown(x, y, size) {
ctx.fillStyle = "#FFD700";
ctx.strokeStyle = "#B38F00";
ctx.lineWidth = 2 * s;
ctx.lineJoin = "round";
ctx.beginPath();
ctx.moveTo(x - size, y);
ctx.lineTo(x - size, y - size);
ctx.lineTo(x - size * 0.4, y - size * 0.5);
ctx.lineTo(x, y - size * 1.3);
ctx.lineTo(x + size * 0.4, y - size * 0.5);
ctx.lineTo(x + size, y - size);
ctx.lineTo(x + size, y);
ctx.closePath();
ctx.fill();
ctx.stroke();
}
drawCrown(portX, portY - portRadius - 20 * s, 22 * s);
// Draw Player Name below portrait
ctx.font = `bold ${24 * s}px 'Georgia', serif`;
ctx.fillStyle = "white";
ctx.shadowColor = "black";
ctx.shadowBlur = 6 * s;
const textW = ctx.measureText(playerName).width;
ctx.fillText(playerName, portX - (textW / 2), portY + portRadius + 50 * s);
ctx.shadowBlur = 0; // reset shadow
return canvas;
}
Apply Changes