/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
worlds: {},
currentWorld: "default",
avatarColor: 3447003
});
/****
* Classes
****/
var Avatar = Container.expand(function () {
var self = Container.call(this);
var avatarGraphics = self.attachAsset('avatar', {
anchorX: 0.5,
anchorY: 0.5
});
self.vx = 0;
self.vy = 0;
self.onGround = false;
self.jumpPower = -15;
self.moveSpeed = 5;
self.gravity = 0.6;
self.updateColor = function (color) {
avatarGraphics.tint = color;
};
self.jump = function () {
if (self.onGround) {
self.vy = self.jumpPower;
self.onGround = false;
LK.getSound('jump').play();
}
};
self.update = function () {
// Apply gravity
self.vy += self.gravity;
// Apply movement
self.x += self.vx;
self.y += self.vy;
// Detect collisions with blocks
self.onGround = false;
for (var i = 0; i < blocks.length; i++) {
if (self.intersects(blocks[i])) {
// Calculate collision sides
var dx = self.x - blocks[i].x;
var dy = self.y - blocks[i].y;
var combinedHalfWidths = (avatarGraphics.width + blocks[i].width) / 2;
var combinedHalfHeights = (avatarGraphics.height + blocks[i].height) / 2;
var overlapX = combinedHalfWidths - Math.abs(dx);
var overlapY = combinedHalfHeights - Math.abs(dy);
// Resolve collision (simple AABB resolution)
if (overlapX < overlapY) {
if (dx > 0) {
self.x += overlapX;
self.vx = 0;
} else {
self.x -= overlapX;
self.vx = 0;
}
} else {
if (dy > 0) {
self.y += overlapY;
self.vy = 0;
} else {
self.y -= overlapY;
self.vy = 0;
self.onGround = true;
}
}
}
}
// Keep avatar within bounds
if (self.x < 0) {
self.x = 0;
}
if (self.x > 2048) {
self.x = 2048;
}
if (self.y < 0) {
self.y = 0;
}
if (self.y > 2732) {
self.y = 2732;
}
};
return self;
});
var Block = Container.expand(function () {
var self = Container.call(this);
self.blockType = 'normal';
self.blockColor = 0x888888;
var blockGraphics = self.attachAsset('block', {
anchorX: 0.5,
anchorY: 0.5
});
self.setType = function (type, color) {
self.blockType = type || 'normal';
self.blockColor = color || 0x888888;
blockGraphics.tint = self.blockColor;
};
self.down = function (x, y, obj) {
if (currentTool === 'delete') {
self.shouldDelete = true;
}
};
return self;
});
var Button = Container.expand(function (label, callback) {
var self = Container.call(this);
var buttonGraphics = self.attachAsset('button', {
anchorX: 0.5,
anchorY: 0.5
});
var labelText = new Text2(label, {
size: 32,
fill: 0xFFFFFF
});
labelText.anchor.set(0.5, 0.5);
self.addChild(labelText);
self.callback = callback;
self.down = function (x, y, obj) {
buttonGraphics.tint = 0x2980b9;
};
self.up = function (x, y, obj) {
buttonGraphics.tint = 0x3498db;
if (self.callback) {
self.callback();
}
LK.getSound('select').play();
};
return self;
});
var ColorSwatch = Container.expand(function (color) {
var self = Container.call(this);
self.color = color;
var swatchGraphics = self.attachAsset('colorSwatch', {
anchorX: 0.5,
anchorY: 0.5
});
swatchGraphics.tint = color;
self.down = function (x, y, obj) {
currentColor = self.color;
colorPalette.visible = false;
LK.getSound('select').play();
};
return self;
});
var Tool = Container.expand(function (type, iconColor) {
var self = Container.call(this);
self.toolType = type;
var toolGraphics = self.attachAsset('toolSelector', {
anchorX: 0.5,
anchorY: 0.5
});
var iconGraphics = self.attachAsset('block', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.6,
scaleY: 0.6
});
iconGraphics.tint = iconColor || 0xffffff;
self.setSelected = function (selected) {
if (selected) {
toolGraphics.tint = 0xffcc00;
} else {
toolGraphics.tint = 0xffffff;
}
};
self.down = function (x, y, obj) {
currentTool = self.toolType;
updateToolSelection();
LK.getSound('select').play();
};
return self;
});
var WorldThumbnail = Container.expand(function (worldName, worldData) {
var self = Container.call(this);
self.worldName = worldName;
var thumbnailGraphics = self.attachAsset('worldThumbnail', {
anchorX: 0.5,
anchorY: 0.5
});
var nameText = new Text2(worldName, {
size: 24,
fill: 0x333333
});
nameText.anchor.set(0.5, 0.5);
nameText.y = thumbnailGraphics.height / 2 + 20;
self.addChild(nameText);
self.down = function (x, y, obj) {
thumbnailGraphics.tint = 0xbbbbbb;
};
self.up = function (x, y, obj) {
thumbnailGraphics.tint = 0xffffff;
loadWorld(self.worldName);
worldsMenu.visible = false;
LK.getSound('select').play();
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87CEEB
});
/****
* Game Code
****/
// Game state variables
var isBuilderMode = true;
var currentTool = 'block';
var currentColor = 0x888888;
var blocks = [];
var avatar;
var colorPalette;
var toolsContainer;
var worldsMenu;
var menuButton;
var colorPickerButton;
var dragStartX, dragStartY;
var isAvatarDragging = false;
var isJumping = false;
var isMovingLeft = false;
var isMovingRight = false;
// Colors for the palette
var paletteColors = [0xff0000, 0xff9900, 0xffff00, 0x00ff00, 0x00ffff, 0x0000ff, 0x9900ff, 0xff00ff, 0xffffff, 0xcccccc, 0x888888, 0x444444, 0x000000, 0x996633, 0x663300, 0x336600];
// Initialize UI
function initUI() {
// Tools container
toolsContainer = new Container();
toolsContainer.x = 120;
toolsContainer.y = 80;
game.addChild(toolsContainer);
// Add tools
var blockTool = new Tool('block', 0x888888);
blockTool.x = 0;
blockTool.y = 0;
toolsContainer.addChild(blockTool);
var deleteTool = new Tool('delete', 0xff0000);
deleteTool.x = 0;
deleteTool.y = 80;
toolsContainer.addChild(deleteTool);
var avatarTool = new Tool('avatar', 0x3498db);
avatarTool.x = 0;
avatarTool.y = 160;
toolsContainer.addChild(avatarTool);
var playTool = new Tool('play', 0x2ecc71);
playTool.x = 0;
playTool.y = 240;
toolsContainer.addChild(playTool);
// Color palette
colorPalette = new Container();
var paletteBackground = LK.getAsset('palette', {
anchorX: 0.5,
anchorY: 0.5
});
colorPalette.addChild(paletteBackground);
var paletteTitle = new Text2("Select Color", {
size: 30,
fill: 0x333333
});
paletteTitle.anchor.set(0.5, 0);
paletteTitle.x = 0;
paletteTitle.y = -120;
colorPalette.addChild(paletteTitle);
// Add color swatches
for (var i = 0; i < paletteColors.length; i++) {
var swatch = new ColorSwatch(paletteColors[i]);
swatch.x = i % 4 * 60 - 90;
swatch.y = Math.floor(i / 4) * 60 - 60;
colorPalette.addChild(swatch);
}
colorPalette.x = 2048 / 2;
colorPalette.y = 2732 / 2;
colorPalette.visible = false;
game.addChild(colorPalette);
// Color picker button
colorPickerButton = new Button("Colors", function () {
colorPalette.visible = true;
});
colorPickerButton.x = 120;
colorPickerButton.y = 400;
game.addChild(colorPickerButton);
// Menu button
menuButton = new Button("Menu", function () {
showWorldsMenu();
});
menuButton.x = 120;
menuButton.y = 500;
game.addChild(menuButton);
// Worlds menu
worldsMenu = new Container();
var menuBackground = LK.getAsset('menuBackground', {
anchorX: 0.5,
anchorY: 0.5
});
worldsMenu.addChild(menuBackground);
var menuTitle = new Text2("Worlds", {
size: 40,
fill: 0x333333
});
menuTitle.anchor.set(0.5, 0);
menuTitle.x = 0;
menuTitle.y = -250;
worldsMenu.addChild(menuTitle);
var newWorldButton = new Button("New World", function () {
createNewWorld();
});
newWorldButton.x = 0;
newWorldButton.y = 200;
worldsMenu.addChild(newWorldButton);
var closeButton = new Button("Close", function () {
worldsMenu.visible = false;
});
closeButton.x = 0;
closeButton.y = 250;
worldsMenu.addChild(closeButton);
worldsMenu.x = 2048 / 2;
worldsMenu.y = 2732 / 2;
worldsMenu.visible = false;
game.addChild(worldsMenu);
// Instructions text
var instructionsText = new Text2("Tap to place blocks\nDrag avatar to move\nUse tools on the left", {
size: 30,
fill: 0x333333
});
instructionsText.anchor.set(0.5, 0);
instructionsText.x = 2048 / 2;
instructionsText.y = 40;
game.addChild(instructionsText);
}
function updateToolSelection() {
for (var i = 0; i < toolsContainer.children.length; i++) {
var tool = toolsContainer.children[i];
if (tool.toolType === currentTool) {
tool.setSelected(true);
} else {
tool.setSelected(false);
}
}
// Toggle builder/play mode
if (currentTool === 'play') {
isBuilderMode = false;
startPlayMode();
} else {
isBuilderMode = true;
endPlayMode();
}
}
function startPlayMode() {
if (!avatar) {
// Create default avatar if none exists
avatar = new Avatar();
avatar.x = 2048 / 2;
avatar.y = 2732 / 2;
avatar.updateColor(storage.avatarColor);
game.addChild(avatar);
}
toolsContainer.visible = false;
colorPickerButton.visible = false;
menuButton.visible = false;
// Alert player
var playingText = new Text2("PLAYING MODE", {
size: 60,
fill: 0xFF0000
});
playingText.anchor.set(0.5, 0.5);
playingText.x = 2048 / 2;
playingText.y = 2732 / 2;
game.addChild(playingText);
LK.setTimeout(function () {
game.removeChild(playingText);
}, 1500);
}
function endPlayMode() {
toolsContainer.visible = true;
colorPickerButton.visible = true;
menuButton.visible = true;
}
function placeBlock(x, y) {
var block = new Block();
block.x = Math.floor(x / 64) * 64 + 32;
block.y = Math.floor(y / 64) * 64 + 32;
block.setType('normal', currentColor);
// Check if block already exists at this position
for (var i = 0; i < blocks.length; i++) {
if (Math.abs(blocks[i].x - block.x) < 5 && Math.abs(blocks[i].y - block.y) < 5) {
return; // Block already exists here
}
}
game.addChild(block);
blocks.push(block);
LK.getSound('place').play();
}
function createAvatar(x, y) {
// Remove existing avatar if present
if (avatar) {
game.removeChild(avatar);
}
avatar = new Avatar();
avatar.x = x;
avatar.y = y;
avatar.updateColor(currentColor);
storage.avatarColor = currentColor;
game.addChild(avatar);
}
function showWorldsMenu() {
// Clear previous world thumbnails
for (var i = worldsMenu.children.length - 1; i >= 0; i--) {
if (worldsMenu.children[i] instanceof WorldThumbnail) {
worldsMenu.removeChild(worldsMenu.children[i]);
}
}
// Add world thumbnails
var worldNames = Object.keys(storage.worlds);
var yPos = -150;
for (var i = 0; i < worldNames.length; i++) {
var thumbnail = new WorldThumbnail(worldNames[i], storage.worlds[worldNames[i]]);
thumbnail.x = 0;
thumbnail.y = yPos;
worldsMenu.addChild(thumbnail);
yPos += 150;
}
worldsMenu.visible = true;
}
function saveCurrentWorld() {
var worldData = {
blocks: [],
avatarPosition: avatar ? {
x: avatar.x,
y: avatar.y
} : null,
avatarColor: storage.avatarColor
};
// Save block data
for (var i = 0; i < blocks.length; i++) {
worldData.blocks.push({
x: blocks[i].x,
y: blocks[i].y,
color: blocks[i].blockColor,
type: blocks[i].blockType
});
}
storage.worlds[storage.currentWorld] = worldData;
}
function loadWorld(worldName) {
saveCurrentWorld(); // Save current world first
// Clear existing blocks
for (var i = blocks.length - 1; i >= 0; i--) {
game.removeChild(blocks[i]);
}
blocks = [];
// Remove existing avatar
if (avatar) {
game.removeChild(avatar);
avatar = null;
}
// Set current world
storage.currentWorld = worldName;
// Load world data
var worldData = storage.worlds[worldName];
if (!worldData) {
// Create empty world if it doesn't exist
return;
}
// Load blocks
for (var i = 0; i < worldData.blocks.length; i++) {
var blockData = worldData.blocks[i];
var block = new Block();
block.x = blockData.x;
block.y = blockData.y;
block.setType(blockData.type, blockData.color);
game.addChild(block);
blocks.push(block);
}
// Load avatar
if (worldData.avatarPosition) {
avatar = new Avatar();
avatar.x = worldData.avatarPosition.x;
avatar.y = worldData.avatarPosition.y;
avatar.updateColor(worldData.avatarColor || 0x3498db);
storage.avatarColor = worldData.avatarColor || 0x3498db;
game.addChild(avatar);
}
}
function createNewWorld() {
var worldName = "World" + Math.floor(Math.random() * 1000);
// Save current world
saveCurrentWorld();
// Initialize new world
storage.worlds[worldName] = {
blocks: [],
avatarPosition: null,
avatarColor: 0x3498db
};
// Load the new empty world
loadWorld(worldName);
worldsMenu.visible = false;
}
// Initialize game
initUI();
// Check if we have any worlds, if not create a default one
if (Object.keys(storage.worlds).length === 0) {
// Create default world with platform
storage.worlds['default'] = {
blocks: [],
avatarPosition: null,
avatarColor: 0x3498db
};
// Add some blocks to the default world
for (var i = 0; i < 20; i++) {
storage.worlds['default'].blocks.push({
x: 400 + i * 64,
y: 1500,
color: 0x888888,
type: 'normal'
});
}
}
// Load the current world
loadWorld(storage.currentWorld);
// Start background music
LK.playMusic('bgmusic');
// Game update logic
game.update = function () {
// Handle block deletion
for (var i = blocks.length - 1; i >= 0; i--) {
if (blocks[i].shouldDelete) {
game.removeChild(blocks[i]);
blocks.splice(i, 1);
}
}
// Update avatar in play mode
if (!isBuilderMode && avatar) {
// Handle input for avatar movement
if (isMovingLeft) {
avatar.vx = -avatar.moveSpeed;
} else if (isMovingRight) {
avatar.vx = avatar.moveSpeed;
} else {
avatar.vx = 0;
}
if (isJumping) {
avatar.jump();
isJumping = false;
}
// Update avatar physics
avatar.update();
}
};
// Game input handlers
game.down = function (x, y, obj) {
// Store drag start position
dragStartX = x;
dragStartY = y;
// Skip if color palette or worlds menu is open
if (colorPalette.visible || worldsMenu.visible) {
return;
}
// Handle building/deleting in builder mode
if (isBuilderMode) {
if (currentTool === 'block') {
placeBlock(x, y);
} else if (currentTool === 'avatar') {
createAvatar(x, y);
}
} else {
// Play mode controls
if (avatar) {
// Check if clicking on avatar (for dragging)
var localPoint = avatar.toLocal({
x: x,
y: y
});
if (Math.abs(localPoint.x) < avatar.width / 2 && Math.abs(localPoint.y) < avatar.height / 2) {
isAvatarDragging = true;
} else {
// Check for movement controls (left side = left, right side = right, top = jump)
if (y < 2732 / 3) {
isJumping = true;
} else if (x < 2048 / 2) {
isMovingLeft = true;
} else {
isMovingRight = true;
}
}
}
}
};
game.move = function (x, y, obj) {
// Skip if color palette or worlds menu is open
if (colorPalette.visible || worldsMenu.visible) {
return;
}
// Handle avatar dragging in play mode
if (!isBuilderMode && isAvatarDragging && avatar) {
avatar.x = x;
avatar.y = y;
avatar.vx = 0;
avatar.vy = 0;
}
};
game.up = function (x, y, obj) {
// Reset movement flags
isAvatarDragging = false;
isMovingLeft = false;
isMovingRight = false;
// Save world when interaction ends
saveCurrentWorld();
}; /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
worlds: {},
currentWorld: "default",
avatarColor: 3447003
});
/****
* Classes
****/
var Avatar = Container.expand(function () {
var self = Container.call(this);
var avatarGraphics = self.attachAsset('avatar', {
anchorX: 0.5,
anchorY: 0.5
});
self.vx = 0;
self.vy = 0;
self.onGround = false;
self.jumpPower = -15;
self.moveSpeed = 5;
self.gravity = 0.6;
self.updateColor = function (color) {
avatarGraphics.tint = color;
};
self.jump = function () {
if (self.onGround) {
self.vy = self.jumpPower;
self.onGround = false;
LK.getSound('jump').play();
}
};
self.update = function () {
// Apply gravity
self.vy += self.gravity;
// Apply movement
self.x += self.vx;
self.y += self.vy;
// Detect collisions with blocks
self.onGround = false;
for (var i = 0; i < blocks.length; i++) {
if (self.intersects(blocks[i])) {
// Calculate collision sides
var dx = self.x - blocks[i].x;
var dy = self.y - blocks[i].y;
var combinedHalfWidths = (avatarGraphics.width + blocks[i].width) / 2;
var combinedHalfHeights = (avatarGraphics.height + blocks[i].height) / 2;
var overlapX = combinedHalfWidths - Math.abs(dx);
var overlapY = combinedHalfHeights - Math.abs(dy);
// Resolve collision (simple AABB resolution)
if (overlapX < overlapY) {
if (dx > 0) {
self.x += overlapX;
self.vx = 0;
} else {
self.x -= overlapX;
self.vx = 0;
}
} else {
if (dy > 0) {
self.y += overlapY;
self.vy = 0;
} else {
self.y -= overlapY;
self.vy = 0;
self.onGround = true;
}
}
}
}
// Keep avatar within bounds
if (self.x < 0) {
self.x = 0;
}
if (self.x > 2048) {
self.x = 2048;
}
if (self.y < 0) {
self.y = 0;
}
if (self.y > 2732) {
self.y = 2732;
}
};
return self;
});
var Block = Container.expand(function () {
var self = Container.call(this);
self.blockType = 'normal';
self.blockColor = 0x888888;
var blockGraphics = self.attachAsset('block', {
anchorX: 0.5,
anchorY: 0.5
});
self.setType = function (type, color) {
self.blockType = type || 'normal';
self.blockColor = color || 0x888888;
blockGraphics.tint = self.blockColor;
};
self.down = function (x, y, obj) {
if (currentTool === 'delete') {
self.shouldDelete = true;
}
};
return self;
});
var Button = Container.expand(function (label, callback) {
var self = Container.call(this);
var buttonGraphics = self.attachAsset('button', {
anchorX: 0.5,
anchorY: 0.5
});
var labelText = new Text2(label, {
size: 32,
fill: 0xFFFFFF
});
labelText.anchor.set(0.5, 0.5);
self.addChild(labelText);
self.callback = callback;
self.down = function (x, y, obj) {
buttonGraphics.tint = 0x2980b9;
};
self.up = function (x, y, obj) {
buttonGraphics.tint = 0x3498db;
if (self.callback) {
self.callback();
}
LK.getSound('select').play();
};
return self;
});
var ColorSwatch = Container.expand(function (color) {
var self = Container.call(this);
self.color = color;
var swatchGraphics = self.attachAsset('colorSwatch', {
anchorX: 0.5,
anchorY: 0.5
});
swatchGraphics.tint = color;
self.down = function (x, y, obj) {
currentColor = self.color;
colorPalette.visible = false;
LK.getSound('select').play();
};
return self;
});
var Tool = Container.expand(function (type, iconColor) {
var self = Container.call(this);
self.toolType = type;
var toolGraphics = self.attachAsset('toolSelector', {
anchorX: 0.5,
anchorY: 0.5
});
var iconGraphics = self.attachAsset('block', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.6,
scaleY: 0.6
});
iconGraphics.tint = iconColor || 0xffffff;
self.setSelected = function (selected) {
if (selected) {
toolGraphics.tint = 0xffcc00;
} else {
toolGraphics.tint = 0xffffff;
}
};
self.down = function (x, y, obj) {
currentTool = self.toolType;
updateToolSelection();
LK.getSound('select').play();
};
return self;
});
var WorldThumbnail = Container.expand(function (worldName, worldData) {
var self = Container.call(this);
self.worldName = worldName;
var thumbnailGraphics = self.attachAsset('worldThumbnail', {
anchorX: 0.5,
anchorY: 0.5
});
var nameText = new Text2(worldName, {
size: 24,
fill: 0x333333
});
nameText.anchor.set(0.5, 0.5);
nameText.y = thumbnailGraphics.height / 2 + 20;
self.addChild(nameText);
self.down = function (x, y, obj) {
thumbnailGraphics.tint = 0xbbbbbb;
};
self.up = function (x, y, obj) {
thumbnailGraphics.tint = 0xffffff;
loadWorld(self.worldName);
worldsMenu.visible = false;
LK.getSound('select').play();
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87CEEB
});
/****
* Game Code
****/
// Game state variables
var isBuilderMode = true;
var currentTool = 'block';
var currentColor = 0x888888;
var blocks = [];
var avatar;
var colorPalette;
var toolsContainer;
var worldsMenu;
var menuButton;
var colorPickerButton;
var dragStartX, dragStartY;
var isAvatarDragging = false;
var isJumping = false;
var isMovingLeft = false;
var isMovingRight = false;
// Colors for the palette
var paletteColors = [0xff0000, 0xff9900, 0xffff00, 0x00ff00, 0x00ffff, 0x0000ff, 0x9900ff, 0xff00ff, 0xffffff, 0xcccccc, 0x888888, 0x444444, 0x000000, 0x996633, 0x663300, 0x336600];
// Initialize UI
function initUI() {
// Tools container
toolsContainer = new Container();
toolsContainer.x = 120;
toolsContainer.y = 80;
game.addChild(toolsContainer);
// Add tools
var blockTool = new Tool('block', 0x888888);
blockTool.x = 0;
blockTool.y = 0;
toolsContainer.addChild(blockTool);
var deleteTool = new Tool('delete', 0xff0000);
deleteTool.x = 0;
deleteTool.y = 80;
toolsContainer.addChild(deleteTool);
var avatarTool = new Tool('avatar', 0x3498db);
avatarTool.x = 0;
avatarTool.y = 160;
toolsContainer.addChild(avatarTool);
var playTool = new Tool('play', 0x2ecc71);
playTool.x = 0;
playTool.y = 240;
toolsContainer.addChild(playTool);
// Color palette
colorPalette = new Container();
var paletteBackground = LK.getAsset('palette', {
anchorX: 0.5,
anchorY: 0.5
});
colorPalette.addChild(paletteBackground);
var paletteTitle = new Text2("Select Color", {
size: 30,
fill: 0x333333
});
paletteTitle.anchor.set(0.5, 0);
paletteTitle.x = 0;
paletteTitle.y = -120;
colorPalette.addChild(paletteTitle);
// Add color swatches
for (var i = 0; i < paletteColors.length; i++) {
var swatch = new ColorSwatch(paletteColors[i]);
swatch.x = i % 4 * 60 - 90;
swatch.y = Math.floor(i / 4) * 60 - 60;
colorPalette.addChild(swatch);
}
colorPalette.x = 2048 / 2;
colorPalette.y = 2732 / 2;
colorPalette.visible = false;
game.addChild(colorPalette);
// Color picker button
colorPickerButton = new Button("Colors", function () {
colorPalette.visible = true;
});
colorPickerButton.x = 120;
colorPickerButton.y = 400;
game.addChild(colorPickerButton);
// Menu button
menuButton = new Button("Menu", function () {
showWorldsMenu();
});
menuButton.x = 120;
menuButton.y = 500;
game.addChild(menuButton);
// Worlds menu
worldsMenu = new Container();
var menuBackground = LK.getAsset('menuBackground', {
anchorX: 0.5,
anchorY: 0.5
});
worldsMenu.addChild(menuBackground);
var menuTitle = new Text2("Worlds", {
size: 40,
fill: 0x333333
});
menuTitle.anchor.set(0.5, 0);
menuTitle.x = 0;
menuTitle.y = -250;
worldsMenu.addChild(menuTitle);
var newWorldButton = new Button("New World", function () {
createNewWorld();
});
newWorldButton.x = 0;
newWorldButton.y = 200;
worldsMenu.addChild(newWorldButton);
var closeButton = new Button("Close", function () {
worldsMenu.visible = false;
});
closeButton.x = 0;
closeButton.y = 250;
worldsMenu.addChild(closeButton);
worldsMenu.x = 2048 / 2;
worldsMenu.y = 2732 / 2;
worldsMenu.visible = false;
game.addChild(worldsMenu);
// Instructions text
var instructionsText = new Text2("Tap to place blocks\nDrag avatar to move\nUse tools on the left", {
size: 30,
fill: 0x333333
});
instructionsText.anchor.set(0.5, 0);
instructionsText.x = 2048 / 2;
instructionsText.y = 40;
game.addChild(instructionsText);
}
function updateToolSelection() {
for (var i = 0; i < toolsContainer.children.length; i++) {
var tool = toolsContainer.children[i];
if (tool.toolType === currentTool) {
tool.setSelected(true);
} else {
tool.setSelected(false);
}
}
// Toggle builder/play mode
if (currentTool === 'play') {
isBuilderMode = false;
startPlayMode();
} else {
isBuilderMode = true;
endPlayMode();
}
}
function startPlayMode() {
if (!avatar) {
// Create default avatar if none exists
avatar = new Avatar();
avatar.x = 2048 / 2;
avatar.y = 2732 / 2;
avatar.updateColor(storage.avatarColor);
game.addChild(avatar);
}
toolsContainer.visible = false;
colorPickerButton.visible = false;
menuButton.visible = false;
// Alert player
var playingText = new Text2("PLAYING MODE", {
size: 60,
fill: 0xFF0000
});
playingText.anchor.set(0.5, 0.5);
playingText.x = 2048 / 2;
playingText.y = 2732 / 2;
game.addChild(playingText);
LK.setTimeout(function () {
game.removeChild(playingText);
}, 1500);
}
function endPlayMode() {
toolsContainer.visible = true;
colorPickerButton.visible = true;
menuButton.visible = true;
}
function placeBlock(x, y) {
var block = new Block();
block.x = Math.floor(x / 64) * 64 + 32;
block.y = Math.floor(y / 64) * 64 + 32;
block.setType('normal', currentColor);
// Check if block already exists at this position
for (var i = 0; i < blocks.length; i++) {
if (Math.abs(blocks[i].x - block.x) < 5 && Math.abs(blocks[i].y - block.y) < 5) {
return; // Block already exists here
}
}
game.addChild(block);
blocks.push(block);
LK.getSound('place').play();
}
function createAvatar(x, y) {
// Remove existing avatar if present
if (avatar) {
game.removeChild(avatar);
}
avatar = new Avatar();
avatar.x = x;
avatar.y = y;
avatar.updateColor(currentColor);
storage.avatarColor = currentColor;
game.addChild(avatar);
}
function showWorldsMenu() {
// Clear previous world thumbnails
for (var i = worldsMenu.children.length - 1; i >= 0; i--) {
if (worldsMenu.children[i] instanceof WorldThumbnail) {
worldsMenu.removeChild(worldsMenu.children[i]);
}
}
// Add world thumbnails
var worldNames = Object.keys(storage.worlds);
var yPos = -150;
for (var i = 0; i < worldNames.length; i++) {
var thumbnail = new WorldThumbnail(worldNames[i], storage.worlds[worldNames[i]]);
thumbnail.x = 0;
thumbnail.y = yPos;
worldsMenu.addChild(thumbnail);
yPos += 150;
}
worldsMenu.visible = true;
}
function saveCurrentWorld() {
var worldData = {
blocks: [],
avatarPosition: avatar ? {
x: avatar.x,
y: avatar.y
} : null,
avatarColor: storage.avatarColor
};
// Save block data
for (var i = 0; i < blocks.length; i++) {
worldData.blocks.push({
x: blocks[i].x,
y: blocks[i].y,
color: blocks[i].blockColor,
type: blocks[i].blockType
});
}
storage.worlds[storage.currentWorld] = worldData;
}
function loadWorld(worldName) {
saveCurrentWorld(); // Save current world first
// Clear existing blocks
for (var i = blocks.length - 1; i >= 0; i--) {
game.removeChild(blocks[i]);
}
blocks = [];
// Remove existing avatar
if (avatar) {
game.removeChild(avatar);
avatar = null;
}
// Set current world
storage.currentWorld = worldName;
// Load world data
var worldData = storage.worlds[worldName];
if (!worldData) {
// Create empty world if it doesn't exist
return;
}
// Load blocks
for (var i = 0; i < worldData.blocks.length; i++) {
var blockData = worldData.blocks[i];
var block = new Block();
block.x = blockData.x;
block.y = blockData.y;
block.setType(blockData.type, blockData.color);
game.addChild(block);
blocks.push(block);
}
// Load avatar
if (worldData.avatarPosition) {
avatar = new Avatar();
avatar.x = worldData.avatarPosition.x;
avatar.y = worldData.avatarPosition.y;
avatar.updateColor(worldData.avatarColor || 0x3498db);
storage.avatarColor = worldData.avatarColor || 0x3498db;
game.addChild(avatar);
}
}
function createNewWorld() {
var worldName = "World" + Math.floor(Math.random() * 1000);
// Save current world
saveCurrentWorld();
// Initialize new world
storage.worlds[worldName] = {
blocks: [],
avatarPosition: null,
avatarColor: 0x3498db
};
// Load the new empty world
loadWorld(worldName);
worldsMenu.visible = false;
}
// Initialize game
initUI();
// Check if we have any worlds, if not create a default one
if (Object.keys(storage.worlds).length === 0) {
// Create default world with platform
storage.worlds['default'] = {
blocks: [],
avatarPosition: null,
avatarColor: 0x3498db
};
// Add some blocks to the default world
for (var i = 0; i < 20; i++) {
storage.worlds['default'].blocks.push({
x: 400 + i * 64,
y: 1500,
color: 0x888888,
type: 'normal'
});
}
}
// Load the current world
loadWorld(storage.currentWorld);
// Start background music
LK.playMusic('bgmusic');
// Game update logic
game.update = function () {
// Handle block deletion
for (var i = blocks.length - 1; i >= 0; i--) {
if (blocks[i].shouldDelete) {
game.removeChild(blocks[i]);
blocks.splice(i, 1);
}
}
// Update avatar in play mode
if (!isBuilderMode && avatar) {
// Handle input for avatar movement
if (isMovingLeft) {
avatar.vx = -avatar.moveSpeed;
} else if (isMovingRight) {
avatar.vx = avatar.moveSpeed;
} else {
avatar.vx = 0;
}
if (isJumping) {
avatar.jump();
isJumping = false;
}
// Update avatar physics
avatar.update();
}
};
// Game input handlers
game.down = function (x, y, obj) {
// Store drag start position
dragStartX = x;
dragStartY = y;
// Skip if color palette or worlds menu is open
if (colorPalette.visible || worldsMenu.visible) {
return;
}
// Handle building/deleting in builder mode
if (isBuilderMode) {
if (currentTool === 'block') {
placeBlock(x, y);
} else if (currentTool === 'avatar') {
createAvatar(x, y);
}
} else {
// Play mode controls
if (avatar) {
// Check if clicking on avatar (for dragging)
var localPoint = avatar.toLocal({
x: x,
y: y
});
if (Math.abs(localPoint.x) < avatar.width / 2 && Math.abs(localPoint.y) < avatar.height / 2) {
isAvatarDragging = true;
} else {
// Check for movement controls (left side = left, right side = right, top = jump)
if (y < 2732 / 3) {
isJumping = true;
} else if (x < 2048 / 2) {
isMovingLeft = true;
} else {
isMovingRight = true;
}
}
}
}
};
game.move = function (x, y, obj) {
// Skip if color palette or worlds menu is open
if (colorPalette.visible || worldsMenu.visible) {
return;
}
// Handle avatar dragging in play mode
if (!isBuilderMode && isAvatarDragging && avatar) {
avatar.x = x;
avatar.y = y;
avatar.vx = 0;
avatar.vy = 0;
}
};
game.up = function (x, y, obj) {
// Reset movement flags
isAvatarDragging = false;
isMovingLeft = false;
isMovingRight = false;
// Save world when interaction ends
saveCurrentWorld();
};