/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1", { savedDrawings: [], currentDrawing: undefined }); /**** * Classes ****/ var ActionButton = Container.expand(function () { var self = Container.call(this); var buttonBg = self.attachAsset('button', { anchorX: 0, anchorY: 0 }); var buttonLabel = new Text2('', { size: 36, fill: 0xFFFFFF }); buttonLabel.anchor.set(0.5, 0.5); buttonLabel.position.set(100, 40); self.addChild(buttonLabel); self.action = ''; self.setAction = function (actionName, label) { self.action = actionName; buttonLabel.setText(label); }; self.down = function (x, y, obj) { pixelEditor.performAction(self.action); LK.getSound('click').play(); }; return self; }); var ColorButton = Container.expand(function () { var self = Container.call(this); var colorSquare = self.attachAsset('colorSquare', { anchorX: 0, anchorY: 0 }); self.colorValue = 0xFFFFFF; self.setColor = function (color) { self.colorValue = color; colorSquare.tint = color; }; self.down = function (x, y, obj) { pixelEditor.selectColor(self.colorValue); LK.getSound('click').play(); }; return self; }); var GridCell = Container.expand(function () { var self = Container.call(this); var cellGraphics = self.attachAsset('gridCell', { anchorX: 0, anchorY: 0, alpha: 1 }); self.color = 0xFFFFFF; self.isEmpty = true; self.setColor = function (newColor) { self.color = newColor; cellGraphics.tint = newColor; self.isEmpty = newColor === 0xFFFFFF; }; self.clear = function () { self.setColor(0xFFFFFF); }; self.down = function (x, y, obj) { pixelEditor.setPixel(self); }; self.move = function (x, y, obj) { if (pixelEditor.isDrawing) { pixelEditor.setPixel(self); } }; return self; }); var PixelEditor = Container.expand(function () { var self = Container.call(this); self.gridSize = 16; // 16x16 grid self.cellSize = 32; self.selectedColor = 0x000000; // Default black self.currentTool = 'draw'; // Default tool self.isDrawing = false; self.grid = []; self.history = []; self.historyIndex = -1; self.maxHistory = 30; self.initialize = function () { self.createGrid(); self.createColorPalette(); self.createTools(); self.createActionButtons(); // Load drawing if it exists if (storage.currentDrawing) { self.loadDrawing(storage.currentDrawing); } }; self.createGrid = function () { var gridContainer = new Container(); self.addChild(gridContainer); // Center the grid var gridWidth = self.gridSize * self.cellSize; var gridX = (2048 - gridWidth) / 2; var gridY = 300; // Position below UI elements gridContainer.position.set(gridX, gridY); for (var y = 0; y < self.gridSize; y++) { self.grid[y] = []; for (var x = 0; x < self.gridSize; x++) { var cell = new GridCell(); cell.position.set(x * self.cellSize, y * self.cellSize); cell.gridX = x; cell.gridY = y; self.grid[y][x] = cell; gridContainer.addChild(cell); } } }; self.createColorPalette = function () { var colors = [0x000000, 0xFFFFFF, 0xFF0000, 0x00FF00, 0x0000FF, 0xFFFF00, 0xFF00FF, 0x00FFFF, 0x800000, 0x008000, 0x000080, 0x808000, 0x800080, 0x008080, 0x808080, 0xC0C0C0]; var paletteContainer = new Container(); self.addChild(paletteContainer); // Position palette on the top paletteContainer.position.set(224, 100); for (var i = 0; i < colors.length; i++) { var colorBtn = new ColorButton(); colorBtn.setColor(colors[i]); colorBtn.position.set(i % 8 * 120, Math.floor(i / 8) * 120); paletteContainer.addChild(colorBtn); } }; self.createTools = function () { var tools = ['draw', 'fill', 'erase']; var toolsContainer = new Container(); self.addChild(toolsContainer); // Position tools to the left of the canvas toolsContainer.position.set(100, 400); for (var i = 0; i < tools.length; i++) { var toolBtn = new ToolButton(); toolBtn.setTool(tools[i]); toolBtn.position.set(0, i * 120); if (tools[i] === self.currentTool) { toolBtn.setSelected(true); } toolsContainer.addChild(toolBtn); } }; self.createActionButtons = function () { var actions = [{ name: 'clear', label: 'Clear' }, { name: 'undo', label: 'Undo' }, { name: 'redo', label: 'Redo' }, { name: 'save', label: 'Save' }, { name: 'load', label: 'Load' }]; var actionsContainer = new Container(); self.addChild(actionsContainer); // Position actions to the right of the canvas actionsContainer.position.set(1648, 400); for (var i = 0; i < actions.length; i++) { var actionBtn = new ActionButton(); actionBtn.setAction(actions[i].name, actions[i].label); actionBtn.position.set(0, i * 100); actionsContainer.addChild(actionBtn); } }; self.selectColor = function (color) { self.selectedColor = color; }; self.selectTool = function (toolName) { self.currentTool = toolName; // Update tool buttons visually var toolsContainer = self.children[2]; // Assuming tools are the 3rd child for (var i = 0; i < toolsContainer.children.length; i++) { var toolBtn = toolsContainer.children[i]; toolBtn.setSelected(toolBtn.toolName === toolName); } }; self.setPixel = function (cell) { if (self.currentTool === 'draw') { if (cell.color !== self.selectedColor) { self.saveState(); cell.setColor(self.selectedColor); LK.getSound('draw').play(); } } else if (self.currentTool === 'erase') { if (!cell.isEmpty) { self.saveState(); cell.clear(); LK.getSound('draw').play(); } } else if (self.currentTool === 'fill') { self.saveState(); self.floodFill(cell.gridX, cell.gridY, cell.color); LK.getSound('fill').play(); } }; self.floodFill = function (x, y, targetColor) { if (x < 0 || x >= self.gridSize || y < 0 || y >= self.gridSize) { return; } if (self.grid[y][x].color !== targetColor) { return; } if (self.grid[y][x].color === self.selectedColor) { return; } self.grid[y][x].setColor(self.selectedColor); self.floodFill(x + 1, y, targetColor); self.floodFill(x - 1, y, targetColor); self.floodFill(x, y + 1, targetColor); self.floodFill(x, y - 1, targetColor); }; self.saveState = function () { // If we've gone back in history and now make a new change, // discard any future states beyond the current index if (self.historyIndex < self.history.length - 1) { self.history = self.history.slice(0, self.historyIndex + 1); } // Save current state var state = []; for (var y = 0; y < self.gridSize; y++) { state[y] = []; for (var x = 0; x < self.gridSize; x++) { state[y][x] = self.grid[y][x].color; } } // Add to history and limit history size self.history.push(state); self.historyIndex++; if (self.history.length > self.maxHistory) { self.history.shift(); self.historyIndex--; } }; self.loadState = function (state) { for (var y = 0; y < self.gridSize; y++) { for (var x = 0; x < self.gridSize; x++) { if (y < state.length && x < state[y].length) { self.grid[y][x].setColor(state[y][x]); } else { self.grid[y][x].clear(); } } } }; self.performAction = function (action) { switch (action) { case 'clear': self.saveState(); self.clearCanvas(); break; case 'undo': self.undo(); break; case 'redo': self.redo(); break; case 'save': self.saveDrawing(); break; case 'load': // This would typically show a UI for selecting a saved drawing // For simplicity, we'll just load the first saved drawing if available if (storage.savedDrawings.length > 0) { self.loadDrawing(storage.savedDrawings[0]); } break; } }; self.clearCanvas = function () { for (var y = 0; y < self.gridSize; y++) { for (var x = 0; x < self.gridSize; x++) { self.grid[y][x].clear(); } } }; self.undo = function () { if (self.historyIndex > 0) { self.historyIndex--; self.loadState(self.history[self.historyIndex]); } }; self.redo = function () { if (self.historyIndex < self.history.length - 1) { self.historyIndex++; self.loadState(self.history[self.historyIndex]); } }; self.saveDrawing = function () { var drawing = []; for (var y = 0; y < self.gridSize; y++) { drawing[y] = []; for (var x = 0; x < self.gridSize; x++) { drawing[y][x] = self.grid[y][x].color; } } // Save to storage storage.currentDrawing = drawing; storage.savedDrawings.push(drawing); // Limit saved drawings to prevent excessive storage if (storage.savedDrawings.length > 10) { storage.savedDrawings.shift(); } LK.getSound('save').play(); }; self.loadDrawing = function (drawing) { if (drawing) { self.clearCanvas(); self.loadState(drawing); // Reset history when loading self.history = [drawing]; self.historyIndex = 0; } }; self.down = function (x, y, obj) { self.isDrawing = true; }; self.up = function (x, y, obj) { self.isDrawing = false; }; return self; }); var ToolButton = Container.expand(function () { var self = Container.call(this); var toolIcon = self.attachAsset('toolIcon', { anchorX: 0, anchorY: 0 }); self.toolName = ''; self.isSelected = false; var toolLabel = new Text2('', { size: 24, fill: 0x000000 }); toolLabel.anchor.set(0.5, 0.5); toolLabel.position.set(50, 50); self.addChild(toolLabel); self.setTool = function (name) { self.toolName = name; toolLabel.setText(name); }; self.setSelected = function (selected) { self.isSelected = selected; toolIcon.tint = selected ? 0x88BBFF : 0xCCCCCC; }; self.down = function (x, y, obj) { pixelEditor.selectTool(self.toolName); LK.getSound('click').play(); }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0xF0F0F0 }); /**** * Game Code ****/ // Create title text var titleText = new Text2('Pixel Crafter', { size: 80, fill: 0x333333 }); titleText.anchor.set(0.5, 0); titleText.position.set(2048 / 2, 20); game.addChild(titleText); // Create pixel editor var pixelEditor = new PixelEditor(); game.addChild(pixelEditor); pixelEditor.initialize(); // Handle game events game.down = function (x, y, obj) { // Start drawing if no specific object was clicked if (!obj || obj === game) { pixelEditor.isDrawing = true; } }; game.up = function (x, y, obj) { pixelEditor.isDrawing = false; }; game.move = function (x, y, obj) { // This is handled by the GridCell move event }; // Play background music LK.playMusic('bgmusic', { fade: { start: 0, end: 0.3, duration: 1000 } });
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
savedDrawings: [],
currentDrawing: undefined
});
/****
* Classes
****/
var ActionButton = Container.expand(function () {
var self = Container.call(this);
var buttonBg = self.attachAsset('button', {
anchorX: 0,
anchorY: 0
});
var buttonLabel = new Text2('', {
size: 36,
fill: 0xFFFFFF
});
buttonLabel.anchor.set(0.5, 0.5);
buttonLabel.position.set(100, 40);
self.addChild(buttonLabel);
self.action = '';
self.setAction = function (actionName, label) {
self.action = actionName;
buttonLabel.setText(label);
};
self.down = function (x, y, obj) {
pixelEditor.performAction(self.action);
LK.getSound('click').play();
};
return self;
});
var ColorButton = Container.expand(function () {
var self = Container.call(this);
var colorSquare = self.attachAsset('colorSquare', {
anchorX: 0,
anchorY: 0
});
self.colorValue = 0xFFFFFF;
self.setColor = function (color) {
self.colorValue = color;
colorSquare.tint = color;
};
self.down = function (x, y, obj) {
pixelEditor.selectColor(self.colorValue);
LK.getSound('click').play();
};
return self;
});
var GridCell = Container.expand(function () {
var self = Container.call(this);
var cellGraphics = self.attachAsset('gridCell', {
anchorX: 0,
anchorY: 0,
alpha: 1
});
self.color = 0xFFFFFF;
self.isEmpty = true;
self.setColor = function (newColor) {
self.color = newColor;
cellGraphics.tint = newColor;
self.isEmpty = newColor === 0xFFFFFF;
};
self.clear = function () {
self.setColor(0xFFFFFF);
};
self.down = function (x, y, obj) {
pixelEditor.setPixel(self);
};
self.move = function (x, y, obj) {
if (pixelEditor.isDrawing) {
pixelEditor.setPixel(self);
}
};
return self;
});
var PixelEditor = Container.expand(function () {
var self = Container.call(this);
self.gridSize = 16; // 16x16 grid
self.cellSize = 32;
self.selectedColor = 0x000000; // Default black
self.currentTool = 'draw'; // Default tool
self.isDrawing = false;
self.grid = [];
self.history = [];
self.historyIndex = -1;
self.maxHistory = 30;
self.initialize = function () {
self.createGrid();
self.createColorPalette();
self.createTools();
self.createActionButtons();
// Load drawing if it exists
if (storage.currentDrawing) {
self.loadDrawing(storage.currentDrawing);
}
};
self.createGrid = function () {
var gridContainer = new Container();
self.addChild(gridContainer);
// Center the grid
var gridWidth = self.gridSize * self.cellSize;
var gridX = (2048 - gridWidth) / 2;
var gridY = 300; // Position below UI elements
gridContainer.position.set(gridX, gridY);
for (var y = 0; y < self.gridSize; y++) {
self.grid[y] = [];
for (var x = 0; x < self.gridSize; x++) {
var cell = new GridCell();
cell.position.set(x * self.cellSize, y * self.cellSize);
cell.gridX = x;
cell.gridY = y;
self.grid[y][x] = cell;
gridContainer.addChild(cell);
}
}
};
self.createColorPalette = function () {
var colors = [0x000000, 0xFFFFFF, 0xFF0000, 0x00FF00, 0x0000FF, 0xFFFF00, 0xFF00FF, 0x00FFFF, 0x800000, 0x008000, 0x000080, 0x808000, 0x800080, 0x008080, 0x808080, 0xC0C0C0];
var paletteContainer = new Container();
self.addChild(paletteContainer);
// Position palette on the top
paletteContainer.position.set(224, 100);
for (var i = 0; i < colors.length; i++) {
var colorBtn = new ColorButton();
colorBtn.setColor(colors[i]);
colorBtn.position.set(i % 8 * 120, Math.floor(i / 8) * 120);
paletteContainer.addChild(colorBtn);
}
};
self.createTools = function () {
var tools = ['draw', 'fill', 'erase'];
var toolsContainer = new Container();
self.addChild(toolsContainer);
// Position tools to the left of the canvas
toolsContainer.position.set(100, 400);
for (var i = 0; i < tools.length; i++) {
var toolBtn = new ToolButton();
toolBtn.setTool(tools[i]);
toolBtn.position.set(0, i * 120);
if (tools[i] === self.currentTool) {
toolBtn.setSelected(true);
}
toolsContainer.addChild(toolBtn);
}
};
self.createActionButtons = function () {
var actions = [{
name: 'clear',
label: 'Clear'
}, {
name: 'undo',
label: 'Undo'
}, {
name: 'redo',
label: 'Redo'
}, {
name: 'save',
label: 'Save'
}, {
name: 'load',
label: 'Load'
}];
var actionsContainer = new Container();
self.addChild(actionsContainer);
// Position actions to the right of the canvas
actionsContainer.position.set(1648, 400);
for (var i = 0; i < actions.length; i++) {
var actionBtn = new ActionButton();
actionBtn.setAction(actions[i].name, actions[i].label);
actionBtn.position.set(0, i * 100);
actionsContainer.addChild(actionBtn);
}
};
self.selectColor = function (color) {
self.selectedColor = color;
};
self.selectTool = function (toolName) {
self.currentTool = toolName;
// Update tool buttons visually
var toolsContainer = self.children[2]; // Assuming tools are the 3rd child
for (var i = 0; i < toolsContainer.children.length; i++) {
var toolBtn = toolsContainer.children[i];
toolBtn.setSelected(toolBtn.toolName === toolName);
}
};
self.setPixel = function (cell) {
if (self.currentTool === 'draw') {
if (cell.color !== self.selectedColor) {
self.saveState();
cell.setColor(self.selectedColor);
LK.getSound('draw').play();
}
} else if (self.currentTool === 'erase') {
if (!cell.isEmpty) {
self.saveState();
cell.clear();
LK.getSound('draw').play();
}
} else if (self.currentTool === 'fill') {
self.saveState();
self.floodFill(cell.gridX, cell.gridY, cell.color);
LK.getSound('fill').play();
}
};
self.floodFill = function (x, y, targetColor) {
if (x < 0 || x >= self.gridSize || y < 0 || y >= self.gridSize) {
return;
}
if (self.grid[y][x].color !== targetColor) {
return;
}
if (self.grid[y][x].color === self.selectedColor) {
return;
}
self.grid[y][x].setColor(self.selectedColor);
self.floodFill(x + 1, y, targetColor);
self.floodFill(x - 1, y, targetColor);
self.floodFill(x, y + 1, targetColor);
self.floodFill(x, y - 1, targetColor);
};
self.saveState = function () {
// If we've gone back in history and now make a new change,
// discard any future states beyond the current index
if (self.historyIndex < self.history.length - 1) {
self.history = self.history.slice(0, self.historyIndex + 1);
}
// Save current state
var state = [];
for (var y = 0; y < self.gridSize; y++) {
state[y] = [];
for (var x = 0; x < self.gridSize; x++) {
state[y][x] = self.grid[y][x].color;
}
}
// Add to history and limit history size
self.history.push(state);
self.historyIndex++;
if (self.history.length > self.maxHistory) {
self.history.shift();
self.historyIndex--;
}
};
self.loadState = function (state) {
for (var y = 0; y < self.gridSize; y++) {
for (var x = 0; x < self.gridSize; x++) {
if (y < state.length && x < state[y].length) {
self.grid[y][x].setColor(state[y][x]);
} else {
self.grid[y][x].clear();
}
}
}
};
self.performAction = function (action) {
switch (action) {
case 'clear':
self.saveState();
self.clearCanvas();
break;
case 'undo':
self.undo();
break;
case 'redo':
self.redo();
break;
case 'save':
self.saveDrawing();
break;
case 'load':
// This would typically show a UI for selecting a saved drawing
// For simplicity, we'll just load the first saved drawing if available
if (storage.savedDrawings.length > 0) {
self.loadDrawing(storage.savedDrawings[0]);
}
break;
}
};
self.clearCanvas = function () {
for (var y = 0; y < self.gridSize; y++) {
for (var x = 0; x < self.gridSize; x++) {
self.grid[y][x].clear();
}
}
};
self.undo = function () {
if (self.historyIndex > 0) {
self.historyIndex--;
self.loadState(self.history[self.historyIndex]);
}
};
self.redo = function () {
if (self.historyIndex < self.history.length - 1) {
self.historyIndex++;
self.loadState(self.history[self.historyIndex]);
}
};
self.saveDrawing = function () {
var drawing = [];
for (var y = 0; y < self.gridSize; y++) {
drawing[y] = [];
for (var x = 0; x < self.gridSize; x++) {
drawing[y][x] = self.grid[y][x].color;
}
}
// Save to storage
storage.currentDrawing = drawing;
storage.savedDrawings.push(drawing);
// Limit saved drawings to prevent excessive storage
if (storage.savedDrawings.length > 10) {
storage.savedDrawings.shift();
}
LK.getSound('save').play();
};
self.loadDrawing = function (drawing) {
if (drawing) {
self.clearCanvas();
self.loadState(drawing);
// Reset history when loading
self.history = [drawing];
self.historyIndex = 0;
}
};
self.down = function (x, y, obj) {
self.isDrawing = true;
};
self.up = function (x, y, obj) {
self.isDrawing = false;
};
return self;
});
var ToolButton = Container.expand(function () {
var self = Container.call(this);
var toolIcon = self.attachAsset('toolIcon', {
anchorX: 0,
anchorY: 0
});
self.toolName = '';
self.isSelected = false;
var toolLabel = new Text2('', {
size: 24,
fill: 0x000000
});
toolLabel.anchor.set(0.5, 0.5);
toolLabel.position.set(50, 50);
self.addChild(toolLabel);
self.setTool = function (name) {
self.toolName = name;
toolLabel.setText(name);
};
self.setSelected = function (selected) {
self.isSelected = selected;
toolIcon.tint = selected ? 0x88BBFF : 0xCCCCCC;
};
self.down = function (x, y, obj) {
pixelEditor.selectTool(self.toolName);
LK.getSound('click').play();
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0xF0F0F0
});
/****
* Game Code
****/
// Create title text
var titleText = new Text2('Pixel Crafter', {
size: 80,
fill: 0x333333
});
titleText.anchor.set(0.5, 0);
titleText.position.set(2048 / 2, 20);
game.addChild(titleText);
// Create pixel editor
var pixelEditor = new PixelEditor();
game.addChild(pixelEditor);
pixelEditor.initialize();
// Handle game events
game.down = function (x, y, obj) {
// Start drawing if no specific object was clicked
if (!obj || obj === game) {
pixelEditor.isDrawing = true;
}
};
game.up = function (x, y, obj) {
pixelEditor.isDrawing = false;
};
game.move = function (x, y, obj) {
// This is handled by the GridCell move event
};
// Play background music
LK.playMusic('bgmusic', {
fade: {
start: 0,
end: 0.3,
duration: 1000
}
});