/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
musicVolume: 1,
soundVolume: 1,
difficulty: "normal"
});
/****
* Classes
****/
var Ball = Container.expand(function () {
var self = Container.call(this);
var graphic = self.attachAsset('ball', {
anchorX: 0.5,
anchorY: 0.5
});
self.speedX = 5;
self.speedY = -5;
self.update = function () {
self.x += self.speedX;
self.y += self.speedY;
// Bounce off walls
if (self.x < 20 || self.x > 2028) {
self.speedX = -self.speedX;
LK.getSound('bounce').play();
}
if (self.y < 20) {
self.speedY = -self.speedY;
LK.getSound('bounce').play();
}
// Game over if ball goes below paddle
if (self.y > 2732) {
endCurrentGame();
}
// Bounce off paddle
if (paddle && self.intersects(paddle) && self.speedY > 0) {
self.speedY = -self.speedY;
LK.getSound('bounce').play();
}
};
return self;
});
var Brick = Container.expand(function () {
var self = Container.call(this);
var graphic = self.attachAsset('brick', {
anchorX: 0.5,
anchorY: 0.5
});
return self;
});
var CatObstacle = Container.expand(function (type) {
var self = Container.call(this);
self.obstacleType = type || 'bird';
var assetName = 'flappyBird';
if (type === 'cloud') assetName = 'circle';else if (type === 'storm') assetName = 'dashSpike';
var graphic = self.attachAsset(assetName, {
anchorX: 0.5,
anchorY: 0.5
});
if (type === 'bird') {
graphic.tint = 0x8b4513; // Brown for enemy birds
graphic.scaleX = 0.8;
graphic.scaleY = 0.8;
} else if (type === 'cloud') {
graphic.tint = 0x708090; // Gray for storm clouds
graphic.scaleX = 1.5;
graphic.scaleY = 1.0;
} else if (type === 'storm') {
graphic.tint = 0x4169e1; // Blue for lightning
}
self.speed = -catGameSpeed;
self.update = function () {
self.x += self.speed;
if (self.x < -100) {
self.shouldRemove = true;
}
// Add movement patterns
if (type === 'bird') {
self.y += Math.sin(LK.ticks * 0.1) * 2;
} else if (type === 'cloud') {
graphic.rotation += 0.02;
}
};
return self;
});
var CatPowerUp = Container.expand(function (type) {
var self = Container.call(this);
self.powerType = type || 'fish';
var assetName = type === 'fish' ? 'food' : 'coin';
var graphic = self.attachAsset(assetName, {
anchorX: 0.5,
anchorY: 0.5
});
if (type === 'fish') {
graphic.tint = 0xff69b4; // Pink for fish
} else if (type === 'life') {
graphic.tint = 0x32cd32; // Green for extra life
}
self.speed = -catGameSpeed;
self.bobOffset = Math.random() * Math.PI * 2;
self.update = function () {
self.x += self.speed;
self.y += Math.sin(LK.ticks * 0.15 + self.bobOffset) * 3;
if (self.x < -100) {
self.shouldRemove = true;
}
graphic.rotation += 0.1;
};
return self;
});
var CategoryButton = Container.expand(function (categoryName, isActive) {
var self = Container.call(this);
var buttonBg = self.attachAsset('categoryButton', {
anchorX: 0.5,
anchorY: 0.5
});
if (isActive) {
buttonBg.tint = 0x0984e3; // Darker blue for active state
}
var buttonText = new Text2(categoryName, {
size: 32,
fill: 0xFFFFFF
});
buttonText.anchor.set(0.5, 0.5);
self.addChild(buttonText);
self.categoryName = categoryName;
self.isActive = isActive;
self.setActive = function (active) {
self.isActive = active;
buttonBg.tint = active ? 0x0984e3 : 0x74b9ff;
};
self.down = function (x, y, obj) {
tween(buttonBg, {
scaleX: 0.95,
scaleY: 0.95
}, {
duration: 100
});
LK.getSound('tap').play();
};
self.up = function (x, y, obj) {
tween(buttonBg, {
scaleX: 1,
scaleY: 1
}, {
duration: 100
});
filterGamesByCategory(self.categoryName);
};
return self;
});
var Circle = Container.expand(function () {
var self = Container.call(this);
var graphic = self.attachAsset('circle', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 2 + Math.random() * 3;
self.direction = Math.random() * Math.PI * 2;
self.lifetime = 180; // 3 seconds at 60fps
self.maxLifetime = self.lifetime;
self.update = function () {
self.x += Math.cos(self.direction) * self.speed;
self.y += Math.sin(self.direction) * self.speed;
// Bounce off walls
if (self.x < 60 || self.x > 1988) {
self.direction = Math.PI - self.direction;
}
if (self.y < 60 || self.y > 2672) {
self.direction = -self.direction;
}
self.lifetime--;
var alpha = self.lifetime / self.maxLifetime;
graphic.alpha = alpha;
if (self.lifetime <= 0) {
self.shouldRemove = true;
}
};
self.down = function (x, y, obj) {
LK.getSound('tap').play();
LK.setScore(LK.getScore() + 10);
updateScoreDisplay();
self.shouldRemove = true;
};
return self;
});
var Coin = Container.expand(function () {
var self = Container.call(this);
var graphic = self.attachAsset('coin', {
anchorX: 0.5,
anchorY: 0.5
});
self.bobOffset = Math.random() * Math.PI * 2;
self.startY = 0;
self.update = function () {
self.y = self.startY + Math.sin(LK.ticks * 0.1 + self.bobOffset) * 10;
};
return self;
});
var DashObstacle = Container.expand(function (type) {
var self = Container.call(this);
self.obstacleType = type || 'block';
var assetName = 'dashObstacle';
if (type === 'spike') assetName = 'dashSpike';else if (type === 'ground') assetName = 'dashGround';
var graphic = self.attachAsset(assetName, {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = -8;
self.update = function () {
self.x += self.speed;
if (self.x < -100) {
self.shouldRemove = true;
}
};
return self;
});
var DashPlayer = Container.expand(function () {
var self = Container.call(this);
var graphic = self.attachAsset('dashPlayer', {
anchorX: 0.5,
anchorY: 0.5
});
self.velocityY = 0;
self.gravity = 1.2;
self.jumpPower = -18;
self.isGrounded = false;
self.isDead = false;
self.lastY = 0;
self.gameMode = 'cube'; // cube, ship, ball, wave
self.update = function () {
if (self.isDead) return;
self.lastY = self.y;
// Apply gravity for cube mode
if (self.gameMode === 'cube') {
self.velocityY += self.gravity;
if (self.velocityY > 15) self.velocityY = 15;
} else if (self.gameMode === 'ship') {
// Ship mode - controlled flight
if (self.isHolding) {
self.velocityY -= 1.5;
if (self.velocityY < -12) self.velocityY = -12;
} else {
self.velocityY += 1.2;
if (self.velocityY > 12) self.velocityY = 12;
}
}
self.y += self.velocityY;
self.isGrounded = false;
// Simple rotation based on velocity
if (self.gameMode === 'cube') {
graphic.rotation = 0;
} else if (self.gameMode === 'ship') {
graphic.rotation = self.velocityY * 0.1;
}
};
self.jump = function () {
if (self.gameMode === 'cube' && self.isGrounded) {
self.velocityY = self.jumpPower;
self.isGrounded = false;
LK.getSound('jump').play();
}
};
self.hold = function () {
self.isHolding = true;
};
self.release = function () {
self.isHolding = false;
};
self.die = function () {
if (self.isDead) return;
self.isDead = true;
// Flash red death effect
tween(graphic, {
tint: 0xff0000
}, {
duration: 200,
onFinish: function onFinish() {
tween(graphic, {
tint: 0xffffff
}, {
duration: 200
});
}
});
LK.setTimeout(function () {
endCurrentGame();
}, 500);
};
self.changeMode = function (newMode) {
self.gameMode = newMode;
if (newMode === 'ship') {
graphic.tint = 0x3498db;
} else if (newMode === 'ball') {
graphic.tint = 0xe67e22;
} else if (newMode === 'wave') {
graphic.tint = 0x9b59b6;
} else {
graphic.tint = 0xf39c12;
}
};
return self;
});
var DashPortal = Container.expand(function (portalType) {
var self = Container.call(this);
var graphic = self.attachAsset('dashPortal', {
anchorX: 0.5,
anchorY: 0.5
});
self.portalType = portalType || 'cube';
self.speed = -8;
// Color portals based on type
if (portalType === 'ship') {
graphic.tint = 0x3498db;
} else if (portalType === 'ball') {
graphic.tint = 0xe67e22;
} else if (portalType === 'wave') {
graphic.tint = 0x9b59b6;
} else {
graphic.tint = 0xf39c12;
}
self.update = function () {
self.x += self.speed;
if (self.x < -100) {
self.shouldRemove = true;
}
// Rotating effect
graphic.rotation += 0.1;
};
return self;
});
var FlappyBird = Container.expand(function () {
var self = Container.call(this);
var graphic = self.attachAsset('flappyBird', {
anchorX: 0.5,
anchorY: 0.5
});
self.velocityY = 0;
self.gravity = 0.8;
self.flapPower = -12;
self.isDead = false;
self.update = function () {
if (self.isDead) return;
self.velocityY += self.gravity;
if (self.velocityY > 15) self.velocityY = 15;
self.y += self.velocityY;
// Simple rotation based on velocity
graphic.rotation = Math.max(-0.5, Math.min(0.5, self.velocityY * 0.1));
// Die if hit ground or ceiling
if (self.y > 2700 || self.y < 50) {
self.die();
}
};
self.flap = function () {
if (!self.isDead) {
self.velocityY = self.flapPower;
LK.getSound('jump').play();
}
};
self.die = function () {
if (self.isDead) return;
self.isDead = true;
tween(graphic, {
tint: 0xff0000
}, {
duration: 200,
onFinish: function onFinish() {
tween(graphic, {
tint: 0xffffff
}, {
duration: 200
});
}
});
LK.setTimeout(function () {
endCurrentGame();
}, 500);
};
return self;
});
var FlappyPipe = Container.expand(function (isTop, gapY) {
var self = Container.call(this);
var graphic = self.attachAsset('flappyPipe', {
anchorX: 0.5,
anchorY: isTop ? 1 : 0
});
self.speed = -4;
self.passed = false;
if (isTop) {
self.y = gapY - 150;
} else {
self.y = gapY + 150;
}
self.update = function () {
self.x += self.speed;
if (self.x < -100) {
self.shouldRemove = true;
}
};
return self;
});
var FlyingCat = Container.expand(function () {
var self = Container.call(this);
var graphic = self.attachAsset('flappyBird', {
anchorX: 0.5,
anchorY: 0.5
});
graphic.tint = 0xffa500; // Orange tint for cat
self.velocityY = 0;
self.gravity = 0.6;
self.flapPower = -10;
self.isDead = false;
self.lives = 3;
self.isInvulnerable = false;
self.invulnerabilityTimer = 0;
self.update = function () {
if (self.isDead) return;
self.velocityY += self.gravity;
if (self.velocityY > 12) self.velocityY = 12;
self.y += self.velocityY;
// Handle invulnerability
if (self.isInvulnerable) {
self.invulnerabilityTimer--;
graphic.alpha = Math.sin(self.invulnerabilityTimer * 0.3) * 0.5 + 0.5;
if (self.invulnerabilityTimer <= 0) {
self.isInvulnerable = false;
graphic.alpha = 1.0;
}
}
// Simple rotation based on velocity
graphic.rotation = Math.max(-0.3, Math.min(0.3, self.velocityY * 0.08));
// Die if hit ground or ceiling
if (self.y > 2650 || self.y < 50) {
self.takeDamage();
}
};
self.flap = function () {
if (!self.isDead) {
self.velocityY = self.flapPower;
LK.getSound('jump').play();
}
};
self.takeDamage = function () {
if (self.isInvulnerable) return;
self.lives--;
if (self.lives <= 0) {
self.die();
} else {
self.isInvulnerable = true;
self.invulnerabilityTimer = 120; // 2 seconds at 60fps
self.y = 1366; // Reset position
self.velocityY = 0;
}
};
self.die = function () {
if (self.isDead) return;
self.isDead = true;
tween(graphic, {
tint: 0xff0000
}, {
duration: 200,
onFinish: function onFinish() {
tween(graphic, {
tint: 0xffffff
}, {
duration: 200
});
}
});
LK.setTimeout(function () {
endCurrentGame();
}, 500);
};
return self;
});
var Food = Container.expand(function () {
var self = Container.call(this);
var graphic = self.attachAsset('food', {
anchorX: 0.5,
anchorY: 0.5
});
self.x = 100 + Math.random() * 1848;
self.y = 100 + Math.random() * 2532;
return self;
});
var GameCard = Container.expand(function (gameInfo) {
var self = Container.call(this);
var isLocked = gameInfo.locked || false;
var cardBg = self.attachAsset(isLocked ? 'gameCardLocked' : 'gameCard', {
anchorX: 0.5,
anchorY: 0.5
});
// Add border effect
cardBg.tint = isLocked ? 0x34495e : 0x2c3e50;
if (isLocked) {
var lock = self.attachAsset('lockIcon', {
anchorX: 0.5,
anchorY: 0.5,
y: -20
});
}
var titleText = new Text2(gameInfo.title, {
size: 36,
fill: isLocked ? "#999999" : "#ffffff"
});
titleText.anchor.set(0.5, 0.5);
titleText.y = isLocked ? 30 : -40;
self.addChild(titleText);
var categoryText = new Text2(gameInfo.category, {
size: 24,
fill: isLocked ? "#666666" : "#74b9ff"
});
categoryText.anchor.set(0.5, 0.5);
categoryText.y = isLocked ? 60 : -10;
self.addChild(categoryText);
var scoreText = new Text2('Best: ' + (gameInfo.bestScore || 0), {
size: 28,
fill: isLocked ? "#555555" : "#00b894"
});
scoreText.anchor.set(0.5, 0.5);
scoreText.y = isLocked ? 90 : 30;
self.addChild(scoreText);
self.gameInfo = gameInfo;
self.isLocked = isLocked;
self.down = function (x, y, obj) {
if (!self.isLocked) {
tween(cardBg, {
scaleX: 0.95,
scaleY: 0.95
}, {
duration: 100
});
LK.getSound('tap').play();
}
};
self.up = function (x, y, obj) {
if (!self.isLocked) {
tween(cardBg, {
scaleX: 1,
scaleY: 1
}, {
duration: 100
});
currentGame = self.gameInfo.id;
switchToGame(currentGame);
}
};
self.updateScore = function (newScore) {
gameInfo.bestScore = newScore;
scoreText.setText('Best: ' + newScore);
};
self.unlock = function () {
self.isLocked = false;
gameInfo.locked = false;
cardBg.tint = 0x16213e;
titleText.tint = 0xffffff;
scoreText.tint = 0xcccccc;
if (lock) {
lock.visible = false;
}
};
return self;
});
var GameCreator = Container.expand(function () {
var self = Container.call(this);
self.mode = 'place'; // 'place', 'delete', 'color', 'resize', 'copy'
self.currentColor = 0x00b894;
self.currentObjectType = 'box'; // 'box', 'circle', 'platform', 'spike', 'goal', 'enemy'
self.gridSize = 40;
self.snapToGrid = true;
self.createdObjects = [];
self.clipboard = null;
self.selectedObject = null;
self.createToolbar = function () {
var toolbar = new Container();
// Row 1 - Main tools
var tools = [{
name: 'Place',
x: 150,
y: 80
}, {
name: 'Delete',
x: 300,
y: 80
}, {
name: 'Copy',
x: 450,
y: 80
}, {
name: 'Resize',
x: 600,
y: 80
}, {
name: 'Grid',
x: 750,
y: 80
}, {
name: 'Color',
x: 900,
y: 80
}, {
name: 'Play',
x: 1200,
y: 80
}, {
name: 'Save',
x: 1350,
y: 80
}, {
name: 'Load',
x: 1500,
y: 80
}, {
name: 'Clear',
x: 1650,
y: 80
}];
for (var i = 0; i < tools.length; i++) {
var tool = tools[i];
var btn = toolbar.addChild(LK.getAsset('toolButton', {
anchorX: 0.5,
anchorY: 0.5,
x: tool.x,
y: tool.y,
scaleX: 0.7,
scaleY: 0.7
}));
var text = new Text2(tool.name, {
size: 24,
fill: 0xFFFFFF
});
text.anchor.set(0.5, 0.5);
text.x = tool.x;
text.y = tool.y;
toolbar.addChild(text);
}
// Row 2 - Object types
var objectTypes = [{
name: 'Box',
type: 'box',
x: 150,
y: 150
}, {
name: 'Circle',
type: 'circle',
x: 300,
y: 150
}, {
name: 'Platform',
type: 'platform',
x: 450,
y: 150
}, {
name: 'Spike',
type: 'spike',
x: 600,
y: 150
}, {
name: 'Goal',
type: 'goal',
x: 750,
y: 150
}, {
name: 'Enemy',
type: 'enemy',
x: 900,
y: 150
}];
for (var i = 0; i < objectTypes.length; i++) {
var objType = objectTypes[i];
var btn = toolbar.addChild(LK.getAsset('categoryButton', {
anchorX: 0.5,
anchorY: 0.5,
x: objType.x,
y: objType.y,
scaleX: 0.6,
scaleY: 0.6
}));
var text = new Text2(objType.name, {
size: 20,
fill: 0xFFFFFF
});
text.anchor.set(0.5, 0.5);
text.x = objType.x;
text.y = objType.y;
toolbar.addChild(text);
}
// Create grid overlay
self.createGrid();
return toolbar;
};
self.createGrid = function () {
self.gridContainer = new Container();
game.addChild(self.gridContainer);
// Create grid dots
for (var x = 0; x < 2048; x += self.gridSize) {
for (var y = 200; y < 2732; y += self.gridSize) {
var dot = self.gridContainer.addChild(LK.getAsset('gridDot', {
anchorX: 0.5,
anchorY: 0.5,
x: x,
y: y
}));
dot.alpha = 0.3;
}
}
self.gridContainer.visible = self.snapToGrid;
};
self.snapToGridPosition = function (x, y) {
if (!self.snapToGrid) return {
x: x,
y: y
};
return {
x: Math.round(x / self.gridSize) * self.gridSize,
y: Math.round(y / self.gridSize) * self.gridSize
};
};
self.getAssetNameForType = function (type) {
switch (type) {
case 'circle':
return 'customCircle';
case 'platform':
return 'customPlatform';
case 'spike':
return 'customSpike';
case 'goal':
return 'customGoal';
case 'enemy':
return 'customEnemy';
default:
return 'customShape';
}
};
self.handleToolClick = function (x, y) {
// Row 1 - Main tools
if (y >= 50 && y <= 110) {
if (x >= 100 && x <= 200) self.mode = 'place';else if (x >= 250 && x <= 350) self.mode = 'delete';else if (x >= 400 && x <= 500) self.mode = 'copy';else if (x >= 550 && x <= 650) self.mode = 'resize';else if (x >= 700 && x <= 800) {
self.snapToGrid = !self.snapToGrid;
if (self.gridContainer) self.gridContainer.visible = self.snapToGrid;
} else if (x >= 850 && x <= 950) {
self.mode = 'color';
self.currentColor = [0xff7675, 0x74b9ff, 0x00b894, 0xfdcb6e, 0xe17055, 0x6c5ce7][Math.floor(Math.random() * 6)];
} else if (x >= 1150 && x <= 1250) {
self.mode = 'play';
self.startCustomGame();
} else if (x >= 1300 && x <= 1400) self.saveLevel();else if (x >= 1450 && x <= 1550) self.loadLevel();else if (x >= 1600 && x <= 1700) self.clearAll();
}
// Row 2 - Object types
else if (y >= 120 && y <= 180) {
if (x >= 100 && x <= 200) self.currentObjectType = 'box';else if (x >= 250 && x <= 350) self.currentObjectType = 'circle';else if (x >= 400 && x <= 500) self.currentObjectType = 'platform';else if (x >= 550 && x <= 650) self.currentObjectType = 'spike';else if (x >= 700 && x <= 800) self.currentObjectType = 'goal';else if (x >= 850 && x <= 950) self.currentObjectType = 'enemy';
}
};
self.handleCanvasClick = function (x, y) {
if (y < 200) return; // Don't place in toolbar area
var snappedPos = self.snapToGridPosition(x, y);
x = snappedPos.x;
y = snappedPos.y;
if (self.mode === 'place') {
var assetName = self.getAssetNameForType(self.currentObjectType);
var newObj = game.addChild(LK.getAsset(assetName, {
anchorX: 0.5,
anchorY: 0.5,
x: x,
y: y
}));
newObj.tint = self.currentColor;
newObj.isCustomObject = true;
newObj.objectType = self.currentObjectType;
newObj.customSize = 1.0;
self.createdObjects.push(newObj);
LK.getSound('tap').play();
} else if (self.mode === 'delete') {
self.deleteObjectAt(x, y);
} else if (self.mode === 'copy') {
var foundObj = self.findObjectAt(x, y);
if (foundObj) {
self.clipboard = {
type: foundObj.objectType,
color: foundObj.tint,
size: foundObj.customSize
};
LK.getSound('tap').play();
}
} else if (self.mode === 'resize') {
var foundObj = self.findObjectAt(x, y);
if (foundObj) {
foundObj.customSize = foundObj.customSize === 1.0 ? 1.5 : foundObj.customSize === 1.5 ? 0.5 : 1.0;
foundObj.scaleX = foundObj.customSize;
foundObj.scaleY = foundObj.customSize;
LK.getSound('tap').play();
}
} else if (self.mode === 'color') {
var foundObj = self.findObjectAt(x, y);
if (foundObj) {
foundObj.tint = self.currentColor;
LK.getSound('tap').play();
}
}
};
self.findObjectAt = function (x, y) {
for (var i = self.createdObjects.length - 1; i >= 0; i--) {
var obj = self.createdObjects[i];
var dx = obj.x - x;
var dy = obj.y - y;
var size = (obj.width || 80) * (obj.customSize || 1.0) / 2;
if (Math.sqrt(dx * dx + dy * dy) < size) {
return obj;
}
}
return null;
};
self.deleteObjectAt = function (x, y) {
for (var i = self.createdObjects.length - 1; i >= 0; i--) {
var obj = self.createdObjects[i];
var dx = obj.x - x;
var dy = obj.y - y;
var size = (obj.width || 80) * (obj.customSize || 1.0) / 2;
if (Math.sqrt(dx * dx + dy * dy) < size) {
obj.destroy();
self.createdObjects.splice(i, 1);
LK.getSound('tap').play();
break;
}
}
};
self.saveLevel = function () {
var levelData = [];
for (var i = 0; i < self.createdObjects.length; i++) {
var obj = self.createdObjects[i];
levelData.push({
type: obj.objectType,
x: obj.x,
y: obj.y,
color: obj.tint,
size: obj.customSize || 1.0
});
}
storage.customLevel = levelData;
LK.getSound('collect').play();
};
self.loadLevel = function () {
if (storage.customLevel) {
self.clearAll();
var levelData = storage.customLevel;
for (var i = 0; i < levelData.length; i++) {
var data = levelData[i];
var assetName = self.getAssetNameForType(data.type);
var newObj = game.addChild(LK.getAsset(assetName, {
anchorX: 0.5,
anchorY: 0.5,
x: data.x,
y: data.y
}));
newObj.tint = data.color;
newObj.isCustomObject = true;
newObj.objectType = data.type;
newObj.customSize = data.size;
newObj.scaleX = data.size;
newObj.scaleY = data.size;
self.createdObjects.push(newObj);
}
LK.getSound('collect').play();
}
};
self.clearAll = function () {
for (var i = 0; i < self.createdObjects.length; i++) {
self.createdObjects[i].destroy();
}
self.createdObjects = [];
if (self.gridContainer) {
self.gridContainer.destroy();
self.createGrid();
}
};
self.startCustomGame = function () {
if (self.createdObjects.length === 0) return;
currentGame = 'customGame';
customGameObjects = self.createdObjects.slice(); // Copy array
LK.setScore(0);
updateScoreDisplay();
};
return self;
});
var MazePlayer = Container.expand(function () {
var self = Container.call(this);
var graphic = self.attachAsset('mazePlayer', {
anchorX: 0.5,
anchorY: 0.5
});
self.gridX = 0;
self.gridY = 0;
self.cellSize = 80;
self.moveToGrid = function (gridX, gridY) {
self.gridX = gridX;
self.gridY = gridY;
self.x = gridX * self.cellSize + self.cellSize / 2;
self.y = gridY * self.cellSize + self.cellSize / 2 + 200;
};
return self;
});
var MazeWall = Container.expand(function () {
var self = Container.call(this);
var graphic = self.attachAsset('mazeWall', {
anchorX: 0.5,
anchorY: 0.5
});
return self;
});
var MovingPlatform = Container.expand(function (width, startX, endX) {
var self = Container.call(this);
var graphic = self.attachAsset('platform', {
anchorX: 0.5,
anchorY: 0.5
});
if (width) {
graphic.scaleX = width / 200;
}
graphic.tint = 0x74b9ff; // Blue tint for moving platforms
self.startX = startX;
self.endX = endX;
self.speed = 2;
self.direction = 1;
self.update = function () {
self.x += self.speed * self.direction;
if (self.x >= self.endX || self.x <= self.startX) {
self.direction *= -1;
}
};
return self;
});
var MultiplayerPlayer = Container.expand(function (playerId, color) {
var self = Container.call(this);
var graphic = self.attachAsset('circle', {
anchorX: 0.5,
anchorY: 0.5
});
graphic.tint = color;
graphic.scaleX = 0.8;
graphic.scaleY = 0.8;
self.playerId = playerId;
self.speed = 5;
self.score = 0;
self.lastX = 0;
self.lastY = 0;
self.update = function () {
self.lastX = self.x;
self.lastY = self.y;
// Keep player on screen
if (self.x < 40) self.x = 40;
if (self.x > 2008) self.x = 2008;
if (self.y < 40) self.y = 40;
if (self.y > 2692) self.y = 2692;
};
self.moveTowards = function (targetX, targetY) {
var dx = targetX - self.x;
var dy = targetY - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > self.speed) {
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
} else {
self.x = targetX;
self.y = targetY;
}
};
return self;
});
var MultiplayerTarget = Container.expand(function () {
var self = Container.call(this);
var graphic = self.attachAsset('food', {
anchorX: 0.5,
anchorY: 0.5
});
self.x = 100 + Math.random() * 1848;
self.y = 100 + Math.random() * 2532;
self.lifetime = 300; // 5 seconds at 60fps
self.maxLifetime = self.lifetime;
self.update = function () {
self.lifetime--;
var alpha = self.lifetime / self.maxLifetime;
graphic.alpha = alpha;
if (self.lifetime <= 0) {
self.shouldRemove = true;
}
};
self.down = function (x, y, obj) {
LK.getSound('collect').play();
self.shouldRemove = true;
return true; // Indicate target was hit
};
return self;
});
var Paddle = Container.expand(function () {
var self = Container.call(this);
var graphic = self.attachAsset('paddle', {
anchorX: 0.5,
anchorY: 0.5
});
self.x = 1024;
self.y = 2600;
return self;
});
var Platform = Container.expand(function () {
var self = Container.call(this);
var graphic = self.attachAsset('platform', {
anchorX: 0.5,
anchorY: 0.5
});
return self;
});
var PlatformPlayer = Container.expand(function () {
var self = Container.call(this);
var graphic = self.attachAsset('platformPlayer', {
anchorX: 0.5,
anchorY: 0.5
});
self.velocityX = 0;
self.velocityY = 0;
self.gravity = 0.8;
self.jumpPower = -15;
self.speed = 6;
self.maxSpeed = 8;
self.onGround = false;
self.lastY = 0;
self.lastX = 0;
self.width = 60;
self.height = 80;
self.update = function () {
self.lastY = self.y;
self.lastX = self.x;
// Apply gravity
self.velocityY += self.gravity;
if (self.velocityY > 20) self.velocityY = 20; // Terminal velocity
// Apply horizontal velocity
self.x += self.velocityX;
// Check horizontal platform collisions
for (var i = 0; i < platforms.length; i++) {
var platform = platforms[i];
if (self.intersects(platform)) {
// Push player out horizontally
if (self.velocityX > 0) {
// Moving right, hit left side of platform
self.x = platform.x - platform.width * platform.scaleX / 2 - self.width / 2;
} else if (self.velocityX < 0) {
// Moving left, hit right side of platform
self.x = platform.x + platform.width * platform.scaleX / 2 + self.width / 2;
}
self.velocityX = 0;
break;
}
}
// Apply vertical velocity
self.y += self.velocityY;
// Friction
self.velocityX *= 0.85;
// Keep player on screen horizontally
if (self.x < 30) {
self.x = 30;
self.velocityX = 0;
}
if (self.x > 2018) {
self.x = 2018;
self.velocityX = 0;
}
// Reset if player falls off screen
if (self.y > 2800) {
self.x = 200;
self.y = 2000;
self.velocityX = 0;
self.velocityY = 0;
}
self.onGround = false;
};
self.jump = function () {
if (self.onGround) {
self.velocityY = self.jumpPower;
self.onGround = false;
LK.getSound('jump').play();
}
};
self.moveLeft = function () {
self.velocityX -= self.speed;
if (self.velocityX < -self.maxSpeed) self.velocityX = -self.maxSpeed;
};
self.moveRight = function () {
self.velocityX += self.speed;
if (self.velocityX > self.maxSpeed) self.velocityX = self.maxSpeed;
};
return self;
});
var ScrollBar = Container.expand(function () {
var self = Container.call(this);
self.scrollPosition = 0;
self.maxScroll = 0;
self.contentHeight = 0;
self.viewHeight = 2000;
// Create scroll bar background
var scrollBg = self.attachAsset('scrollBar', {
anchorX: 0.5,
anchorY: 0
});
// Create scroll thumb
var scrollThumb = self.attachAsset('scrollThumb', {
anchorX: 0.5,
anchorY: 0
});
// Create up button
var upBtn = self.attachAsset('scrollUpBtn', {
anchorX: 0.5,
anchorY: 0.5,
y: -50
});
// Create down button
var downBtn = self.attachAsset('scrollDownBtn', {
anchorX: 0.5,
anchorY: 0.5,
y: 450
});
// Add up/down arrows as text
var upText = new Text2('ā²', {
size: 24,
fill: 0xFFFFFF
});
upText.anchor.set(0.5, 0.5);
upText.y = -50;
self.addChild(upText);
var downText = new Text2('ā¼', {
size: 24,
fill: 0xFFFFFF
});
downText.anchor.set(0.5, 0.5);
downText.y = 450;
self.addChild(downText);
self.setContentHeight = function (height) {
self.contentHeight = height;
self.maxScroll = Math.max(0, height - self.viewHeight);
self.updateThumb();
};
self.updateThumb = function () {
if (self.maxScroll > 0) {
var thumbRatio = self.viewHeight / self.contentHeight;
var thumbHeight = Math.max(30, scrollBg.height * thumbRatio);
scrollThumb.scaleY = thumbHeight / 60;
var thumbPosition = self.scrollPosition / self.maxScroll * (scrollBg.height - thumbHeight);
scrollThumb.y = thumbPosition;
} else {
scrollThumb.y = 0;
}
};
self.scroll = function (delta) {
self.scrollPosition = Math.max(0, Math.min(self.maxScroll, self.scrollPosition + delta));
self.updateThumb();
return self.scrollPosition;
};
self.down = function (x, y, obj) {
var localY = y - self.y;
if (localY >= -75 && localY <= -25) {
// Up button clicked
self.scroll(-200);
LK.getSound('tap').play();
} else if (localY >= 425 && localY <= 475) {
// Down button clicked
self.scroll(200);
LK.getSound('tap').play();
}
};
return self;
});
var SettingsPanel = Container.expand(function () {
var self = Container.call(this);
// Create background panel
var panelBg = self.attachAsset('gameCardActive', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2.5,
scaleY: 2.0
});
panelBg.tint = 0x2c3e50;
// Title
var titleText = new Text2('Settings', {
size: 48,
fill: 0xFFFFFF
});
titleText.anchor.set(0.5, 0.5);
titleText.y = -250;
self.addChild(titleText);
// Music Volume
var musicLabel = new Text2('Music Volume: ' + Math.round(storage.musicVolume * 100) + '%', {
size: 32,
fill: 0xFFFFFF
});
musicLabel.anchor.set(0.5, 0.5);
musicLabel.y = -150;
self.addChild(musicLabel);
var musicSlider = self.attachAsset('scrollBar', {
anchorX: 0.5,
anchorY: 0.5,
y: -100,
scaleX: 2.0,
scaleY: 0.5
});
var musicThumb = self.attachAsset('scrollThumb', {
anchorX: 0.5,
anchorY: 0.5,
y: -100,
x: (storage.musicVolume - 0.5) * 80
});
// Sound Volume
var soundLabel = new Text2('Sound Volume: ' + Math.round(storage.soundVolume * 100) + '%', {
size: 32,
fill: 0xFFFFFF
});
soundLabel.anchor.set(0.5, 0.5);
soundLabel.y = -20;
self.addChild(soundLabel);
var soundSlider = self.attachAsset('scrollBar', {
anchorX: 0.5,
anchorY: 0.5,
y: 30,
scaleX: 2.0,
scaleY: 0.5
});
var soundThumb = self.attachAsset('scrollThumb', {
anchorX: 0.5,
anchorY: 0.5,
y: 30,
x: (storage.soundVolume - 0.5) * 80
});
// Difficulty Setting
var difficultyLabel = new Text2('Difficulty: ' + storage.difficulty, {
size: 32,
fill: 0xFFFFFF
});
difficultyLabel.anchor.set(0.5, 0.5);
difficultyLabel.y = 110;
self.addChild(difficultyLabel);
var difficultyButton = self.attachAsset('categoryButton', {
anchorX: 0.5,
anchorY: 0.5,
y: 160,
scaleX: 0.8,
scaleY: 0.8
});
var difficultyText = new Text2(storage.difficulty, {
size: 28,
fill: 0xFFFFFF
});
difficultyText.anchor.set(0.5, 0.5);
difficultyText.y = 160;
self.addChild(difficultyText);
// Close button
var closeButton = self.attachAsset('categoryButton', {
anchorX: 0.5,
anchorY: 0.5,
y: 240,
scaleX: 0.6,
scaleY: 0.6
});
closeButton.tint = 0xe74c3c;
var closeText = new Text2('Close', {
size: 24,
fill: 0xFFFFFF
});
closeText.anchor.set(0.5, 0.5);
closeText.y = 240;
self.addChild(closeText);
var isDragging = false;
var dragTarget = null;
self.updateMusicVolume = function (volume) {
storage.musicVolume = Math.max(0, Math.min(1, volume));
musicLabel.setText('Music Volume: ' + Math.round(storage.musicVolume * 100) + '%');
musicThumb.x = (storage.musicVolume - 0.5) * 80;
// Apply volume to current music
LK.stopMusic();
LK.playMusic('bgMusic', {
volume: storage.musicVolume
});
};
self.updateSoundVolume = function (volume) {
storage.soundVolume = Math.max(0, Math.min(1, volume));
soundLabel.setText('Sound Volume: ' + Math.round(storage.soundVolume * 100) + '%');
soundThumb.x = (storage.soundVolume - 0.5) * 80;
};
self.cycleDifficulty = function () {
var difficulties = ['easy', 'normal', 'hard'];
var currentIndex = difficulties.indexOf(storage.difficulty);
var nextIndex = (currentIndex + 1) % difficulties.length;
storage.difficulty = difficulties[nextIndex];
difficultyLabel.setText('Difficulty: ' + storage.difficulty);
difficultyText.setText(storage.difficulty);
};
self.down = function (x, y, obj) {
var localPos;
try {
if (obj && obj.parent && obj.position) {
localPos = self.toLocal(obj.parent.toGlobal(obj.position));
} else {
localPos = {
x: x,
y: y
};
}
} catch (e) {
localPos = {
x: x,
y: y
};
}
// Check music slider
if (localPos.y >= -120 && localPos.y <= -80 && localPos.x >= -80 && localPos.x <= 80) {
isDragging = true;
dragTarget = 'music';
var volume = (localPos.x + 80) / 160;
self.updateMusicVolume(volume);
}
// Check sound slider
else if (localPos.y >= 10 && localPos.y <= 50 && localPos.x >= -80 && localPos.x <= 80) {
isDragging = true;
dragTarget = 'sound';
var volume = (localPos.x + 80) / 160;
self.updateSoundVolume(volume);
}
// Check difficulty button
else if (localPos.y >= 140 && localPos.y <= 180 && localPos.x >= -120 && localPos.x <= 120) {
tween(difficultyButton, {
scaleX: 0.75,
scaleY: 0.75
}, {
duration: 100
});
LK.getSound('tap').play();
}
// Check close button
else if (localPos.y >= 220 && localPos.y <= 260 && localPos.x >= -90 && localPos.x <= 90) {
tween(closeButton, {
scaleX: 0.55,
scaleY: 0.55
}, {
duration: 100
});
LK.getSound('tap').play();
}
};
self.move = function (x, y, obj) {
if (isDragging) {
var localPos;
try {
if (obj && obj.parent && obj.position) {
localPos = self.toLocal(obj.parent.toGlobal(obj.position));
} else {
localPos = {
x: x,
y: y
};
}
} catch (e) {
localPos = {
x: x,
y: y
};
}
if (dragTarget === 'music') {
var volume = (localPos.x + 80) / 160;
self.updateMusicVolume(volume);
} else if (dragTarget === 'sound') {
var volume = (localPos.x + 80) / 160;
self.updateSoundVolume(volume);
}
}
};
self.up = function (x, y, obj) {
var localPos;
try {
if (obj && obj.parent && obj.position) {
localPos = self.toLocal(obj.parent.toGlobal(obj.position));
} else {
localPos = {
x: x,
y: y
};
}
} catch (e) {
localPos = {
x: x,
y: y
};
}
if (isDragging) {
isDragging = false;
dragTarget = null;
}
// Check difficulty button
else if (localPos.y >= 140 && localPos.y <= 180 && localPos.x >= -120 && localPos.x <= 120) {
tween(difficultyButton, {
scaleX: 0.8,
scaleY: 0.8
}, {
duration: 100
});
self.cycleDifficulty();
}
// Check close button
else if (localPos.y >= 220 && localPos.y <= 260 && localPos.x >= -90 && localPos.x <= 90) {
tween(closeButton, {
scaleX: 0.6,
scaleY: 0.6
}, {
duration: 100
});
self.onClose();
}
};
self.onClose = function () {
// Override this function when creating the panel
};
return self;
});
var Snake = Container.expand(function () {
var self = Container.call(this);
var graphic = self.attachAsset('snake', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 4;
self.direction = {
x: 0,
y: -1
};
self.bodySegments = []; // Array to store body segments
self.segmentSize = 80; // Size of each body segment
self.moveCounter = 0; // Counter to control movement timing
self.update = function () {
self.moveCounter++;
// Only move every few frames to make it more manageable
if (self.moveCounter >= 15) {
self.moveCounter = 0;
// Store previous position for body segments to follow
var previousPositions = [{
x: self.x,
y: self.y
}];
for (var i = 0; i < self.bodySegments.length; i++) {
previousPositions.push({
x: self.bodySegments[i].x,
y: self.bodySegments[i].y
});
}
// Move head
self.x += self.direction.x * self.segmentSize;
self.y += self.direction.y * self.segmentSize;
// Move body segments to follow the segment in front
for (var i = 0; i < self.bodySegments.length; i++) {
self.bodySegments[i].x = previousPositions[i].x;
self.bodySegments[i].y = previousPositions[i].y;
}
}
// Wrap around screen
if (self.x < 0) self.x = 2048;
if (self.x > 2048) self.x = 0;
if (self.y < 0) self.y = 2732;
if (self.y > 2732) self.y = 0;
};
self.grow = function () {
// Create a new body segment
var newSegment = game.addChild(LK.getAsset('snake', {
anchorX: 0.5,
anchorY: 0.5
}));
// Position it at the tail (or at head if no body exists)
if (self.bodySegments.length > 0) {
var lastSegment = self.bodySegments[self.bodySegments.length - 1];
newSegment.x = lastSegment.x;
newSegment.y = lastSegment.y;
} else {
newSegment.x = self.x;
newSegment.y = self.y;
}
// Make it slightly different color to distinguish from head
newSegment.tint = 0x95a5a6;
self.bodySegments.push(newSegment);
};
return self;
});
var TetrisBlock = Container.expand(function (color) {
var self = Container.call(this);
var graphic = self.attachAsset('customShape', {
anchorX: 0.5,
anchorY: 0.5
});
graphic.tint = color || 0x3498db;
self.blockColor = color || 0x3498db;
return self;
});
var TetrisPiece = Container.expand(function (type) {
var self = Container.call(this);
self.pieceType = type || 'I';
self.rotation = 0;
self.blocks = [];
self.gridX = 4;
self.gridY = 0;
// Define piece shapes
var pieceShapes = {
'I': [[1, 1, 1, 1]],
'O': [[1, 1], [1, 1]],
'T': [[0, 1, 0], [1, 1, 1]],
'S': [[0, 1, 1], [1, 1, 0]],
'Z': [[1, 1, 0], [0, 1, 1]],
'J': [[1, 0, 0], [1, 1, 1]],
'L': [[0, 0, 1], [1, 1, 1]]
};
var pieceColors = {
'I': 0x00bcd4,
'O': 0xffeb3b,
'T': 0x9c27b0,
'S': 0x4caf50,
'Z': 0xf44336,
'J': 0x2196f3,
'L': 0xff9800
};
self.shape = pieceShapes[type];
self.color = pieceColors[type];
self.createBlocks = function () {
// Clear existing blocks
for (var i = 0; i < self.blocks.length; i++) {
self.blocks[i].destroy();
}
self.blocks = [];
// Create new blocks based on shape
for (var row = 0; row < self.shape.length; row++) {
for (var col = 0; col < self.shape[row].length; col++) {
if (self.shape[row][col] === 1) {
var block = self.addChild(new TetrisBlock(self.color));
block.x = col * tetrisCellSize;
block.y = row * tetrisCellSize;
self.blocks.push(block);
}
}
}
};
self.rotate = function () {
// Rotate the shape array 90 degrees clockwise
var newShape = [];
var rows = self.shape.length;
var cols = self.shape[0].length;
for (var col = 0; col < cols; col++) {
newShape[col] = [];
for (var row = rows - 1; row >= 0; row--) {
newShape[col][rows - 1 - row] = self.shape[row][col];
}
}
self.shape = newShape;
self.rotation = (self.rotation + 1) % 4;
self.createBlocks();
};
self.getBlockPositions = function () {
var positions = [];
for (var row = 0; row < self.shape.length; row++) {
for (var col = 0; col < self.shape[row].length; col++) {
if (self.shape[row][col] === 1) {
positions.push({
x: self.gridX + col,
y: self.gridY + row
});
}
}
}
return positions;
};
self.canMoveTo = function (newX, newY) {
var positions = [];
for (var row = 0; row < self.shape.length; row++) {
for (var col = 0; col < self.shape[row].length; col++) {
if (self.shape[row][col] === 1) {
var x = newX + col;
var y = newY + row;
if (x < 0 || x >= tetrisGridWidth || y >= tetrisGridHeight) {
return false;
}
if (y >= 0 && tetrisGrid[y][x] !== 0) {
return false;
}
}
}
}
return true;
};
self.updatePosition = function () {
self.x = tetrisOffsetX + self.gridX * tetrisCellSize;
self.y = tetrisOffsetY + self.gridY * tetrisCellSize;
};
self.createBlocks();
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x1a1a2e
});
/****
* Game Code
****/
// Game state management
var currentGame = null;
var gameContainer = null;
var hubContainer = null;
var scoreText = null;
var backButton = null;
var settingsPanel = null;
var settingsButton = null;
// Game data
var games = [{
id: 'snake',
title: 'Snake',
category: 'Classic',
locked: false,
bestScore: storage.snakeBest || 0
}, {
id: 'circle',
title: 'Circle Tap',
category: 'Arcade',
locked: false,
bestScore: storage.circleBest || 0
}, {
id: 'breakout',
title: 'Breakout',
category: 'Classic',
locked: false,
bestScore: storage.breakoutBest || 0
}, {
id: 'platform',
title: 'Platformer',
category: 'Adventure',
locked: false,
bestScore: storage.platformBest || 0
}, {
id: 'maze',
title: 'Maze Runner',
category: 'Puzzle',
locked: false,
bestScore: storage.mazeBest || 0
}, {
id: 'dash',
title: 'Geometry Dash',
category: 'Arcade',
locked: false,
bestScore: storage.dashBest || 0
}, {
id: 'flappybird',
title: 'Flappy Bird',
category: 'Arcade',
locked: false,
bestScore: storage.flappyBirdBest || 0
}, {
id: 'multiplayer',
title: 'Multiplayer Mode',
category: 'Multiplayer',
locked: false,
bestScore: storage.multiplayerBest || 0
}, {
id: 'creator',
title: 'Level Creator',
category: 'Tools',
locked: false,
bestScore: 0
}, {
id: 'flyingcat',
title: 'Flying Cat',
category: 'Arcade',
locked: false,
bestScore: storage.flyingCatBest || 0
}, {
id: 'tetris',
title: 'Tetris',
category: 'Puzzle',
locked: false,
bestScore: storage.tetrisBest || 0
}];
var categories = ['All', 'Classic', 'Arcade', 'Adventure', 'Puzzle', 'Tools', 'Multiplayer'];
var currentCategory = 'All';
var gameCards = [];
var categoryButtons = [];
// Game variables
var snake = null;
var food = null;
var circles = [];
var ball = null;
var paddle = null;
var bricks = [];
var platforms = [];
var platformPlayer = null;
var maze = null;
var mazePlayer = null;
var coins = [];
var dashPlayer = null;
var dashObstacles = [];
var dashPortals = [];
var dashGameSpeed = 8;
var dashScore = 0;
var dashCameraX = 0;
var dashGroundY = 2400;
var gameCreator = null;
var customGameObjects = [];
var scrollBar = null;
// Multiplayer game variables
var multiplayerPlayers = [];
var multiplayerTargets = [];
var multiplayerGameMode = 'cooperative'; // 'cooperative' or 'competitive'
var multiplayerTimer = 0;
var multiplayerTimeLimit = 3600; // 60 seconds at 60fps
// Flappy bird game variables
var flappyBird = null;
var flappyPipes = [];
var flappyPipeTimer = 0;
// Flying cat game variables
var flyingCat = null;
var catObstacles = [];
var catPowerUps = [];
var catClouds = [];
var catGameSpeed = 4;
var flappyGapSize = 300;
// Tetris game variables
var tetrisGrid = null;
var currentPiece = null;
var nextPiece = null;
var tetrisDropTimer = 0;
var tetrisDropSpeed = 60;
var tetrisGridWidth = 10;
var tetrisGridHeight = 20;
var tetrisCellSize = 80;
var tetrisOffsetX = 400;
var tetrisOffsetY = 200;
var tetrisLines = 0;
var tetrisLevel = 1;
function initializeHub() {
hubContainer = new Container();
game.addChild(hubContainer);
// Add background
var bg = hubContainer.addChild(LK.getAsset('hubBackground', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0
}));
// Title
var titleText = new Text2('FRVR Games Hub', {
size: 80,
fill: 0xFFFFFF
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 1024;
titleText.y = 150;
hubContainer.addChild(titleText);
// Create category buttons
createCategoryButtons();
// Create scroll bar
scrollBar = hubContainer.addChild(new ScrollBar());
scrollBar.x = 1900;
scrollBar.y = 400;
// Create settings button
settingsButton = hubContainer.addChild(LK.getAsset('categoryButton', {
anchorX: 1,
anchorY: 0,
x: 1900,
y: 100,
scaleX: 0.7,
scaleY: 0.7
}));
settingsButton.tint = 0x74b9ff;
// Update scroll content
var settingsText = new Text2('Settings', {
size: 24,
fill: 0xFFFFFF
});
settingsText.anchor.set(0.5, 0.5);
settingsText.x = 1795;
settingsText.y = 128;
hubContainer.addChild(settingsText);
settingsButton.down = function () {
tween(settingsButton, {
scaleX: 0.65,
scaleY: 0.65
}, {
duration: 100
});
LK.getSound('tap').play();
};
function updateFlyingCatGame() {
if (!flyingCat || flyingCat.isDead) return;
// Spawn obstacles
if (LK.ticks % 180 === 0) {
// Every 3 seconds
var obstacleTypes = ['bird', 'cloud', 'storm'];
var obstacleType = obstacleTypes[Math.floor(Math.random() * obstacleTypes.length)];
var obstacle = gameContainer.addChild(new CatObstacle(obstacleType));
obstacle.x = 2200;
obstacle.y = 200 + Math.random() * 2000;
catObstacles.push(obstacle);
}
// Spawn power-ups occasionally
if (LK.ticks % 300 === 0) {
// Every 5 seconds
var powerUpTypes = ['fish', 'life'];
var powerUpType = powerUpTypes[Math.floor(Math.random() * powerUpTypes.length)];
var powerUp = gameContainer.addChild(new CatPowerUp(powerUpType));
powerUp.x = 2200;
powerUp.y = 300 + Math.random() * 1800;
catPowerUps.push(powerUp);
}
// Check obstacle collisions
for (var i = 0; i < catObstacles.length; i++) {
var obstacle = catObstacles[i];
if (flyingCat.intersects(obstacle)) {
flyingCat.takeDamage();
obstacle.destroy();
catObstacles.splice(i, 1);
break;
}
}
// Check power-up collisions
for (var i = catPowerUps.length - 1; i >= 0; i--) {
var powerUp = catPowerUps[i];
if (flyingCat.intersects(powerUp)) {
if (powerUp.powerType === 'fish') {
LK.setScore(LK.getScore() + 50);
} else if (powerUp.powerType === 'life') {
flyingCat.lives = Math.min(flyingCat.lives + 1, 5);
}
updateScoreDisplay();
LK.getSound('collect').play();
powerUp.destroy();
catPowerUps.splice(i, 1);
}
}
// Remove off-screen obstacles and power-ups
for (var i = catObstacles.length - 1; i >= 0; i--) {
if (catObstacles[i].shouldRemove) {
catObstacles[i].destroy();
catObstacles.splice(i, 1);
}
}
for (var i = catPowerUps.length - 1; i >= 0; i--) {
if (catPowerUps[i].shouldRemove) {
catPowerUps[i].destroy();
catPowerUps.splice(i, 1);
}
}
// Increase score over time
if (LK.ticks % 60 === 0) {
LK.setScore(LK.getScore() + 10);
updateScoreDisplay();
}
}
function updateTetrisGame() {
if (!currentPiece) return;
tetrisDropTimer++;
// Auto-drop piece
if (tetrisDropTimer >= tetrisDropSpeed) {
tetrisDropTimer = 0;
if (currentPiece.canMoveTo(currentPiece.gridX, currentPiece.gridY + 1)) {
currentPiece.gridY++;
currentPiece.updatePosition();
} else {
// Piece has landed, place it in grid
placeTetrisPieceInGrid();
}
}
}
function placeTetrisPieceInGrid() {
var positions = currentPiece.getBlockPositions();
// Place blocks in grid
for (var i = 0; i < positions.length; i++) {
var pos = positions[i];
if (pos.y >= 0) {
tetrisGrid[pos.y][pos.x] = currentPiece.color;
// Create static block
var block = gameContainer.addChild(new TetrisBlock(currentPiece.color));
block.x = tetrisOffsetX + pos.x * tetrisCellSize;
block.y = tetrisOffsetY + pos.y * tetrisCellSize;
}
}
// Check for completed lines
checkTetrisCompletedLines();
// Create new piece
var pieceTypes = ['I', 'O', 'T', 'S', 'Z', 'J', 'L'];
var randomType = pieceTypes[Math.floor(Math.random() * pieceTypes.length)];
currentPiece.destroy();
currentPiece = gameContainer.addChild(new TetrisPiece(randomType));
currentPiece.updatePosition();
// Check game over
if (!currentPiece.canMoveTo(currentPiece.gridX, currentPiece.gridY)) {
endCurrentGame();
}
}
function checkTetrisCompletedLines() {
var completedRows = [];
// Find completed rows
for (var row = 0; row < tetrisGridHeight; row++) {
var isComplete = true;
for (var col = 0; col < tetrisGridWidth; col++) {
if (tetrisGrid[row][col] === 0) {
isComplete = false;
break;
}
}
if (isComplete) {
completedRows.push(row);
}
}
// Remove completed rows and add score
if (completedRows.length > 0) {
tetrisLines += completedRows.length;
var points = completedRows.length * 100 * tetrisLevel; // Multiply by level
LK.setScore(LK.getScore() + points);
updateScoreDisplay();
// Remove completed rows from grid
for (var i = completedRows.length - 1; i >= 0; i--) {
var row = completedRows[i];
tetrisGrid.splice(row, 1);
tetrisGrid.unshift(new Array(tetrisGridWidth).fill(0));
}
// Increase level every 10 lines and speed up
tetrisLevel = Math.floor(tetrisLines / 10) + 1;
tetrisDropSpeed = Math.max(5, 60 - tetrisLevel * 5);
LK.getSound('collect').play();
}
}
settingsButton.up = function () {
tween(settingsButton, {
scaleX: 0.7,
scaleY: 0.7
}, {
duration: 100
});
showSettingsPanel();
};
// Create game cards
createGameCards();
updateScrollContent();
}
function createCategoryButtons() {
categoryButtons = [];
for (var i = 0; i < categories.length; i++) {
var category = categories[i];
var isActive = category === currentCategory;
var btn = hubContainer.addChild(new CategoryButton(category, isActive));
btn.x = 150 + i * 320;
if (category === 'Multiplayer') {
btn.x = 400; // Move multiplayer category more to the left
btn.y = 2500; // Move multiplayer category higher on bottom screen
} else if (category === 'Tools') {
btn.x = 800; // Position tools category on bottom screen
btn.y = 2500; // Move tools category to bottom screen
} else {
btn.y = 250; // Keep other categories on screen
}
categoryButtons.push(btn);
}
}
function createGameCards() {
gameCards = [];
for (var i = 0; i < games.length; i++) {
var gameInfo = games[i];
var card = hubContainer.addChild(new GameCard(gameInfo));
card.visible = false; // Start hidden, will be shown by updateGameCardPositions
gameCards.push(card);
}
updateGameCardPositions();
}
function updateGameCardPositions() {
var visibleGames = getFilteredGames();
var cardsPerRow = 4;
var cardSpacing = 450;
var rowSpacing = 400;
var startX = 300;
var startY = 500;
// Hide all cards first
for (var i = 0; i < gameCards.length; i++) {
gameCards[i].visible = false;
}
// Position visible cards
for (var i = 0; i < visibleGames.length; i++) {
var gameInfo = visibleGames[i];
var card = findGameCard(gameInfo.id);
if (card) {
card.visible = true;
var row = Math.floor(i / cardsPerRow);
var col = i % cardsPerRow;
card.x = startX + col * cardSpacing;
card.y = startY + row * rowSpacing - scrollBar.scrollPosition;
// Ensure cards stay within proper view bounds with better margins
if (card.y < 350 || card.y > 2400) {
card.visible = false;
}
}
}
}
function findGameCard(gameId) {
for (var i = 0; i < gameCards.length; i++) {
if (gameCards[i].gameInfo.id === gameId) {
return gameCards[i];
}
}
return null;
}
function getFilteredGames() {
if (currentCategory === 'All') {
return games;
}
var filtered = [];
for (var i = 0; i < games.length; i++) {
if (games[i].category === currentCategory) {
filtered.push(games[i]);
}
}
return filtered;
}
function filterGamesByCategory(category) {
currentCategory = category;
// Update category button states
for (var i = 0; i < categoryButtons.length; i++) {
categoryButtons[i].setActive(categoryButtons[i].categoryName === category);
}
updateGameCardPositions();
updateScrollContent();
}
function updateScrollContent() {
var visibleGames = getFilteredGames();
var cardsPerRow = 4;
var rows = Math.ceil(visibleGames.length / cardsPerRow);
var contentHeight = rows * 400 + 800;
scrollBar.setContentHeight(contentHeight);
}
function switchToGame(gameId) {
currentGame = gameId;
// Hide hub
if (hubContainer) {
hubContainer.visible = false;
}
// Create game container
gameContainer = new Container();
game.addChild(gameContainer);
// Create back button
createBackButton();
// Initialize specific game
if (gameId === 'snake') {
initializeSnakeGame();
} else if (gameId === 'circle') {
initializeCircleGame();
} else if (gameId === 'breakout') {
initializeBreakoutGame();
} else if (gameId === 'platform') {
initializePlatformGame();
} else if (gameId === 'maze') {
initializeMazeGame();
} else if (gameId === 'dash') {
initializeDashGame();
} else if (gameId === 'flappybird') {
initializeFlappyBirdGame();
} else if (gameId === 'multiplayer') {
initializeMultiplayerGame();
} else if (gameId === 'creator') {
initializeCreatorGame();
} else if (gameId === 'flyingcat') {
initializeFlyingCatGame();
} else if (gameId === 'tetris') {
initializeTetrisGame();
}
// Create score display
createScoreDisplay();
// Apply difficulty settings
applyDifficultySettings();
}
function createBackButton() {
backButton = LK.gui.topRight.addChild(LK.getAsset('categoryButton', {
anchorX: 1,
anchorY: 0,
x: -20,
y: 20,
scaleX: 0.6,
scaleY: 0.6
}));
var backText = new Text2('Hub', {
size: 28,
fill: 0xFFFFFF
});
backText.anchor.set(0.5, 0.5);
backText.x = backButton.x - backButton.width * 0.3;
backText.y = backButton.y + backButton.height * 0.3;
LK.gui.topRight.addChild(backText);
backButton.down = function () {
tween(backButton, {
scaleX: 0.55,
scaleY: 0.55
}, {
duration: 100
});
LK.getSound('tap').play();
};
backButton.up = function () {
tween(backButton, {
scaleX: 0.6,
scaleY: 0.6
}, {
duration: 100
});
returnToHub();
};
}
function createScoreDisplay() {
scoreText = new Text2('Score: 0', {
size: 48,
fill: 0xFFFFFF
});
scoreText.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreText);
}
function updateScoreDisplay() {
if (scoreText) {
scoreText.setText('Score: ' + LK.getScore());
}
}
function returnToHub() {
// Clean up current game
endCurrentGame();
// Show hub
if (hubContainer) {
hubContainer.visible = true;
}
// Remove back button and score
if (backButton) {
backButton.destroy();
backButton = null;
}
if (scoreText) {
scoreText.destroy();
scoreText = null;
}
currentGame = null;
}
function endCurrentGame() {
// Save high score
saveHighScore();
// Clean up game objects
cleanupGameObjects();
// Remove game container
if (gameContainer) {
gameContainer.destroy();
gameContainer = null;
}
// Reset score
LK.setScore(0);
}
function saveHighScore() {
if (!currentGame) return;
var currentScore = LK.getScore();
var gameInfo = findGameInfo(currentGame);
if (gameInfo && currentScore > gameInfo.bestScore) {
gameInfo.bestScore = currentScore;
storage[currentGame + 'Best'] = currentScore;
// Update game card
var card = findGameCard(currentGame);
if (card) {
card.updateScore(currentScore);
}
}
}
function findGameInfo(gameId) {
for (var i = 0; i < games.length; i++) {
if (games[i].id === gameId) {
return games[i];
}
}
return null;
}
function cleanupGameObjects() {
// Reset all game variables
snake = null;
food = null;
circles = [];
ball = null;
paddle = null;
bricks = [];
platforms = [];
platformPlayer = null;
maze = null;
mazePlayer = null;
coins = [];
dashPlayer = null;
dashObstacles = [];
dashPortals = [];
gameCreator = null;
customGameObjects = [];
// Multiplayer cleanup
multiplayerPlayers = [];
multiplayerTargets = [];
multiplayerTimer = 0;
// Flappy bird cleanup
flappyBird = null;
flappyPipes = [];
flappyPipeTimer = 0;
// Flying cat cleanup
flyingCat = null;
catObstacles = [];
catPowerUps = [];
catClouds = [];
// Tetris cleanup
tetrisGrid = null;
currentPiece = null;
nextPiece = null;
tetrisDropTimer = 0;
tetrisLines = 0;
tetrisLevel = 1;
}
// Game initialization functions
function initializeSnakeGame() {
game.setBackgroundColor(0x2c3e50);
snake = gameContainer.addChild(new Snake());
snake.x = 1024;
snake.y = 1366;
food = gameContainer.addChild(new Food());
LK.setScore(0);
updateScoreDisplay();
}
function initializeCircleGame() {
game.setBackgroundColor(0x2d3436);
circles = [];
LK.setScore(0);
updateScoreDisplay();
}
function initializeBreakoutGame() {
game.setBackgroundColor(0x000000);
// Create paddle
paddle = gameContainer.addChild(new Paddle());
// Create ball
ball = gameContainer.addChild(new Ball());
ball.x = 1024;
ball.y = 2500;
// Create bricks
bricks = [];
for (var row = 0; row < 6; row++) {
for (var col = 0; col < 10; col++) {
var brick = gameContainer.addChild(new Brick());
brick.x = 200 + col * 165;
brick.y = 300 + row * 80;
bricks.push(brick);
}
}
LK.setScore(0);
updateScoreDisplay();
}
function initializePlatformGame() {
var bg = gameContainer.addChild(LK.getAsset('gameBackground1', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0
}));
// Create platforms
platforms = [];
var platformData = [{
x: 300,
y: 2600,
width: 400
}, {
x: 800,
y: 2400,
width: 200
}, {
x: 1200,
y: 2200,
width: 300
}, {
x: 400,
y: 2000,
width: 250
}, {
x: 1000,
y: 1800,
width: 200
}, {
x: 600,
y: 1600,
width: 350
}];
for (var i = 0; i < platformData.length; i++) {
var data = platformData[i];
var platform = gameContainer.addChild(new Platform());
platform.x = data.x;
platform.y = data.y;
if (data.width) {
platform.scaleX = data.width / 200;
}
platforms.push(platform);
}
// Create coins
coins = [];
var coinPositions = [{
x: 800,
y: 2300
}, {
x: 1200,
y: 2100
}, {
x: 400,
y: 1900
}, {
x: 1000,
y: 1700
}, {
x: 600,
y: 1500
}];
for (var i = 0; i < coinPositions.length; i++) {
var pos = coinPositions[i];
var coin = gameContainer.addChild(new Coin());
coin.x = pos.x;
coin.y = pos.y;
coin.startY = pos.y;
coins.push(coin);
}
// Create player
platformPlayer = gameContainer.addChild(new PlatformPlayer());
platformPlayer.x = 300;
platformPlayer.y = 2500;
LK.setScore(0);
updateScoreDisplay();
}
function initializeMazeGame() {
game.setBackgroundColor(0x34495e);
// Create simple maze layout
var mazeLayout = [[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1], [1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1], [1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]];
maze = mazeLayout;
// Create walls
for (var row = 0; row < maze.length; row++) {
for (var col = 0; col < maze[row].length; col++) {
if (maze[row][col] === 1) {
var wall = gameContainer.addChild(new MazeWall());
wall.x = col * 80 + 40;
wall.y = row * 80 + 40 + 200;
}
}
}
// Create exit
var exit = gameContainer.addChild(LK.getAsset('mazeExit', {
anchorX: 0.5,
anchorY: 0.5,
x: 23 * 80 + 40,
y: 7 * 80 + 40 + 200
}));
// Create player
mazePlayer = gameContainer.addChild(new MazePlayer());
mazePlayer.moveToGrid(1, 1);
LK.setScore(0);
updateScoreDisplay();
}
function initializeDashGame() {
var bg = gameContainer.addChild(LK.getAsset('gameBackground2', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0
}));
// Create player
dashPlayer = gameContainer.addChild(new DashPlayer());
dashPlayer.x = 300;
dashPlayer.y = dashGroundY - 100;
// Initialize game variables
dashObstacles = [];
dashPortals = [];
dashScore = 0;
dashCameraX = 0;
LK.setScore(0);
updateScoreDisplay();
}
function initializeMultiplayerGame() {
game.setBackgroundColor(0x2c3e50);
// Create two players
multiplayerPlayers = [];
var player1 = gameContainer.addChild(new MultiplayerPlayer(1, 0x3498db)); // Blue
player1.x = 400;
player1.y = 1366;
multiplayerPlayers.push(player1);
var player2 = gameContainer.addChild(new MultiplayerPlayer(2, 0xe74c3c)); // Red
player2.x = 1600;
player2.y = 1366;
multiplayerPlayers.push(player2);
// Initialize game variables
multiplayerTargets = [];
multiplayerTimer = 0;
multiplayerGameMode = 'cooperative';
LK.setScore(0);
updateScoreDisplay();
}
function initializeCreatorGame() {
var bg = gameContainer.addChild(LK.getAsset('creatorBackground', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0
}));
gameCreator = new GameCreator();
var toolbar = gameCreator.createToolbar();
gameContainer.addChild(toolbar);
LK.setScore(0);
updateScoreDisplay();
}
function showSettingsPanel() {
if (settingsPanel) return;
settingsPanel = hubContainer.addChild(new SettingsPanel());
settingsPanel.x = 1024;
settingsPanel.y = 1366;
settingsPanel.onClose = function () {
hideSettingsPanel();
};
// Disable other hub interactions
if (scrollBar) scrollBar.visible = false;
for (var i = 0; i < gameCards.length; i++) {
gameCards[i].visible = false;
}
for (var i = 0; i < categoryButtons.length; i++) {
categoryButtons[i].visible = false;
}
}
function hideSettingsPanel() {
if (settingsPanel) {
settingsPanel.destroy();
settingsPanel = null;
}
// Re-enable hub interactions
if (scrollBar) scrollBar.visible = true;
updateGameCardPositions();
for (var i = 0; i < categoryButtons.length; i++) {
categoryButtons[i].visible = true;
}
}
function applyDifficultySettings() {
// Apply difficulty settings to current game
if (currentGame === 'snake' && snake) {
// Adjust snake speed based on difficulty
var speedMultiplier = storage.difficulty === 'easy' ? 0.7 : storage.difficulty === 'hard' ? 1.5 : 1.0;
snake.speed = snake.speed * speedMultiplier;
}
if (currentGame === 'dash' && dashPlayer) {
// Adjust dash game speed based on difficulty
var dashSpeedMultiplier = storage.difficulty === 'easy' ? 0.8 : storage.difficulty === 'hard' ? 1.3 : 1.0;
dashGameSpeed = 8 * dashSpeedMultiplier;
}
}
// Initialize the hub
initializeHub();
// Event handlers
game.down = function (x, y, obj) {
if (!currentGame) {
// Hub navigation
if (settingsPanel) {
// Settings panel is open, handle its interactions
return;
}
if (scrollBar && scrollBar.visible) {
var oldScrollPosition = scrollBar.scrollPosition;
scrollBar.down(x, y, obj);
if (scrollBar.scrollPosition !== oldScrollPosition) {
updateGameCardPositions();
}
}
} else {
// Game-specific controls
if (currentGame === 'snake') {
// Touch controls for snake direction
var dx = x - snake.x;
var dy = y - snake.y;
if (Math.abs(dx) > Math.abs(dy)) {
snake.direction = dx > 0 ? {
x: 1,
y: 0
} : {
x: -1,
y: 0
};
} else {
snake.direction = dy > 0 ? {
x: 0,
y: 1
} : {
x: 0,
y: -1
};
}
} else if (currentGame === 'platform') {
// Touch controls for platformer
if (x < 1024) {
platformPlayer.moveLeft();
} else {
platformPlayer.moveRight();
}
if (y > 2000) {
platformPlayer.jump();
}
} else if (currentGame === 'maze') {
// Touch controls for maze
var dx = x - mazePlayer.x;
var dy = y - mazePlayer.y;
var newGridX = mazePlayer.gridX;
var newGridY = mazePlayer.gridY;
if (Math.abs(dx) > Math.abs(dy)) {
newGridX += dx > 0 ? 1 : -1;
} else {
newGridY += dy > 0 ? 1 : -1;
}
if (newGridX >= 0 && newGridX < maze[0].length && newGridY >= 0 && newGridY < maze.length && maze[newGridY][newGridX] === 0) {
mazePlayer.moveToGrid(newGridX, newGridY);
}
} else if (currentGame === 'dash') {
if (dashPlayer.gameMode === 'cube') {
dashPlayer.jump();
} else if (dashPlayer.gameMode === 'ship') {
dashPlayer.hold();
}
} else if (currentGame === 'flappybird') {
if (flappyBird) {
flappyBird.flap();
}
} else if (currentGame === 'flyingcat') {
if (flyingCat) {
flyingCat.flap();
}
} else if (currentGame === 'multiplayer') {
// Handle multiplayer controls - players move towards touch point
for (var i = 0; i < multiplayerPlayers.length; i++) {
var player = multiplayerPlayers[i];
// In cooperative mode, both players move to the same point
// In competitive mode, alternate which player moves
if (multiplayerGameMode === 'cooperative' || i === LK.ticks % multiplayerPlayers.length) {
player.moveTowards(x, y);
}
}
} else if (currentGame === 'creator') {
gameCreator.handleToolClick(x, y);
gameCreator.handleCanvasClick(x, y);
} else if (currentGame === 'tetris') {
// Touch controls for Tetris
if (currentPiece) {
if (x < 1024) {
// Left side - move left or rotate
if (y > 2000) {
// Bottom area - move left
if (currentPiece.canMoveTo(currentPiece.gridX - 1, currentPiece.gridY)) {
currentPiece.gridX--;
currentPiece.updatePosition();
}
} else {
// Top area - rotate
var oldShape = currentPiece.shape;
var oldRotation = currentPiece.rotation;
currentPiece.rotate();
if (!currentPiece.canMoveTo(currentPiece.gridX, currentPiece.gridY)) {
// Rotation failed, revert
currentPiece.shape = oldShape;
currentPiece.rotation = oldRotation;
currentPiece.createBlocks();
}
}
} else {
// Right side - move right or drop
if (y > 2000) {
// Bottom area - move right
if (currentPiece.canMoveTo(currentPiece.gridX + 1, currentPiece.gridY)) {
currentPiece.gridX++;
currentPiece.updatePosition();
}
} else {
// Top area - hard drop piece
while (currentPiece.canMoveTo(currentPiece.gridX, currentPiece.gridY + 1)) {
currentPiece.gridY++;
}
currentPiece.updatePosition();
placeTetrisPieceInGrid();
}
}
}
}
}
LK.getSound('tap').play();
};
game.up = function (x, y, obj) {
if (currentGame === 'dash' && dashPlayer && dashPlayer.gameMode === 'ship') {
dashPlayer.release();
}
};
game.move = function (x, y, obj) {
if (currentGame === 'breakout' && paddle) {
paddle.x = x;
if (paddle.x < 100) paddle.x = 100;
if (paddle.x > 1948) paddle.x = 1948;
}
};
game.update = function () {
if (!currentGame) {
// Hub update
return;
}
// Game-specific updates
if (currentGame === 'snake') {
updateSnakeGame();
} else if (currentGame === 'circle') {
updateCircleGame();
} else if (currentGame === 'breakout') {
updateBreakoutGame();
} else if (currentGame === 'platform') {
updatePlatformGame();
} else if (currentGame === 'maze') {
updateMazeGame();
} else if (currentGame === 'dash') {
updateDashGame();
} else if (currentGame === 'flappybird') {
updateFlappyBirdGame();
} else if (currentGame === 'multiplayer') {
updateMultiplayerGame();
} else if (currentGame === 'flyingcat') {
updateFlyingCatGame();
} else if (currentGame === 'tetris') {
updateTetrisGame();
}
};
function updateSnakeGame() {
// Check food collision
if (snake && food && snake.intersects(food)) {
LK.setScore(LK.getScore() + 10);
updateScoreDisplay();
snake.grow();
food.destroy();
food = gameContainer.addChild(new Food());
LK.getSound('collect').play();
}
}
function updateCircleGame() {
// Spawn circles
if (LK.ticks % 90 === 0) {
var circle = gameContainer.addChild(new Circle());
circle.x = 100 + Math.random() * 1848;
circle.y = 100 + Math.random() * 2532;
circles.push(circle);
}
// Remove expired circles
for (var i = circles.length - 1; i >= 0; i--) {
if (circles[i].shouldRemove) {
circles[i].destroy();
circles.splice(i, 1);
}
}
}
function updateBreakoutGame() {
// Check brick collisions
for (var i = bricks.length - 1; i >= 0; i--) {
if (ball && ball.intersects(bricks[i])) {
ball.speedY = -ball.speedY;
bricks[i].destroy();
bricks.splice(i, 1);
LK.setScore(LK.getScore() + 10);
updateScoreDisplay();
LK.getSound('collect').play();
if (bricks.length === 0) {
LK.showYouWin();
}
}
}
}
function updatePlatformGame() {
// Check platform collisions for player
if (platformPlayer) {
platformPlayer.onGround = false;
for (var i = 0; i < platforms.length; i++) {
var platform = platforms[i];
if (platformPlayer.intersects(platform) && platformPlayer.lastY <= platform.y - platform.height * platform.scaleY / 2 && platformPlayer.velocityY > 0) {
platformPlayer.y = platform.y - platform.height * platform.scaleY / 2 - platformPlayer.height / 2;
platformPlayer.velocityY = 0;
platformPlayer.onGround = true;
break;
}
}
// Check coin collisions
for (var i = coins.length - 1; i >= 0; i--) {
var coin = coins[i];
if (platformPlayer.intersects(coin)) {
LK.setScore(LK.getScore() + 100);
updateScoreDisplay();
coin.destroy();
coins.splice(i, 1);
LK.getSound('collect').play();
if (coins.length === 0) {
LK.showYouWin();
}
}
}
}
}
function updateMazeGame() {
if (mazePlayer) {
// Check if reached exit
if (mazePlayer.gridX === 23 && mazePlayer.gridY === 7) {
LK.setScore(LK.getScore() + 1000);
updateScoreDisplay();
LK.showYouWin();
}
}
}
function updateMultiplayerGame() {
multiplayerTimer++;
// Switch game modes every 10 seconds
if (multiplayerTimer % 600 === 0) {
multiplayerGameMode = multiplayerGameMode === 'cooperative' ? 'competitive' : 'cooperative';
}
// Spawn targets
if (LK.ticks % 120 === 0) {
var target = gameContainer.addChild(new MultiplayerTarget());
multiplayerTargets.push(target);
}
// Check target collisions
for (var i = multiplayerTargets.length - 1; i >= 0; i--) {
var target = multiplayerTargets[i];
var targetHit = false;
for (var j = 0; j < multiplayerPlayers.length; j++) {
var player = multiplayerPlayers[j];
if (player.intersects(target)) {
if (multiplayerGameMode === 'cooperative') {
// Both players get points in cooperative mode
LK.setScore(LK.getScore() + 10);
} else {
// Only the hitting player gets points in competitive mode
player.score += 10;
LK.setScore(LK.getScore() + 10);
}
updateScoreDisplay();
target.destroy();
multiplayerTargets.splice(i, 1);
targetHit = true;
LK.getSound('collect').play();
break;
}
}
}
// Remove expired targets
for (var i = multiplayerTargets.length - 1; i >= 0; i--) {
if (multiplayerTargets[i].shouldRemove) {
multiplayerTargets[i].destroy();
multiplayerTargets.splice(i, 1);
}
}
// Game over condition
if (multiplayerTimer >= multiplayerTimeLimit) {
LK.showYouWin();
}
}
function updateDashGame() {
if (!dashPlayer || dashPlayer.isDead) return;
dashScore++;
LK.setScore(Math.floor(dashScore / 10));
updateScoreDisplay();
// Spawn obstacles
if (LK.ticks % 60 === 0) {
var obstacleType = Math.random() < 0.7 ? 'block' : 'spike';
var obstacle = gameContainer.addChild(new DashObstacle(obstacleType));
obstacle.x = 2200;
obstacle.y = dashGroundY - 40;
dashObstacles.push(obstacle);
}
// Spawn portals occasionally
if (LK.ticks % 300 === 0) {
var portalTypes = ['cube', 'ship', 'ball', 'wave'];
var portalType = portalTypes[Math.floor(Math.random() * portalTypes.length)];
var portal = gameContainer.addChild(new DashPortal(portalType));
portal.x = 2200;
portal.y = dashGroundY - 100;
dashPortals.push(portal);
}
// Check obstacle collisions
for (var i = 0; i < dashObstacles.length; i++) {
var obstacle = dashObstacles[i];
if (dashPlayer.intersects(obstacle)) {
dashPlayer.die();
break;
}
}
// Check portal collisions
for (var i = dashPortals.length - 1; i >= 0; i--) {
var portal = dashPortals[i];
if (dashPlayer.intersects(portal)) {
dashPlayer.changeMode(portal.portalType);
portal.destroy();
dashPortals.splice(i, 1);
LK.getSound('collect').play();
}
}
// Ground collision for cube mode
if (dashPlayer.gameMode === 'cube' && dashPlayer.y >= dashGroundY - 30) {
dashPlayer.y = dashGroundY - 30;
dashPlayer.velocityY = 0;
dashPlayer.isGrounded = true;
}
// Remove off-screen obstacles
for (var i = dashObstacles.length - 1; i >= 0; i--) {
if (dashObstacles[i].shouldRemove) {
dashObstacles[i].destroy();
dashObstacles.splice(i, 1);
}
}
for (var i = dashPortals.length - 1; i >= 0; i--) {
if (dashPortals[i].shouldRemove) {
dashPortals[i].destroy();
dashPortals.splice(i, 1);
}
}
}
LK.playMusic('bgMusic', {
volume: storage.musicVolume
});
// Override sound play to apply volume settings
var originalGetSound = LK.getSound;
LK.getSound = function (soundId) {
var sound = originalGetSound(soundId);
var originalPlay = sound.play;
sound.play = function () {
// Apply volume from settings
var result = originalPlay.call(this);
if (this.volume !== undefined) {
this.volume *= storage.soundVolume;
}
return result;
};
return sound;
};
function initializeFlappyBirdGame() {
game.setBackgroundColor(0x87ceeb);
// Create bird
flappyBird = gameContainer.addChild(new FlappyBird());
flappyBird.x = 400;
flappyBird.y = 1366;
// Initialize game variables
flappyPipes = [];
flappyPipeTimer = 0;
LK.setScore(0);
updateScoreDisplay();
}
function initializeFlyingCatGame() {
game.setBackgroundColor(0x87ceeb);
// Create flying cat
flyingCat = gameContainer.addChild(new FlyingCat());
flyingCat.x = 400;
flyingCat.y = 1366;
// Initialize game variables
catObstacles = [];
catPowerUps = [];
catClouds = [];
catGameSpeed = 4;
LK.setScore(0);
updateScoreDisplay();
}
function initializeTetrisGame() {
game.setBackgroundColor(0x2c3e50);
// Initialize grid
tetrisGrid = [];
for (var row = 0; row < tetrisGridHeight; row++) {
tetrisGrid[row] = [];
for (var col = 0; col < tetrisGridWidth; col++) {
tetrisGrid[row][col] = 0;
}
}
// Draw grid background
for (var row = 0; row < tetrisGridHeight; row++) {
for (var col = 0; col < tetrisGridWidth; col++) {
var gridCell = gameContainer.addChild(LK.getAsset('customShape', {
anchorX: 0.5,
anchorY: 0.5,
x: tetrisOffsetX + col * tetrisCellSize,
y: tetrisOffsetY + row * tetrisCellSize
}));
gridCell.tint = 0x34495e;
gridCell.alpha = 0.3;
}
}
// Create first piece
var pieceTypes = ['I', 'O', 'T', 'S', 'Z', 'J', 'L'];
var randomType = pieceTypes[Math.floor(Math.random() * pieceTypes.length)];
currentPiece = gameContainer.addChild(new TetrisPiece(randomType));
currentPiece.updatePosition();
// Create next piece preview
var nextType = pieceTypes[Math.floor(Math.random() * pieceTypes.length)];
nextPiece = new TetrisPiece(nextType);
// Initialize game variables
tetrisDropTimer = 0;
tetrisLines = 0;
tetrisLevel = 1;
tetrisDropSpeed = 60;
LK.setScore(0);
updateScoreDisplay();
}
function updateFlappyBirdGame() {
if (!flappyBird || flappyBird.isDead) return;
flappyPipeTimer++;
// Spawn pipes every 2 seconds
if (flappyPipeTimer % 120 === 0) {
var gapY = 400 + Math.random() * 1500;
var topPipe = gameContainer.addChild(new FlappyPipe(true, gapY));
var bottomPipe = gameContainer.addChild(new FlappyPipe(false, gapY));
topPipe.x = 2200;
bottomPipe.x = 2200;
flappyPipes.push(topPipe);
flappyPipes.push(bottomPipe);
}
// Check pipe collisions and scoring
for (var i = flappyPipes.length - 1; i >= 0; i--) {
var pipe = flappyPipes[i];
if (flappyBird.intersects(pipe)) {
flappyBird.die();
break;
}
// Score when bird passes through pipes
if (!pipe.passed && pipe.x < flappyBird.x) {
pipe.passed = true;
// Only count score for bottom pipes to avoid double counting
if (pipe.y > 1366) {
LK.setScore(LK.getScore() + 1);
updateScoreDisplay();
LK.getSound('collect').play();
}
}
}
// Remove off-screen pipes
for (var i = flappyPipes.length - 1; i >= 0; i--) {
if (flappyPipes[i].shouldRemove) {
flappyPipes[i].destroy();
flappyPipes.splice(i, 1);
}
}
} /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
musicVolume: 1,
soundVolume: 1,
difficulty: "normal"
});
/****
* Classes
****/
var Ball = Container.expand(function () {
var self = Container.call(this);
var graphic = self.attachAsset('ball', {
anchorX: 0.5,
anchorY: 0.5
});
self.speedX = 5;
self.speedY = -5;
self.update = function () {
self.x += self.speedX;
self.y += self.speedY;
// Bounce off walls
if (self.x < 20 || self.x > 2028) {
self.speedX = -self.speedX;
LK.getSound('bounce').play();
}
if (self.y < 20) {
self.speedY = -self.speedY;
LK.getSound('bounce').play();
}
// Game over if ball goes below paddle
if (self.y > 2732) {
endCurrentGame();
}
// Bounce off paddle
if (paddle && self.intersects(paddle) && self.speedY > 0) {
self.speedY = -self.speedY;
LK.getSound('bounce').play();
}
};
return self;
});
var Brick = Container.expand(function () {
var self = Container.call(this);
var graphic = self.attachAsset('brick', {
anchorX: 0.5,
anchorY: 0.5
});
return self;
});
var CatObstacle = Container.expand(function (type) {
var self = Container.call(this);
self.obstacleType = type || 'bird';
var assetName = 'flappyBird';
if (type === 'cloud') assetName = 'circle';else if (type === 'storm') assetName = 'dashSpike';
var graphic = self.attachAsset(assetName, {
anchorX: 0.5,
anchorY: 0.5
});
if (type === 'bird') {
graphic.tint = 0x8b4513; // Brown for enemy birds
graphic.scaleX = 0.8;
graphic.scaleY = 0.8;
} else if (type === 'cloud') {
graphic.tint = 0x708090; // Gray for storm clouds
graphic.scaleX = 1.5;
graphic.scaleY = 1.0;
} else if (type === 'storm') {
graphic.tint = 0x4169e1; // Blue for lightning
}
self.speed = -catGameSpeed;
self.update = function () {
self.x += self.speed;
if (self.x < -100) {
self.shouldRemove = true;
}
// Add movement patterns
if (type === 'bird') {
self.y += Math.sin(LK.ticks * 0.1) * 2;
} else if (type === 'cloud') {
graphic.rotation += 0.02;
}
};
return self;
});
var CatPowerUp = Container.expand(function (type) {
var self = Container.call(this);
self.powerType = type || 'fish';
var assetName = type === 'fish' ? 'food' : 'coin';
var graphic = self.attachAsset(assetName, {
anchorX: 0.5,
anchorY: 0.5
});
if (type === 'fish') {
graphic.tint = 0xff69b4; // Pink for fish
} else if (type === 'life') {
graphic.tint = 0x32cd32; // Green for extra life
}
self.speed = -catGameSpeed;
self.bobOffset = Math.random() * Math.PI * 2;
self.update = function () {
self.x += self.speed;
self.y += Math.sin(LK.ticks * 0.15 + self.bobOffset) * 3;
if (self.x < -100) {
self.shouldRemove = true;
}
graphic.rotation += 0.1;
};
return self;
});
var CategoryButton = Container.expand(function (categoryName, isActive) {
var self = Container.call(this);
var buttonBg = self.attachAsset('categoryButton', {
anchorX: 0.5,
anchorY: 0.5
});
if (isActive) {
buttonBg.tint = 0x0984e3; // Darker blue for active state
}
var buttonText = new Text2(categoryName, {
size: 32,
fill: 0xFFFFFF
});
buttonText.anchor.set(0.5, 0.5);
self.addChild(buttonText);
self.categoryName = categoryName;
self.isActive = isActive;
self.setActive = function (active) {
self.isActive = active;
buttonBg.tint = active ? 0x0984e3 : 0x74b9ff;
};
self.down = function (x, y, obj) {
tween(buttonBg, {
scaleX: 0.95,
scaleY: 0.95
}, {
duration: 100
});
LK.getSound('tap').play();
};
self.up = function (x, y, obj) {
tween(buttonBg, {
scaleX: 1,
scaleY: 1
}, {
duration: 100
});
filterGamesByCategory(self.categoryName);
};
return self;
});
var Circle = Container.expand(function () {
var self = Container.call(this);
var graphic = self.attachAsset('circle', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 2 + Math.random() * 3;
self.direction = Math.random() * Math.PI * 2;
self.lifetime = 180; // 3 seconds at 60fps
self.maxLifetime = self.lifetime;
self.update = function () {
self.x += Math.cos(self.direction) * self.speed;
self.y += Math.sin(self.direction) * self.speed;
// Bounce off walls
if (self.x < 60 || self.x > 1988) {
self.direction = Math.PI - self.direction;
}
if (self.y < 60 || self.y > 2672) {
self.direction = -self.direction;
}
self.lifetime--;
var alpha = self.lifetime / self.maxLifetime;
graphic.alpha = alpha;
if (self.lifetime <= 0) {
self.shouldRemove = true;
}
};
self.down = function (x, y, obj) {
LK.getSound('tap').play();
LK.setScore(LK.getScore() + 10);
updateScoreDisplay();
self.shouldRemove = true;
};
return self;
});
var Coin = Container.expand(function () {
var self = Container.call(this);
var graphic = self.attachAsset('coin', {
anchorX: 0.5,
anchorY: 0.5
});
self.bobOffset = Math.random() * Math.PI * 2;
self.startY = 0;
self.update = function () {
self.y = self.startY + Math.sin(LK.ticks * 0.1 + self.bobOffset) * 10;
};
return self;
});
var DashObstacle = Container.expand(function (type) {
var self = Container.call(this);
self.obstacleType = type || 'block';
var assetName = 'dashObstacle';
if (type === 'spike') assetName = 'dashSpike';else if (type === 'ground') assetName = 'dashGround';
var graphic = self.attachAsset(assetName, {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = -8;
self.update = function () {
self.x += self.speed;
if (self.x < -100) {
self.shouldRemove = true;
}
};
return self;
});
var DashPlayer = Container.expand(function () {
var self = Container.call(this);
var graphic = self.attachAsset('dashPlayer', {
anchorX: 0.5,
anchorY: 0.5
});
self.velocityY = 0;
self.gravity = 1.2;
self.jumpPower = -18;
self.isGrounded = false;
self.isDead = false;
self.lastY = 0;
self.gameMode = 'cube'; // cube, ship, ball, wave
self.update = function () {
if (self.isDead) return;
self.lastY = self.y;
// Apply gravity for cube mode
if (self.gameMode === 'cube') {
self.velocityY += self.gravity;
if (self.velocityY > 15) self.velocityY = 15;
} else if (self.gameMode === 'ship') {
// Ship mode - controlled flight
if (self.isHolding) {
self.velocityY -= 1.5;
if (self.velocityY < -12) self.velocityY = -12;
} else {
self.velocityY += 1.2;
if (self.velocityY > 12) self.velocityY = 12;
}
}
self.y += self.velocityY;
self.isGrounded = false;
// Simple rotation based on velocity
if (self.gameMode === 'cube') {
graphic.rotation = 0;
} else if (self.gameMode === 'ship') {
graphic.rotation = self.velocityY * 0.1;
}
};
self.jump = function () {
if (self.gameMode === 'cube' && self.isGrounded) {
self.velocityY = self.jumpPower;
self.isGrounded = false;
LK.getSound('jump').play();
}
};
self.hold = function () {
self.isHolding = true;
};
self.release = function () {
self.isHolding = false;
};
self.die = function () {
if (self.isDead) return;
self.isDead = true;
// Flash red death effect
tween(graphic, {
tint: 0xff0000
}, {
duration: 200,
onFinish: function onFinish() {
tween(graphic, {
tint: 0xffffff
}, {
duration: 200
});
}
});
LK.setTimeout(function () {
endCurrentGame();
}, 500);
};
self.changeMode = function (newMode) {
self.gameMode = newMode;
if (newMode === 'ship') {
graphic.tint = 0x3498db;
} else if (newMode === 'ball') {
graphic.tint = 0xe67e22;
} else if (newMode === 'wave') {
graphic.tint = 0x9b59b6;
} else {
graphic.tint = 0xf39c12;
}
};
return self;
});
var DashPortal = Container.expand(function (portalType) {
var self = Container.call(this);
var graphic = self.attachAsset('dashPortal', {
anchorX: 0.5,
anchorY: 0.5
});
self.portalType = portalType || 'cube';
self.speed = -8;
// Color portals based on type
if (portalType === 'ship') {
graphic.tint = 0x3498db;
} else if (portalType === 'ball') {
graphic.tint = 0xe67e22;
} else if (portalType === 'wave') {
graphic.tint = 0x9b59b6;
} else {
graphic.tint = 0xf39c12;
}
self.update = function () {
self.x += self.speed;
if (self.x < -100) {
self.shouldRemove = true;
}
// Rotating effect
graphic.rotation += 0.1;
};
return self;
});
var FlappyBird = Container.expand(function () {
var self = Container.call(this);
var graphic = self.attachAsset('flappyBird', {
anchorX: 0.5,
anchorY: 0.5
});
self.velocityY = 0;
self.gravity = 0.8;
self.flapPower = -12;
self.isDead = false;
self.update = function () {
if (self.isDead) return;
self.velocityY += self.gravity;
if (self.velocityY > 15) self.velocityY = 15;
self.y += self.velocityY;
// Simple rotation based on velocity
graphic.rotation = Math.max(-0.5, Math.min(0.5, self.velocityY * 0.1));
// Die if hit ground or ceiling
if (self.y > 2700 || self.y < 50) {
self.die();
}
};
self.flap = function () {
if (!self.isDead) {
self.velocityY = self.flapPower;
LK.getSound('jump').play();
}
};
self.die = function () {
if (self.isDead) return;
self.isDead = true;
tween(graphic, {
tint: 0xff0000
}, {
duration: 200,
onFinish: function onFinish() {
tween(graphic, {
tint: 0xffffff
}, {
duration: 200
});
}
});
LK.setTimeout(function () {
endCurrentGame();
}, 500);
};
return self;
});
var FlappyPipe = Container.expand(function (isTop, gapY) {
var self = Container.call(this);
var graphic = self.attachAsset('flappyPipe', {
anchorX: 0.5,
anchorY: isTop ? 1 : 0
});
self.speed = -4;
self.passed = false;
if (isTop) {
self.y = gapY - 150;
} else {
self.y = gapY + 150;
}
self.update = function () {
self.x += self.speed;
if (self.x < -100) {
self.shouldRemove = true;
}
};
return self;
});
var FlyingCat = Container.expand(function () {
var self = Container.call(this);
var graphic = self.attachAsset('flappyBird', {
anchorX: 0.5,
anchorY: 0.5
});
graphic.tint = 0xffa500; // Orange tint for cat
self.velocityY = 0;
self.gravity = 0.6;
self.flapPower = -10;
self.isDead = false;
self.lives = 3;
self.isInvulnerable = false;
self.invulnerabilityTimer = 0;
self.update = function () {
if (self.isDead) return;
self.velocityY += self.gravity;
if (self.velocityY > 12) self.velocityY = 12;
self.y += self.velocityY;
// Handle invulnerability
if (self.isInvulnerable) {
self.invulnerabilityTimer--;
graphic.alpha = Math.sin(self.invulnerabilityTimer * 0.3) * 0.5 + 0.5;
if (self.invulnerabilityTimer <= 0) {
self.isInvulnerable = false;
graphic.alpha = 1.0;
}
}
// Simple rotation based on velocity
graphic.rotation = Math.max(-0.3, Math.min(0.3, self.velocityY * 0.08));
// Die if hit ground or ceiling
if (self.y > 2650 || self.y < 50) {
self.takeDamage();
}
};
self.flap = function () {
if (!self.isDead) {
self.velocityY = self.flapPower;
LK.getSound('jump').play();
}
};
self.takeDamage = function () {
if (self.isInvulnerable) return;
self.lives--;
if (self.lives <= 0) {
self.die();
} else {
self.isInvulnerable = true;
self.invulnerabilityTimer = 120; // 2 seconds at 60fps
self.y = 1366; // Reset position
self.velocityY = 0;
}
};
self.die = function () {
if (self.isDead) return;
self.isDead = true;
tween(graphic, {
tint: 0xff0000
}, {
duration: 200,
onFinish: function onFinish() {
tween(graphic, {
tint: 0xffffff
}, {
duration: 200
});
}
});
LK.setTimeout(function () {
endCurrentGame();
}, 500);
};
return self;
});
var Food = Container.expand(function () {
var self = Container.call(this);
var graphic = self.attachAsset('food', {
anchorX: 0.5,
anchorY: 0.5
});
self.x = 100 + Math.random() * 1848;
self.y = 100 + Math.random() * 2532;
return self;
});
var GameCard = Container.expand(function (gameInfo) {
var self = Container.call(this);
var isLocked = gameInfo.locked || false;
var cardBg = self.attachAsset(isLocked ? 'gameCardLocked' : 'gameCard', {
anchorX: 0.5,
anchorY: 0.5
});
// Add border effect
cardBg.tint = isLocked ? 0x34495e : 0x2c3e50;
if (isLocked) {
var lock = self.attachAsset('lockIcon', {
anchorX: 0.5,
anchorY: 0.5,
y: -20
});
}
var titleText = new Text2(gameInfo.title, {
size: 36,
fill: isLocked ? "#999999" : "#ffffff"
});
titleText.anchor.set(0.5, 0.5);
titleText.y = isLocked ? 30 : -40;
self.addChild(titleText);
var categoryText = new Text2(gameInfo.category, {
size: 24,
fill: isLocked ? "#666666" : "#74b9ff"
});
categoryText.anchor.set(0.5, 0.5);
categoryText.y = isLocked ? 60 : -10;
self.addChild(categoryText);
var scoreText = new Text2('Best: ' + (gameInfo.bestScore || 0), {
size: 28,
fill: isLocked ? "#555555" : "#00b894"
});
scoreText.anchor.set(0.5, 0.5);
scoreText.y = isLocked ? 90 : 30;
self.addChild(scoreText);
self.gameInfo = gameInfo;
self.isLocked = isLocked;
self.down = function (x, y, obj) {
if (!self.isLocked) {
tween(cardBg, {
scaleX: 0.95,
scaleY: 0.95
}, {
duration: 100
});
LK.getSound('tap').play();
}
};
self.up = function (x, y, obj) {
if (!self.isLocked) {
tween(cardBg, {
scaleX: 1,
scaleY: 1
}, {
duration: 100
});
currentGame = self.gameInfo.id;
switchToGame(currentGame);
}
};
self.updateScore = function (newScore) {
gameInfo.bestScore = newScore;
scoreText.setText('Best: ' + newScore);
};
self.unlock = function () {
self.isLocked = false;
gameInfo.locked = false;
cardBg.tint = 0x16213e;
titleText.tint = 0xffffff;
scoreText.tint = 0xcccccc;
if (lock) {
lock.visible = false;
}
};
return self;
});
var GameCreator = Container.expand(function () {
var self = Container.call(this);
self.mode = 'place'; // 'place', 'delete', 'color', 'resize', 'copy'
self.currentColor = 0x00b894;
self.currentObjectType = 'box'; // 'box', 'circle', 'platform', 'spike', 'goal', 'enemy'
self.gridSize = 40;
self.snapToGrid = true;
self.createdObjects = [];
self.clipboard = null;
self.selectedObject = null;
self.createToolbar = function () {
var toolbar = new Container();
// Row 1 - Main tools
var tools = [{
name: 'Place',
x: 150,
y: 80
}, {
name: 'Delete',
x: 300,
y: 80
}, {
name: 'Copy',
x: 450,
y: 80
}, {
name: 'Resize',
x: 600,
y: 80
}, {
name: 'Grid',
x: 750,
y: 80
}, {
name: 'Color',
x: 900,
y: 80
}, {
name: 'Play',
x: 1200,
y: 80
}, {
name: 'Save',
x: 1350,
y: 80
}, {
name: 'Load',
x: 1500,
y: 80
}, {
name: 'Clear',
x: 1650,
y: 80
}];
for (var i = 0; i < tools.length; i++) {
var tool = tools[i];
var btn = toolbar.addChild(LK.getAsset('toolButton', {
anchorX: 0.5,
anchorY: 0.5,
x: tool.x,
y: tool.y,
scaleX: 0.7,
scaleY: 0.7
}));
var text = new Text2(tool.name, {
size: 24,
fill: 0xFFFFFF
});
text.anchor.set(0.5, 0.5);
text.x = tool.x;
text.y = tool.y;
toolbar.addChild(text);
}
// Row 2 - Object types
var objectTypes = [{
name: 'Box',
type: 'box',
x: 150,
y: 150
}, {
name: 'Circle',
type: 'circle',
x: 300,
y: 150
}, {
name: 'Platform',
type: 'platform',
x: 450,
y: 150
}, {
name: 'Spike',
type: 'spike',
x: 600,
y: 150
}, {
name: 'Goal',
type: 'goal',
x: 750,
y: 150
}, {
name: 'Enemy',
type: 'enemy',
x: 900,
y: 150
}];
for (var i = 0; i < objectTypes.length; i++) {
var objType = objectTypes[i];
var btn = toolbar.addChild(LK.getAsset('categoryButton', {
anchorX: 0.5,
anchorY: 0.5,
x: objType.x,
y: objType.y,
scaleX: 0.6,
scaleY: 0.6
}));
var text = new Text2(objType.name, {
size: 20,
fill: 0xFFFFFF
});
text.anchor.set(0.5, 0.5);
text.x = objType.x;
text.y = objType.y;
toolbar.addChild(text);
}
// Create grid overlay
self.createGrid();
return toolbar;
};
self.createGrid = function () {
self.gridContainer = new Container();
game.addChild(self.gridContainer);
// Create grid dots
for (var x = 0; x < 2048; x += self.gridSize) {
for (var y = 200; y < 2732; y += self.gridSize) {
var dot = self.gridContainer.addChild(LK.getAsset('gridDot', {
anchorX: 0.5,
anchorY: 0.5,
x: x,
y: y
}));
dot.alpha = 0.3;
}
}
self.gridContainer.visible = self.snapToGrid;
};
self.snapToGridPosition = function (x, y) {
if (!self.snapToGrid) return {
x: x,
y: y
};
return {
x: Math.round(x / self.gridSize) * self.gridSize,
y: Math.round(y / self.gridSize) * self.gridSize
};
};
self.getAssetNameForType = function (type) {
switch (type) {
case 'circle':
return 'customCircle';
case 'platform':
return 'customPlatform';
case 'spike':
return 'customSpike';
case 'goal':
return 'customGoal';
case 'enemy':
return 'customEnemy';
default:
return 'customShape';
}
};
self.handleToolClick = function (x, y) {
// Row 1 - Main tools
if (y >= 50 && y <= 110) {
if (x >= 100 && x <= 200) self.mode = 'place';else if (x >= 250 && x <= 350) self.mode = 'delete';else if (x >= 400 && x <= 500) self.mode = 'copy';else if (x >= 550 && x <= 650) self.mode = 'resize';else if (x >= 700 && x <= 800) {
self.snapToGrid = !self.snapToGrid;
if (self.gridContainer) self.gridContainer.visible = self.snapToGrid;
} else if (x >= 850 && x <= 950) {
self.mode = 'color';
self.currentColor = [0xff7675, 0x74b9ff, 0x00b894, 0xfdcb6e, 0xe17055, 0x6c5ce7][Math.floor(Math.random() * 6)];
} else if (x >= 1150 && x <= 1250) {
self.mode = 'play';
self.startCustomGame();
} else if (x >= 1300 && x <= 1400) self.saveLevel();else if (x >= 1450 && x <= 1550) self.loadLevel();else if (x >= 1600 && x <= 1700) self.clearAll();
}
// Row 2 - Object types
else if (y >= 120 && y <= 180) {
if (x >= 100 && x <= 200) self.currentObjectType = 'box';else if (x >= 250 && x <= 350) self.currentObjectType = 'circle';else if (x >= 400 && x <= 500) self.currentObjectType = 'platform';else if (x >= 550 && x <= 650) self.currentObjectType = 'spike';else if (x >= 700 && x <= 800) self.currentObjectType = 'goal';else if (x >= 850 && x <= 950) self.currentObjectType = 'enemy';
}
};
self.handleCanvasClick = function (x, y) {
if (y < 200) return; // Don't place in toolbar area
var snappedPos = self.snapToGridPosition(x, y);
x = snappedPos.x;
y = snappedPos.y;
if (self.mode === 'place') {
var assetName = self.getAssetNameForType(self.currentObjectType);
var newObj = game.addChild(LK.getAsset(assetName, {
anchorX: 0.5,
anchorY: 0.5,
x: x,
y: y
}));
newObj.tint = self.currentColor;
newObj.isCustomObject = true;
newObj.objectType = self.currentObjectType;
newObj.customSize = 1.0;
self.createdObjects.push(newObj);
LK.getSound('tap').play();
} else if (self.mode === 'delete') {
self.deleteObjectAt(x, y);
} else if (self.mode === 'copy') {
var foundObj = self.findObjectAt(x, y);
if (foundObj) {
self.clipboard = {
type: foundObj.objectType,
color: foundObj.tint,
size: foundObj.customSize
};
LK.getSound('tap').play();
}
} else if (self.mode === 'resize') {
var foundObj = self.findObjectAt(x, y);
if (foundObj) {
foundObj.customSize = foundObj.customSize === 1.0 ? 1.5 : foundObj.customSize === 1.5 ? 0.5 : 1.0;
foundObj.scaleX = foundObj.customSize;
foundObj.scaleY = foundObj.customSize;
LK.getSound('tap').play();
}
} else if (self.mode === 'color') {
var foundObj = self.findObjectAt(x, y);
if (foundObj) {
foundObj.tint = self.currentColor;
LK.getSound('tap').play();
}
}
};
self.findObjectAt = function (x, y) {
for (var i = self.createdObjects.length - 1; i >= 0; i--) {
var obj = self.createdObjects[i];
var dx = obj.x - x;
var dy = obj.y - y;
var size = (obj.width || 80) * (obj.customSize || 1.0) / 2;
if (Math.sqrt(dx * dx + dy * dy) < size) {
return obj;
}
}
return null;
};
self.deleteObjectAt = function (x, y) {
for (var i = self.createdObjects.length - 1; i >= 0; i--) {
var obj = self.createdObjects[i];
var dx = obj.x - x;
var dy = obj.y - y;
var size = (obj.width || 80) * (obj.customSize || 1.0) / 2;
if (Math.sqrt(dx * dx + dy * dy) < size) {
obj.destroy();
self.createdObjects.splice(i, 1);
LK.getSound('tap').play();
break;
}
}
};
self.saveLevel = function () {
var levelData = [];
for (var i = 0; i < self.createdObjects.length; i++) {
var obj = self.createdObjects[i];
levelData.push({
type: obj.objectType,
x: obj.x,
y: obj.y,
color: obj.tint,
size: obj.customSize || 1.0
});
}
storage.customLevel = levelData;
LK.getSound('collect').play();
};
self.loadLevel = function () {
if (storage.customLevel) {
self.clearAll();
var levelData = storage.customLevel;
for (var i = 0; i < levelData.length; i++) {
var data = levelData[i];
var assetName = self.getAssetNameForType(data.type);
var newObj = game.addChild(LK.getAsset(assetName, {
anchorX: 0.5,
anchorY: 0.5,
x: data.x,
y: data.y
}));
newObj.tint = data.color;
newObj.isCustomObject = true;
newObj.objectType = data.type;
newObj.customSize = data.size;
newObj.scaleX = data.size;
newObj.scaleY = data.size;
self.createdObjects.push(newObj);
}
LK.getSound('collect').play();
}
};
self.clearAll = function () {
for (var i = 0; i < self.createdObjects.length; i++) {
self.createdObjects[i].destroy();
}
self.createdObjects = [];
if (self.gridContainer) {
self.gridContainer.destroy();
self.createGrid();
}
};
self.startCustomGame = function () {
if (self.createdObjects.length === 0) return;
currentGame = 'customGame';
customGameObjects = self.createdObjects.slice(); // Copy array
LK.setScore(0);
updateScoreDisplay();
};
return self;
});
var MazePlayer = Container.expand(function () {
var self = Container.call(this);
var graphic = self.attachAsset('mazePlayer', {
anchorX: 0.5,
anchorY: 0.5
});
self.gridX = 0;
self.gridY = 0;
self.cellSize = 80;
self.moveToGrid = function (gridX, gridY) {
self.gridX = gridX;
self.gridY = gridY;
self.x = gridX * self.cellSize + self.cellSize / 2;
self.y = gridY * self.cellSize + self.cellSize / 2 + 200;
};
return self;
});
var MazeWall = Container.expand(function () {
var self = Container.call(this);
var graphic = self.attachAsset('mazeWall', {
anchorX: 0.5,
anchorY: 0.5
});
return self;
});
var MovingPlatform = Container.expand(function (width, startX, endX) {
var self = Container.call(this);
var graphic = self.attachAsset('platform', {
anchorX: 0.5,
anchorY: 0.5
});
if (width) {
graphic.scaleX = width / 200;
}
graphic.tint = 0x74b9ff; // Blue tint for moving platforms
self.startX = startX;
self.endX = endX;
self.speed = 2;
self.direction = 1;
self.update = function () {
self.x += self.speed * self.direction;
if (self.x >= self.endX || self.x <= self.startX) {
self.direction *= -1;
}
};
return self;
});
var MultiplayerPlayer = Container.expand(function (playerId, color) {
var self = Container.call(this);
var graphic = self.attachAsset('circle', {
anchorX: 0.5,
anchorY: 0.5
});
graphic.tint = color;
graphic.scaleX = 0.8;
graphic.scaleY = 0.8;
self.playerId = playerId;
self.speed = 5;
self.score = 0;
self.lastX = 0;
self.lastY = 0;
self.update = function () {
self.lastX = self.x;
self.lastY = self.y;
// Keep player on screen
if (self.x < 40) self.x = 40;
if (self.x > 2008) self.x = 2008;
if (self.y < 40) self.y = 40;
if (self.y > 2692) self.y = 2692;
};
self.moveTowards = function (targetX, targetY) {
var dx = targetX - self.x;
var dy = targetY - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > self.speed) {
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
} else {
self.x = targetX;
self.y = targetY;
}
};
return self;
});
var MultiplayerTarget = Container.expand(function () {
var self = Container.call(this);
var graphic = self.attachAsset('food', {
anchorX: 0.5,
anchorY: 0.5
});
self.x = 100 + Math.random() * 1848;
self.y = 100 + Math.random() * 2532;
self.lifetime = 300; // 5 seconds at 60fps
self.maxLifetime = self.lifetime;
self.update = function () {
self.lifetime--;
var alpha = self.lifetime / self.maxLifetime;
graphic.alpha = alpha;
if (self.lifetime <= 0) {
self.shouldRemove = true;
}
};
self.down = function (x, y, obj) {
LK.getSound('collect').play();
self.shouldRemove = true;
return true; // Indicate target was hit
};
return self;
});
var Paddle = Container.expand(function () {
var self = Container.call(this);
var graphic = self.attachAsset('paddle', {
anchorX: 0.5,
anchorY: 0.5
});
self.x = 1024;
self.y = 2600;
return self;
});
var Platform = Container.expand(function () {
var self = Container.call(this);
var graphic = self.attachAsset('platform', {
anchorX: 0.5,
anchorY: 0.5
});
return self;
});
var PlatformPlayer = Container.expand(function () {
var self = Container.call(this);
var graphic = self.attachAsset('platformPlayer', {
anchorX: 0.5,
anchorY: 0.5
});
self.velocityX = 0;
self.velocityY = 0;
self.gravity = 0.8;
self.jumpPower = -15;
self.speed = 6;
self.maxSpeed = 8;
self.onGround = false;
self.lastY = 0;
self.lastX = 0;
self.width = 60;
self.height = 80;
self.update = function () {
self.lastY = self.y;
self.lastX = self.x;
// Apply gravity
self.velocityY += self.gravity;
if (self.velocityY > 20) self.velocityY = 20; // Terminal velocity
// Apply horizontal velocity
self.x += self.velocityX;
// Check horizontal platform collisions
for (var i = 0; i < platforms.length; i++) {
var platform = platforms[i];
if (self.intersects(platform)) {
// Push player out horizontally
if (self.velocityX > 0) {
// Moving right, hit left side of platform
self.x = platform.x - platform.width * platform.scaleX / 2 - self.width / 2;
} else if (self.velocityX < 0) {
// Moving left, hit right side of platform
self.x = platform.x + platform.width * platform.scaleX / 2 + self.width / 2;
}
self.velocityX = 0;
break;
}
}
// Apply vertical velocity
self.y += self.velocityY;
// Friction
self.velocityX *= 0.85;
// Keep player on screen horizontally
if (self.x < 30) {
self.x = 30;
self.velocityX = 0;
}
if (self.x > 2018) {
self.x = 2018;
self.velocityX = 0;
}
// Reset if player falls off screen
if (self.y > 2800) {
self.x = 200;
self.y = 2000;
self.velocityX = 0;
self.velocityY = 0;
}
self.onGround = false;
};
self.jump = function () {
if (self.onGround) {
self.velocityY = self.jumpPower;
self.onGround = false;
LK.getSound('jump').play();
}
};
self.moveLeft = function () {
self.velocityX -= self.speed;
if (self.velocityX < -self.maxSpeed) self.velocityX = -self.maxSpeed;
};
self.moveRight = function () {
self.velocityX += self.speed;
if (self.velocityX > self.maxSpeed) self.velocityX = self.maxSpeed;
};
return self;
});
var ScrollBar = Container.expand(function () {
var self = Container.call(this);
self.scrollPosition = 0;
self.maxScroll = 0;
self.contentHeight = 0;
self.viewHeight = 2000;
// Create scroll bar background
var scrollBg = self.attachAsset('scrollBar', {
anchorX: 0.5,
anchorY: 0
});
// Create scroll thumb
var scrollThumb = self.attachAsset('scrollThumb', {
anchorX: 0.5,
anchorY: 0
});
// Create up button
var upBtn = self.attachAsset('scrollUpBtn', {
anchorX: 0.5,
anchorY: 0.5,
y: -50
});
// Create down button
var downBtn = self.attachAsset('scrollDownBtn', {
anchorX: 0.5,
anchorY: 0.5,
y: 450
});
// Add up/down arrows as text
var upText = new Text2('ā²', {
size: 24,
fill: 0xFFFFFF
});
upText.anchor.set(0.5, 0.5);
upText.y = -50;
self.addChild(upText);
var downText = new Text2('ā¼', {
size: 24,
fill: 0xFFFFFF
});
downText.anchor.set(0.5, 0.5);
downText.y = 450;
self.addChild(downText);
self.setContentHeight = function (height) {
self.contentHeight = height;
self.maxScroll = Math.max(0, height - self.viewHeight);
self.updateThumb();
};
self.updateThumb = function () {
if (self.maxScroll > 0) {
var thumbRatio = self.viewHeight / self.contentHeight;
var thumbHeight = Math.max(30, scrollBg.height * thumbRatio);
scrollThumb.scaleY = thumbHeight / 60;
var thumbPosition = self.scrollPosition / self.maxScroll * (scrollBg.height - thumbHeight);
scrollThumb.y = thumbPosition;
} else {
scrollThumb.y = 0;
}
};
self.scroll = function (delta) {
self.scrollPosition = Math.max(0, Math.min(self.maxScroll, self.scrollPosition + delta));
self.updateThumb();
return self.scrollPosition;
};
self.down = function (x, y, obj) {
var localY = y - self.y;
if (localY >= -75 && localY <= -25) {
// Up button clicked
self.scroll(-200);
LK.getSound('tap').play();
} else if (localY >= 425 && localY <= 475) {
// Down button clicked
self.scroll(200);
LK.getSound('tap').play();
}
};
return self;
});
var SettingsPanel = Container.expand(function () {
var self = Container.call(this);
// Create background panel
var panelBg = self.attachAsset('gameCardActive', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2.5,
scaleY: 2.0
});
panelBg.tint = 0x2c3e50;
// Title
var titleText = new Text2('Settings', {
size: 48,
fill: 0xFFFFFF
});
titleText.anchor.set(0.5, 0.5);
titleText.y = -250;
self.addChild(titleText);
// Music Volume
var musicLabel = new Text2('Music Volume: ' + Math.round(storage.musicVolume * 100) + '%', {
size: 32,
fill: 0xFFFFFF
});
musicLabel.anchor.set(0.5, 0.5);
musicLabel.y = -150;
self.addChild(musicLabel);
var musicSlider = self.attachAsset('scrollBar', {
anchorX: 0.5,
anchorY: 0.5,
y: -100,
scaleX: 2.0,
scaleY: 0.5
});
var musicThumb = self.attachAsset('scrollThumb', {
anchorX: 0.5,
anchorY: 0.5,
y: -100,
x: (storage.musicVolume - 0.5) * 80
});
// Sound Volume
var soundLabel = new Text2('Sound Volume: ' + Math.round(storage.soundVolume * 100) + '%', {
size: 32,
fill: 0xFFFFFF
});
soundLabel.anchor.set(0.5, 0.5);
soundLabel.y = -20;
self.addChild(soundLabel);
var soundSlider = self.attachAsset('scrollBar', {
anchorX: 0.5,
anchorY: 0.5,
y: 30,
scaleX: 2.0,
scaleY: 0.5
});
var soundThumb = self.attachAsset('scrollThumb', {
anchorX: 0.5,
anchorY: 0.5,
y: 30,
x: (storage.soundVolume - 0.5) * 80
});
// Difficulty Setting
var difficultyLabel = new Text2('Difficulty: ' + storage.difficulty, {
size: 32,
fill: 0xFFFFFF
});
difficultyLabel.anchor.set(0.5, 0.5);
difficultyLabel.y = 110;
self.addChild(difficultyLabel);
var difficultyButton = self.attachAsset('categoryButton', {
anchorX: 0.5,
anchorY: 0.5,
y: 160,
scaleX: 0.8,
scaleY: 0.8
});
var difficultyText = new Text2(storage.difficulty, {
size: 28,
fill: 0xFFFFFF
});
difficultyText.anchor.set(0.5, 0.5);
difficultyText.y = 160;
self.addChild(difficultyText);
// Close button
var closeButton = self.attachAsset('categoryButton', {
anchorX: 0.5,
anchorY: 0.5,
y: 240,
scaleX: 0.6,
scaleY: 0.6
});
closeButton.tint = 0xe74c3c;
var closeText = new Text2('Close', {
size: 24,
fill: 0xFFFFFF
});
closeText.anchor.set(0.5, 0.5);
closeText.y = 240;
self.addChild(closeText);
var isDragging = false;
var dragTarget = null;
self.updateMusicVolume = function (volume) {
storage.musicVolume = Math.max(0, Math.min(1, volume));
musicLabel.setText('Music Volume: ' + Math.round(storage.musicVolume * 100) + '%');
musicThumb.x = (storage.musicVolume - 0.5) * 80;
// Apply volume to current music
LK.stopMusic();
LK.playMusic('bgMusic', {
volume: storage.musicVolume
});
};
self.updateSoundVolume = function (volume) {
storage.soundVolume = Math.max(0, Math.min(1, volume));
soundLabel.setText('Sound Volume: ' + Math.round(storage.soundVolume * 100) + '%');
soundThumb.x = (storage.soundVolume - 0.5) * 80;
};
self.cycleDifficulty = function () {
var difficulties = ['easy', 'normal', 'hard'];
var currentIndex = difficulties.indexOf(storage.difficulty);
var nextIndex = (currentIndex + 1) % difficulties.length;
storage.difficulty = difficulties[nextIndex];
difficultyLabel.setText('Difficulty: ' + storage.difficulty);
difficultyText.setText(storage.difficulty);
};
self.down = function (x, y, obj) {
var localPos;
try {
if (obj && obj.parent && obj.position) {
localPos = self.toLocal(obj.parent.toGlobal(obj.position));
} else {
localPos = {
x: x,
y: y
};
}
} catch (e) {
localPos = {
x: x,
y: y
};
}
// Check music slider
if (localPos.y >= -120 && localPos.y <= -80 && localPos.x >= -80 && localPos.x <= 80) {
isDragging = true;
dragTarget = 'music';
var volume = (localPos.x + 80) / 160;
self.updateMusicVolume(volume);
}
// Check sound slider
else if (localPos.y >= 10 && localPos.y <= 50 && localPos.x >= -80 && localPos.x <= 80) {
isDragging = true;
dragTarget = 'sound';
var volume = (localPos.x + 80) / 160;
self.updateSoundVolume(volume);
}
// Check difficulty button
else if (localPos.y >= 140 && localPos.y <= 180 && localPos.x >= -120 && localPos.x <= 120) {
tween(difficultyButton, {
scaleX: 0.75,
scaleY: 0.75
}, {
duration: 100
});
LK.getSound('tap').play();
}
// Check close button
else if (localPos.y >= 220 && localPos.y <= 260 && localPos.x >= -90 && localPos.x <= 90) {
tween(closeButton, {
scaleX: 0.55,
scaleY: 0.55
}, {
duration: 100
});
LK.getSound('tap').play();
}
};
self.move = function (x, y, obj) {
if (isDragging) {
var localPos;
try {
if (obj && obj.parent && obj.position) {
localPos = self.toLocal(obj.parent.toGlobal(obj.position));
} else {
localPos = {
x: x,
y: y
};
}
} catch (e) {
localPos = {
x: x,
y: y
};
}
if (dragTarget === 'music') {
var volume = (localPos.x + 80) / 160;
self.updateMusicVolume(volume);
} else if (dragTarget === 'sound') {
var volume = (localPos.x + 80) / 160;
self.updateSoundVolume(volume);
}
}
};
self.up = function (x, y, obj) {
var localPos;
try {
if (obj && obj.parent && obj.position) {
localPos = self.toLocal(obj.parent.toGlobal(obj.position));
} else {
localPos = {
x: x,
y: y
};
}
} catch (e) {
localPos = {
x: x,
y: y
};
}
if (isDragging) {
isDragging = false;
dragTarget = null;
}
// Check difficulty button
else if (localPos.y >= 140 && localPos.y <= 180 && localPos.x >= -120 && localPos.x <= 120) {
tween(difficultyButton, {
scaleX: 0.8,
scaleY: 0.8
}, {
duration: 100
});
self.cycleDifficulty();
}
// Check close button
else if (localPos.y >= 220 && localPos.y <= 260 && localPos.x >= -90 && localPos.x <= 90) {
tween(closeButton, {
scaleX: 0.6,
scaleY: 0.6
}, {
duration: 100
});
self.onClose();
}
};
self.onClose = function () {
// Override this function when creating the panel
};
return self;
});
var Snake = Container.expand(function () {
var self = Container.call(this);
var graphic = self.attachAsset('snake', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 4;
self.direction = {
x: 0,
y: -1
};
self.bodySegments = []; // Array to store body segments
self.segmentSize = 80; // Size of each body segment
self.moveCounter = 0; // Counter to control movement timing
self.update = function () {
self.moveCounter++;
// Only move every few frames to make it more manageable
if (self.moveCounter >= 15) {
self.moveCounter = 0;
// Store previous position for body segments to follow
var previousPositions = [{
x: self.x,
y: self.y
}];
for (var i = 0; i < self.bodySegments.length; i++) {
previousPositions.push({
x: self.bodySegments[i].x,
y: self.bodySegments[i].y
});
}
// Move head
self.x += self.direction.x * self.segmentSize;
self.y += self.direction.y * self.segmentSize;
// Move body segments to follow the segment in front
for (var i = 0; i < self.bodySegments.length; i++) {
self.bodySegments[i].x = previousPositions[i].x;
self.bodySegments[i].y = previousPositions[i].y;
}
}
// Wrap around screen
if (self.x < 0) self.x = 2048;
if (self.x > 2048) self.x = 0;
if (self.y < 0) self.y = 2732;
if (self.y > 2732) self.y = 0;
};
self.grow = function () {
// Create a new body segment
var newSegment = game.addChild(LK.getAsset('snake', {
anchorX: 0.5,
anchorY: 0.5
}));
// Position it at the tail (or at head if no body exists)
if (self.bodySegments.length > 0) {
var lastSegment = self.bodySegments[self.bodySegments.length - 1];
newSegment.x = lastSegment.x;
newSegment.y = lastSegment.y;
} else {
newSegment.x = self.x;
newSegment.y = self.y;
}
// Make it slightly different color to distinguish from head
newSegment.tint = 0x95a5a6;
self.bodySegments.push(newSegment);
};
return self;
});
var TetrisBlock = Container.expand(function (color) {
var self = Container.call(this);
var graphic = self.attachAsset('customShape', {
anchorX: 0.5,
anchorY: 0.5
});
graphic.tint = color || 0x3498db;
self.blockColor = color || 0x3498db;
return self;
});
var TetrisPiece = Container.expand(function (type) {
var self = Container.call(this);
self.pieceType = type || 'I';
self.rotation = 0;
self.blocks = [];
self.gridX = 4;
self.gridY = 0;
// Define piece shapes
var pieceShapes = {
'I': [[1, 1, 1, 1]],
'O': [[1, 1], [1, 1]],
'T': [[0, 1, 0], [1, 1, 1]],
'S': [[0, 1, 1], [1, 1, 0]],
'Z': [[1, 1, 0], [0, 1, 1]],
'J': [[1, 0, 0], [1, 1, 1]],
'L': [[0, 0, 1], [1, 1, 1]]
};
var pieceColors = {
'I': 0x00bcd4,
'O': 0xffeb3b,
'T': 0x9c27b0,
'S': 0x4caf50,
'Z': 0xf44336,
'J': 0x2196f3,
'L': 0xff9800
};
self.shape = pieceShapes[type];
self.color = pieceColors[type];
self.createBlocks = function () {
// Clear existing blocks
for (var i = 0; i < self.blocks.length; i++) {
self.blocks[i].destroy();
}
self.blocks = [];
// Create new blocks based on shape
for (var row = 0; row < self.shape.length; row++) {
for (var col = 0; col < self.shape[row].length; col++) {
if (self.shape[row][col] === 1) {
var block = self.addChild(new TetrisBlock(self.color));
block.x = col * tetrisCellSize;
block.y = row * tetrisCellSize;
self.blocks.push(block);
}
}
}
};
self.rotate = function () {
// Rotate the shape array 90 degrees clockwise
var newShape = [];
var rows = self.shape.length;
var cols = self.shape[0].length;
for (var col = 0; col < cols; col++) {
newShape[col] = [];
for (var row = rows - 1; row >= 0; row--) {
newShape[col][rows - 1 - row] = self.shape[row][col];
}
}
self.shape = newShape;
self.rotation = (self.rotation + 1) % 4;
self.createBlocks();
};
self.getBlockPositions = function () {
var positions = [];
for (var row = 0; row < self.shape.length; row++) {
for (var col = 0; col < self.shape[row].length; col++) {
if (self.shape[row][col] === 1) {
positions.push({
x: self.gridX + col,
y: self.gridY + row
});
}
}
}
return positions;
};
self.canMoveTo = function (newX, newY) {
var positions = [];
for (var row = 0; row < self.shape.length; row++) {
for (var col = 0; col < self.shape[row].length; col++) {
if (self.shape[row][col] === 1) {
var x = newX + col;
var y = newY + row;
if (x < 0 || x >= tetrisGridWidth || y >= tetrisGridHeight) {
return false;
}
if (y >= 0 && tetrisGrid[y][x] !== 0) {
return false;
}
}
}
}
return true;
};
self.updatePosition = function () {
self.x = tetrisOffsetX + self.gridX * tetrisCellSize;
self.y = tetrisOffsetY + self.gridY * tetrisCellSize;
};
self.createBlocks();
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x1a1a2e
});
/****
* Game Code
****/
// Game state management
var currentGame = null;
var gameContainer = null;
var hubContainer = null;
var scoreText = null;
var backButton = null;
var settingsPanel = null;
var settingsButton = null;
// Game data
var games = [{
id: 'snake',
title: 'Snake',
category: 'Classic',
locked: false,
bestScore: storage.snakeBest || 0
}, {
id: 'circle',
title: 'Circle Tap',
category: 'Arcade',
locked: false,
bestScore: storage.circleBest || 0
}, {
id: 'breakout',
title: 'Breakout',
category: 'Classic',
locked: false,
bestScore: storage.breakoutBest || 0
}, {
id: 'platform',
title: 'Platformer',
category: 'Adventure',
locked: false,
bestScore: storage.platformBest || 0
}, {
id: 'maze',
title: 'Maze Runner',
category: 'Puzzle',
locked: false,
bestScore: storage.mazeBest || 0
}, {
id: 'dash',
title: 'Geometry Dash',
category: 'Arcade',
locked: false,
bestScore: storage.dashBest || 0
}, {
id: 'flappybird',
title: 'Flappy Bird',
category: 'Arcade',
locked: false,
bestScore: storage.flappyBirdBest || 0
}, {
id: 'multiplayer',
title: 'Multiplayer Mode',
category: 'Multiplayer',
locked: false,
bestScore: storage.multiplayerBest || 0
}, {
id: 'creator',
title: 'Level Creator',
category: 'Tools',
locked: false,
bestScore: 0
}, {
id: 'flyingcat',
title: 'Flying Cat',
category: 'Arcade',
locked: false,
bestScore: storage.flyingCatBest || 0
}, {
id: 'tetris',
title: 'Tetris',
category: 'Puzzle',
locked: false,
bestScore: storage.tetrisBest || 0
}];
var categories = ['All', 'Classic', 'Arcade', 'Adventure', 'Puzzle', 'Tools', 'Multiplayer'];
var currentCategory = 'All';
var gameCards = [];
var categoryButtons = [];
// Game variables
var snake = null;
var food = null;
var circles = [];
var ball = null;
var paddle = null;
var bricks = [];
var platforms = [];
var platformPlayer = null;
var maze = null;
var mazePlayer = null;
var coins = [];
var dashPlayer = null;
var dashObstacles = [];
var dashPortals = [];
var dashGameSpeed = 8;
var dashScore = 0;
var dashCameraX = 0;
var dashGroundY = 2400;
var gameCreator = null;
var customGameObjects = [];
var scrollBar = null;
// Multiplayer game variables
var multiplayerPlayers = [];
var multiplayerTargets = [];
var multiplayerGameMode = 'cooperative'; // 'cooperative' or 'competitive'
var multiplayerTimer = 0;
var multiplayerTimeLimit = 3600; // 60 seconds at 60fps
// Flappy bird game variables
var flappyBird = null;
var flappyPipes = [];
var flappyPipeTimer = 0;
// Flying cat game variables
var flyingCat = null;
var catObstacles = [];
var catPowerUps = [];
var catClouds = [];
var catGameSpeed = 4;
var flappyGapSize = 300;
// Tetris game variables
var tetrisGrid = null;
var currentPiece = null;
var nextPiece = null;
var tetrisDropTimer = 0;
var tetrisDropSpeed = 60;
var tetrisGridWidth = 10;
var tetrisGridHeight = 20;
var tetrisCellSize = 80;
var tetrisOffsetX = 400;
var tetrisOffsetY = 200;
var tetrisLines = 0;
var tetrisLevel = 1;
function initializeHub() {
hubContainer = new Container();
game.addChild(hubContainer);
// Add background
var bg = hubContainer.addChild(LK.getAsset('hubBackground', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0
}));
// Title
var titleText = new Text2('FRVR Games Hub', {
size: 80,
fill: 0xFFFFFF
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 1024;
titleText.y = 150;
hubContainer.addChild(titleText);
// Create category buttons
createCategoryButtons();
// Create scroll bar
scrollBar = hubContainer.addChild(new ScrollBar());
scrollBar.x = 1900;
scrollBar.y = 400;
// Create settings button
settingsButton = hubContainer.addChild(LK.getAsset('categoryButton', {
anchorX: 1,
anchorY: 0,
x: 1900,
y: 100,
scaleX: 0.7,
scaleY: 0.7
}));
settingsButton.tint = 0x74b9ff;
// Update scroll content
var settingsText = new Text2('Settings', {
size: 24,
fill: 0xFFFFFF
});
settingsText.anchor.set(0.5, 0.5);
settingsText.x = 1795;
settingsText.y = 128;
hubContainer.addChild(settingsText);
settingsButton.down = function () {
tween(settingsButton, {
scaleX: 0.65,
scaleY: 0.65
}, {
duration: 100
});
LK.getSound('tap').play();
};
function updateFlyingCatGame() {
if (!flyingCat || flyingCat.isDead) return;
// Spawn obstacles
if (LK.ticks % 180 === 0) {
// Every 3 seconds
var obstacleTypes = ['bird', 'cloud', 'storm'];
var obstacleType = obstacleTypes[Math.floor(Math.random() * obstacleTypes.length)];
var obstacle = gameContainer.addChild(new CatObstacle(obstacleType));
obstacle.x = 2200;
obstacle.y = 200 + Math.random() * 2000;
catObstacles.push(obstacle);
}
// Spawn power-ups occasionally
if (LK.ticks % 300 === 0) {
// Every 5 seconds
var powerUpTypes = ['fish', 'life'];
var powerUpType = powerUpTypes[Math.floor(Math.random() * powerUpTypes.length)];
var powerUp = gameContainer.addChild(new CatPowerUp(powerUpType));
powerUp.x = 2200;
powerUp.y = 300 + Math.random() * 1800;
catPowerUps.push(powerUp);
}
// Check obstacle collisions
for (var i = 0; i < catObstacles.length; i++) {
var obstacle = catObstacles[i];
if (flyingCat.intersects(obstacle)) {
flyingCat.takeDamage();
obstacle.destroy();
catObstacles.splice(i, 1);
break;
}
}
// Check power-up collisions
for (var i = catPowerUps.length - 1; i >= 0; i--) {
var powerUp = catPowerUps[i];
if (flyingCat.intersects(powerUp)) {
if (powerUp.powerType === 'fish') {
LK.setScore(LK.getScore() + 50);
} else if (powerUp.powerType === 'life') {
flyingCat.lives = Math.min(flyingCat.lives + 1, 5);
}
updateScoreDisplay();
LK.getSound('collect').play();
powerUp.destroy();
catPowerUps.splice(i, 1);
}
}
// Remove off-screen obstacles and power-ups
for (var i = catObstacles.length - 1; i >= 0; i--) {
if (catObstacles[i].shouldRemove) {
catObstacles[i].destroy();
catObstacles.splice(i, 1);
}
}
for (var i = catPowerUps.length - 1; i >= 0; i--) {
if (catPowerUps[i].shouldRemove) {
catPowerUps[i].destroy();
catPowerUps.splice(i, 1);
}
}
// Increase score over time
if (LK.ticks % 60 === 0) {
LK.setScore(LK.getScore() + 10);
updateScoreDisplay();
}
}
function updateTetrisGame() {
if (!currentPiece) return;
tetrisDropTimer++;
// Auto-drop piece
if (tetrisDropTimer >= tetrisDropSpeed) {
tetrisDropTimer = 0;
if (currentPiece.canMoveTo(currentPiece.gridX, currentPiece.gridY + 1)) {
currentPiece.gridY++;
currentPiece.updatePosition();
} else {
// Piece has landed, place it in grid
placeTetrisPieceInGrid();
}
}
}
function placeTetrisPieceInGrid() {
var positions = currentPiece.getBlockPositions();
// Place blocks in grid
for (var i = 0; i < positions.length; i++) {
var pos = positions[i];
if (pos.y >= 0) {
tetrisGrid[pos.y][pos.x] = currentPiece.color;
// Create static block
var block = gameContainer.addChild(new TetrisBlock(currentPiece.color));
block.x = tetrisOffsetX + pos.x * tetrisCellSize;
block.y = tetrisOffsetY + pos.y * tetrisCellSize;
}
}
// Check for completed lines
checkTetrisCompletedLines();
// Create new piece
var pieceTypes = ['I', 'O', 'T', 'S', 'Z', 'J', 'L'];
var randomType = pieceTypes[Math.floor(Math.random() * pieceTypes.length)];
currentPiece.destroy();
currentPiece = gameContainer.addChild(new TetrisPiece(randomType));
currentPiece.updatePosition();
// Check game over
if (!currentPiece.canMoveTo(currentPiece.gridX, currentPiece.gridY)) {
endCurrentGame();
}
}
function checkTetrisCompletedLines() {
var completedRows = [];
// Find completed rows
for (var row = 0; row < tetrisGridHeight; row++) {
var isComplete = true;
for (var col = 0; col < tetrisGridWidth; col++) {
if (tetrisGrid[row][col] === 0) {
isComplete = false;
break;
}
}
if (isComplete) {
completedRows.push(row);
}
}
// Remove completed rows and add score
if (completedRows.length > 0) {
tetrisLines += completedRows.length;
var points = completedRows.length * 100 * tetrisLevel; // Multiply by level
LK.setScore(LK.getScore() + points);
updateScoreDisplay();
// Remove completed rows from grid
for (var i = completedRows.length - 1; i >= 0; i--) {
var row = completedRows[i];
tetrisGrid.splice(row, 1);
tetrisGrid.unshift(new Array(tetrisGridWidth).fill(0));
}
// Increase level every 10 lines and speed up
tetrisLevel = Math.floor(tetrisLines / 10) + 1;
tetrisDropSpeed = Math.max(5, 60 - tetrisLevel * 5);
LK.getSound('collect').play();
}
}
settingsButton.up = function () {
tween(settingsButton, {
scaleX: 0.7,
scaleY: 0.7
}, {
duration: 100
});
showSettingsPanel();
};
// Create game cards
createGameCards();
updateScrollContent();
}
function createCategoryButtons() {
categoryButtons = [];
for (var i = 0; i < categories.length; i++) {
var category = categories[i];
var isActive = category === currentCategory;
var btn = hubContainer.addChild(new CategoryButton(category, isActive));
btn.x = 150 + i * 320;
if (category === 'Multiplayer') {
btn.x = 400; // Move multiplayer category more to the left
btn.y = 2500; // Move multiplayer category higher on bottom screen
} else if (category === 'Tools') {
btn.x = 800; // Position tools category on bottom screen
btn.y = 2500; // Move tools category to bottom screen
} else {
btn.y = 250; // Keep other categories on screen
}
categoryButtons.push(btn);
}
}
function createGameCards() {
gameCards = [];
for (var i = 0; i < games.length; i++) {
var gameInfo = games[i];
var card = hubContainer.addChild(new GameCard(gameInfo));
card.visible = false; // Start hidden, will be shown by updateGameCardPositions
gameCards.push(card);
}
updateGameCardPositions();
}
function updateGameCardPositions() {
var visibleGames = getFilteredGames();
var cardsPerRow = 4;
var cardSpacing = 450;
var rowSpacing = 400;
var startX = 300;
var startY = 500;
// Hide all cards first
for (var i = 0; i < gameCards.length; i++) {
gameCards[i].visible = false;
}
// Position visible cards
for (var i = 0; i < visibleGames.length; i++) {
var gameInfo = visibleGames[i];
var card = findGameCard(gameInfo.id);
if (card) {
card.visible = true;
var row = Math.floor(i / cardsPerRow);
var col = i % cardsPerRow;
card.x = startX + col * cardSpacing;
card.y = startY + row * rowSpacing - scrollBar.scrollPosition;
// Ensure cards stay within proper view bounds with better margins
if (card.y < 350 || card.y > 2400) {
card.visible = false;
}
}
}
}
function findGameCard(gameId) {
for (var i = 0; i < gameCards.length; i++) {
if (gameCards[i].gameInfo.id === gameId) {
return gameCards[i];
}
}
return null;
}
function getFilteredGames() {
if (currentCategory === 'All') {
return games;
}
var filtered = [];
for (var i = 0; i < games.length; i++) {
if (games[i].category === currentCategory) {
filtered.push(games[i]);
}
}
return filtered;
}
function filterGamesByCategory(category) {
currentCategory = category;
// Update category button states
for (var i = 0; i < categoryButtons.length; i++) {
categoryButtons[i].setActive(categoryButtons[i].categoryName === category);
}
updateGameCardPositions();
updateScrollContent();
}
function updateScrollContent() {
var visibleGames = getFilteredGames();
var cardsPerRow = 4;
var rows = Math.ceil(visibleGames.length / cardsPerRow);
var contentHeight = rows * 400 + 800;
scrollBar.setContentHeight(contentHeight);
}
function switchToGame(gameId) {
currentGame = gameId;
// Hide hub
if (hubContainer) {
hubContainer.visible = false;
}
// Create game container
gameContainer = new Container();
game.addChild(gameContainer);
// Create back button
createBackButton();
// Initialize specific game
if (gameId === 'snake') {
initializeSnakeGame();
} else if (gameId === 'circle') {
initializeCircleGame();
} else if (gameId === 'breakout') {
initializeBreakoutGame();
} else if (gameId === 'platform') {
initializePlatformGame();
} else if (gameId === 'maze') {
initializeMazeGame();
} else if (gameId === 'dash') {
initializeDashGame();
} else if (gameId === 'flappybird') {
initializeFlappyBirdGame();
} else if (gameId === 'multiplayer') {
initializeMultiplayerGame();
} else if (gameId === 'creator') {
initializeCreatorGame();
} else if (gameId === 'flyingcat') {
initializeFlyingCatGame();
} else if (gameId === 'tetris') {
initializeTetrisGame();
}
// Create score display
createScoreDisplay();
// Apply difficulty settings
applyDifficultySettings();
}
function createBackButton() {
backButton = LK.gui.topRight.addChild(LK.getAsset('categoryButton', {
anchorX: 1,
anchorY: 0,
x: -20,
y: 20,
scaleX: 0.6,
scaleY: 0.6
}));
var backText = new Text2('Hub', {
size: 28,
fill: 0xFFFFFF
});
backText.anchor.set(0.5, 0.5);
backText.x = backButton.x - backButton.width * 0.3;
backText.y = backButton.y + backButton.height * 0.3;
LK.gui.topRight.addChild(backText);
backButton.down = function () {
tween(backButton, {
scaleX: 0.55,
scaleY: 0.55
}, {
duration: 100
});
LK.getSound('tap').play();
};
backButton.up = function () {
tween(backButton, {
scaleX: 0.6,
scaleY: 0.6
}, {
duration: 100
});
returnToHub();
};
}
function createScoreDisplay() {
scoreText = new Text2('Score: 0', {
size: 48,
fill: 0xFFFFFF
});
scoreText.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreText);
}
function updateScoreDisplay() {
if (scoreText) {
scoreText.setText('Score: ' + LK.getScore());
}
}
function returnToHub() {
// Clean up current game
endCurrentGame();
// Show hub
if (hubContainer) {
hubContainer.visible = true;
}
// Remove back button and score
if (backButton) {
backButton.destroy();
backButton = null;
}
if (scoreText) {
scoreText.destroy();
scoreText = null;
}
currentGame = null;
}
function endCurrentGame() {
// Save high score
saveHighScore();
// Clean up game objects
cleanupGameObjects();
// Remove game container
if (gameContainer) {
gameContainer.destroy();
gameContainer = null;
}
// Reset score
LK.setScore(0);
}
function saveHighScore() {
if (!currentGame) return;
var currentScore = LK.getScore();
var gameInfo = findGameInfo(currentGame);
if (gameInfo && currentScore > gameInfo.bestScore) {
gameInfo.bestScore = currentScore;
storage[currentGame + 'Best'] = currentScore;
// Update game card
var card = findGameCard(currentGame);
if (card) {
card.updateScore(currentScore);
}
}
}
function findGameInfo(gameId) {
for (var i = 0; i < games.length; i++) {
if (games[i].id === gameId) {
return games[i];
}
}
return null;
}
function cleanupGameObjects() {
// Reset all game variables
snake = null;
food = null;
circles = [];
ball = null;
paddle = null;
bricks = [];
platforms = [];
platformPlayer = null;
maze = null;
mazePlayer = null;
coins = [];
dashPlayer = null;
dashObstacles = [];
dashPortals = [];
gameCreator = null;
customGameObjects = [];
// Multiplayer cleanup
multiplayerPlayers = [];
multiplayerTargets = [];
multiplayerTimer = 0;
// Flappy bird cleanup
flappyBird = null;
flappyPipes = [];
flappyPipeTimer = 0;
// Flying cat cleanup
flyingCat = null;
catObstacles = [];
catPowerUps = [];
catClouds = [];
// Tetris cleanup
tetrisGrid = null;
currentPiece = null;
nextPiece = null;
tetrisDropTimer = 0;
tetrisLines = 0;
tetrisLevel = 1;
}
// Game initialization functions
function initializeSnakeGame() {
game.setBackgroundColor(0x2c3e50);
snake = gameContainer.addChild(new Snake());
snake.x = 1024;
snake.y = 1366;
food = gameContainer.addChild(new Food());
LK.setScore(0);
updateScoreDisplay();
}
function initializeCircleGame() {
game.setBackgroundColor(0x2d3436);
circles = [];
LK.setScore(0);
updateScoreDisplay();
}
function initializeBreakoutGame() {
game.setBackgroundColor(0x000000);
// Create paddle
paddle = gameContainer.addChild(new Paddle());
// Create ball
ball = gameContainer.addChild(new Ball());
ball.x = 1024;
ball.y = 2500;
// Create bricks
bricks = [];
for (var row = 0; row < 6; row++) {
for (var col = 0; col < 10; col++) {
var brick = gameContainer.addChild(new Brick());
brick.x = 200 + col * 165;
brick.y = 300 + row * 80;
bricks.push(brick);
}
}
LK.setScore(0);
updateScoreDisplay();
}
function initializePlatformGame() {
var bg = gameContainer.addChild(LK.getAsset('gameBackground1', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0
}));
// Create platforms
platforms = [];
var platformData = [{
x: 300,
y: 2600,
width: 400
}, {
x: 800,
y: 2400,
width: 200
}, {
x: 1200,
y: 2200,
width: 300
}, {
x: 400,
y: 2000,
width: 250
}, {
x: 1000,
y: 1800,
width: 200
}, {
x: 600,
y: 1600,
width: 350
}];
for (var i = 0; i < platformData.length; i++) {
var data = platformData[i];
var platform = gameContainer.addChild(new Platform());
platform.x = data.x;
platform.y = data.y;
if (data.width) {
platform.scaleX = data.width / 200;
}
platforms.push(platform);
}
// Create coins
coins = [];
var coinPositions = [{
x: 800,
y: 2300
}, {
x: 1200,
y: 2100
}, {
x: 400,
y: 1900
}, {
x: 1000,
y: 1700
}, {
x: 600,
y: 1500
}];
for (var i = 0; i < coinPositions.length; i++) {
var pos = coinPositions[i];
var coin = gameContainer.addChild(new Coin());
coin.x = pos.x;
coin.y = pos.y;
coin.startY = pos.y;
coins.push(coin);
}
// Create player
platformPlayer = gameContainer.addChild(new PlatformPlayer());
platformPlayer.x = 300;
platformPlayer.y = 2500;
LK.setScore(0);
updateScoreDisplay();
}
function initializeMazeGame() {
game.setBackgroundColor(0x34495e);
// Create simple maze layout
var mazeLayout = [[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1], [1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1], [1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]];
maze = mazeLayout;
// Create walls
for (var row = 0; row < maze.length; row++) {
for (var col = 0; col < maze[row].length; col++) {
if (maze[row][col] === 1) {
var wall = gameContainer.addChild(new MazeWall());
wall.x = col * 80 + 40;
wall.y = row * 80 + 40 + 200;
}
}
}
// Create exit
var exit = gameContainer.addChild(LK.getAsset('mazeExit', {
anchorX: 0.5,
anchorY: 0.5,
x: 23 * 80 + 40,
y: 7 * 80 + 40 + 200
}));
// Create player
mazePlayer = gameContainer.addChild(new MazePlayer());
mazePlayer.moveToGrid(1, 1);
LK.setScore(0);
updateScoreDisplay();
}
function initializeDashGame() {
var bg = gameContainer.addChild(LK.getAsset('gameBackground2', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0
}));
// Create player
dashPlayer = gameContainer.addChild(new DashPlayer());
dashPlayer.x = 300;
dashPlayer.y = dashGroundY - 100;
// Initialize game variables
dashObstacles = [];
dashPortals = [];
dashScore = 0;
dashCameraX = 0;
LK.setScore(0);
updateScoreDisplay();
}
function initializeMultiplayerGame() {
game.setBackgroundColor(0x2c3e50);
// Create two players
multiplayerPlayers = [];
var player1 = gameContainer.addChild(new MultiplayerPlayer(1, 0x3498db)); // Blue
player1.x = 400;
player1.y = 1366;
multiplayerPlayers.push(player1);
var player2 = gameContainer.addChild(new MultiplayerPlayer(2, 0xe74c3c)); // Red
player2.x = 1600;
player2.y = 1366;
multiplayerPlayers.push(player2);
// Initialize game variables
multiplayerTargets = [];
multiplayerTimer = 0;
multiplayerGameMode = 'cooperative';
LK.setScore(0);
updateScoreDisplay();
}
function initializeCreatorGame() {
var bg = gameContainer.addChild(LK.getAsset('creatorBackground', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0
}));
gameCreator = new GameCreator();
var toolbar = gameCreator.createToolbar();
gameContainer.addChild(toolbar);
LK.setScore(0);
updateScoreDisplay();
}
function showSettingsPanel() {
if (settingsPanel) return;
settingsPanel = hubContainer.addChild(new SettingsPanel());
settingsPanel.x = 1024;
settingsPanel.y = 1366;
settingsPanel.onClose = function () {
hideSettingsPanel();
};
// Disable other hub interactions
if (scrollBar) scrollBar.visible = false;
for (var i = 0; i < gameCards.length; i++) {
gameCards[i].visible = false;
}
for (var i = 0; i < categoryButtons.length; i++) {
categoryButtons[i].visible = false;
}
}
function hideSettingsPanel() {
if (settingsPanel) {
settingsPanel.destroy();
settingsPanel = null;
}
// Re-enable hub interactions
if (scrollBar) scrollBar.visible = true;
updateGameCardPositions();
for (var i = 0; i < categoryButtons.length; i++) {
categoryButtons[i].visible = true;
}
}
function applyDifficultySettings() {
// Apply difficulty settings to current game
if (currentGame === 'snake' && snake) {
// Adjust snake speed based on difficulty
var speedMultiplier = storage.difficulty === 'easy' ? 0.7 : storage.difficulty === 'hard' ? 1.5 : 1.0;
snake.speed = snake.speed * speedMultiplier;
}
if (currentGame === 'dash' && dashPlayer) {
// Adjust dash game speed based on difficulty
var dashSpeedMultiplier = storage.difficulty === 'easy' ? 0.8 : storage.difficulty === 'hard' ? 1.3 : 1.0;
dashGameSpeed = 8 * dashSpeedMultiplier;
}
}
// Initialize the hub
initializeHub();
// Event handlers
game.down = function (x, y, obj) {
if (!currentGame) {
// Hub navigation
if (settingsPanel) {
// Settings panel is open, handle its interactions
return;
}
if (scrollBar && scrollBar.visible) {
var oldScrollPosition = scrollBar.scrollPosition;
scrollBar.down(x, y, obj);
if (scrollBar.scrollPosition !== oldScrollPosition) {
updateGameCardPositions();
}
}
} else {
// Game-specific controls
if (currentGame === 'snake') {
// Touch controls for snake direction
var dx = x - snake.x;
var dy = y - snake.y;
if (Math.abs(dx) > Math.abs(dy)) {
snake.direction = dx > 0 ? {
x: 1,
y: 0
} : {
x: -1,
y: 0
};
} else {
snake.direction = dy > 0 ? {
x: 0,
y: 1
} : {
x: 0,
y: -1
};
}
} else if (currentGame === 'platform') {
// Touch controls for platformer
if (x < 1024) {
platformPlayer.moveLeft();
} else {
platformPlayer.moveRight();
}
if (y > 2000) {
platformPlayer.jump();
}
} else if (currentGame === 'maze') {
// Touch controls for maze
var dx = x - mazePlayer.x;
var dy = y - mazePlayer.y;
var newGridX = mazePlayer.gridX;
var newGridY = mazePlayer.gridY;
if (Math.abs(dx) > Math.abs(dy)) {
newGridX += dx > 0 ? 1 : -1;
} else {
newGridY += dy > 0 ? 1 : -1;
}
if (newGridX >= 0 && newGridX < maze[0].length && newGridY >= 0 && newGridY < maze.length && maze[newGridY][newGridX] === 0) {
mazePlayer.moveToGrid(newGridX, newGridY);
}
} else if (currentGame === 'dash') {
if (dashPlayer.gameMode === 'cube') {
dashPlayer.jump();
} else if (dashPlayer.gameMode === 'ship') {
dashPlayer.hold();
}
} else if (currentGame === 'flappybird') {
if (flappyBird) {
flappyBird.flap();
}
} else if (currentGame === 'flyingcat') {
if (flyingCat) {
flyingCat.flap();
}
} else if (currentGame === 'multiplayer') {
// Handle multiplayer controls - players move towards touch point
for (var i = 0; i < multiplayerPlayers.length; i++) {
var player = multiplayerPlayers[i];
// In cooperative mode, both players move to the same point
// In competitive mode, alternate which player moves
if (multiplayerGameMode === 'cooperative' || i === LK.ticks % multiplayerPlayers.length) {
player.moveTowards(x, y);
}
}
} else if (currentGame === 'creator') {
gameCreator.handleToolClick(x, y);
gameCreator.handleCanvasClick(x, y);
} else if (currentGame === 'tetris') {
// Touch controls for Tetris
if (currentPiece) {
if (x < 1024) {
// Left side - move left or rotate
if (y > 2000) {
// Bottom area - move left
if (currentPiece.canMoveTo(currentPiece.gridX - 1, currentPiece.gridY)) {
currentPiece.gridX--;
currentPiece.updatePosition();
}
} else {
// Top area - rotate
var oldShape = currentPiece.shape;
var oldRotation = currentPiece.rotation;
currentPiece.rotate();
if (!currentPiece.canMoveTo(currentPiece.gridX, currentPiece.gridY)) {
// Rotation failed, revert
currentPiece.shape = oldShape;
currentPiece.rotation = oldRotation;
currentPiece.createBlocks();
}
}
} else {
// Right side - move right or drop
if (y > 2000) {
// Bottom area - move right
if (currentPiece.canMoveTo(currentPiece.gridX + 1, currentPiece.gridY)) {
currentPiece.gridX++;
currentPiece.updatePosition();
}
} else {
// Top area - hard drop piece
while (currentPiece.canMoveTo(currentPiece.gridX, currentPiece.gridY + 1)) {
currentPiece.gridY++;
}
currentPiece.updatePosition();
placeTetrisPieceInGrid();
}
}
}
}
}
LK.getSound('tap').play();
};
game.up = function (x, y, obj) {
if (currentGame === 'dash' && dashPlayer && dashPlayer.gameMode === 'ship') {
dashPlayer.release();
}
};
game.move = function (x, y, obj) {
if (currentGame === 'breakout' && paddle) {
paddle.x = x;
if (paddle.x < 100) paddle.x = 100;
if (paddle.x > 1948) paddle.x = 1948;
}
};
game.update = function () {
if (!currentGame) {
// Hub update
return;
}
// Game-specific updates
if (currentGame === 'snake') {
updateSnakeGame();
} else if (currentGame === 'circle') {
updateCircleGame();
} else if (currentGame === 'breakout') {
updateBreakoutGame();
} else if (currentGame === 'platform') {
updatePlatformGame();
} else if (currentGame === 'maze') {
updateMazeGame();
} else if (currentGame === 'dash') {
updateDashGame();
} else if (currentGame === 'flappybird') {
updateFlappyBirdGame();
} else if (currentGame === 'multiplayer') {
updateMultiplayerGame();
} else if (currentGame === 'flyingcat') {
updateFlyingCatGame();
} else if (currentGame === 'tetris') {
updateTetrisGame();
}
};
function updateSnakeGame() {
// Check food collision
if (snake && food && snake.intersects(food)) {
LK.setScore(LK.getScore() + 10);
updateScoreDisplay();
snake.grow();
food.destroy();
food = gameContainer.addChild(new Food());
LK.getSound('collect').play();
}
}
function updateCircleGame() {
// Spawn circles
if (LK.ticks % 90 === 0) {
var circle = gameContainer.addChild(new Circle());
circle.x = 100 + Math.random() * 1848;
circle.y = 100 + Math.random() * 2532;
circles.push(circle);
}
// Remove expired circles
for (var i = circles.length - 1; i >= 0; i--) {
if (circles[i].shouldRemove) {
circles[i].destroy();
circles.splice(i, 1);
}
}
}
function updateBreakoutGame() {
// Check brick collisions
for (var i = bricks.length - 1; i >= 0; i--) {
if (ball && ball.intersects(bricks[i])) {
ball.speedY = -ball.speedY;
bricks[i].destroy();
bricks.splice(i, 1);
LK.setScore(LK.getScore() + 10);
updateScoreDisplay();
LK.getSound('collect').play();
if (bricks.length === 0) {
LK.showYouWin();
}
}
}
}
function updatePlatformGame() {
// Check platform collisions for player
if (platformPlayer) {
platformPlayer.onGround = false;
for (var i = 0; i < platforms.length; i++) {
var platform = platforms[i];
if (platformPlayer.intersects(platform) && platformPlayer.lastY <= platform.y - platform.height * platform.scaleY / 2 && platformPlayer.velocityY > 0) {
platformPlayer.y = platform.y - platform.height * platform.scaleY / 2 - platformPlayer.height / 2;
platformPlayer.velocityY = 0;
platformPlayer.onGround = true;
break;
}
}
// Check coin collisions
for (var i = coins.length - 1; i >= 0; i--) {
var coin = coins[i];
if (platformPlayer.intersects(coin)) {
LK.setScore(LK.getScore() + 100);
updateScoreDisplay();
coin.destroy();
coins.splice(i, 1);
LK.getSound('collect').play();
if (coins.length === 0) {
LK.showYouWin();
}
}
}
}
}
function updateMazeGame() {
if (mazePlayer) {
// Check if reached exit
if (mazePlayer.gridX === 23 && mazePlayer.gridY === 7) {
LK.setScore(LK.getScore() + 1000);
updateScoreDisplay();
LK.showYouWin();
}
}
}
function updateMultiplayerGame() {
multiplayerTimer++;
// Switch game modes every 10 seconds
if (multiplayerTimer % 600 === 0) {
multiplayerGameMode = multiplayerGameMode === 'cooperative' ? 'competitive' : 'cooperative';
}
// Spawn targets
if (LK.ticks % 120 === 0) {
var target = gameContainer.addChild(new MultiplayerTarget());
multiplayerTargets.push(target);
}
// Check target collisions
for (var i = multiplayerTargets.length - 1; i >= 0; i--) {
var target = multiplayerTargets[i];
var targetHit = false;
for (var j = 0; j < multiplayerPlayers.length; j++) {
var player = multiplayerPlayers[j];
if (player.intersects(target)) {
if (multiplayerGameMode === 'cooperative') {
// Both players get points in cooperative mode
LK.setScore(LK.getScore() + 10);
} else {
// Only the hitting player gets points in competitive mode
player.score += 10;
LK.setScore(LK.getScore() + 10);
}
updateScoreDisplay();
target.destroy();
multiplayerTargets.splice(i, 1);
targetHit = true;
LK.getSound('collect').play();
break;
}
}
}
// Remove expired targets
for (var i = multiplayerTargets.length - 1; i >= 0; i--) {
if (multiplayerTargets[i].shouldRemove) {
multiplayerTargets[i].destroy();
multiplayerTargets.splice(i, 1);
}
}
// Game over condition
if (multiplayerTimer >= multiplayerTimeLimit) {
LK.showYouWin();
}
}
function updateDashGame() {
if (!dashPlayer || dashPlayer.isDead) return;
dashScore++;
LK.setScore(Math.floor(dashScore / 10));
updateScoreDisplay();
// Spawn obstacles
if (LK.ticks % 60 === 0) {
var obstacleType = Math.random() < 0.7 ? 'block' : 'spike';
var obstacle = gameContainer.addChild(new DashObstacle(obstacleType));
obstacle.x = 2200;
obstacle.y = dashGroundY - 40;
dashObstacles.push(obstacle);
}
// Spawn portals occasionally
if (LK.ticks % 300 === 0) {
var portalTypes = ['cube', 'ship', 'ball', 'wave'];
var portalType = portalTypes[Math.floor(Math.random() * portalTypes.length)];
var portal = gameContainer.addChild(new DashPortal(portalType));
portal.x = 2200;
portal.y = dashGroundY - 100;
dashPortals.push(portal);
}
// Check obstacle collisions
for (var i = 0; i < dashObstacles.length; i++) {
var obstacle = dashObstacles[i];
if (dashPlayer.intersects(obstacle)) {
dashPlayer.die();
break;
}
}
// Check portal collisions
for (var i = dashPortals.length - 1; i >= 0; i--) {
var portal = dashPortals[i];
if (dashPlayer.intersects(portal)) {
dashPlayer.changeMode(portal.portalType);
portal.destroy();
dashPortals.splice(i, 1);
LK.getSound('collect').play();
}
}
// Ground collision for cube mode
if (dashPlayer.gameMode === 'cube' && dashPlayer.y >= dashGroundY - 30) {
dashPlayer.y = dashGroundY - 30;
dashPlayer.velocityY = 0;
dashPlayer.isGrounded = true;
}
// Remove off-screen obstacles
for (var i = dashObstacles.length - 1; i >= 0; i--) {
if (dashObstacles[i].shouldRemove) {
dashObstacles[i].destroy();
dashObstacles.splice(i, 1);
}
}
for (var i = dashPortals.length - 1; i >= 0; i--) {
if (dashPortals[i].shouldRemove) {
dashPortals[i].destroy();
dashPortals.splice(i, 1);
}
}
}
LK.playMusic('bgMusic', {
volume: storage.musicVolume
});
// Override sound play to apply volume settings
var originalGetSound = LK.getSound;
LK.getSound = function (soundId) {
var sound = originalGetSound(soundId);
var originalPlay = sound.play;
sound.play = function () {
// Apply volume from settings
var result = originalPlay.call(this);
if (this.volume !== undefined) {
this.volume *= storage.soundVolume;
}
return result;
};
return sound;
};
function initializeFlappyBirdGame() {
game.setBackgroundColor(0x87ceeb);
// Create bird
flappyBird = gameContainer.addChild(new FlappyBird());
flappyBird.x = 400;
flappyBird.y = 1366;
// Initialize game variables
flappyPipes = [];
flappyPipeTimer = 0;
LK.setScore(0);
updateScoreDisplay();
}
function initializeFlyingCatGame() {
game.setBackgroundColor(0x87ceeb);
// Create flying cat
flyingCat = gameContainer.addChild(new FlyingCat());
flyingCat.x = 400;
flyingCat.y = 1366;
// Initialize game variables
catObstacles = [];
catPowerUps = [];
catClouds = [];
catGameSpeed = 4;
LK.setScore(0);
updateScoreDisplay();
}
function initializeTetrisGame() {
game.setBackgroundColor(0x2c3e50);
// Initialize grid
tetrisGrid = [];
for (var row = 0; row < tetrisGridHeight; row++) {
tetrisGrid[row] = [];
for (var col = 0; col < tetrisGridWidth; col++) {
tetrisGrid[row][col] = 0;
}
}
// Draw grid background
for (var row = 0; row < tetrisGridHeight; row++) {
for (var col = 0; col < tetrisGridWidth; col++) {
var gridCell = gameContainer.addChild(LK.getAsset('customShape', {
anchorX: 0.5,
anchorY: 0.5,
x: tetrisOffsetX + col * tetrisCellSize,
y: tetrisOffsetY + row * tetrisCellSize
}));
gridCell.tint = 0x34495e;
gridCell.alpha = 0.3;
}
}
// Create first piece
var pieceTypes = ['I', 'O', 'T', 'S', 'Z', 'J', 'L'];
var randomType = pieceTypes[Math.floor(Math.random() * pieceTypes.length)];
currentPiece = gameContainer.addChild(new TetrisPiece(randomType));
currentPiece.updatePosition();
// Create next piece preview
var nextType = pieceTypes[Math.floor(Math.random() * pieceTypes.length)];
nextPiece = new TetrisPiece(nextType);
// Initialize game variables
tetrisDropTimer = 0;
tetrisLines = 0;
tetrisLevel = 1;
tetrisDropSpeed = 60;
LK.setScore(0);
updateScoreDisplay();
}
function updateFlappyBirdGame() {
if (!flappyBird || flappyBird.isDead) return;
flappyPipeTimer++;
// Spawn pipes every 2 seconds
if (flappyPipeTimer % 120 === 0) {
var gapY = 400 + Math.random() * 1500;
var topPipe = gameContainer.addChild(new FlappyPipe(true, gapY));
var bottomPipe = gameContainer.addChild(new FlappyPipe(false, gapY));
topPipe.x = 2200;
bottomPipe.x = 2200;
flappyPipes.push(topPipe);
flappyPipes.push(bottomPipe);
}
// Check pipe collisions and scoring
for (var i = flappyPipes.length - 1; i >= 0; i--) {
var pipe = flappyPipes[i];
if (flappyBird.intersects(pipe)) {
flappyBird.die();
break;
}
// Score when bird passes through pipes
if (!pipe.passed && pipe.x < flappyBird.x) {
pipe.passed = true;
// Only count score for bottom pipes to avoid double counting
if (pipe.y > 1366) {
LK.setScore(LK.getScore() + 1);
updateScoreDisplay();
LK.getSound('collect').play();
}
}
}
// Remove off-screen pipes
for (var i = flappyPipes.length - 1; i >= 0; i--) {
if (flappyPipes[i].shouldRemove) {
flappyPipes[i].destroy();
flappyPipes.splice(i, 1);
}
}
}
Lock. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
Bricks and sky. In-Game asset. 2d. High contrast. No shadows
Stars. In-Game asset. 2d. High contrast. No shadows
Paddle. In-Game asset. 2d. High contrast. No shadows
Brick. In-Game asset. 2d. High contrast. No shadows
A Roblox noob. In-Game asset. 2d. High contrast. No shadows
Platform. In-Game asset. 2d. High contrast. No shadows
Coin. In-Game asset. 2d. High contrast. No shadows
Wall. In-Game asset. 2d. High contrast. No shadows
Game hub. In-Game asset. 2d. High contrast. No shadows
Snake. In-Game asset. 2d. High contrast. No shadows
Ball. In-Game asset. 2d. High contrast. No shadows
Paint brush. In-Game asset. 2d. High contrast. No shadows
Dash. In-Game asset. 2d. High contrast. No shadows
Robot. In-Game asset. 2d. High contrast. No shadows
Game hub with a black background. In-Game asset. 2d. High contrast. No shadows
Flappy bird. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
Enemy. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat