/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var BackButton = Container.expand(function () {
var self = Container.call(this);
var buttonBg = self.attachAsset('backButton', {
anchorX: 0.5,
anchorY: 0.5
});
self.down = function (x, y, obj) {
tween(self.scale, {
x: 0.9,
y: 0.9
}, {
duration: 200
});
};
self.up = function (x, y, obj) {
tween(self.scale, {
x: 1.0,
y: 1.0
}, {
duration: 200
});
};
return self;
});
var Coin = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('coin', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 3;
self.lastY = undefined;
self.update = function () {
self.y += self.speed;
// Add floating animation
self.x += Math.sin(LK.ticks * 0.1 + self.y * 0.01) * 0.5;
// Add rotation
graphics.rotation += 0.05;
};
return self;
});
var Debris = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('debris', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 6;
self.lastY = undefined;
self.update = function () {
self.y += self.speed;
};
return self;
});
var ImmunityPower = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('immunityPower', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 2;
self.lastY = undefined;
self.update = function () {
self.y += self.speed;
// Add pulsing animation
graphics.scaleX = 1 + Math.sin(LK.ticks * 0.1) * 0.2;
graphics.scaleY = 1 + Math.sin(LK.ticks * 0.1) * 0.2;
// Add rotation
graphics.rotation += 0.03;
};
return self;
});
var MenuButton = Container.expand(function (color) {
var self = Container.call(this);
var buttonBg = self.attachAsset('menuButton', {
anchorX: 0.5,
anchorY: 0.5
});
if (color) buttonBg.tint = color;
self.down = function (x, y, obj) {
tween(self.scale, {
x: 0.9,
y: 0.9
}, {
duration: 200
});
};
self.up = function (x, y, obj) {
tween(self.scale, {
x: 1.0,
y: 1.0
}, {
duration: 200
});
};
return self;
});
var Meteorite = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('meteorite', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 4;
self.lastY = undefined;
self.update = function () {
self.y += self.speed;
};
return self;
});
var Projectile = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('boostButton', {
anchorX: 0.5,
anchorY: 0.5
});
graphics.scaleX = 0.3;
graphics.scaleY = 0.3;
self.speed = -8;
self.lastY = undefined;
self.update = function () {
self.y += self.speed;
};
return self;
});
var SensitivitySlider = Container.expand(function () {
var self = Container.call(this);
var sliderBar = self.attachAsset('sensSlider', {
anchorX: 0.5,
anchorY: 0.5
});
var sliderHandle = self.addChild(LK.getAsset('sensHandle', {
anchorX: 0.5,
anchorY: 0.5
}));
self.minX = -280;
self.maxX = 280;
self.isDragging = false;
self.down = function (x, y, obj) {
self.isDragging = true;
self.updateHandle(x);
};
self.up = function (x, y, obj) {
self.isDragging = false;
};
self.updateHandle = function (x) {
var localX = x - self.x;
localX = Math.max(self.minX, Math.min(self.maxX, localX));
sliderHandle.x = localX;
};
self.getSensitivity = function () {
return (sliderHandle.x + 280) / 560; // 0 to 1
};
self.setSensitivity = function (value) {
sliderHandle.x = value * 560 - 280;
};
return self;
});
var SettingsButton = Container.expand(function () {
var self = Container.call(this);
var buttonBg = self.attachAsset('settingsButton', {
anchorX: 0.5,
anchorY: 0.5
});
self.down = function (x, y, obj) {
tween(self.scale, {
x: 0.9,
y: 0.9
}, {
duration: 200
});
};
self.up = function (x, y, obj) {
tween(self.scale, {
x: 1.0,
y: 1.0
}, {
duration: 200
});
};
return self;
});
var Spaceship = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('spaceship', {
anchorX: 0.5,
anchorY: 0.5
});
return self;
});
var StartButton = Container.expand(function () {
var self = Container.call(this);
var buttonBg = self.attachAsset('startButton', {
anchorX: 0.5,
anchorY: 0.5
});
self.down = function (x, y, obj) {
tween(self.scale, {
x: 0.9,
y: 0.9
}, {
duration: 200
});
};
self.up = function (x, y, obj) {
tween(self.scale, {
x: 1.0,
y: 1.0
}, {
duration: 200
});
};
return self;
});
var TouchSlider = Container.expand(function () {
var self = Container.call(this);
var sliderBar = self.attachAsset('sliderBar', {
anchorX: 0.5,
anchorY: 0.5
});
var sliderHandle = self.addChild(LK.getAsset('sliderHandle', {
anchorX: 0.5,
anchorY: 0.5
}));
self.minX = -380;
self.maxX = 380;
self.isDragging = false;
self.down = function (x, y, obj) {
self.isDragging = true;
self.updateHandle(x);
};
self.up = function (x, y, obj) {
self.isDragging = false;
};
self.updateHandle = function (x) {
var localX = x - self.x;
localX = Math.max(self.minX, Math.min(self.maxX, localX));
sliderHandle.x = localX;
};
self.getSliderValue = function () {
return sliderHandle.x / 380;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000011
});
/****
* Game Code
****/
// Game state management
var gameState = 'menu'; // 'menu', 'settings', 'playing', 'airplanes'
var sensitivity = storage.sensitivity || 1.0;
var selectedAirplane = storage.selectedAirplane || 'classic';
// Menu elements
var titleText = new Text2('Hasta el infinito y más allá', {
size: 110,
fill: 0xFFD700,
font: "'Press Start 2P', 'VT323', 'Pixel Emulator', 'Courier New', monospace"
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 2048 / 2;
titleText.y = 600;
game.addChild(titleText);
var startButton = game.addChild(new StartButton());
startButton.x = 2048 / 2;
startButton.y = 1200;
var settingsButton = game.addChild(new SettingsButton());
settingsButton.x = 2048 / 2;
settingsButton.y = 1400;
var airplaneButton = game.addChild(new MenuButton(0x44aa44));
airplaneButton.x = 2048 / 2;
airplaneButton.y = 1600;
// Settings menu elements (initially hidden)
var settingsTitle = new Text2('AJUSTAR SENSIBILIDAD', {
size: 80,
fill: 0xFFFFFF
});
settingsTitle.anchor.set(0.5, 0.5);
settingsTitle.x = 2048 / 2;
settingsTitle.y = 800;
settingsTitle.visible = false;
game.addChild(settingsTitle);
var sensitivitySlider = game.addChild(new SensitivitySlider());
sensitivitySlider.x = 2048 / 2;
sensitivitySlider.y = 1200;
sensitivitySlider.visible = false;
sensitivitySlider.setSensitivity(sensitivity);
var sensValueText = new Text2('Sensibilidad: ' + Math.round(sensitivity * 100) + '%', {
size: 60,
fill: 0xFFFFFF
});
sensValueText.anchor.set(0.5, 0.5);
sensValueText.x = 2048 / 2;
sensValueText.y = 1350;
sensValueText.visible = false;
game.addChild(sensValueText);
var backButton = game.addChild(new BackButton());
backButton.x = 2048 / 2;
backButton.y = 1500;
backButton.visible = false;
// Airplane selection menu elements (initially hidden)
var airplaneTitle = new Text2('ELEGIR AVIÓN', {
size: 80,
fill: 0xFFFFFF
});
airplaneTitle.anchor.set(0.5, 0.5);
airplaneTitle.x = 2048 / 2;
airplaneTitle.y = 600;
airplaneTitle.visible = false;
game.addChild(airplaneTitle);
var airplane1Button = game.addChild(new MenuButton(0x4444aa));
airplane1Button.x = 2048 / 2;
airplane1Button.y = 1000;
airplane1Button.visible = false;
var airplane2Button = game.addChild(new MenuButton(0xaa4444));
airplane2Button.x = 2048 / 2;
airplane2Button.y = 1200;
airplane2Button.visible = false;
var airplane3Button = game.addChild(new MenuButton(0x44aa44));
airplane3Button.x = 2048 / 2;
airplane3Button.y = 1400;
airplane3Button.visible = false;
var airplaneBackButton = game.addChild(new BackButton());
airplaneBackButton.x = 2048 / 2;
airplaneBackButton.y = 1600;
airplaneBackButton.visible = false;
// Decorative elements
var stars = [];
for (var i = 0; i < 50; i++) {
var star = game.addChild(LK.getAsset('star', {
anchorX: 0.5,
anchorY: 0.5
}));
star.x = Math.random() * 2048;
star.y = Math.random() * 2732;
star.alpha = Math.random() * 0.8 + 0.2;
stars.push(star);
}
var planet1 = game.addChild(LK.getAsset('planet', {
anchorX: 0.5,
anchorY: 0.5
}));
planet1.x = 200;
planet1.y = 300;
planet1.alpha = 0.6;
planet1.tint = 0x8888ff;
var planet2 = game.addChild(LK.getAsset('planet', {
anchorX: 0.5,
anchorY: 0.5
}));
planet2.x = 1800;
planet2.y = 2400;
planet2.alpha = 0.4;
planet2.tint = 0xff8888;
planet2.scaleX = 0.7;
planet2.scaleY = 0.7;
// Game elements (initially hidden)
var spaceship;
var obstacles = [];
var coins = [];
var coinSpawnTimer = 0;
var coinSpawnRate = 180;
var totalCoins = storage.totalCoins || 0;
var obstacleSpawnTimer = 0;
var obstacleSpawnRate = 90;
var gameSpeed = 1;
var spaceshipSpeed = 1;
var survivalTime = 0;
var difficultyTimer = 0;
var lastScoreCheck = 0;
var speedIncreaseTimer = 0;
var slider;
// Heart system variables
var hearts = 3;
var heartElements = [];
// Immunity power variables
var immunityPowers = [];
var immunitySpawnTimer = 0;
var immunitySpawnRate = 1500; // 25 seconds at 60 FPS
var isImmune = false;
var immunityDuration = 0;
var immunityMaxDuration = 600; // 10 seconds at 60 FPS
// Boost power variables
var isBoostActive = false;
var boostDuration = 0;
var boostMaxDuration = 1200; // 20 seconds at 60 FPS
var boostMultiplier = 2.5;
var boostCooldown = 0;
var boostMaxCooldown = 1800; // 30 seconds cooldown
// Shooting system variables
var projectiles = [];
var shootCooldown = 0;
var shootMaxCooldown = 900; // 15 seconds at 60 FPS
var canShoot = true;
// GUI elements (created but initially hidden)
var scoreTxt = new Text2('0', {
size: 80,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
scoreTxt.visible = false;
LK.gui.top.addChild(scoreTxt);
var timeTxt = new Text2('Time: 0s', {
size: 60,
fill: 0xFFFFFF
});
timeTxt.anchor.set(1, 0);
timeTxt.visible = false;
LK.gui.topRight.addChild(timeTxt);
timeTxt.x = -20;
timeTxt.y = 100;
var coinsTxt = new Text2('Coins: ' + totalCoins, {
size: 50,
fill: 0xffd700
});
coinsTxt.anchor.set(0, 0);
coinsTxt.visible = false;
LK.gui.topLeft.addChild(coinsTxt);
coinsTxt.x = 120;
coinsTxt.y = 20;
var shootButton = LK.getAsset('boostButton', {
anchorX: 0.5,
anchorY: 0.5
});
shootButton.visible = false;
LK.gui.bottomRight.addChild(shootButton);
shootButton.x = -120;
shootButton.y = -120;
var shootStatusText = new Text2('SHOOT READY', {
size: 40,
fill: 0xff6600
});
shootStatusText.anchor.set(0.5, 0.5);
shootStatusText.visible = false;
LK.gui.bottom.addChild(shootStatusText);
shootStatusText.y = -180;
// Add cooldown indicator circle
var cooldownIndicator = LK.getAsset('boostButton', {
anchorX: 0.5,
anchorY: 0.5
});
cooldownIndicator.visible = false;
cooldownIndicator.alpha = 0.3;
cooldownIndicator.tint = 0x000000;
LK.gui.bottomRight.addChild(cooldownIndicator);
cooldownIndicator.x = -120;
cooldownIndicator.y = -120;
// Create heart GUI elements
for (var h = 0; h < 3; h++) {
var heartGui = LK.getAsset('heart', {
anchorX: 0.5,
anchorY: 0.5
});
heartGui.visible = false;
LK.gui.topRight.addChild(heartGui);
heartGui.x = -280 + h * 90;
heartGui.y = 40;
heartElements.push(heartGui);
}
var immunityStatusText = new Text2('', {
size: 50,
fill: 0x00ff88
});
immunityStatusText.anchor.set(0.5, 0.5);
immunityStatusText.visible = false;
LK.gui.center.addChild(immunityStatusText);
immunityStatusText.y = -200;
game.move = function (x, y, obj) {
if (gameState === 'playing' && slider && slider.isDragging) {
slider.updateHandle(x);
var sliderValue = slider.getSliderValue();
var currentSpeed = spaceshipSpeed * (isBoostActive ? boostMultiplier : 1);
spaceship.x = 2048 / 2 + sliderValue * 800 * currentSpeed * sensitivity;
spaceship.x = Math.max(100, Math.min(1948, spaceship.x));
} else if (gameState === 'settings' && sensitivitySlider.isDragging) {
sensitivitySlider.updateHandle(x);
sensitivity = sensitivitySlider.getSensitivity();
sensValueText.setText('Sensibilidad: ' + Math.round(sensitivity * 100) + '%');
storage.sensitivity = sensitivity;
}
};
// Add shoot button click handler
shootButton.down = function (x, y, obj) {
if (gameState === 'playing' && canShoot && shootCooldown <= 0) {
// Fire projectile
var projectile = new Projectile();
projectile.x = spaceship.x;
projectile.y = spaceship.y - 50;
projectile.lastY = projectile.y;
projectiles.push(projectile);
game.addChild(projectile);
// Play shooting sound
LK.getSound('shoot').play();
// Start cooldown
canShoot = false;
shootCooldown = shootMaxCooldown;
shootStatusText.setText('RELOADING...');
shootStatusText.fill = 0xff0000;
shootButton.tint = 0x666666;
// Button press animation
tween(shootButton.scale, {
x: 0.9,
y: 0.9
}, {
duration: 100,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(shootButton.scale, {
x: 1.0,
y: 1.0
}, {
duration: 100,
easing: tween.easeIn
});
}
});
}
};
shootButton.up = function (x, y, obj) {
// Reset button scale on release
tween(shootButton.scale, {
x: 1.0,
y: 1.0
}, {
duration: 100,
easing: tween.easeOut
});
};
game.down = function (x, y, obj) {
// Game down handler for other interactions
};
// Button handlers
startButton.up = function (x, y, obj) {
tween(startButton.scale, {
x: 1.0,
y: 1.0
}, {
duration: 200
});
startGame();
};
settingsButton.up = function (x, y, obj) {
tween(settingsButton.scale, {
x: 1.0,
y: 1.0
}, {
duration: 200
});
showSettings();
};
backButton.up = function (x, y, obj) {
tween(backButton.scale, {
x: 1.0,
y: 1.0
}, {
duration: 200
});
showMenu();
};
airplaneButton.up = function (x, y, obj) {
tween(airplaneButton.scale, {
x: 1.0,
y: 1.0
}, {
duration: 200
});
showAirplaneSelection();
};
airplane1Button.up = function (x, y, obj) {
tween(airplane1Button.scale, {
x: 1.0,
y: 1.0
}, {
duration: 200
});
selectedAirplane = 'classic';
storage.selectedAirplane = selectedAirplane;
showMenu();
};
airplane2Button.up = function (x, y, obj) {
tween(airplane2Button.scale, {
x: 1.0,
y: 1.0
}, {
duration: 200
});
selectedAirplane = 'fast';
storage.selectedAirplane = selectedAirplane;
showMenu();
};
airplane3Button.up = function (x, y, obj) {
tween(airplane3Button.scale, {
x: 1.0,
y: 1.0
}, {
duration: 200
});
selectedAirplane = 'robust';
storage.selectedAirplane = selectedAirplane;
showMenu();
};
airplaneBackButton.up = function (x, y, obj) {
tween(airplaneBackButton.scale, {
x: 1.0,
y: 1.0
}, {
duration: 200
});
showMenu();
};
function startGame() {
gameState = 'playing';
// Hide menu elements
titleText.visible = false;
startButton.visible = false;
settingsButton.visible = false;
airplaneButton.visible = false;
// Show game elements
spaceship = game.addChild(new Spaceship());
spaceship.x = 2048 / 2;
spaceship.y = 2000;
slider = game.addChild(new TouchSlider());
slider.x = 2048 / 2;
slider.y = 2600;
scoreTxt.visible = true;
timeTxt.visible = true;
// Reset game variables
obstacles = [];
coins = [];
coinSpawnTimer = 0;
obstacleSpawnTimer = 0;
obstacleSpawnRate = 90;
coinSpawnRate = 180;
gameSpeed = 1;
spaceshipSpeed = 1;
survivalTime = 0;
difficultyTimer = 0;
speedIncreaseTimer = 0;
lastScoreCheck = 0;
LK.setScore(0);
scoreTxt.setText('0');
timeTxt.setText('Time: 0s');
coinsTxt.visible = true;
coinsTxt.setText('Coins: ' + totalCoins);
// Reset heart system
hearts = 3;
for (var h = 0; h < heartElements.length; h++) {
heartElements[h].visible = true;
heartElements[h].alpha = 1;
}
// Reset immunity power system
immunityPowers = [];
immunitySpawnTimer = 0;
isImmune = false;
immunityDuration = 0;
immunityStatusText.visible = false;
// Show shooting elements
shootButton.visible = true;
shootStatusText.visible = true;
cooldownIndicator.visible = true;
projectiles = [];
canShoot = true;
shootCooldown = 0;
shootStatusText.setText('SHOOT READY');
shootStatusText.fill = 0xff6600;
shootButton.tint = 0xff6600;
cooldownIndicator.scaleX = 0;
cooldownIndicator.scaleY = 0;
// Start background music
LK.playMusic('bgMusic');
}
function showSettings() {
gameState = 'settings';
// Hide menu elements
titleText.visible = false;
startButton.visible = false;
settingsButton.visible = false;
airplaneButton.visible = false;
coinsTxt.visible = false;
shootButton.visible = false;
shootStatusText.visible = false;
cooldownIndicator.visible = false;
// Hide heart elements
for (var h = 0; h < heartElements.length; h++) {
heartElements[h].visible = false;
}
immunityStatusText.visible = false;
// Hide heart elements
for (var h = 0; h < heartElements.length; h++) {
heartElements[h].visible = false;
}
immunityStatusText.visible = false;
// Hide heart elements
for (var h = 0; h < heartElements.length; h++) {
heartElements[h].visible = false;
}
immunityStatusText.visible = false;
// Show settings elements
settingsTitle.visible = true;
sensitivitySlider.visible = true;
sensValueText.visible = true;
backButton.visible = true;
}
function showAirplaneSelection() {
gameState = 'airplanes';
// Hide menu elements
titleText.visible = false;
startButton.visible = false;
settingsButton.visible = false;
airplaneButton.visible = false;
coinsTxt.visible = false;
shootButton.visible = false;
shootStatusText.visible = false;
cooldownIndicator.visible = false;
// Show airplane selection elements
airplaneTitle.visible = true;
airplane1Button.visible = true;
airplane2Button.visible = true;
airplane3Button.visible = true;
airplaneBackButton.visible = true;
}
function showMenu() {
gameState = 'menu';
// Hide settings elements
settingsTitle.visible = false;
sensitivitySlider.visible = false;
sensValueText.visible = false;
backButton.visible = false;
// Hide airplane selection elements
airplaneTitle.visible = false;
airplane1Button.visible = false;
airplane2Button.visible = false;
airplane3Button.visible = false;
airplaneBackButton.visible = false;
// Hide game elements if they exist
if (spaceship) {
spaceship.destroy();
spaceship = null;
}
if (slider) {
slider.destroy();
slider = null;
}
scoreTxt.visible = false;
timeTxt.visible = false;
coinsTxt.visible = false;
shootButton.visible = false;
shootStatusText.visible = false;
cooldownIndicator.visible = false;
// Clear obstacles
for (var i = 0; i < obstacles.length; i++) {
obstacles[i].destroy();
}
obstacles = [];
// Clear coins
for (var i = 0; i < coins.length; i++) {
coins[i].destroy();
}
coins = [];
// Clear immunity powers
for (var i = 0; i < immunityPowers.length; i++) {
immunityPowers[i].destroy();
}
immunityPowers = [];
// Clear projectiles
for (var i = 0; i < projectiles.length; i++) {
projectiles[i].destroy();
}
projectiles = [];
// Show menu elements
titleText.visible = true;
startButton.visible = true;
settingsButton.visible = true;
airplaneButton.visible = true;
// Stop background music
LK.stopMusic();
}
game.update = function () {
// Animate stars
for (var s = 0; s < stars.length; s++) {
stars[s].alpha = Math.sin(LK.ticks * 0.02 + s) * 0.3 + 0.5;
}
// Rotate planets slowly
planet1.rotation += 0.005;
planet2.rotation -= 0.003;
// Only run game logic during gameplay
if (gameState !== 'playing' || !spaceship) {
return;
}
// Handle shooting system cooldown
if (shootCooldown > 0) {
shootCooldown--;
var cooldownProgress = 1 - shootCooldown / shootMaxCooldown;
// Update cooldown indicator with growing circle animation
cooldownIndicator.scaleX = cooldownProgress;
cooldownIndicator.scaleY = cooldownProgress;
// Update status text with remaining time
var timeLeft = Math.ceil(shootCooldown / 60);
shootStatusText.setText('RELOAD: ' + timeLeft + 's');
if (shootCooldown <= 0) {
canShoot = true;
shootStatusText.setText('SHOOT READY');
shootStatusText.fill = 0xff6600;
shootButton.tint = 0xff6600;
cooldownIndicator.scaleX = 0;
cooldownIndicator.scaleY = 0;
}
}
// Update projectiles
for (var p = projectiles.length - 1; p >= 0; p--) {
var projectile = projectiles[p];
// Remove projectiles that go off screen
if (projectile.y < -100) {
projectile.destroy();
projectiles.splice(p, 1);
continue;
}
// Check projectile collision with obstacles
for (var o = obstacles.length - 1; o >= 0; o--) {
var obstacle = obstacles[o];
var dx = projectile.x - obstacle.x;
var dy = projectile.y - obstacle.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 100) {
// Explosion effect
tween(obstacle, {
scaleX: 2,
scaleY: 2,
alpha: 0
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
obstacle.destroy();
}
});
// Remove projectile
projectile.destroy();
projectiles.splice(p, 1);
// Remove obstacle
obstacles.splice(o, 1);
// Add score bonus
LK.setScore(LK.getScore() + 50);
scoreTxt.setText(LK.getScore());
// Play destroy sound
LK.getSound('destroy').play();
// Screen flash effect
LK.effects.flashScreen(0xffff00, 200);
break;
}
}
if (projectile.parent) {
projectile.lastY = projectile.y;
}
}
survivalTime++;
difficultyTimer++;
speedIncreaseTimer++;
if (survivalTime % 60 === 0) {
var seconds = Math.floor(survivalTime / 60);
timeTxt.setText('Time: ' + seconds + 's');
}
// Every 10 seconds (600 ticks), increase both airplane and obstacle speeds
if (speedIncreaseTimer >= 600) {
speedIncreaseTimer = 0;
gameSpeed *= 1.1; // Increase falling object speed by 10%
spaceshipSpeed *= 1.1; // Increase airplane speed by 10%
}
// Every 15 seconds (900 ticks), increase obstacle speed by 5%
if (difficultyTimer >= 900) {
difficultyTimer = 0;
gameSpeed *= 1.05;
obstacleSpawnRate = Math.max(30, obstacleSpawnRate - 5);
}
// Every 50 points, increase spaceship speed slightly
var currentScore = LK.getScore();
if (Math.floor(currentScore / 50) > Math.floor(lastScoreCheck / 50)) {
spaceshipSpeed += 0.1;
}
lastScoreCheck = currentScore;
obstacleSpawnTimer++;
if (obstacleSpawnTimer >= obstacleSpawnRate) {
obstacleSpawnTimer = 0;
var obstacle;
if (Math.random() < 0.7) {
obstacle = new Meteorite();
} else {
obstacle = new Debris();
}
obstacle.x = Math.random() * 1800 + 124;
obstacle.y = -100;
obstacle.speed *= gameSpeed;
obstacle.lastY = obstacle.y;
obstacles.push(obstacle);
game.addChild(obstacle);
}
// Spawn coins
coinSpawnTimer++;
if (coinSpawnTimer >= coinSpawnRate) {
coinSpawnTimer = 0;
var coin = new Coin();
coin.x = Math.random() * 1800 + 124;
coin.y = -100;
coin.speed *= gameSpeed;
coin.lastY = coin.y;
coins.push(coin);
game.addChild(coin);
}
// Spawn immunity powers every 25 seconds
immunitySpawnTimer++;
if (immunitySpawnTimer >= immunitySpawnRate) {
immunitySpawnTimer = 0;
var immunityPower = new ImmunityPower();
immunityPower.x = Math.random() * 1800 + 124;
immunityPower.y = -100;
immunityPower.speed *= gameSpeed;
immunityPower.lastY = immunityPower.y;
immunityPowers.push(immunityPower);
game.addChild(immunityPower);
}
// Update and check coin collection
for (var c = coins.length - 1; c >= 0; c--) {
var coin = coins[c];
// Remove coins that go off screen
if (coin.y > 2800) {
coin.destroy();
coins.splice(c, 1);
continue;
}
// Check coin collection with spaceship
var dx = spaceship.x - coin.x;
var dy = spaceship.y - coin.y;
var distance = Math.sqrt(dx * dx + dy * dy);
var collectionDistance = 80; // Generous collection radius
if (distance < collectionDistance) {
// Collect coin
totalCoins++;
storage.totalCoins = totalCoins;
coinsTxt.setText('Coins: ' + totalCoins);
// Play coin collection sound
LK.getSound('coinCollect').play();
// Add coin collection animation
tween(coin, {
scaleX: 2,
scaleY: 2,
alpha: 0
}, {
duration: 200,
onFinish: function onFinish() {
coin.destroy();
}
});
coins.splice(c, 1);
continue;
}
coin.lastY = coin.y;
}
// Handle immunity system
if (isImmune) {
immunityDuration--;
// Update immunity status text
var timeLeft = Math.ceil(immunityDuration / 60);
immunityStatusText.setText('IMMUNE: ' + timeLeft + 's');
immunityStatusText.visible = true;
// Add immunity visual effects to spaceship
if (LK.ticks % 20 === 0) {
tween(spaceship, {
alpha: 0.3
}, {
duration: 200,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(spaceship, {
alpha: 1.0
}, {
duration: 200,
easing: tween.easeInOut
});
}
});
}
if (immunityDuration <= 0) {
isImmune = false;
immunityStatusText.visible = false;
spaceship.alpha = 1.0;
}
}
// Update and check immunity power collection
for (var ip = immunityPowers.length - 1; ip >= 0; ip--) {
var immunityPower = immunityPowers[ip];
// Remove immunity powers that go off screen
if (immunityPower.y > 2800) {
immunityPower.destroy();
immunityPowers.splice(ip, 1);
continue;
}
// Check immunity power collection with spaceship
var dx = spaceship.x - immunityPower.x;
var dy = spaceship.y - immunityPower.y;
var distance = Math.sqrt(dx * dx + dy * dy);
var collectionDistance = 100;
if (distance < collectionDistance) {
// Collect immunity power
isImmune = true;
immunityDuration = immunityMaxDuration;
// Play powerup sound
LK.getSound('powerup').play();
// Add collection animation
tween(immunityPower, {
scaleX: 3,
scaleY: 3,
alpha: 0
}, {
duration: 300,
onFinish: function onFinish() {
immunityPower.destroy();
}
});
immunityPowers.splice(ip, 1);
continue;
}
immunityPower.lastY = immunityPower.y;
}
for (var i = obstacles.length - 1; i >= 0; i--) {
var obstacle = obstacles[i];
if (obstacle.lastY < 2800 && obstacle.y >= 2800) {
LK.setScore(LK.getScore() + 10);
scoreTxt.setText(LK.getScore());
}
if (obstacle.y > 2800) {
obstacle.destroy();
obstacles.splice(i, 1);
continue;
}
// Only lose if spaceship intersects with meteorites or debris with more precise collision
if (obstacle instanceof Meteorite || obstacle instanceof Debris) {
// Calculate distance between centers
var dx = spaceship.x - obstacle.x;
var dy = spaceship.y - obstacle.y;
var distance = Math.sqrt(dx * dx + dy * dy);
// Use smaller collision radius for more precise collision (about 60% of original size)
var spaceshipRadius = spaceship.width * 0.6 / 2;
var obstacleRadius = obstacle.width * 0.6 / 2;
var collisionDistance = spaceshipRadius + obstacleRadius;
if (distance < collisionDistance && !isImmune) {
// Lose a heart instead of immediate game over
hearts--;
// Update heart display
if (hearts >= 0 && hearts < heartElements.length) {
heartElements[hearts].alpha = 0.3;
tween(heartElements[hearts], {
scaleX: 2,
scaleY: 2,
alpha: 0
}, {
duration: 500,
easing: tween.easeOut
});
}
// Flash effect when hit
LK.effects.flashScreen(0xff0000, 500);
// Play hit sound
LK.getSound('hit').play();
// Remove the obstacle that hit the player
obstacle.destroy();
obstacles.splice(i, 1);
// Check if game over (no hearts left)
if (hearts <= 0) {
LK.getSound('destroy').play();
LK.showGameOver();
showMenu();
return;
}
// Temporary immunity after getting hit (1 second)
if (!isImmune) {
isImmune = true;
immunityDuration = 60; // 1 second
}
continue;
}
}
obstacle.lastY = obstacle.y;
}
}; /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var BackButton = Container.expand(function () {
var self = Container.call(this);
var buttonBg = self.attachAsset('backButton', {
anchorX: 0.5,
anchorY: 0.5
});
self.down = function (x, y, obj) {
tween(self.scale, {
x: 0.9,
y: 0.9
}, {
duration: 200
});
};
self.up = function (x, y, obj) {
tween(self.scale, {
x: 1.0,
y: 1.0
}, {
duration: 200
});
};
return self;
});
var Coin = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('coin', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 3;
self.lastY = undefined;
self.update = function () {
self.y += self.speed;
// Add floating animation
self.x += Math.sin(LK.ticks * 0.1 + self.y * 0.01) * 0.5;
// Add rotation
graphics.rotation += 0.05;
};
return self;
});
var Debris = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('debris', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 6;
self.lastY = undefined;
self.update = function () {
self.y += self.speed;
};
return self;
});
var ImmunityPower = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('immunityPower', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 2;
self.lastY = undefined;
self.update = function () {
self.y += self.speed;
// Add pulsing animation
graphics.scaleX = 1 + Math.sin(LK.ticks * 0.1) * 0.2;
graphics.scaleY = 1 + Math.sin(LK.ticks * 0.1) * 0.2;
// Add rotation
graphics.rotation += 0.03;
};
return self;
});
var MenuButton = Container.expand(function (color) {
var self = Container.call(this);
var buttonBg = self.attachAsset('menuButton', {
anchorX: 0.5,
anchorY: 0.5
});
if (color) buttonBg.tint = color;
self.down = function (x, y, obj) {
tween(self.scale, {
x: 0.9,
y: 0.9
}, {
duration: 200
});
};
self.up = function (x, y, obj) {
tween(self.scale, {
x: 1.0,
y: 1.0
}, {
duration: 200
});
};
return self;
});
var Meteorite = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('meteorite', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 4;
self.lastY = undefined;
self.update = function () {
self.y += self.speed;
};
return self;
});
var Projectile = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('boostButton', {
anchorX: 0.5,
anchorY: 0.5
});
graphics.scaleX = 0.3;
graphics.scaleY = 0.3;
self.speed = -8;
self.lastY = undefined;
self.update = function () {
self.y += self.speed;
};
return self;
});
var SensitivitySlider = Container.expand(function () {
var self = Container.call(this);
var sliderBar = self.attachAsset('sensSlider', {
anchorX: 0.5,
anchorY: 0.5
});
var sliderHandle = self.addChild(LK.getAsset('sensHandle', {
anchorX: 0.5,
anchorY: 0.5
}));
self.minX = -280;
self.maxX = 280;
self.isDragging = false;
self.down = function (x, y, obj) {
self.isDragging = true;
self.updateHandle(x);
};
self.up = function (x, y, obj) {
self.isDragging = false;
};
self.updateHandle = function (x) {
var localX = x - self.x;
localX = Math.max(self.minX, Math.min(self.maxX, localX));
sliderHandle.x = localX;
};
self.getSensitivity = function () {
return (sliderHandle.x + 280) / 560; // 0 to 1
};
self.setSensitivity = function (value) {
sliderHandle.x = value * 560 - 280;
};
return self;
});
var SettingsButton = Container.expand(function () {
var self = Container.call(this);
var buttonBg = self.attachAsset('settingsButton', {
anchorX: 0.5,
anchorY: 0.5
});
self.down = function (x, y, obj) {
tween(self.scale, {
x: 0.9,
y: 0.9
}, {
duration: 200
});
};
self.up = function (x, y, obj) {
tween(self.scale, {
x: 1.0,
y: 1.0
}, {
duration: 200
});
};
return self;
});
var Spaceship = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('spaceship', {
anchorX: 0.5,
anchorY: 0.5
});
return self;
});
var StartButton = Container.expand(function () {
var self = Container.call(this);
var buttonBg = self.attachAsset('startButton', {
anchorX: 0.5,
anchorY: 0.5
});
self.down = function (x, y, obj) {
tween(self.scale, {
x: 0.9,
y: 0.9
}, {
duration: 200
});
};
self.up = function (x, y, obj) {
tween(self.scale, {
x: 1.0,
y: 1.0
}, {
duration: 200
});
};
return self;
});
var TouchSlider = Container.expand(function () {
var self = Container.call(this);
var sliderBar = self.attachAsset('sliderBar', {
anchorX: 0.5,
anchorY: 0.5
});
var sliderHandle = self.addChild(LK.getAsset('sliderHandle', {
anchorX: 0.5,
anchorY: 0.5
}));
self.minX = -380;
self.maxX = 380;
self.isDragging = false;
self.down = function (x, y, obj) {
self.isDragging = true;
self.updateHandle(x);
};
self.up = function (x, y, obj) {
self.isDragging = false;
};
self.updateHandle = function (x) {
var localX = x - self.x;
localX = Math.max(self.minX, Math.min(self.maxX, localX));
sliderHandle.x = localX;
};
self.getSliderValue = function () {
return sliderHandle.x / 380;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000011
});
/****
* Game Code
****/
// Game state management
var gameState = 'menu'; // 'menu', 'settings', 'playing', 'airplanes'
var sensitivity = storage.sensitivity || 1.0;
var selectedAirplane = storage.selectedAirplane || 'classic';
// Menu elements
var titleText = new Text2('Hasta el infinito y más allá', {
size: 110,
fill: 0xFFD700,
font: "'Press Start 2P', 'VT323', 'Pixel Emulator', 'Courier New', monospace"
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 2048 / 2;
titleText.y = 600;
game.addChild(titleText);
var startButton = game.addChild(new StartButton());
startButton.x = 2048 / 2;
startButton.y = 1200;
var settingsButton = game.addChild(new SettingsButton());
settingsButton.x = 2048 / 2;
settingsButton.y = 1400;
var airplaneButton = game.addChild(new MenuButton(0x44aa44));
airplaneButton.x = 2048 / 2;
airplaneButton.y = 1600;
// Settings menu elements (initially hidden)
var settingsTitle = new Text2('AJUSTAR SENSIBILIDAD', {
size: 80,
fill: 0xFFFFFF
});
settingsTitle.anchor.set(0.5, 0.5);
settingsTitle.x = 2048 / 2;
settingsTitle.y = 800;
settingsTitle.visible = false;
game.addChild(settingsTitle);
var sensitivitySlider = game.addChild(new SensitivitySlider());
sensitivitySlider.x = 2048 / 2;
sensitivitySlider.y = 1200;
sensitivitySlider.visible = false;
sensitivitySlider.setSensitivity(sensitivity);
var sensValueText = new Text2('Sensibilidad: ' + Math.round(sensitivity * 100) + '%', {
size: 60,
fill: 0xFFFFFF
});
sensValueText.anchor.set(0.5, 0.5);
sensValueText.x = 2048 / 2;
sensValueText.y = 1350;
sensValueText.visible = false;
game.addChild(sensValueText);
var backButton = game.addChild(new BackButton());
backButton.x = 2048 / 2;
backButton.y = 1500;
backButton.visible = false;
// Airplane selection menu elements (initially hidden)
var airplaneTitle = new Text2('ELEGIR AVIÓN', {
size: 80,
fill: 0xFFFFFF
});
airplaneTitle.anchor.set(0.5, 0.5);
airplaneTitle.x = 2048 / 2;
airplaneTitle.y = 600;
airplaneTitle.visible = false;
game.addChild(airplaneTitle);
var airplane1Button = game.addChild(new MenuButton(0x4444aa));
airplane1Button.x = 2048 / 2;
airplane1Button.y = 1000;
airplane1Button.visible = false;
var airplane2Button = game.addChild(new MenuButton(0xaa4444));
airplane2Button.x = 2048 / 2;
airplane2Button.y = 1200;
airplane2Button.visible = false;
var airplane3Button = game.addChild(new MenuButton(0x44aa44));
airplane3Button.x = 2048 / 2;
airplane3Button.y = 1400;
airplane3Button.visible = false;
var airplaneBackButton = game.addChild(new BackButton());
airplaneBackButton.x = 2048 / 2;
airplaneBackButton.y = 1600;
airplaneBackButton.visible = false;
// Decorative elements
var stars = [];
for (var i = 0; i < 50; i++) {
var star = game.addChild(LK.getAsset('star', {
anchorX: 0.5,
anchorY: 0.5
}));
star.x = Math.random() * 2048;
star.y = Math.random() * 2732;
star.alpha = Math.random() * 0.8 + 0.2;
stars.push(star);
}
var planet1 = game.addChild(LK.getAsset('planet', {
anchorX: 0.5,
anchorY: 0.5
}));
planet1.x = 200;
planet1.y = 300;
planet1.alpha = 0.6;
planet1.tint = 0x8888ff;
var planet2 = game.addChild(LK.getAsset('planet', {
anchorX: 0.5,
anchorY: 0.5
}));
planet2.x = 1800;
planet2.y = 2400;
planet2.alpha = 0.4;
planet2.tint = 0xff8888;
planet2.scaleX = 0.7;
planet2.scaleY = 0.7;
// Game elements (initially hidden)
var spaceship;
var obstacles = [];
var coins = [];
var coinSpawnTimer = 0;
var coinSpawnRate = 180;
var totalCoins = storage.totalCoins || 0;
var obstacleSpawnTimer = 0;
var obstacleSpawnRate = 90;
var gameSpeed = 1;
var spaceshipSpeed = 1;
var survivalTime = 0;
var difficultyTimer = 0;
var lastScoreCheck = 0;
var speedIncreaseTimer = 0;
var slider;
// Heart system variables
var hearts = 3;
var heartElements = [];
// Immunity power variables
var immunityPowers = [];
var immunitySpawnTimer = 0;
var immunitySpawnRate = 1500; // 25 seconds at 60 FPS
var isImmune = false;
var immunityDuration = 0;
var immunityMaxDuration = 600; // 10 seconds at 60 FPS
// Boost power variables
var isBoostActive = false;
var boostDuration = 0;
var boostMaxDuration = 1200; // 20 seconds at 60 FPS
var boostMultiplier = 2.5;
var boostCooldown = 0;
var boostMaxCooldown = 1800; // 30 seconds cooldown
// Shooting system variables
var projectiles = [];
var shootCooldown = 0;
var shootMaxCooldown = 900; // 15 seconds at 60 FPS
var canShoot = true;
// GUI elements (created but initially hidden)
var scoreTxt = new Text2('0', {
size: 80,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
scoreTxt.visible = false;
LK.gui.top.addChild(scoreTxt);
var timeTxt = new Text2('Time: 0s', {
size: 60,
fill: 0xFFFFFF
});
timeTxt.anchor.set(1, 0);
timeTxt.visible = false;
LK.gui.topRight.addChild(timeTxt);
timeTxt.x = -20;
timeTxt.y = 100;
var coinsTxt = new Text2('Coins: ' + totalCoins, {
size: 50,
fill: 0xffd700
});
coinsTxt.anchor.set(0, 0);
coinsTxt.visible = false;
LK.gui.topLeft.addChild(coinsTxt);
coinsTxt.x = 120;
coinsTxt.y = 20;
var shootButton = LK.getAsset('boostButton', {
anchorX: 0.5,
anchorY: 0.5
});
shootButton.visible = false;
LK.gui.bottomRight.addChild(shootButton);
shootButton.x = -120;
shootButton.y = -120;
var shootStatusText = new Text2('SHOOT READY', {
size: 40,
fill: 0xff6600
});
shootStatusText.anchor.set(0.5, 0.5);
shootStatusText.visible = false;
LK.gui.bottom.addChild(shootStatusText);
shootStatusText.y = -180;
// Add cooldown indicator circle
var cooldownIndicator = LK.getAsset('boostButton', {
anchorX: 0.5,
anchorY: 0.5
});
cooldownIndicator.visible = false;
cooldownIndicator.alpha = 0.3;
cooldownIndicator.tint = 0x000000;
LK.gui.bottomRight.addChild(cooldownIndicator);
cooldownIndicator.x = -120;
cooldownIndicator.y = -120;
// Create heart GUI elements
for (var h = 0; h < 3; h++) {
var heartGui = LK.getAsset('heart', {
anchorX: 0.5,
anchorY: 0.5
});
heartGui.visible = false;
LK.gui.topRight.addChild(heartGui);
heartGui.x = -280 + h * 90;
heartGui.y = 40;
heartElements.push(heartGui);
}
var immunityStatusText = new Text2('', {
size: 50,
fill: 0x00ff88
});
immunityStatusText.anchor.set(0.5, 0.5);
immunityStatusText.visible = false;
LK.gui.center.addChild(immunityStatusText);
immunityStatusText.y = -200;
game.move = function (x, y, obj) {
if (gameState === 'playing' && slider && slider.isDragging) {
slider.updateHandle(x);
var sliderValue = slider.getSliderValue();
var currentSpeed = spaceshipSpeed * (isBoostActive ? boostMultiplier : 1);
spaceship.x = 2048 / 2 + sliderValue * 800 * currentSpeed * sensitivity;
spaceship.x = Math.max(100, Math.min(1948, spaceship.x));
} else if (gameState === 'settings' && sensitivitySlider.isDragging) {
sensitivitySlider.updateHandle(x);
sensitivity = sensitivitySlider.getSensitivity();
sensValueText.setText('Sensibilidad: ' + Math.round(sensitivity * 100) + '%');
storage.sensitivity = sensitivity;
}
};
// Add shoot button click handler
shootButton.down = function (x, y, obj) {
if (gameState === 'playing' && canShoot && shootCooldown <= 0) {
// Fire projectile
var projectile = new Projectile();
projectile.x = spaceship.x;
projectile.y = spaceship.y - 50;
projectile.lastY = projectile.y;
projectiles.push(projectile);
game.addChild(projectile);
// Play shooting sound
LK.getSound('shoot').play();
// Start cooldown
canShoot = false;
shootCooldown = shootMaxCooldown;
shootStatusText.setText('RELOADING...');
shootStatusText.fill = 0xff0000;
shootButton.tint = 0x666666;
// Button press animation
tween(shootButton.scale, {
x: 0.9,
y: 0.9
}, {
duration: 100,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(shootButton.scale, {
x: 1.0,
y: 1.0
}, {
duration: 100,
easing: tween.easeIn
});
}
});
}
};
shootButton.up = function (x, y, obj) {
// Reset button scale on release
tween(shootButton.scale, {
x: 1.0,
y: 1.0
}, {
duration: 100,
easing: tween.easeOut
});
};
game.down = function (x, y, obj) {
// Game down handler for other interactions
};
// Button handlers
startButton.up = function (x, y, obj) {
tween(startButton.scale, {
x: 1.0,
y: 1.0
}, {
duration: 200
});
startGame();
};
settingsButton.up = function (x, y, obj) {
tween(settingsButton.scale, {
x: 1.0,
y: 1.0
}, {
duration: 200
});
showSettings();
};
backButton.up = function (x, y, obj) {
tween(backButton.scale, {
x: 1.0,
y: 1.0
}, {
duration: 200
});
showMenu();
};
airplaneButton.up = function (x, y, obj) {
tween(airplaneButton.scale, {
x: 1.0,
y: 1.0
}, {
duration: 200
});
showAirplaneSelection();
};
airplane1Button.up = function (x, y, obj) {
tween(airplane1Button.scale, {
x: 1.0,
y: 1.0
}, {
duration: 200
});
selectedAirplane = 'classic';
storage.selectedAirplane = selectedAirplane;
showMenu();
};
airplane2Button.up = function (x, y, obj) {
tween(airplane2Button.scale, {
x: 1.0,
y: 1.0
}, {
duration: 200
});
selectedAirplane = 'fast';
storage.selectedAirplane = selectedAirplane;
showMenu();
};
airplane3Button.up = function (x, y, obj) {
tween(airplane3Button.scale, {
x: 1.0,
y: 1.0
}, {
duration: 200
});
selectedAirplane = 'robust';
storage.selectedAirplane = selectedAirplane;
showMenu();
};
airplaneBackButton.up = function (x, y, obj) {
tween(airplaneBackButton.scale, {
x: 1.0,
y: 1.0
}, {
duration: 200
});
showMenu();
};
function startGame() {
gameState = 'playing';
// Hide menu elements
titleText.visible = false;
startButton.visible = false;
settingsButton.visible = false;
airplaneButton.visible = false;
// Show game elements
spaceship = game.addChild(new Spaceship());
spaceship.x = 2048 / 2;
spaceship.y = 2000;
slider = game.addChild(new TouchSlider());
slider.x = 2048 / 2;
slider.y = 2600;
scoreTxt.visible = true;
timeTxt.visible = true;
// Reset game variables
obstacles = [];
coins = [];
coinSpawnTimer = 0;
obstacleSpawnTimer = 0;
obstacleSpawnRate = 90;
coinSpawnRate = 180;
gameSpeed = 1;
spaceshipSpeed = 1;
survivalTime = 0;
difficultyTimer = 0;
speedIncreaseTimer = 0;
lastScoreCheck = 0;
LK.setScore(0);
scoreTxt.setText('0');
timeTxt.setText('Time: 0s');
coinsTxt.visible = true;
coinsTxt.setText('Coins: ' + totalCoins);
// Reset heart system
hearts = 3;
for (var h = 0; h < heartElements.length; h++) {
heartElements[h].visible = true;
heartElements[h].alpha = 1;
}
// Reset immunity power system
immunityPowers = [];
immunitySpawnTimer = 0;
isImmune = false;
immunityDuration = 0;
immunityStatusText.visible = false;
// Show shooting elements
shootButton.visible = true;
shootStatusText.visible = true;
cooldownIndicator.visible = true;
projectiles = [];
canShoot = true;
shootCooldown = 0;
shootStatusText.setText('SHOOT READY');
shootStatusText.fill = 0xff6600;
shootButton.tint = 0xff6600;
cooldownIndicator.scaleX = 0;
cooldownIndicator.scaleY = 0;
// Start background music
LK.playMusic('bgMusic');
}
function showSettings() {
gameState = 'settings';
// Hide menu elements
titleText.visible = false;
startButton.visible = false;
settingsButton.visible = false;
airplaneButton.visible = false;
coinsTxt.visible = false;
shootButton.visible = false;
shootStatusText.visible = false;
cooldownIndicator.visible = false;
// Hide heart elements
for (var h = 0; h < heartElements.length; h++) {
heartElements[h].visible = false;
}
immunityStatusText.visible = false;
// Hide heart elements
for (var h = 0; h < heartElements.length; h++) {
heartElements[h].visible = false;
}
immunityStatusText.visible = false;
// Hide heart elements
for (var h = 0; h < heartElements.length; h++) {
heartElements[h].visible = false;
}
immunityStatusText.visible = false;
// Show settings elements
settingsTitle.visible = true;
sensitivitySlider.visible = true;
sensValueText.visible = true;
backButton.visible = true;
}
function showAirplaneSelection() {
gameState = 'airplanes';
// Hide menu elements
titleText.visible = false;
startButton.visible = false;
settingsButton.visible = false;
airplaneButton.visible = false;
coinsTxt.visible = false;
shootButton.visible = false;
shootStatusText.visible = false;
cooldownIndicator.visible = false;
// Show airplane selection elements
airplaneTitle.visible = true;
airplane1Button.visible = true;
airplane2Button.visible = true;
airplane3Button.visible = true;
airplaneBackButton.visible = true;
}
function showMenu() {
gameState = 'menu';
// Hide settings elements
settingsTitle.visible = false;
sensitivitySlider.visible = false;
sensValueText.visible = false;
backButton.visible = false;
// Hide airplane selection elements
airplaneTitle.visible = false;
airplane1Button.visible = false;
airplane2Button.visible = false;
airplane3Button.visible = false;
airplaneBackButton.visible = false;
// Hide game elements if they exist
if (spaceship) {
spaceship.destroy();
spaceship = null;
}
if (slider) {
slider.destroy();
slider = null;
}
scoreTxt.visible = false;
timeTxt.visible = false;
coinsTxt.visible = false;
shootButton.visible = false;
shootStatusText.visible = false;
cooldownIndicator.visible = false;
// Clear obstacles
for (var i = 0; i < obstacles.length; i++) {
obstacles[i].destroy();
}
obstacles = [];
// Clear coins
for (var i = 0; i < coins.length; i++) {
coins[i].destroy();
}
coins = [];
// Clear immunity powers
for (var i = 0; i < immunityPowers.length; i++) {
immunityPowers[i].destroy();
}
immunityPowers = [];
// Clear projectiles
for (var i = 0; i < projectiles.length; i++) {
projectiles[i].destroy();
}
projectiles = [];
// Show menu elements
titleText.visible = true;
startButton.visible = true;
settingsButton.visible = true;
airplaneButton.visible = true;
// Stop background music
LK.stopMusic();
}
game.update = function () {
// Animate stars
for (var s = 0; s < stars.length; s++) {
stars[s].alpha = Math.sin(LK.ticks * 0.02 + s) * 0.3 + 0.5;
}
// Rotate planets slowly
planet1.rotation += 0.005;
planet2.rotation -= 0.003;
// Only run game logic during gameplay
if (gameState !== 'playing' || !spaceship) {
return;
}
// Handle shooting system cooldown
if (shootCooldown > 0) {
shootCooldown--;
var cooldownProgress = 1 - shootCooldown / shootMaxCooldown;
// Update cooldown indicator with growing circle animation
cooldownIndicator.scaleX = cooldownProgress;
cooldownIndicator.scaleY = cooldownProgress;
// Update status text with remaining time
var timeLeft = Math.ceil(shootCooldown / 60);
shootStatusText.setText('RELOAD: ' + timeLeft + 's');
if (shootCooldown <= 0) {
canShoot = true;
shootStatusText.setText('SHOOT READY');
shootStatusText.fill = 0xff6600;
shootButton.tint = 0xff6600;
cooldownIndicator.scaleX = 0;
cooldownIndicator.scaleY = 0;
}
}
// Update projectiles
for (var p = projectiles.length - 1; p >= 0; p--) {
var projectile = projectiles[p];
// Remove projectiles that go off screen
if (projectile.y < -100) {
projectile.destroy();
projectiles.splice(p, 1);
continue;
}
// Check projectile collision with obstacles
for (var o = obstacles.length - 1; o >= 0; o--) {
var obstacle = obstacles[o];
var dx = projectile.x - obstacle.x;
var dy = projectile.y - obstacle.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 100) {
// Explosion effect
tween(obstacle, {
scaleX: 2,
scaleY: 2,
alpha: 0
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
obstacle.destroy();
}
});
// Remove projectile
projectile.destroy();
projectiles.splice(p, 1);
// Remove obstacle
obstacles.splice(o, 1);
// Add score bonus
LK.setScore(LK.getScore() + 50);
scoreTxt.setText(LK.getScore());
// Play destroy sound
LK.getSound('destroy').play();
// Screen flash effect
LK.effects.flashScreen(0xffff00, 200);
break;
}
}
if (projectile.parent) {
projectile.lastY = projectile.y;
}
}
survivalTime++;
difficultyTimer++;
speedIncreaseTimer++;
if (survivalTime % 60 === 0) {
var seconds = Math.floor(survivalTime / 60);
timeTxt.setText('Time: ' + seconds + 's');
}
// Every 10 seconds (600 ticks), increase both airplane and obstacle speeds
if (speedIncreaseTimer >= 600) {
speedIncreaseTimer = 0;
gameSpeed *= 1.1; // Increase falling object speed by 10%
spaceshipSpeed *= 1.1; // Increase airplane speed by 10%
}
// Every 15 seconds (900 ticks), increase obstacle speed by 5%
if (difficultyTimer >= 900) {
difficultyTimer = 0;
gameSpeed *= 1.05;
obstacleSpawnRate = Math.max(30, obstacleSpawnRate - 5);
}
// Every 50 points, increase spaceship speed slightly
var currentScore = LK.getScore();
if (Math.floor(currentScore / 50) > Math.floor(lastScoreCheck / 50)) {
spaceshipSpeed += 0.1;
}
lastScoreCheck = currentScore;
obstacleSpawnTimer++;
if (obstacleSpawnTimer >= obstacleSpawnRate) {
obstacleSpawnTimer = 0;
var obstacle;
if (Math.random() < 0.7) {
obstacle = new Meteorite();
} else {
obstacle = new Debris();
}
obstacle.x = Math.random() * 1800 + 124;
obstacle.y = -100;
obstacle.speed *= gameSpeed;
obstacle.lastY = obstacle.y;
obstacles.push(obstacle);
game.addChild(obstacle);
}
// Spawn coins
coinSpawnTimer++;
if (coinSpawnTimer >= coinSpawnRate) {
coinSpawnTimer = 0;
var coin = new Coin();
coin.x = Math.random() * 1800 + 124;
coin.y = -100;
coin.speed *= gameSpeed;
coin.lastY = coin.y;
coins.push(coin);
game.addChild(coin);
}
// Spawn immunity powers every 25 seconds
immunitySpawnTimer++;
if (immunitySpawnTimer >= immunitySpawnRate) {
immunitySpawnTimer = 0;
var immunityPower = new ImmunityPower();
immunityPower.x = Math.random() * 1800 + 124;
immunityPower.y = -100;
immunityPower.speed *= gameSpeed;
immunityPower.lastY = immunityPower.y;
immunityPowers.push(immunityPower);
game.addChild(immunityPower);
}
// Update and check coin collection
for (var c = coins.length - 1; c >= 0; c--) {
var coin = coins[c];
// Remove coins that go off screen
if (coin.y > 2800) {
coin.destroy();
coins.splice(c, 1);
continue;
}
// Check coin collection with spaceship
var dx = spaceship.x - coin.x;
var dy = spaceship.y - coin.y;
var distance = Math.sqrt(dx * dx + dy * dy);
var collectionDistance = 80; // Generous collection radius
if (distance < collectionDistance) {
// Collect coin
totalCoins++;
storage.totalCoins = totalCoins;
coinsTxt.setText('Coins: ' + totalCoins);
// Play coin collection sound
LK.getSound('coinCollect').play();
// Add coin collection animation
tween(coin, {
scaleX: 2,
scaleY: 2,
alpha: 0
}, {
duration: 200,
onFinish: function onFinish() {
coin.destroy();
}
});
coins.splice(c, 1);
continue;
}
coin.lastY = coin.y;
}
// Handle immunity system
if (isImmune) {
immunityDuration--;
// Update immunity status text
var timeLeft = Math.ceil(immunityDuration / 60);
immunityStatusText.setText('IMMUNE: ' + timeLeft + 's');
immunityStatusText.visible = true;
// Add immunity visual effects to spaceship
if (LK.ticks % 20 === 0) {
tween(spaceship, {
alpha: 0.3
}, {
duration: 200,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(spaceship, {
alpha: 1.0
}, {
duration: 200,
easing: tween.easeInOut
});
}
});
}
if (immunityDuration <= 0) {
isImmune = false;
immunityStatusText.visible = false;
spaceship.alpha = 1.0;
}
}
// Update and check immunity power collection
for (var ip = immunityPowers.length - 1; ip >= 0; ip--) {
var immunityPower = immunityPowers[ip];
// Remove immunity powers that go off screen
if (immunityPower.y > 2800) {
immunityPower.destroy();
immunityPowers.splice(ip, 1);
continue;
}
// Check immunity power collection with spaceship
var dx = spaceship.x - immunityPower.x;
var dy = spaceship.y - immunityPower.y;
var distance = Math.sqrt(dx * dx + dy * dy);
var collectionDistance = 100;
if (distance < collectionDistance) {
// Collect immunity power
isImmune = true;
immunityDuration = immunityMaxDuration;
// Play powerup sound
LK.getSound('powerup').play();
// Add collection animation
tween(immunityPower, {
scaleX: 3,
scaleY: 3,
alpha: 0
}, {
duration: 300,
onFinish: function onFinish() {
immunityPower.destroy();
}
});
immunityPowers.splice(ip, 1);
continue;
}
immunityPower.lastY = immunityPower.y;
}
for (var i = obstacles.length - 1; i >= 0; i--) {
var obstacle = obstacles[i];
if (obstacle.lastY < 2800 && obstacle.y >= 2800) {
LK.setScore(LK.getScore() + 10);
scoreTxt.setText(LK.getScore());
}
if (obstacle.y > 2800) {
obstacle.destroy();
obstacles.splice(i, 1);
continue;
}
// Only lose if spaceship intersects with meteorites or debris with more precise collision
if (obstacle instanceof Meteorite || obstacle instanceof Debris) {
// Calculate distance between centers
var dx = spaceship.x - obstacle.x;
var dy = spaceship.y - obstacle.y;
var distance = Math.sqrt(dx * dx + dy * dy);
// Use smaller collision radius for more precise collision (about 60% of original size)
var spaceshipRadius = spaceship.width * 0.6 / 2;
var obstacleRadius = obstacle.width * 0.6 / 2;
var collisionDistance = spaceshipRadius + obstacleRadius;
if (distance < collisionDistance && !isImmune) {
// Lose a heart instead of immediate game over
hearts--;
// Update heart display
if (hearts >= 0 && hearts < heartElements.length) {
heartElements[hearts].alpha = 0.3;
tween(heartElements[hearts], {
scaleX: 2,
scaleY: 2,
alpha: 0
}, {
duration: 500,
easing: tween.easeOut
});
}
// Flash effect when hit
LK.effects.flashScreen(0xff0000, 500);
// Play hit sound
LK.getSound('hit').play();
// Remove the obstacle that hit the player
obstacle.destroy();
obstacles.splice(i, 1);
// Check if game over (no hearts left)
if (hearts <= 0) {
LK.getSound('destroy').play();
LK.showGameOver();
showMenu();
return;
}
// Temporary immunity after getting hit (1 second)
if (!isImmune) {
isImmune = true;
immunityDuration = 60; // 1 second
}
continue;
}
}
obstacle.lastY = obstacle.y;
}
};