/****
* 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
}
});