/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Molecule = Container.expand(function (type) {
var self = Container.call(this);
self.type = type || 'glucose';
self.value = type === 'glucose' ? 10 : type === 'aminoAcid' ? 8 : 12;
var graphics = self.attachAsset(self.type, {
anchorX: 0.5,
anchorY: 0.5
});
// Gentle floating animation
self.floatOffset = Math.random() * Math.PI * 2;
self.floatSpeed = 0.02 + Math.random() * 0.02;
self.update = function () {
graphics.y += Math.sin(LK.ticks * self.floatSpeed + self.floatOffset) * 0.5;
graphics.x += Math.cos(LK.ticks * self.floatSpeed * 0.7 + self.floatOffset) * 0.3;
// Proximity glow effect when E.L.Y.S. is near
if (elys) {
var distance = Math.sqrt(Math.pow(self.x - elys.x, 2) + Math.pow(self.y - elys.y, 2));
if (distance < 120) {
var glowIntensity = 1 - distance / 120;
graphics.alpha = 0.8 + glowIntensity * 0.5;
graphics.scaleX = graphics.scaleY = 1 + glowIntensity * 0.3;
} else {
graphics.alpha = 0.8;
graphics.scaleX = graphics.scaleY = 1;
}
}
};
return self;
});
var Organelle = Container.expand(function (type, x, y) {
var self = Container.call(this);
self.type = type;
self.energyRate = type === 'mitochondria' ? 2 : 1;
self.active = false;
var graphics = self.attachAsset(self.type, {
anchorX: 0.5,
anchorY: 0.5
});
self.x = x;
self.y = y;
graphics.alpha = 0.7;
self.activate = function () {
self.active = true;
graphics.alpha = 1.0;
tween(graphics, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 200,
easing: tween.easeOut
});
tween(graphics, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 200,
easing: tween.easeIn
});
};
self.update = function () {
if (self.active && LK.ticks % 60 === 0) {
// Generate energy periodically
currentATP = Math.min(maxATP, currentATP + self.energyRate);
}
};
return self;
});
var Toxin = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('toxin', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 1 + Math.random() * 2;
self.direction = Math.random() * Math.PI * 2;
self.damage = 15;
self.update = function () {
self.x += Math.cos(self.direction) * self.speed;
self.y += Math.sin(self.direction) * self.speed;
// Bounce off edges
if (self.x < 50 || self.x > 1998) {
self.direction = Math.PI - self.direction;
}
if (self.y < 50 || self.y > 2682) {
self.direction = -self.direction;
}
// Keep in bounds
self.x = Math.max(50, Math.min(1998, self.x));
self.y = Math.max(50, Math.min(2682, self.y));
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x001122
});
/****
* Game Code
****/
// Game state management
var gameState = 'playing'; // 'mainMenu', 'intro', 'playing', 'paused'
var currentLevel = 1;
var levelNames = ['Cytoplasm Caverns', 'Mitochondrial Core', 'Nucleus Nexus', 'Photosynthesis Fields', 'Energy Restoration'];
// Main Menu Elements
var titleText = new Text2('E.L.Y.S.', {
size: 180,
fill: '#00FFFF'
});
var subtitleText = new Text2('Energy Linking Your System', {
size: 60,
fill: '#88AAFF'
});
var beginButton = LK.getAsset('elys', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 0.8,
tint: 0x00AA88
});
var continueButton = LK.getAsset('elys', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 0.8,
tint: 0xAA8800
});
var aboutButton = LK.getAsset('elys', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 0.8,
tint: 0x8800AA
});
var beginText = new Text2('Begin Journey', {
size: 48,
fill: '#FFFFFF'
});
var continueText = new Text2('Continue', {
size: 48,
fill: '#FFFFFF'
});
var aboutText = new Text2('About E.L.Y.S.', {
size: 48,
fill: '#FFFFFF'
});
// Add exit text for exit functionality
var exitText = new Text2('Exit Game', {
size: 48,
fill: '#FFFFFF'
});
// Story text elements
var storyText = new Text2('', {
size: 40,
fill: '#CCCCFF'
});
// Dynamic space background variables with exciting colors
var backgroundPhase = 0;
var backgroundColors = [0x0a0040, 0x1a0080, 0x2010a0, 0x4020c0, 0x6030e0, 0x8040ff, 0xa060ff, 0xc080ff];
var starField = [];
var nebulaClouds = [];
// Game state variables
var currentATP = 50;
var maxATP = 100;
var glucoseCount = 0;
var aminoAcidCount = 0;
var lipidCount = 0;
var worldBrightness = 0.2;
var level = 1;
// Game objects
var elys;
var molecules = [];
var organelles = [];
var toxins = [];
var dragNode = null;
// UI Elements - Futuristic ATP Bar
var atpBarBackground = LK.getAsset('glucose', {
anchorX: 0,
anchorY: 0,
scaleX: 4,
scaleY: 0.4,
tint: 0x112233
});
var atpBar = LK.getAsset('glucose', {
anchorX: 0,
anchorY: 0,
scaleX: 4,
scaleY: 0.4,
tint: 0x00AAFF
});
var atpGlow = LK.getAsset('glucose', {
anchorX: 0,
anchorY: 0,
scaleX: 4,
scaleY: 0.4,
tint: 0x00FFFF,
alpha: 0.5
});
var atpText = new Text2('ATP: 50/100', {
size: 45,
fill: '#00FFFF'
});
// Modern resource display with icons
var glucoseIcon = LK.getAsset('glucose', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.9,
scaleY: 0.9
});
var aminoIcon = LK.getAsset('aminoAcid', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.9,
scaleY: 0.9
});
var lipidIcon = LK.getAsset('lipid', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.9,
scaleY: 0.9
});
var glucoseText = new Text2('0', {
size: 38,
fill: '#FFFF00'
});
var aminoText = new Text2('0', {
size: 38,
fill: '#FF8800'
});
var lipidText = new Text2('0', {
size: 38,
fill: '#FF0080'
});
var resourceText = new Text2('MOLECULES:', {
size: 32,
fill: '#AAAAAA'
});
var instructionText = new Text2('Collect molecules, build organelles!', {
size: 30,
fill: 0xFFFF88
});
// Add hint system
var hintText = new Text2('', {
size: 26,
fill: 0x88FFAA
});
hintText.anchor.set(0.5, 0);
hintText.alpha = 0;
LK.gui.bottom.addChild(hintText);
hintText.x = 1024;
hintText.y = 2550;
var hintTimer = 0;
var hints = ["Move E.L.Y.S. to collect glowing molecules", "ATP energy decreases over time - stay active!", "Build mitochondria with 3 glucose + 2 amino acids", "Avoid red toxins - they drain your energy", "Balance anabolism and catabolism to survive"];
var currentHint = 0;
// Narrative system
var narrativeTexts = ["The system must be restored...", "Balance... energy... life...", "The world remembers...", "Life connects everything.", "Energy is the link.", "Darkness cannot overcome the spark.", "Each molecule holds hope.", "The planet waits for revival."];
var currentNarrative = 0;
var narrativeTimer = 0;
var floatingNarrative = new Text2('', {
size: 36,
fill: '#AACCFF'
});
floatingNarrative.anchor.set(0.5, 0.5);
floatingNarrative.alpha = 0;
game.addChild(floatingNarrative);
// Position UI elements with modern spacing
atpBarBackground.x = 120;
atpBarBackground.y = 160;
atpBar.x = 120;
atpBar.y = 160;
atpGlow.x = 120;
atpGlow.y = 160;
atpText.anchor.set(0, 0);
atpText.x = 120;
atpText.y = 110;
// Position resource elements
resourceText.anchor.set(0, 0);
resourceText.x = 120;
resourceText.y = 220;
glucoseIcon.x = 150;
glucoseIcon.y = 270;
glucoseText.anchor.set(0, 0.5);
glucoseText.x = 180;
glucoseText.y = 270;
aminoIcon.x = 250;
aminoIcon.y = 270;
aminoText.anchor.set(0, 0.5);
aminoText.x = 280;
aminoText.y = 270;
lipidIcon.x = 350;
lipidIcon.y = 270;
lipidText.anchor.set(0, 0.5);
lipidText.x = 380;
lipidText.y = 270;
instructionText.anchor.set(0.5, 0);
instructionText.x = 1024;
instructionText.y = 2600;
// Position main menu elements
titleText.anchor.set(0.5, 0.5);
titleText.x = 1024;
titleText.y = 800;
subtitleText.anchor.set(0.5, 0.5);
subtitleText.x = 1024;
subtitleText.y = 920;
beginButton.x = 1024;
beginButton.y = 1200;
continueButton.x = 1024;
continueButton.y = 1350;
aboutButton.x = 1024;
aboutButton.y = 1500;
// Position exit button
var exitButton = LK.getAsset('elys', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 0.8,
tint: 0xAA0055
});
exitButton.x = 1024;
exitButton.y = 1700;
beginText.anchor.set(0.5, 0.5);
beginText.x = 1024;
beginText.y = 1200;
continueText.anchor.set(0.5, 0.5);
continueText.x = 1024;
continueText.y = 1350;
aboutText.anchor.set(0.5, 0.5);
aboutText.x = 1024;
aboutText.y = 1500;
exitText.anchor.set(0.5, 0.5);
exitText.x = 1024;
exitText.y = 1700;
storyText.anchor.set(0.5, 0.5);
storyText.x = 1024;
storyText.y = 1366;
// Add main menu elements to game
game.addChild(titleText);
game.addChild(subtitleText);
game.addChild(beginButton);
game.addChild(continueButton);
game.addChild(aboutButton);
game.addChild(beginText);
game.addChild(continueText);
game.addChild(aboutText);
game.addChild(exitButton);
game.addChild(exitText);
game.addChild(storyText);
// Add UI to GUI
LK.gui.topLeft.addChild(atpBarBackground);
LK.gui.topLeft.addChild(atpBar);
LK.gui.topLeft.addChild(atpGlow);
LK.gui.topLeft.addChild(atpText);
LK.gui.topLeft.addChild(resourceText);
LK.gui.topLeft.addChild(glucoseIcon);
LK.gui.topLeft.addChild(glucoseText);
LK.gui.topLeft.addChild(aminoIcon);
LK.gui.topLeft.addChild(aminoText);
LK.gui.topLeft.addChild(lipidIcon);
LK.gui.topLeft.addChild(lipidText);
LK.gui.bottom.addChild(instructionText);
// Create stunning space background with stars
for (var i = 0; i < 150; i++) {
var star = game.addChild(LK.getAsset('glucose', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.1 + Math.random() * 0.3,
scaleY: 0.1 + Math.random() * 0.3,
tint: Math.random() > 0.7 ? 0xffffff : Math.random() > 0.4 ? 0x88ccff : 0xffccaa,
alpha: 0.3 + Math.random() * 0.7
}));
star.x = Math.random() * 2048;
star.y = Math.random() * 2732;
star.twinkleSpeed = 0.01 + Math.random() * 0.03;
star.twinkleOffset = Math.random() * Math.PI * 2;
starField.push(star);
}
// Create nebula cloud effects
for (var i = 0; i < 8; i++) {
var cloud = game.addChild(LK.getAsset('elys', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 3 + Math.random() * 4,
scaleY: 2 + Math.random() * 3,
tint: [0xff00ff, 0x00ffff, 0xff8800, 0x8800ff, 0x00ff88][Math.floor(Math.random() * 5)],
alpha: 0.1 + Math.random() * 0.2
}));
cloud.x = Math.random() * 2048;
cloud.y = Math.random() * 2732;
cloud.driftSpeed = 0.2 + Math.random() * 0.5;
cloud.driftDirection = Math.random() * Math.PI * 2;
nebulaClouds.push(cloud);
}
// Create E.L.Y.S.
elys = game.addChild(LK.getAsset('elys', {
anchorX: 0.5,
anchorY: 0.5
}));
elys.x = 1024;
elys.y = 1366;
// Add smooth movement physics
elys.targetX = elys.x;
elys.targetY = elys.y;
elys.velocity = {
x: 0,
y: 0
};
// Create bioluminescent glow effect with enhanced styling
var elysglow = game.addChild(LK.getAsset('elys', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2.0,
scaleY: 2.0,
alpha: 0.4,
tint: 0x00FFFF
}));
elysglow.x = elys.x;
elysglow.y = elys.y;
// Create secondary outer glow for depth
var elysOuterGlow = game.addChild(LK.getAsset('elys', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 3.0,
scaleY: 3.0,
alpha: 0.15,
tint: 0xFF00FF
}));
elysOuterGlow.x = elys.x;
elysOuterGlow.y = elys.y;
// Add pulsating energy core
var elysPulse = game.addChild(LK.getAsset('elys', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
scaleY: 0.8,
alpha: 0.8,
tint: 0xFFFFFF
}));
elysPulse.x = elys.x;
elysPulse.y = elys.y;
// Initialize molecules
function spawnMolecule() {
var types = ['glucose', 'aminoAcid', 'lipid'];
var type = types[Math.floor(Math.random() * types.length)];
var molecule = game.addChild(new Molecule(type));
molecule.x = 100 + Math.random() * 1848;
molecule.y = 100 + Math.random() * 2532;
molecules.push(molecule);
}
// Initialize toxins
function spawnToxin() {
var toxin = game.addChild(new Toxin());
toxin.x = Math.random() * 2048;
toxin.y = Math.random() * 2732;
toxins.push(toxin);
}
// Add button hover detection system
var lastHoveredButton = null;
function checkButtonHover(x, y) {
if (gameState !== 'mainMenu') return;
var gamePos = game.toLocal({
x: x,
y: y
});
var currentHover = null;
// Check which button we're hovering over with more precise hit detection
if (Math.abs(gamePos.x - beginButton.x) < 100 && Math.abs(gamePos.y - beginButton.y) < 50) {
currentHover = 'begin';
} else if (Math.abs(gamePos.x - continueButton.x) < 100 && Math.abs(gamePos.y - continueButton.y) < 50) {
currentHover = 'continue';
} else if (Math.abs(gamePos.x - aboutButton.x) < 100 && Math.abs(gamePos.y - aboutButton.y) < 50) {
currentHover = 'about';
}
// Handle hover state changes
if (currentHover !== lastHoveredButton) {
// Reset previous button
if (lastHoveredButton === 'begin') {
tween(beginButton, {
scaleX: 1.5,
scaleY: 0.8,
tint: 0x00AA88
}, {
duration: 200
});
tween(beginText, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 200
});
} else if (lastHoveredButton === 'continue') {
tween(continueButton, {
scaleX: 1.5,
scaleY: 0.8,
tint: 0xAA8800
}, {
duration: 200
});
tween(continueText, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 200
});
} else if (lastHoveredButton === 'about') {
tween(aboutButton, {
scaleX: 1.5,
scaleY: 0.8,
tint: 0x8800AA
}, {
duration: 200
});
tween(aboutText, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 200
});
}
// Highlight current button
if (currentHover === 'begin') {
LK.getSound('menuHover').play();
tween(beginButton, {
scaleX: 1.6,
scaleY: 0.9,
tint: 0x00FFFF
}, {
duration: 200
});
tween(beginText, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 200
});
} else if (currentHover === 'continue') {
LK.getSound('menuHover').play();
tween(continueButton, {
scaleX: 1.6,
scaleY: 0.9,
tint: 0xFFFF00
}, {
duration: 200
});
tween(continueText, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 200
});
} else if (currentHover === 'about') {
LK.getSound('menuHover').play();
tween(aboutButton, {
scaleX: 1.6,
scaleY: 0.9,
tint: 0xFF00FF
}, {
duration: 200
});
tween(aboutText, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 200
});
}
lastHoveredButton = currentHover;
}
}
// Start directly in game mode
hideMainMenu();
// Start background music immediately
LK.playMusic('song', {
fade: {
start: 0,
end: 0.6,
duration: 2000
}
});
// Spawn initial molecules and toxins immediately
for (var i = 0; i < 15; i++) {
spawnMolecule();
}
for (var i = 0; i < 3; i++) {
spawnToxin();
}
// Game state management functions
function showMainMenu() {
titleText.alpha = 1;
subtitleText.alpha = 1;
beginButton.alpha = 1;
continueButton.alpha = 1;
aboutButton.alpha = 1;
beginText.alpha = 1;
continueText.alpha = 1;
aboutText.alpha = 1;
exitButton.alpha = 1;
exitText.alpha = 1;
storyText.alpha = 0;
// Hide game UI
atpBarBackground.alpha = 0;
atpBar.alpha = 0;
atpGlow.alpha = 0;
atpText.alpha = 0;
resourceText.alpha = 0;
glucoseIcon.alpha = 0;
glucoseText.alpha = 0;
aminoIcon.alpha = 0;
aminoText.alpha = 0;
lipidIcon.alpha = 0;
lipidText.alpha = 0;
instructionText.alpha = 0;
// Hide E.L.Y.S.
if (elys) elys.alpha = 0;
if (elysglow) elysglow.alpha = 0;
}
function hideMainMenu() {
titleText.alpha = 0;
subtitleText.alpha = 0;
beginButton.alpha = 0;
continueButton.alpha = 0;
aboutButton.alpha = 0;
beginText.alpha = 0;
continueText.alpha = 0;
aboutText.alpha = 0;
exitButton.alpha = 0;
exitText.alpha = 0;
// Show game UI
atpBarBackground.alpha = 1;
atpBar.alpha = 1;
atpGlow.alpha = 0.5;
atpText.alpha = 1;
resourceText.alpha = 1;
glucoseIcon.alpha = 1;
glucoseText.alpha = 1;
aminoIcon.alpha = 1;
aminoText.alpha = 1;
lipidIcon.alpha = 1;
lipidText.alpha = 1;
instructionText.alpha = 1;
// Show E.L.Y.S.
if (elys) elys.alpha = 1;
if (elysglow) elysglow.alpha = 0.3;
}
function showIntroSequence() {
gameState = 'intro';
hideMainMenu();
// Create cinematic spark effect
var spark = game.addChild(LK.getAsset('elys', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.1,
scaleY: 0.1,
alpha: 0,
tint: 0xFFFFFF
}));
spark.x = 1024;
spark.y = 200;
// Show E.L.Y.S. and glows during intro
if (elys) {
elys.alpha = 0.3;
elys.x = 1024;
elys.y = 1366;
}
if (elysglow) {
elysglow.alpha = 0.1;
elysglow.x = 1024;
elysglow.y = 1366;
}
if (elysOuterGlow) {
elysOuterGlow.alpha = 0.05;
elysOuterGlow.x = 1024;
elysOuterGlow.y = 1366;
}
if (elysPulse) {
elysPulse.alpha = 0.2;
elysPulse.x = 1024;
elysPulse.y = 1366;
}
// Animate spark falling
tween(spark, {
y: 1366,
alpha: 1,
scaleX: 0.5,
scaleY: 0.5
}, {
duration: 2000,
easing: tween.easeOut,
onFinish: function onFinish() {
// Spark impact effect
LK.effects.flashScreen(0x00FFFF, 800);
// Show E.L.Y.S. awakening
if (elys) {
tween(elys, {
alpha: 1
}, {
duration: 1000
});
}
if (elysglow) {
tween(elysglow, {
alpha: 0.4
}, {
duration: 1000
});
}
if (elysOuterGlow) {
tween(elysOuterGlow, {
alpha: 0.15
}, {
duration: 1000
});
}
if (elysPulse) {
tween(elysPulse, {
alpha: 0.8
}, {
duration: 1000
});
}
tween(spark, {
scaleX: 2.0,
scaleY: 2.0,
alpha: 0
}, {
duration: 1000,
onFinish: function onFinish() {
spark.destroy();
}
});
}
});
storyText.alpha = 1;
storyText.setText('In an ancient and silent planet,\na single spark of life called E.L.Y.S. awakens\nin the midst of darkness...');
storyText.tint = 0x88CCFF;
// Animate intro text with glow effect
tween(storyText, {
alpha: 1,
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 2000,
easing: tween.easeOut,
onFinish: function onFinish() {
LK.setTimeout(function () {
tween(storyText, {
alpha: 0,
y: storyText.y - 100
}, {
duration: 1000,
easing: tween.easeIn,
onFinish: function onFinish() {
storyText.y = 1366; // Reset position
startGame();
}
});
}, 3000);
}
});
}
function startGame() {
gameState = 'playing';
storyText.alpha = 0;
hideMainMenu();
// Reset game variables
currentATP = 50;
glucoseCount = 0;
aminoAcidCount = 0;
lipidCount = 0;
worldBrightness = 0.2;
currentLevel = 1;
// Clear existing game objects
for (var i = molecules.length - 1; i >= 0; i--) {
molecules[i].destroy();
molecules.splice(i, 1);
}
for (var i = organelles.length - 1; i >= 0; i--) {
organelles[i].destroy();
organelles.splice(i, 1);
}
for (var i = toxins.length - 1; i >= 0; i--) {
toxins[i].destroy();
toxins.splice(i, 1);
}
// Reset E.L.Y.S. position and ensure it's visible
elys.x = 1024;
elys.y = 1366;
elys.alpha = 1;
elys.targetX = elys.x;
elys.targetY = elys.y;
elys.velocity = {
x: 0,
y: 0
};
// Update all glow effects positions
elysglow.x = elys.x;
elysglow.y = elys.y;
elysglow.alpha = 0.4;
elysOuterGlow.x = elys.x;
elysOuterGlow.y = elys.y;
elysOuterGlow.alpha = 0.15;
elysPulse.x = elys.x;
elysPulse.y = elys.y;
elysPulse.alpha = 0.8;
// Initialize starting molecules and toxins
for (var i = 0; i < 15; i++) {
spawnMolecule();
}
for (var i = 0; i < 3; i++) {
spawnToxin();
}
// Start background music
LK.playMusic('song', {
fade: {
start: 0,
end: 0.6,
duration: 2000
}
});
}
// Helper functions
function updateUI() {
var atpPercent = currentATP / maxATP;
// Smooth ATP bar animation
tween(atpBar, {
scaleX: 4 * atpPercent
}, {
duration: 200,
easing: tween.easeOut
});
tween(atpGlow, {
scaleX: 4 * atpPercent
}, {
duration: 300,
easing: tween.easeOut
});
// Dynamic color transitions
if (atpPercent > 0.6) {
tween(atpBar, {
tint: 0x00AAFF
}, {
duration: 300
});
tween(atpGlow, {
tint: 0x00FFFF
}, {
duration: 300
});
} else if (atpPercent > 0.3) {
tween(atpBar, {
tint: 0xFFAA00
}, {
duration: 300
});
tween(atpGlow, {
tint: 0xFFFF00
}, {
duration: 300
});
} else {
tween(atpBar, {
tint: 0xFF3300
}, {
duration: 300
});
tween(atpGlow, {
tint: 0xFF0000
}, {
duration: 300
});
}
// Pulsing glow effect
atpGlow.alpha = 0.3 + Math.sin(LK.ticks * 0.1) * 0.2;
atpText.setText('ENERGY: ' + Math.floor(currentATP) + '/' + maxATP);
glucoseText.setText(glucoseCount);
aminoText.setText(aminoAcidCount);
lipidText.setText(lipidCount);
// Update E.L.Y.S. glow based on energy with enhanced effects
var targetAlpha = 0.6 + atpPercent * 0.4;
var targetScale = 0.9 + atpPercent * 0.3;
var energyTint = atpPercent > 0.6 ? 0x00FFFF : atpPercent > 0.3 ? 0xFFFF00 : 0xFF3300;
tween(elys, {
alpha: targetAlpha,
tint: energyTint
}, {
duration: 300
});
tween(elysglow, {
scaleX: 1.8 + targetScale,
scaleY: 1.8 + targetScale,
alpha: 0.3 + atpPercent * 0.2,
tint: energyTint
}, {
duration: 500
});
// Update outer glow
tween(elysOuterGlow, {
scaleX: 2.5 + targetScale,
scaleY: 2.5 + targetScale,
alpha: 0.1 + atpPercent * 0.1
}, {
duration: 800
});
// Pulsating core effect
var pulseIntensity = 0.6 + Math.sin(LK.ticks * 0.08) * 0.2;
tween(elysPulse, {
alpha: pulseIntensity,
scaleX: 0.7 + pulseIntensity * 0.2,
scaleY: 0.7 + pulseIntensity * 0.2
}, {
duration: 200
});
// Dynamic space background with exciting effects
backgroundPhase += 0.015;
var colorIndex = Math.floor(backgroundPhase) % backgroundColors.length;
var nextColorIndex = (colorIndex + 1) % backgroundColors.length;
var lerpFactor = backgroundPhase - Math.floor(backgroundPhase);
var currentBg = backgroundColors[colorIndex];
game.setBackgroundColor(currentBg);
// Animate twinkling stars
for (var i = 0; i < starField.length; i++) {
var star = starField[i];
star.alpha = 0.3 + Math.sin(LK.ticks * star.twinkleSpeed + star.twinkleOffset) * 0.4 + Math.random() * 0.2;
// Some stars slowly drift
if (i % 5 === 0) {
star.x += Math.sin(LK.ticks * 0.001 + i) * 0.1;
star.y += Math.cos(LK.ticks * 0.0008 + i) * 0.1;
}
}
// Animate nebula clouds with gentle drift and color shifts
for (var i = 0; i < nebulaClouds.length; i++) {
var cloud = nebulaClouds[i];
cloud.x += Math.cos(cloud.driftDirection) * cloud.driftSpeed;
cloud.y += Math.sin(cloud.driftDirection) * cloud.driftSpeed;
// Wrap around screen edges
if (cloud.x > 2100) cloud.x = -100;
if (cloud.x < -100) cloud.x = 2100;
if (cloud.y > 2800) cloud.y = -100;
if (cloud.y < -100) cloud.y = 2800;
// Subtle alpha pulsing for mystical effect
cloud.alpha = 0.1 + Math.sin(LK.ticks * 0.008 + i) * 0.1;
// Occasional color shifts for dynamic feel
if (LK.ticks % 600 === i * 20) {
var newColors = [0xff00ff, 0x00ffff, 0xff8800, 0x8800ff, 0x00ff88, 0xff4080, 0x4080ff];
tween(cloud, {
tint: newColors[Math.floor(Math.random() * newColors.length)]
}, {
duration: 2000,
easing: tween.easeInOut
});
}
}
// Update narrative system
if (gameState === 'playing') {
narrativeTimer++;
if (narrativeTimer > 1200) {
// Show narrative every 20 seconds
narrativeTimer = 0;
floatingNarrative.setText(narrativeTexts[currentNarrative]);
floatingNarrative.x = 1024 + (Math.random() - 0.5) * 400;
floatingNarrative.y = 1366 + (Math.random() - 0.5) * 300;
// Animate floating narrative
tween(floatingNarrative, {
alpha: 0.8
}, {
duration: 500,
onFinish: function onFinish() {
LK.setTimeout(function () {
tween(floatingNarrative, {
alpha: 0,
y: floatingNarrative.y - 50
}, {
duration: 1000
});
}, 2000);
}
});
currentNarrative = (currentNarrative + 1) % narrativeTexts.length;
}
// Update world transformation based on progress
var progress = organelles.length / 5;
worldBrightness = 0.2 + progress * 0.8;
// Transform environment colors as progress increases
if (progress > 0.8) {
// Final transformation - vibrant life
game.setBackgroundColor(0x002244);
for (var i = 0; i < starField.length; i++) {
starField[i].tint = 0xffff88;
starField[i].alpha = 0.8 + Math.sin(LK.ticks * 0.05 + i) * 0.2;
}
} else if (progress > 0.6) {
// Growing life
game.setBackgroundColor(0x001833);
} else if (progress > 0.4) {
// First signs of life
game.setBackgroundColor(0x001122);
}
// Update level display with glow effect
instructionText.setText('Level ' + currentLevel + ': ' + levelNames[currentLevel - 1]);
instructionText.tint = 0xFFFF88 + Math.floor(Math.sin(LK.ticks * 0.05) * 0x003300);
// Update hint system
if (gameState === 'playing') {
hintTimer++;
if (hintTimer > 900 && hintText.alpha === 0) {
// Show hint every 15 seconds
hintText.setText(hints[currentHint]);
tween(hintText, {
alpha: 0.8
}, {
duration: 500,
onFinish: function onFinish() {
LK.setTimeout(function () {
tween(hintText, {
alpha: 0
}, {
duration: 500
});
}, 3000);
}
});
currentHint = (currentHint + 1) % hints.length;
hintTimer = 0;
}
}
}
}
function buildOrganelle(type) {
var cost = type === 'mitochondria' ? {
glucose: 3,
aminoAcid: 2
} : {
glucose: 2,
lipid: 2
};
if ((cost.glucose || 0) <= glucoseCount && (cost.aminoAcid || 0) <= aminoAcidCount && (cost.lipid || 0) <= lipidCount) {
glucoseCount -= cost.glucose || 0;
aminoAcidCount -= cost.aminoAcid || 0;
lipidCount -= cost.lipid || 0;
var organelle = game.addChild(new Organelle(type, elys.x + (Math.random() - 0.5) * 200, elys.y + (Math.random() - 0.5) * 200));
organelles.push(organelle);
organelle.activate();
worldBrightness = Math.min(1.0, worldBrightness + 0.1);
LK.getSound('build').play();
LK.effects.flashObject(organelle, 0x00ffff, 500);
return true;
}
return false;
}
// Event handlers
function handleMove(x, y, obj) {
if (dragNode) {
// Smooth movement with physics
dragNode.targetX = x;
dragNode.targetY = y;
// Add momentum and fluid movement
var dx = dragNode.targetX - dragNode.x;
var dy = dragNode.targetY - dragNode.y;
dragNode.velocity.x += dx * 0.1;
dragNode.velocity.y += dy * 0.1;
dragNode.velocity.x *= 0.85;
dragNode.velocity.y *= 0.85;
dragNode.x += dragNode.velocity.x;
dragNode.y += dragNode.velocity.y;
// Update all glow effects positions smoothly
tween(elysglow, {
x: dragNode.x,
y: dragNode.y
}, {
duration: 100,
easing: tween.easeOut
});
tween(elysOuterGlow, {
x: dragNode.x,
y: dragNode.y
}, {
duration: 150,
easing: tween.easeOut
});
tween(elysPulse, {
x: dragNode.x,
y: dragNode.y
}, {
duration: 80,
easing: tween.easeOut
});
// Moving costs energy with visual feedback
if (LK.ticks % 10 === 0) {
currentATP = Math.max(0, currentATP - 0.5);
// Create trailing particle effect when moving fast
var speed = Math.sqrt(dragNode.velocity.x * dragNode.velocity.x + dragNode.velocity.y * dragNode.velocity.y);
if (speed > 2) {
elysglow.alpha = 0.5 + speed * 0.1;
}
}
}
}
game.move = function (x, y, obj) {
// Handle game movement
handleMove(x, y, obj);
};
game.down = function (x, y, obj) {
dragNode = elys;
handleMove(x, y, obj);
// Try building organelles on double tap
if (glucoseCount >= 3 && aminoAcidCount >= 2) {
buildOrganelle('mitochondria');
} else if (glucoseCount >= 2 && lipidCount >= 2) {
buildOrganelle('chloroplast');
}
};
game.up = function (x, y, obj) {
dragNode = null;
};
// Main game loop
game.update = function () {
// Update UI
updateUI();
// Only run game logic when playing
if (gameState !== 'playing') {
return;
}
// Initialize molecules and toxins when starting to play
if (molecules.length === 0 && toxins.length === 0) {
for (var i = 0; i < 15; i++) {
spawnMolecule();
}
for (var i = 0; i < 3; i++) {
spawnToxin();
}
}
// Check for game over
if (currentATP <= 0) {
LK.effects.flashScreen(0xff0000, 1000);
LK.showGameOver();
return;
}
// ATP decay over time
if (LK.ticks % 120 === 0) {
currentATP = Math.max(0, currentATP - 1);
}
// Check molecule collection
for (var i = molecules.length - 1; i >= 0; i--) {
var molecule = molecules[i];
if (elys.intersects(molecule)) {
// Create floating text feedback
var collectText = new Text2('', {
size: 28,
fill: '#FFFFFF'
});
collectText.anchor.set(0.5, 0.5);
collectText.x = molecule.x;
collectText.y = molecule.y;
game.addChild(collectText);
// Collect molecule with specific feedback
if (molecule.type === 'glucose') {
glucoseCount++;
collectText.setText('Glucose +' + molecule.value);
collectText.fill = '#FFFF00';
tween(glucoseIcon, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 150,
onFinish: function onFinish() {
tween(glucoseIcon, {
scaleX: 0.9,
scaleY: 0.9
}, {
duration: 150
});
}
});
} else if (molecule.type === 'aminoAcid') {
aminoAcidCount++;
collectText.setText('Amino Acid +' + molecule.value);
collectText.fill = '#FF8800';
tween(aminoIcon, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 150,
onFinish: function onFinish() {
tween(aminoIcon, {
scaleX: 0.9,
scaleY: 0.9
}, {
duration: 150
});
}
});
} else if (molecule.type === 'lipid') {
lipidCount++;
collectText.setText('Lipid +' + molecule.value);
collectText.fill = '#FF0080';
tween(lipidIcon, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 150,
onFinish: function onFinish() {
tween(lipidIcon, {
scaleX: 0.9,
scaleY: 0.9
}, {
duration: 150
});
}
});
}
// Animate floating text
tween(collectText, {
y: collectText.y - 80,
alpha: 0
}, {
duration: 1000,
easing: tween.easeOut,
onFinish: function onFinish() {
collectText.destroy();
}
});
currentATP = Math.min(maxATP, currentATP + molecule.value);
LK.getSound('collect').play();
LK.effects.flashObject(elys, 0x00ff00, 300);
// Enhance collection effect
tween(elys, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 150,
onFinish: function onFinish() {
tween(elys, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 150
});
}
});
molecule.destroy();
molecules.splice(i, 1);
}
}
// Check toxin collision
for (var i = toxins.length - 1; i >= 0; i--) {
var toxin = toxins[i];
if (elys.intersects(toxin)) {
currentATP = Math.max(0, currentATP - toxin.damage);
LK.getSound('damage').play();
LK.effects.flashObject(elys, 0xff0000, 500);
LK.effects.flashScreen(0xff0000, 200);
// Remove toxin after hit
toxin.destroy();
toxins.splice(i, 1);
}
}
// Spawn new molecules periodically
if (LK.ticks % 300 === 0 && molecules.length < 20) {
spawnMolecule();
}
// Spawn new toxins occasionally
if (LK.ticks % 600 === 0 && toxins.length < 5) {
spawnToxin();
}
// Check win condition with epic ending
if (organelles.length >= 5 && worldBrightness >= 0.8) {
// Epic planetary restoration effect
for (var i = 0; i < starField.length; i++) {
tween(starField[i], {
tint: 0xFFFF88,
alpha: 1.0,
scaleX: starField[i].scaleX * 2,
scaleY: starField[i].scaleY * 2
}, {
duration: 3000,
easing: tween.easeOut
});
}
// Transform nebula to living colors
for (var i = 0; i < nebulaClouds.length; i++) {
tween(nebulaClouds[i], {
tint: 0x00FF88,
alpha: 0.6,
scaleX: nebulaClouds[i].scaleX * 1.5,
scaleY: nebulaClouds[i].scaleY * 1.5
}, {
duration: 4000,
easing: tween.easeOut
});
}
// Show final transformation
floatingNarrative.setText('Life connects everything.\nEnergy is the link.');
floatingNarrative.x = 1024;
floatingNarrative.y = 1366;
floatingNarrative.tint = 0x00FFAA;
tween(floatingNarrative, {
alpha: 1,
scaleX: 2.0,
scaleY: 2.0
}, {
duration: 3000,
easing: tween.easeOut,
onFinish: function onFinish() {
// Create energy pulse from center
LK.effects.flashScreen(0x00FFFF, 1000);
LK.setTimeout(function () {
LK.effects.flashScreen(0x00ff88, 2000);
// Play victory sound
LK.getSound('energyPulse').play();
LK.showYouWin();
}, 1500);
}
});
}
// Update score based on organelles built
LK.setScore(organelles.length * 100 + Math.floor(worldBrightness * 500));
}; /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Molecule = Container.expand(function (type) {
var self = Container.call(this);
self.type = type || 'glucose';
self.value = type === 'glucose' ? 10 : type === 'aminoAcid' ? 8 : 12;
var graphics = self.attachAsset(self.type, {
anchorX: 0.5,
anchorY: 0.5
});
// Gentle floating animation
self.floatOffset = Math.random() * Math.PI * 2;
self.floatSpeed = 0.02 + Math.random() * 0.02;
self.update = function () {
graphics.y += Math.sin(LK.ticks * self.floatSpeed + self.floatOffset) * 0.5;
graphics.x += Math.cos(LK.ticks * self.floatSpeed * 0.7 + self.floatOffset) * 0.3;
// Proximity glow effect when E.L.Y.S. is near
if (elys) {
var distance = Math.sqrt(Math.pow(self.x - elys.x, 2) + Math.pow(self.y - elys.y, 2));
if (distance < 120) {
var glowIntensity = 1 - distance / 120;
graphics.alpha = 0.8 + glowIntensity * 0.5;
graphics.scaleX = graphics.scaleY = 1 + glowIntensity * 0.3;
} else {
graphics.alpha = 0.8;
graphics.scaleX = graphics.scaleY = 1;
}
}
};
return self;
});
var Organelle = Container.expand(function (type, x, y) {
var self = Container.call(this);
self.type = type;
self.energyRate = type === 'mitochondria' ? 2 : 1;
self.active = false;
var graphics = self.attachAsset(self.type, {
anchorX: 0.5,
anchorY: 0.5
});
self.x = x;
self.y = y;
graphics.alpha = 0.7;
self.activate = function () {
self.active = true;
graphics.alpha = 1.0;
tween(graphics, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 200,
easing: tween.easeOut
});
tween(graphics, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 200,
easing: tween.easeIn
});
};
self.update = function () {
if (self.active && LK.ticks % 60 === 0) {
// Generate energy periodically
currentATP = Math.min(maxATP, currentATP + self.energyRate);
}
};
return self;
});
var Toxin = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('toxin', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 1 + Math.random() * 2;
self.direction = Math.random() * Math.PI * 2;
self.damage = 15;
self.update = function () {
self.x += Math.cos(self.direction) * self.speed;
self.y += Math.sin(self.direction) * self.speed;
// Bounce off edges
if (self.x < 50 || self.x > 1998) {
self.direction = Math.PI - self.direction;
}
if (self.y < 50 || self.y > 2682) {
self.direction = -self.direction;
}
// Keep in bounds
self.x = Math.max(50, Math.min(1998, self.x));
self.y = Math.max(50, Math.min(2682, self.y));
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x001122
});
/****
* Game Code
****/
// Game state management
var gameState = 'playing'; // 'mainMenu', 'intro', 'playing', 'paused'
var currentLevel = 1;
var levelNames = ['Cytoplasm Caverns', 'Mitochondrial Core', 'Nucleus Nexus', 'Photosynthesis Fields', 'Energy Restoration'];
// Main Menu Elements
var titleText = new Text2('E.L.Y.S.', {
size: 180,
fill: '#00FFFF'
});
var subtitleText = new Text2('Energy Linking Your System', {
size: 60,
fill: '#88AAFF'
});
var beginButton = LK.getAsset('elys', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 0.8,
tint: 0x00AA88
});
var continueButton = LK.getAsset('elys', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 0.8,
tint: 0xAA8800
});
var aboutButton = LK.getAsset('elys', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 0.8,
tint: 0x8800AA
});
var beginText = new Text2('Begin Journey', {
size: 48,
fill: '#FFFFFF'
});
var continueText = new Text2('Continue', {
size: 48,
fill: '#FFFFFF'
});
var aboutText = new Text2('About E.L.Y.S.', {
size: 48,
fill: '#FFFFFF'
});
// Add exit text for exit functionality
var exitText = new Text2('Exit Game', {
size: 48,
fill: '#FFFFFF'
});
// Story text elements
var storyText = new Text2('', {
size: 40,
fill: '#CCCCFF'
});
// Dynamic space background variables with exciting colors
var backgroundPhase = 0;
var backgroundColors = [0x0a0040, 0x1a0080, 0x2010a0, 0x4020c0, 0x6030e0, 0x8040ff, 0xa060ff, 0xc080ff];
var starField = [];
var nebulaClouds = [];
// Game state variables
var currentATP = 50;
var maxATP = 100;
var glucoseCount = 0;
var aminoAcidCount = 0;
var lipidCount = 0;
var worldBrightness = 0.2;
var level = 1;
// Game objects
var elys;
var molecules = [];
var organelles = [];
var toxins = [];
var dragNode = null;
// UI Elements - Futuristic ATP Bar
var atpBarBackground = LK.getAsset('glucose', {
anchorX: 0,
anchorY: 0,
scaleX: 4,
scaleY: 0.4,
tint: 0x112233
});
var atpBar = LK.getAsset('glucose', {
anchorX: 0,
anchorY: 0,
scaleX: 4,
scaleY: 0.4,
tint: 0x00AAFF
});
var atpGlow = LK.getAsset('glucose', {
anchorX: 0,
anchorY: 0,
scaleX: 4,
scaleY: 0.4,
tint: 0x00FFFF,
alpha: 0.5
});
var atpText = new Text2('ATP: 50/100', {
size: 45,
fill: '#00FFFF'
});
// Modern resource display with icons
var glucoseIcon = LK.getAsset('glucose', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.9,
scaleY: 0.9
});
var aminoIcon = LK.getAsset('aminoAcid', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.9,
scaleY: 0.9
});
var lipidIcon = LK.getAsset('lipid', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.9,
scaleY: 0.9
});
var glucoseText = new Text2('0', {
size: 38,
fill: '#FFFF00'
});
var aminoText = new Text2('0', {
size: 38,
fill: '#FF8800'
});
var lipidText = new Text2('0', {
size: 38,
fill: '#FF0080'
});
var resourceText = new Text2('MOLECULES:', {
size: 32,
fill: '#AAAAAA'
});
var instructionText = new Text2('Collect molecules, build organelles!', {
size: 30,
fill: 0xFFFF88
});
// Add hint system
var hintText = new Text2('', {
size: 26,
fill: 0x88FFAA
});
hintText.anchor.set(0.5, 0);
hintText.alpha = 0;
LK.gui.bottom.addChild(hintText);
hintText.x = 1024;
hintText.y = 2550;
var hintTimer = 0;
var hints = ["Move E.L.Y.S. to collect glowing molecules", "ATP energy decreases over time - stay active!", "Build mitochondria with 3 glucose + 2 amino acids", "Avoid red toxins - they drain your energy", "Balance anabolism and catabolism to survive"];
var currentHint = 0;
// Narrative system
var narrativeTexts = ["The system must be restored...", "Balance... energy... life...", "The world remembers...", "Life connects everything.", "Energy is the link.", "Darkness cannot overcome the spark.", "Each molecule holds hope.", "The planet waits for revival."];
var currentNarrative = 0;
var narrativeTimer = 0;
var floatingNarrative = new Text2('', {
size: 36,
fill: '#AACCFF'
});
floatingNarrative.anchor.set(0.5, 0.5);
floatingNarrative.alpha = 0;
game.addChild(floatingNarrative);
// Position UI elements with modern spacing
atpBarBackground.x = 120;
atpBarBackground.y = 160;
atpBar.x = 120;
atpBar.y = 160;
atpGlow.x = 120;
atpGlow.y = 160;
atpText.anchor.set(0, 0);
atpText.x = 120;
atpText.y = 110;
// Position resource elements
resourceText.anchor.set(0, 0);
resourceText.x = 120;
resourceText.y = 220;
glucoseIcon.x = 150;
glucoseIcon.y = 270;
glucoseText.anchor.set(0, 0.5);
glucoseText.x = 180;
glucoseText.y = 270;
aminoIcon.x = 250;
aminoIcon.y = 270;
aminoText.anchor.set(0, 0.5);
aminoText.x = 280;
aminoText.y = 270;
lipidIcon.x = 350;
lipidIcon.y = 270;
lipidText.anchor.set(0, 0.5);
lipidText.x = 380;
lipidText.y = 270;
instructionText.anchor.set(0.5, 0);
instructionText.x = 1024;
instructionText.y = 2600;
// Position main menu elements
titleText.anchor.set(0.5, 0.5);
titleText.x = 1024;
titleText.y = 800;
subtitleText.anchor.set(0.5, 0.5);
subtitleText.x = 1024;
subtitleText.y = 920;
beginButton.x = 1024;
beginButton.y = 1200;
continueButton.x = 1024;
continueButton.y = 1350;
aboutButton.x = 1024;
aboutButton.y = 1500;
// Position exit button
var exitButton = LK.getAsset('elys', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 0.8,
tint: 0xAA0055
});
exitButton.x = 1024;
exitButton.y = 1700;
beginText.anchor.set(0.5, 0.5);
beginText.x = 1024;
beginText.y = 1200;
continueText.anchor.set(0.5, 0.5);
continueText.x = 1024;
continueText.y = 1350;
aboutText.anchor.set(0.5, 0.5);
aboutText.x = 1024;
aboutText.y = 1500;
exitText.anchor.set(0.5, 0.5);
exitText.x = 1024;
exitText.y = 1700;
storyText.anchor.set(0.5, 0.5);
storyText.x = 1024;
storyText.y = 1366;
// Add main menu elements to game
game.addChild(titleText);
game.addChild(subtitleText);
game.addChild(beginButton);
game.addChild(continueButton);
game.addChild(aboutButton);
game.addChild(beginText);
game.addChild(continueText);
game.addChild(aboutText);
game.addChild(exitButton);
game.addChild(exitText);
game.addChild(storyText);
// Add UI to GUI
LK.gui.topLeft.addChild(atpBarBackground);
LK.gui.topLeft.addChild(atpBar);
LK.gui.topLeft.addChild(atpGlow);
LK.gui.topLeft.addChild(atpText);
LK.gui.topLeft.addChild(resourceText);
LK.gui.topLeft.addChild(glucoseIcon);
LK.gui.topLeft.addChild(glucoseText);
LK.gui.topLeft.addChild(aminoIcon);
LK.gui.topLeft.addChild(aminoText);
LK.gui.topLeft.addChild(lipidIcon);
LK.gui.topLeft.addChild(lipidText);
LK.gui.bottom.addChild(instructionText);
// Create stunning space background with stars
for (var i = 0; i < 150; i++) {
var star = game.addChild(LK.getAsset('glucose', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.1 + Math.random() * 0.3,
scaleY: 0.1 + Math.random() * 0.3,
tint: Math.random() > 0.7 ? 0xffffff : Math.random() > 0.4 ? 0x88ccff : 0xffccaa,
alpha: 0.3 + Math.random() * 0.7
}));
star.x = Math.random() * 2048;
star.y = Math.random() * 2732;
star.twinkleSpeed = 0.01 + Math.random() * 0.03;
star.twinkleOffset = Math.random() * Math.PI * 2;
starField.push(star);
}
// Create nebula cloud effects
for (var i = 0; i < 8; i++) {
var cloud = game.addChild(LK.getAsset('elys', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 3 + Math.random() * 4,
scaleY: 2 + Math.random() * 3,
tint: [0xff00ff, 0x00ffff, 0xff8800, 0x8800ff, 0x00ff88][Math.floor(Math.random() * 5)],
alpha: 0.1 + Math.random() * 0.2
}));
cloud.x = Math.random() * 2048;
cloud.y = Math.random() * 2732;
cloud.driftSpeed = 0.2 + Math.random() * 0.5;
cloud.driftDirection = Math.random() * Math.PI * 2;
nebulaClouds.push(cloud);
}
// Create E.L.Y.S.
elys = game.addChild(LK.getAsset('elys', {
anchorX: 0.5,
anchorY: 0.5
}));
elys.x = 1024;
elys.y = 1366;
// Add smooth movement physics
elys.targetX = elys.x;
elys.targetY = elys.y;
elys.velocity = {
x: 0,
y: 0
};
// Create bioluminescent glow effect with enhanced styling
var elysglow = game.addChild(LK.getAsset('elys', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2.0,
scaleY: 2.0,
alpha: 0.4,
tint: 0x00FFFF
}));
elysglow.x = elys.x;
elysglow.y = elys.y;
// Create secondary outer glow for depth
var elysOuterGlow = game.addChild(LK.getAsset('elys', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 3.0,
scaleY: 3.0,
alpha: 0.15,
tint: 0xFF00FF
}));
elysOuterGlow.x = elys.x;
elysOuterGlow.y = elys.y;
// Add pulsating energy core
var elysPulse = game.addChild(LK.getAsset('elys', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
scaleY: 0.8,
alpha: 0.8,
tint: 0xFFFFFF
}));
elysPulse.x = elys.x;
elysPulse.y = elys.y;
// Initialize molecules
function spawnMolecule() {
var types = ['glucose', 'aminoAcid', 'lipid'];
var type = types[Math.floor(Math.random() * types.length)];
var molecule = game.addChild(new Molecule(type));
molecule.x = 100 + Math.random() * 1848;
molecule.y = 100 + Math.random() * 2532;
molecules.push(molecule);
}
// Initialize toxins
function spawnToxin() {
var toxin = game.addChild(new Toxin());
toxin.x = Math.random() * 2048;
toxin.y = Math.random() * 2732;
toxins.push(toxin);
}
// Add button hover detection system
var lastHoveredButton = null;
function checkButtonHover(x, y) {
if (gameState !== 'mainMenu') return;
var gamePos = game.toLocal({
x: x,
y: y
});
var currentHover = null;
// Check which button we're hovering over with more precise hit detection
if (Math.abs(gamePos.x - beginButton.x) < 100 && Math.abs(gamePos.y - beginButton.y) < 50) {
currentHover = 'begin';
} else if (Math.abs(gamePos.x - continueButton.x) < 100 && Math.abs(gamePos.y - continueButton.y) < 50) {
currentHover = 'continue';
} else if (Math.abs(gamePos.x - aboutButton.x) < 100 && Math.abs(gamePos.y - aboutButton.y) < 50) {
currentHover = 'about';
}
// Handle hover state changes
if (currentHover !== lastHoveredButton) {
// Reset previous button
if (lastHoveredButton === 'begin') {
tween(beginButton, {
scaleX: 1.5,
scaleY: 0.8,
tint: 0x00AA88
}, {
duration: 200
});
tween(beginText, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 200
});
} else if (lastHoveredButton === 'continue') {
tween(continueButton, {
scaleX: 1.5,
scaleY: 0.8,
tint: 0xAA8800
}, {
duration: 200
});
tween(continueText, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 200
});
} else if (lastHoveredButton === 'about') {
tween(aboutButton, {
scaleX: 1.5,
scaleY: 0.8,
tint: 0x8800AA
}, {
duration: 200
});
tween(aboutText, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 200
});
}
// Highlight current button
if (currentHover === 'begin') {
LK.getSound('menuHover').play();
tween(beginButton, {
scaleX: 1.6,
scaleY: 0.9,
tint: 0x00FFFF
}, {
duration: 200
});
tween(beginText, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 200
});
} else if (currentHover === 'continue') {
LK.getSound('menuHover').play();
tween(continueButton, {
scaleX: 1.6,
scaleY: 0.9,
tint: 0xFFFF00
}, {
duration: 200
});
tween(continueText, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 200
});
} else if (currentHover === 'about') {
LK.getSound('menuHover').play();
tween(aboutButton, {
scaleX: 1.6,
scaleY: 0.9,
tint: 0xFF00FF
}, {
duration: 200
});
tween(aboutText, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 200
});
}
lastHoveredButton = currentHover;
}
}
// Start directly in game mode
hideMainMenu();
// Start background music immediately
LK.playMusic('song', {
fade: {
start: 0,
end: 0.6,
duration: 2000
}
});
// Spawn initial molecules and toxins immediately
for (var i = 0; i < 15; i++) {
spawnMolecule();
}
for (var i = 0; i < 3; i++) {
spawnToxin();
}
// Game state management functions
function showMainMenu() {
titleText.alpha = 1;
subtitleText.alpha = 1;
beginButton.alpha = 1;
continueButton.alpha = 1;
aboutButton.alpha = 1;
beginText.alpha = 1;
continueText.alpha = 1;
aboutText.alpha = 1;
exitButton.alpha = 1;
exitText.alpha = 1;
storyText.alpha = 0;
// Hide game UI
atpBarBackground.alpha = 0;
atpBar.alpha = 0;
atpGlow.alpha = 0;
atpText.alpha = 0;
resourceText.alpha = 0;
glucoseIcon.alpha = 0;
glucoseText.alpha = 0;
aminoIcon.alpha = 0;
aminoText.alpha = 0;
lipidIcon.alpha = 0;
lipidText.alpha = 0;
instructionText.alpha = 0;
// Hide E.L.Y.S.
if (elys) elys.alpha = 0;
if (elysglow) elysglow.alpha = 0;
}
function hideMainMenu() {
titleText.alpha = 0;
subtitleText.alpha = 0;
beginButton.alpha = 0;
continueButton.alpha = 0;
aboutButton.alpha = 0;
beginText.alpha = 0;
continueText.alpha = 0;
aboutText.alpha = 0;
exitButton.alpha = 0;
exitText.alpha = 0;
// Show game UI
atpBarBackground.alpha = 1;
atpBar.alpha = 1;
atpGlow.alpha = 0.5;
atpText.alpha = 1;
resourceText.alpha = 1;
glucoseIcon.alpha = 1;
glucoseText.alpha = 1;
aminoIcon.alpha = 1;
aminoText.alpha = 1;
lipidIcon.alpha = 1;
lipidText.alpha = 1;
instructionText.alpha = 1;
// Show E.L.Y.S.
if (elys) elys.alpha = 1;
if (elysglow) elysglow.alpha = 0.3;
}
function showIntroSequence() {
gameState = 'intro';
hideMainMenu();
// Create cinematic spark effect
var spark = game.addChild(LK.getAsset('elys', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.1,
scaleY: 0.1,
alpha: 0,
tint: 0xFFFFFF
}));
spark.x = 1024;
spark.y = 200;
// Show E.L.Y.S. and glows during intro
if (elys) {
elys.alpha = 0.3;
elys.x = 1024;
elys.y = 1366;
}
if (elysglow) {
elysglow.alpha = 0.1;
elysglow.x = 1024;
elysglow.y = 1366;
}
if (elysOuterGlow) {
elysOuterGlow.alpha = 0.05;
elysOuterGlow.x = 1024;
elysOuterGlow.y = 1366;
}
if (elysPulse) {
elysPulse.alpha = 0.2;
elysPulse.x = 1024;
elysPulse.y = 1366;
}
// Animate spark falling
tween(spark, {
y: 1366,
alpha: 1,
scaleX: 0.5,
scaleY: 0.5
}, {
duration: 2000,
easing: tween.easeOut,
onFinish: function onFinish() {
// Spark impact effect
LK.effects.flashScreen(0x00FFFF, 800);
// Show E.L.Y.S. awakening
if (elys) {
tween(elys, {
alpha: 1
}, {
duration: 1000
});
}
if (elysglow) {
tween(elysglow, {
alpha: 0.4
}, {
duration: 1000
});
}
if (elysOuterGlow) {
tween(elysOuterGlow, {
alpha: 0.15
}, {
duration: 1000
});
}
if (elysPulse) {
tween(elysPulse, {
alpha: 0.8
}, {
duration: 1000
});
}
tween(spark, {
scaleX: 2.0,
scaleY: 2.0,
alpha: 0
}, {
duration: 1000,
onFinish: function onFinish() {
spark.destroy();
}
});
}
});
storyText.alpha = 1;
storyText.setText('In an ancient and silent planet,\na single spark of life called E.L.Y.S. awakens\nin the midst of darkness...');
storyText.tint = 0x88CCFF;
// Animate intro text with glow effect
tween(storyText, {
alpha: 1,
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 2000,
easing: tween.easeOut,
onFinish: function onFinish() {
LK.setTimeout(function () {
tween(storyText, {
alpha: 0,
y: storyText.y - 100
}, {
duration: 1000,
easing: tween.easeIn,
onFinish: function onFinish() {
storyText.y = 1366; // Reset position
startGame();
}
});
}, 3000);
}
});
}
function startGame() {
gameState = 'playing';
storyText.alpha = 0;
hideMainMenu();
// Reset game variables
currentATP = 50;
glucoseCount = 0;
aminoAcidCount = 0;
lipidCount = 0;
worldBrightness = 0.2;
currentLevel = 1;
// Clear existing game objects
for (var i = molecules.length - 1; i >= 0; i--) {
molecules[i].destroy();
molecules.splice(i, 1);
}
for (var i = organelles.length - 1; i >= 0; i--) {
organelles[i].destroy();
organelles.splice(i, 1);
}
for (var i = toxins.length - 1; i >= 0; i--) {
toxins[i].destroy();
toxins.splice(i, 1);
}
// Reset E.L.Y.S. position and ensure it's visible
elys.x = 1024;
elys.y = 1366;
elys.alpha = 1;
elys.targetX = elys.x;
elys.targetY = elys.y;
elys.velocity = {
x: 0,
y: 0
};
// Update all glow effects positions
elysglow.x = elys.x;
elysglow.y = elys.y;
elysglow.alpha = 0.4;
elysOuterGlow.x = elys.x;
elysOuterGlow.y = elys.y;
elysOuterGlow.alpha = 0.15;
elysPulse.x = elys.x;
elysPulse.y = elys.y;
elysPulse.alpha = 0.8;
// Initialize starting molecules and toxins
for (var i = 0; i < 15; i++) {
spawnMolecule();
}
for (var i = 0; i < 3; i++) {
spawnToxin();
}
// Start background music
LK.playMusic('song', {
fade: {
start: 0,
end: 0.6,
duration: 2000
}
});
}
// Helper functions
function updateUI() {
var atpPercent = currentATP / maxATP;
// Smooth ATP bar animation
tween(atpBar, {
scaleX: 4 * atpPercent
}, {
duration: 200,
easing: tween.easeOut
});
tween(atpGlow, {
scaleX: 4 * atpPercent
}, {
duration: 300,
easing: tween.easeOut
});
// Dynamic color transitions
if (atpPercent > 0.6) {
tween(atpBar, {
tint: 0x00AAFF
}, {
duration: 300
});
tween(atpGlow, {
tint: 0x00FFFF
}, {
duration: 300
});
} else if (atpPercent > 0.3) {
tween(atpBar, {
tint: 0xFFAA00
}, {
duration: 300
});
tween(atpGlow, {
tint: 0xFFFF00
}, {
duration: 300
});
} else {
tween(atpBar, {
tint: 0xFF3300
}, {
duration: 300
});
tween(atpGlow, {
tint: 0xFF0000
}, {
duration: 300
});
}
// Pulsing glow effect
atpGlow.alpha = 0.3 + Math.sin(LK.ticks * 0.1) * 0.2;
atpText.setText('ENERGY: ' + Math.floor(currentATP) + '/' + maxATP);
glucoseText.setText(glucoseCount);
aminoText.setText(aminoAcidCount);
lipidText.setText(lipidCount);
// Update E.L.Y.S. glow based on energy with enhanced effects
var targetAlpha = 0.6 + atpPercent * 0.4;
var targetScale = 0.9 + atpPercent * 0.3;
var energyTint = atpPercent > 0.6 ? 0x00FFFF : atpPercent > 0.3 ? 0xFFFF00 : 0xFF3300;
tween(elys, {
alpha: targetAlpha,
tint: energyTint
}, {
duration: 300
});
tween(elysglow, {
scaleX: 1.8 + targetScale,
scaleY: 1.8 + targetScale,
alpha: 0.3 + atpPercent * 0.2,
tint: energyTint
}, {
duration: 500
});
// Update outer glow
tween(elysOuterGlow, {
scaleX: 2.5 + targetScale,
scaleY: 2.5 + targetScale,
alpha: 0.1 + atpPercent * 0.1
}, {
duration: 800
});
// Pulsating core effect
var pulseIntensity = 0.6 + Math.sin(LK.ticks * 0.08) * 0.2;
tween(elysPulse, {
alpha: pulseIntensity,
scaleX: 0.7 + pulseIntensity * 0.2,
scaleY: 0.7 + pulseIntensity * 0.2
}, {
duration: 200
});
// Dynamic space background with exciting effects
backgroundPhase += 0.015;
var colorIndex = Math.floor(backgroundPhase) % backgroundColors.length;
var nextColorIndex = (colorIndex + 1) % backgroundColors.length;
var lerpFactor = backgroundPhase - Math.floor(backgroundPhase);
var currentBg = backgroundColors[colorIndex];
game.setBackgroundColor(currentBg);
// Animate twinkling stars
for (var i = 0; i < starField.length; i++) {
var star = starField[i];
star.alpha = 0.3 + Math.sin(LK.ticks * star.twinkleSpeed + star.twinkleOffset) * 0.4 + Math.random() * 0.2;
// Some stars slowly drift
if (i % 5 === 0) {
star.x += Math.sin(LK.ticks * 0.001 + i) * 0.1;
star.y += Math.cos(LK.ticks * 0.0008 + i) * 0.1;
}
}
// Animate nebula clouds with gentle drift and color shifts
for (var i = 0; i < nebulaClouds.length; i++) {
var cloud = nebulaClouds[i];
cloud.x += Math.cos(cloud.driftDirection) * cloud.driftSpeed;
cloud.y += Math.sin(cloud.driftDirection) * cloud.driftSpeed;
// Wrap around screen edges
if (cloud.x > 2100) cloud.x = -100;
if (cloud.x < -100) cloud.x = 2100;
if (cloud.y > 2800) cloud.y = -100;
if (cloud.y < -100) cloud.y = 2800;
// Subtle alpha pulsing for mystical effect
cloud.alpha = 0.1 + Math.sin(LK.ticks * 0.008 + i) * 0.1;
// Occasional color shifts for dynamic feel
if (LK.ticks % 600 === i * 20) {
var newColors = [0xff00ff, 0x00ffff, 0xff8800, 0x8800ff, 0x00ff88, 0xff4080, 0x4080ff];
tween(cloud, {
tint: newColors[Math.floor(Math.random() * newColors.length)]
}, {
duration: 2000,
easing: tween.easeInOut
});
}
}
// Update narrative system
if (gameState === 'playing') {
narrativeTimer++;
if (narrativeTimer > 1200) {
// Show narrative every 20 seconds
narrativeTimer = 0;
floatingNarrative.setText(narrativeTexts[currentNarrative]);
floatingNarrative.x = 1024 + (Math.random() - 0.5) * 400;
floatingNarrative.y = 1366 + (Math.random() - 0.5) * 300;
// Animate floating narrative
tween(floatingNarrative, {
alpha: 0.8
}, {
duration: 500,
onFinish: function onFinish() {
LK.setTimeout(function () {
tween(floatingNarrative, {
alpha: 0,
y: floatingNarrative.y - 50
}, {
duration: 1000
});
}, 2000);
}
});
currentNarrative = (currentNarrative + 1) % narrativeTexts.length;
}
// Update world transformation based on progress
var progress = organelles.length / 5;
worldBrightness = 0.2 + progress * 0.8;
// Transform environment colors as progress increases
if (progress > 0.8) {
// Final transformation - vibrant life
game.setBackgroundColor(0x002244);
for (var i = 0; i < starField.length; i++) {
starField[i].tint = 0xffff88;
starField[i].alpha = 0.8 + Math.sin(LK.ticks * 0.05 + i) * 0.2;
}
} else if (progress > 0.6) {
// Growing life
game.setBackgroundColor(0x001833);
} else if (progress > 0.4) {
// First signs of life
game.setBackgroundColor(0x001122);
}
// Update level display with glow effect
instructionText.setText('Level ' + currentLevel + ': ' + levelNames[currentLevel - 1]);
instructionText.tint = 0xFFFF88 + Math.floor(Math.sin(LK.ticks * 0.05) * 0x003300);
// Update hint system
if (gameState === 'playing') {
hintTimer++;
if (hintTimer > 900 && hintText.alpha === 0) {
// Show hint every 15 seconds
hintText.setText(hints[currentHint]);
tween(hintText, {
alpha: 0.8
}, {
duration: 500,
onFinish: function onFinish() {
LK.setTimeout(function () {
tween(hintText, {
alpha: 0
}, {
duration: 500
});
}, 3000);
}
});
currentHint = (currentHint + 1) % hints.length;
hintTimer = 0;
}
}
}
}
function buildOrganelle(type) {
var cost = type === 'mitochondria' ? {
glucose: 3,
aminoAcid: 2
} : {
glucose: 2,
lipid: 2
};
if ((cost.glucose || 0) <= glucoseCount && (cost.aminoAcid || 0) <= aminoAcidCount && (cost.lipid || 0) <= lipidCount) {
glucoseCount -= cost.glucose || 0;
aminoAcidCount -= cost.aminoAcid || 0;
lipidCount -= cost.lipid || 0;
var organelle = game.addChild(new Organelle(type, elys.x + (Math.random() - 0.5) * 200, elys.y + (Math.random() - 0.5) * 200));
organelles.push(organelle);
organelle.activate();
worldBrightness = Math.min(1.0, worldBrightness + 0.1);
LK.getSound('build').play();
LK.effects.flashObject(organelle, 0x00ffff, 500);
return true;
}
return false;
}
// Event handlers
function handleMove(x, y, obj) {
if (dragNode) {
// Smooth movement with physics
dragNode.targetX = x;
dragNode.targetY = y;
// Add momentum and fluid movement
var dx = dragNode.targetX - dragNode.x;
var dy = dragNode.targetY - dragNode.y;
dragNode.velocity.x += dx * 0.1;
dragNode.velocity.y += dy * 0.1;
dragNode.velocity.x *= 0.85;
dragNode.velocity.y *= 0.85;
dragNode.x += dragNode.velocity.x;
dragNode.y += dragNode.velocity.y;
// Update all glow effects positions smoothly
tween(elysglow, {
x: dragNode.x,
y: dragNode.y
}, {
duration: 100,
easing: tween.easeOut
});
tween(elysOuterGlow, {
x: dragNode.x,
y: dragNode.y
}, {
duration: 150,
easing: tween.easeOut
});
tween(elysPulse, {
x: dragNode.x,
y: dragNode.y
}, {
duration: 80,
easing: tween.easeOut
});
// Moving costs energy with visual feedback
if (LK.ticks % 10 === 0) {
currentATP = Math.max(0, currentATP - 0.5);
// Create trailing particle effect when moving fast
var speed = Math.sqrt(dragNode.velocity.x * dragNode.velocity.x + dragNode.velocity.y * dragNode.velocity.y);
if (speed > 2) {
elysglow.alpha = 0.5 + speed * 0.1;
}
}
}
}
game.move = function (x, y, obj) {
// Handle game movement
handleMove(x, y, obj);
};
game.down = function (x, y, obj) {
dragNode = elys;
handleMove(x, y, obj);
// Try building organelles on double tap
if (glucoseCount >= 3 && aminoAcidCount >= 2) {
buildOrganelle('mitochondria');
} else if (glucoseCount >= 2 && lipidCount >= 2) {
buildOrganelle('chloroplast');
}
};
game.up = function (x, y, obj) {
dragNode = null;
};
// Main game loop
game.update = function () {
// Update UI
updateUI();
// Only run game logic when playing
if (gameState !== 'playing') {
return;
}
// Initialize molecules and toxins when starting to play
if (molecules.length === 0 && toxins.length === 0) {
for (var i = 0; i < 15; i++) {
spawnMolecule();
}
for (var i = 0; i < 3; i++) {
spawnToxin();
}
}
// Check for game over
if (currentATP <= 0) {
LK.effects.flashScreen(0xff0000, 1000);
LK.showGameOver();
return;
}
// ATP decay over time
if (LK.ticks % 120 === 0) {
currentATP = Math.max(0, currentATP - 1);
}
// Check molecule collection
for (var i = molecules.length - 1; i >= 0; i--) {
var molecule = molecules[i];
if (elys.intersects(molecule)) {
// Create floating text feedback
var collectText = new Text2('', {
size: 28,
fill: '#FFFFFF'
});
collectText.anchor.set(0.5, 0.5);
collectText.x = molecule.x;
collectText.y = molecule.y;
game.addChild(collectText);
// Collect molecule with specific feedback
if (molecule.type === 'glucose') {
glucoseCount++;
collectText.setText('Glucose +' + molecule.value);
collectText.fill = '#FFFF00';
tween(glucoseIcon, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 150,
onFinish: function onFinish() {
tween(glucoseIcon, {
scaleX: 0.9,
scaleY: 0.9
}, {
duration: 150
});
}
});
} else if (molecule.type === 'aminoAcid') {
aminoAcidCount++;
collectText.setText('Amino Acid +' + molecule.value);
collectText.fill = '#FF8800';
tween(aminoIcon, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 150,
onFinish: function onFinish() {
tween(aminoIcon, {
scaleX: 0.9,
scaleY: 0.9
}, {
duration: 150
});
}
});
} else if (molecule.type === 'lipid') {
lipidCount++;
collectText.setText('Lipid +' + molecule.value);
collectText.fill = '#FF0080';
tween(lipidIcon, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 150,
onFinish: function onFinish() {
tween(lipidIcon, {
scaleX: 0.9,
scaleY: 0.9
}, {
duration: 150
});
}
});
}
// Animate floating text
tween(collectText, {
y: collectText.y - 80,
alpha: 0
}, {
duration: 1000,
easing: tween.easeOut,
onFinish: function onFinish() {
collectText.destroy();
}
});
currentATP = Math.min(maxATP, currentATP + molecule.value);
LK.getSound('collect').play();
LK.effects.flashObject(elys, 0x00ff00, 300);
// Enhance collection effect
tween(elys, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 150,
onFinish: function onFinish() {
tween(elys, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 150
});
}
});
molecule.destroy();
molecules.splice(i, 1);
}
}
// Check toxin collision
for (var i = toxins.length - 1; i >= 0; i--) {
var toxin = toxins[i];
if (elys.intersects(toxin)) {
currentATP = Math.max(0, currentATP - toxin.damage);
LK.getSound('damage').play();
LK.effects.flashObject(elys, 0xff0000, 500);
LK.effects.flashScreen(0xff0000, 200);
// Remove toxin after hit
toxin.destroy();
toxins.splice(i, 1);
}
}
// Spawn new molecules periodically
if (LK.ticks % 300 === 0 && molecules.length < 20) {
spawnMolecule();
}
// Spawn new toxins occasionally
if (LK.ticks % 600 === 0 && toxins.length < 5) {
spawnToxin();
}
// Check win condition with epic ending
if (organelles.length >= 5 && worldBrightness >= 0.8) {
// Epic planetary restoration effect
for (var i = 0; i < starField.length; i++) {
tween(starField[i], {
tint: 0xFFFF88,
alpha: 1.0,
scaleX: starField[i].scaleX * 2,
scaleY: starField[i].scaleY * 2
}, {
duration: 3000,
easing: tween.easeOut
});
}
// Transform nebula to living colors
for (var i = 0; i < nebulaClouds.length; i++) {
tween(nebulaClouds[i], {
tint: 0x00FF88,
alpha: 0.6,
scaleX: nebulaClouds[i].scaleX * 1.5,
scaleY: nebulaClouds[i].scaleY * 1.5
}, {
duration: 4000,
easing: tween.easeOut
});
}
// Show final transformation
floatingNarrative.setText('Life connects everything.\nEnergy is the link.');
floatingNarrative.x = 1024;
floatingNarrative.y = 1366;
floatingNarrative.tint = 0x00FFAA;
tween(floatingNarrative, {
alpha: 1,
scaleX: 2.0,
scaleY: 2.0
}, {
duration: 3000,
easing: tween.easeOut,
onFinish: function onFinish() {
// Create energy pulse from center
LK.effects.flashScreen(0x00FFFF, 1000);
LK.setTimeout(function () {
LK.effects.flashScreen(0x00ff88, 2000);
// Play victory sound
LK.getSound('energyPulse').play();
LK.showYouWin();
}, 1500);
}
});
}
// Update score based on organelles built
LK.setScore(organelles.length * 100 + Math.floor(worldBrightness * 500));
};