/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
highScore: 0
});
/****
* Classes
****/
var Cavern = Container.expand(function () {
var self = Container.call(this);
var cavernGraphics = self.attachAsset('cavern', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = -2;
self.update = function () {
self.x += self.speed;
// If cavern moves off-screen, we'll handle its removal in the main game loop
};
return self;
});
var Gem = Container.expand(function () {
var self = Container.call(this);
var gemGraphics = self.attachAsset('gem', {
anchorX: 0.5,
anchorY: 0.5
});
self.value = 10;
self.collect = function () {
LK.getSound('collect').play();
LK.effects.flashObject(self, 0xFFFFFF, 300);
};
return self;
});
var Obstacle = Container.expand(function () {
var self = Container.call(this);
var obstacleGraphics = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 0;
self.update = function () {
self.x += self.speed;
// If obstacle moves off-screen, we'll handle its removal in the main game loop
};
return self;
});
var OxygenBubble = Container.expand(function () {
var self = Container.call(this);
var bubbleGraphics = self.attachAsset('oxygen', {
anchorX: 0.5,
anchorY: 0.5
});
self.oxygenValue = 20;
self.speed = -1;
self.oscillationSpeed = 0.05;
self.initialY = 0;
self.update = function () {
self.x += self.speed;
self.y = self.initialY + Math.sin(LK.ticks * self.oscillationSpeed) * 15;
// If bubble moves off-screen, we'll handle its removal in the main game loop
};
self.collect = function () {
LK.getSound('bubble').play();
LK.effects.flashObject(self, 0xFFFFFF, 300);
};
return self;
});
var SeaCreature = Container.expand(function () {
var self = Container.call(this);
var creatureGraphics = self.attachAsset('seaCreature', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = -2;
self.amplitude = 50;
self.frequency = 0.02;
self.initialY = 0;
self.update = function () {
self.x += self.speed;
self.y = self.initialY + Math.sin(self.x * self.frequency) * self.amplitude;
// If creature moves off-screen, we'll handle its removal in the main game loop
};
return self;
});
var Submarine = Container.expand(function () {
var self = Container.call(this);
var submarineGraphics = self.attachAsset('submarine', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 0;
self.verticalSpeed = 0;
self.acceleration = 0.2;
self.maxSpeed = 10;
self.deceleration = 0.1;
self.update = function () {
// Apply physics
self.x += self.speed;
self.y += self.verticalSpeed;
// Apply deceleration
if (self.speed > 0) {
self.speed -= self.deceleration;
if (self.speed < 0) {
self.speed = 0;
}
} else if (self.speed < 0) {
self.speed += self.deceleration;
if (self.speed > 0) {
self.speed = 0;
}
}
// Apply gravity
self.verticalSpeed += 0.1;
// Restrict submarine from going above the water surface
if (self.y < 100) {
self.y = 100;
self.verticalSpeed = 0;
}
// Restrict submarine from going outside the horizontal boundaries
if (self.x < 100) {
self.x = 100;
self.speed = 0;
} else if (self.x > 2048 - 100) {
self.x = 2048 - 100;
self.speed = 0;
}
};
self.moveLeft = function () {
self.speed = Math.max(self.speed - self.acceleration, -self.maxSpeed);
};
self.moveRight = function () {
self.speed = Math.min(self.speed + self.acceleration, self.maxSpeed);
};
self.moveUp = function () {
self.verticalSpeed = Math.max(self.verticalSpeed - self.acceleration * 2, -self.maxSpeed);
};
self.hit = function () {
LK.getSound('crash').play();
LK.effects.flashObject(self, 0xFF0000, 500);
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000033
});
/****
* Game Code
****/
// Create UI elements
var scoreTxt = new Text2('Score: 0', {
size: 60,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0, 0);
LK.gui.topRight.addChild(scoreTxt);
scoreTxt.x = -350;
scoreTxt.y = 50;
var highScoreTxt = new Text2('High Score: ' + storage.highScore, {
size: 40,
fill: 0xAAAAFF
});
highScoreTxt.anchor.set(0, 0);
LK.gui.topRight.addChild(highScoreTxt);
highScoreTxt.x = -350;
highScoreTxt.y = 120;
var depthTxt = new Text2('Depth: 0m', {
size: 50,
fill: 0xFFFFFF
});
depthTxt.anchor.set(0, 0);
LK.gui.topLeft.addChild(depthTxt);
depthTxt.x = 150;
depthTxt.y = 50;
// Create oxygen bar background
var oxygenBarBg = game.addChild(LK.getAsset('oxygenBarBg', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 80
}));
// Create oxygen bar foreground
var oxygenBar = game.addChild(LK.getAsset('oxygenBar', {
anchorX: 0,
anchorY: 0.5,
x: 2048 / 2 - 400,
y: 80
}));
// Create submarine
var submarine = game.addChild(new Submarine());
submarine.x = 500;
submarine.y = 400;
// Game variables
var score = 0;
var depth = 0;
var oxygen = 100;
var gameSpeed = 1;
var spawnTimer = 0;
var oxygenDecreaseRate = 0.1;
var gems = [];
var obstacles = [];
var seaCreatures = [];
var oxygenBubbles = [];
var caverns = [];
var dragNode = null;
var lastTouchY = 0;
// Play background music
LK.playMusic('underwaterAmbience');
// Generate initial caverns
function generateInitialCaverns() {
var cavernSpacing = 800;
var numInitialCaverns = Math.ceil(2048 / cavernSpacing) + 1;
for (var i = 0; i < numInitialCaverns; i++) {
var cavern = new Cavern();
cavern.y = 2732 - 150; // Bottom of the screen
cavern.x = i * cavernSpacing;
game.addChild(cavern);
caverns.push(cavern);
}
}
generateInitialCaverns();
// Handle touch and drag events
function handleMove(x, y, obj) {
if (dragNode) {
var deltaY = lastTouchY - y;
// If dragging upward, ascend
if (deltaY > 0) {
submarine.moveUp();
}
// If position is to the left of submarine, move left
if (x < submarine.x - 50) {
submarine.moveLeft();
}
// If position is to the right of submarine, move right
else if (x > submarine.x + 50) {
submarine.moveRight();
}
lastTouchY = y;
}
}
game.move = handleMove;
game.down = function (x, y, obj) {
dragNode = submarine;
lastTouchY = y;
handleMove(x, y, obj);
};
game.up = function (x, y, obj) {
dragNode = null;
};
// Spawn game objects
function spawnGem() {
var gem = new Gem();
gem.x = 2048 + 50;
gem.y = 300 + Math.random() * (2732 - 500);
gem.value = Math.floor(10 + depth / 100);
game.addChild(gem);
gems.push(gem);
}
function spawnObstacle() {
var obstacle = new Obstacle();
obstacle.x = 2048 + 125;
obstacle.y = 200 + Math.random() * (2732 - 400);
obstacle.speed = -3 - gameSpeed * 0.5;
game.addChild(obstacle);
obstacles.push(obstacle);
}
function spawnSeaCreature() {
var creature = new SeaCreature();
creature.x = 2048 + 75;
creature.y = 300 + Math.random() * (2732 - 600);
creature.initialY = creature.y;
creature.speed = -4 - gameSpeed * 0.5;
game.addChild(creature);
seaCreatures.push(creature);
}
function spawnOxygenBubble() {
var bubble = new OxygenBubble();
bubble.x = 2048 + 30;
bubble.y = 300 + Math.random() * (2732 - 600);
bubble.initialY = bubble.y;
bubble.speed = -2 - gameSpeed * 0.3;
game.addChild(bubble);
oxygenBubbles.push(bubble);
}
function spawnCavern() {
var cavern = new Cavern();
cavern.y = 2732 - 150; // Bottom of the screen
cavern.x = 2048 + 125;
cavern.speed = -2 - gameSpeed * 0.3;
game.addChild(cavern);
caverns.push(cavern);
}
// Main game update loop
game.update = function () {
// Update depth based on submarine position
depth = Math.floor((submarine.y - 100) / 10);
depthTxt.setText('Depth: ' + depth + 'm');
// Increase game speed based on depth
gameSpeed = 1 + depth / 500;
// Update oxygen level
oxygen -= oxygenDecreaseRate * gameSpeed;
if (oxygen <= 0) {
oxygen = 0;
LK.effects.flashScreen(0x0000FF, 1000);
// Update high score if needed
if (score > storage.highScore) {
storage.highScore = score;
highScoreTxt.setText('High Score: ' + storage.highScore);
}
LK.showGameOver();
}
// Update oxygen bar width
oxygenBar.width = oxygen / 100 * 800;
// Spawn game objects based on timers
spawnTimer++;
if (spawnTimer % 120 === 0) {
spawnGem();
}
if (spawnTimer % 180 === 0) {
spawnObstacle();
}
if (spawnTimer % 240 === 0) {
spawnSeaCreature();
}
if (spawnTimer % 300 === 0) {
spawnOxygenBubble();
}
if (spawnTimer % 200 === 0) {
spawnCavern();
}
// Check for and remove off-screen objects
for (var i = gems.length - 1; i >= 0; i--) {
var gem = gems[i];
// Check for collision with submarine
if (gem.intersects(submarine)) {
gem.collect();
score += gem.value;
scoreTxt.setText('Score: ' + score);
gem.destroy();
gems.splice(i, 1);
continue;
}
// Remove if off-screen
if (gem.x < -50) {
gem.destroy();
gems.splice(i, 1);
}
}
for (var i = obstacles.length - 1; i >= 0; i--) {
var obstacle = obstacles[i];
obstacle.update();
// Check for collision with submarine
if (obstacle.intersects(submarine)) {
submarine.hit();
oxygen -= 10;
// Push submarine back
submarine.speed = -5;
submarine.verticalSpeed = -3;
}
// Remove if off-screen
if (obstacle.x < -125) {
obstacle.destroy();
obstacles.splice(i, 1);
}
}
for (var i = seaCreatures.length - 1; i >= 0; i--) {
var creature = seaCreatures[i];
creature.update();
// Check for collision with submarine
if (creature.intersects(submarine)) {
submarine.hit();
oxygen -= 5;
// Push submarine back slightly
submarine.speed = -3;
}
// Remove if off-screen
if (creature.x < -75) {
creature.destroy();
seaCreatures.splice(i, 1);
}
}
for (var i = oxygenBubbles.length - 1; i >= 0; i--) {
var bubble = oxygenBubbles[i];
bubble.update();
// Check for collision with submarine
if (bubble.intersects(submarine)) {
bubble.collect();
oxygen = Math.min(oxygen + bubble.oxygenValue, 100);
bubble.destroy();
oxygenBubbles.splice(i, 1);
continue;
}
// Remove if off-screen
if (bubble.x < -30) {
bubble.destroy();
oxygenBubbles.splice(i, 1);
}
}
for (var i = caverns.length - 1; i >= 0; i--) {
var cavern = caverns[i];
cavern.update();
// Remove if off-screen
if (cavern.x < -125) {
cavern.destroy();
caverns.splice(i, 1);
}
}
// Update submarine
submarine.update();
// Win condition - reaching a certain score
if (score >= 1000) {
// Update high score
if (score > storage.highScore) {
storage.highScore = score;
highScoreTxt.setText('High Score: ' + storage.highScore);
}
LK.showYouWin();
}
}; /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
highScore: 0
});
/****
* Classes
****/
var Cavern = Container.expand(function () {
var self = Container.call(this);
var cavernGraphics = self.attachAsset('cavern', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = -2;
self.update = function () {
self.x += self.speed;
// If cavern moves off-screen, we'll handle its removal in the main game loop
};
return self;
});
var Gem = Container.expand(function () {
var self = Container.call(this);
var gemGraphics = self.attachAsset('gem', {
anchorX: 0.5,
anchorY: 0.5
});
self.value = 10;
self.collect = function () {
LK.getSound('collect').play();
LK.effects.flashObject(self, 0xFFFFFF, 300);
};
return self;
});
var Obstacle = Container.expand(function () {
var self = Container.call(this);
var obstacleGraphics = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 0;
self.update = function () {
self.x += self.speed;
// If obstacle moves off-screen, we'll handle its removal in the main game loop
};
return self;
});
var OxygenBubble = Container.expand(function () {
var self = Container.call(this);
var bubbleGraphics = self.attachAsset('oxygen', {
anchorX: 0.5,
anchorY: 0.5
});
self.oxygenValue = 20;
self.speed = -1;
self.oscillationSpeed = 0.05;
self.initialY = 0;
self.update = function () {
self.x += self.speed;
self.y = self.initialY + Math.sin(LK.ticks * self.oscillationSpeed) * 15;
// If bubble moves off-screen, we'll handle its removal in the main game loop
};
self.collect = function () {
LK.getSound('bubble').play();
LK.effects.flashObject(self, 0xFFFFFF, 300);
};
return self;
});
var SeaCreature = Container.expand(function () {
var self = Container.call(this);
var creatureGraphics = self.attachAsset('seaCreature', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = -2;
self.amplitude = 50;
self.frequency = 0.02;
self.initialY = 0;
self.update = function () {
self.x += self.speed;
self.y = self.initialY + Math.sin(self.x * self.frequency) * self.amplitude;
// If creature moves off-screen, we'll handle its removal in the main game loop
};
return self;
});
var Submarine = Container.expand(function () {
var self = Container.call(this);
var submarineGraphics = self.attachAsset('submarine', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 0;
self.verticalSpeed = 0;
self.acceleration = 0.2;
self.maxSpeed = 10;
self.deceleration = 0.1;
self.update = function () {
// Apply physics
self.x += self.speed;
self.y += self.verticalSpeed;
// Apply deceleration
if (self.speed > 0) {
self.speed -= self.deceleration;
if (self.speed < 0) {
self.speed = 0;
}
} else if (self.speed < 0) {
self.speed += self.deceleration;
if (self.speed > 0) {
self.speed = 0;
}
}
// Apply gravity
self.verticalSpeed += 0.1;
// Restrict submarine from going above the water surface
if (self.y < 100) {
self.y = 100;
self.verticalSpeed = 0;
}
// Restrict submarine from going outside the horizontal boundaries
if (self.x < 100) {
self.x = 100;
self.speed = 0;
} else if (self.x > 2048 - 100) {
self.x = 2048 - 100;
self.speed = 0;
}
};
self.moveLeft = function () {
self.speed = Math.max(self.speed - self.acceleration, -self.maxSpeed);
};
self.moveRight = function () {
self.speed = Math.min(self.speed + self.acceleration, self.maxSpeed);
};
self.moveUp = function () {
self.verticalSpeed = Math.max(self.verticalSpeed - self.acceleration * 2, -self.maxSpeed);
};
self.hit = function () {
LK.getSound('crash').play();
LK.effects.flashObject(self, 0xFF0000, 500);
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000033
});
/****
* Game Code
****/
// Create UI elements
var scoreTxt = new Text2('Score: 0', {
size: 60,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0, 0);
LK.gui.topRight.addChild(scoreTxt);
scoreTxt.x = -350;
scoreTxt.y = 50;
var highScoreTxt = new Text2('High Score: ' + storage.highScore, {
size: 40,
fill: 0xAAAAFF
});
highScoreTxt.anchor.set(0, 0);
LK.gui.topRight.addChild(highScoreTxt);
highScoreTxt.x = -350;
highScoreTxt.y = 120;
var depthTxt = new Text2('Depth: 0m', {
size: 50,
fill: 0xFFFFFF
});
depthTxt.anchor.set(0, 0);
LK.gui.topLeft.addChild(depthTxt);
depthTxt.x = 150;
depthTxt.y = 50;
// Create oxygen bar background
var oxygenBarBg = game.addChild(LK.getAsset('oxygenBarBg', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 80
}));
// Create oxygen bar foreground
var oxygenBar = game.addChild(LK.getAsset('oxygenBar', {
anchorX: 0,
anchorY: 0.5,
x: 2048 / 2 - 400,
y: 80
}));
// Create submarine
var submarine = game.addChild(new Submarine());
submarine.x = 500;
submarine.y = 400;
// Game variables
var score = 0;
var depth = 0;
var oxygen = 100;
var gameSpeed = 1;
var spawnTimer = 0;
var oxygenDecreaseRate = 0.1;
var gems = [];
var obstacles = [];
var seaCreatures = [];
var oxygenBubbles = [];
var caverns = [];
var dragNode = null;
var lastTouchY = 0;
// Play background music
LK.playMusic('underwaterAmbience');
// Generate initial caverns
function generateInitialCaverns() {
var cavernSpacing = 800;
var numInitialCaverns = Math.ceil(2048 / cavernSpacing) + 1;
for (var i = 0; i < numInitialCaverns; i++) {
var cavern = new Cavern();
cavern.y = 2732 - 150; // Bottom of the screen
cavern.x = i * cavernSpacing;
game.addChild(cavern);
caverns.push(cavern);
}
}
generateInitialCaverns();
// Handle touch and drag events
function handleMove(x, y, obj) {
if (dragNode) {
var deltaY = lastTouchY - y;
// If dragging upward, ascend
if (deltaY > 0) {
submarine.moveUp();
}
// If position is to the left of submarine, move left
if (x < submarine.x - 50) {
submarine.moveLeft();
}
// If position is to the right of submarine, move right
else if (x > submarine.x + 50) {
submarine.moveRight();
}
lastTouchY = y;
}
}
game.move = handleMove;
game.down = function (x, y, obj) {
dragNode = submarine;
lastTouchY = y;
handleMove(x, y, obj);
};
game.up = function (x, y, obj) {
dragNode = null;
};
// Spawn game objects
function spawnGem() {
var gem = new Gem();
gem.x = 2048 + 50;
gem.y = 300 + Math.random() * (2732 - 500);
gem.value = Math.floor(10 + depth / 100);
game.addChild(gem);
gems.push(gem);
}
function spawnObstacle() {
var obstacle = new Obstacle();
obstacle.x = 2048 + 125;
obstacle.y = 200 + Math.random() * (2732 - 400);
obstacle.speed = -3 - gameSpeed * 0.5;
game.addChild(obstacle);
obstacles.push(obstacle);
}
function spawnSeaCreature() {
var creature = new SeaCreature();
creature.x = 2048 + 75;
creature.y = 300 + Math.random() * (2732 - 600);
creature.initialY = creature.y;
creature.speed = -4 - gameSpeed * 0.5;
game.addChild(creature);
seaCreatures.push(creature);
}
function spawnOxygenBubble() {
var bubble = new OxygenBubble();
bubble.x = 2048 + 30;
bubble.y = 300 + Math.random() * (2732 - 600);
bubble.initialY = bubble.y;
bubble.speed = -2 - gameSpeed * 0.3;
game.addChild(bubble);
oxygenBubbles.push(bubble);
}
function spawnCavern() {
var cavern = new Cavern();
cavern.y = 2732 - 150; // Bottom of the screen
cavern.x = 2048 + 125;
cavern.speed = -2 - gameSpeed * 0.3;
game.addChild(cavern);
caverns.push(cavern);
}
// Main game update loop
game.update = function () {
// Update depth based on submarine position
depth = Math.floor((submarine.y - 100) / 10);
depthTxt.setText('Depth: ' + depth + 'm');
// Increase game speed based on depth
gameSpeed = 1 + depth / 500;
// Update oxygen level
oxygen -= oxygenDecreaseRate * gameSpeed;
if (oxygen <= 0) {
oxygen = 0;
LK.effects.flashScreen(0x0000FF, 1000);
// Update high score if needed
if (score > storage.highScore) {
storage.highScore = score;
highScoreTxt.setText('High Score: ' + storage.highScore);
}
LK.showGameOver();
}
// Update oxygen bar width
oxygenBar.width = oxygen / 100 * 800;
// Spawn game objects based on timers
spawnTimer++;
if (spawnTimer % 120 === 0) {
spawnGem();
}
if (spawnTimer % 180 === 0) {
spawnObstacle();
}
if (spawnTimer % 240 === 0) {
spawnSeaCreature();
}
if (spawnTimer % 300 === 0) {
spawnOxygenBubble();
}
if (spawnTimer % 200 === 0) {
spawnCavern();
}
// Check for and remove off-screen objects
for (var i = gems.length - 1; i >= 0; i--) {
var gem = gems[i];
// Check for collision with submarine
if (gem.intersects(submarine)) {
gem.collect();
score += gem.value;
scoreTxt.setText('Score: ' + score);
gem.destroy();
gems.splice(i, 1);
continue;
}
// Remove if off-screen
if (gem.x < -50) {
gem.destroy();
gems.splice(i, 1);
}
}
for (var i = obstacles.length - 1; i >= 0; i--) {
var obstacle = obstacles[i];
obstacle.update();
// Check for collision with submarine
if (obstacle.intersects(submarine)) {
submarine.hit();
oxygen -= 10;
// Push submarine back
submarine.speed = -5;
submarine.verticalSpeed = -3;
}
// Remove if off-screen
if (obstacle.x < -125) {
obstacle.destroy();
obstacles.splice(i, 1);
}
}
for (var i = seaCreatures.length - 1; i >= 0; i--) {
var creature = seaCreatures[i];
creature.update();
// Check for collision with submarine
if (creature.intersects(submarine)) {
submarine.hit();
oxygen -= 5;
// Push submarine back slightly
submarine.speed = -3;
}
// Remove if off-screen
if (creature.x < -75) {
creature.destroy();
seaCreatures.splice(i, 1);
}
}
for (var i = oxygenBubbles.length - 1; i >= 0; i--) {
var bubble = oxygenBubbles[i];
bubble.update();
// Check for collision with submarine
if (bubble.intersects(submarine)) {
bubble.collect();
oxygen = Math.min(oxygen + bubble.oxygenValue, 100);
bubble.destroy();
oxygenBubbles.splice(i, 1);
continue;
}
// Remove if off-screen
if (bubble.x < -30) {
bubble.destroy();
oxygenBubbles.splice(i, 1);
}
}
for (var i = caverns.length - 1; i >= 0; i--) {
var cavern = caverns[i];
cavern.update();
// Remove if off-screen
if (cavern.x < -125) {
cavern.destroy();
caverns.splice(i, 1);
}
}
// Update submarine
submarine.update();
// Win condition - reaching a certain score
if (score >= 1000) {
// Update high score
if (score > storage.highScore) {
storage.highScore = score;
highScoreTxt.setText('High Score: ' + storage.highScore);
}
LK.showYouWin();
}
};