/****
* Classes
****/
// Background class
var Background = Container.expand(function () {
var self = Container.call(this);
var backgroundGraphics = self.attachAsset('background', {
anchorX: 0.5,
anchorY: 0.5,
width: 2048,
height: 2732
});
backgroundGraphics.anchor.set(0, 0);
// Add black overlay on top of the background
var overlay = self.attachAsset('shape', {
width: 2048,
height: 2732,
color: 0x000000,
alpha: 0.0,
shape: 'box'
});
overlay.anchor.set(0, 0);
// This is automatically called every game tick, if the background is attached!
self.update = function () {
if (overlay.alpha < 1) {
overlay.alpha += 0.0001; // Increase alpha over time
}
};
});
// Bubble class
var Bubble = Container.expand(function () {
var self = Container.call(this);
var bubbleGraphics = self.attachAsset('bubble', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.5
});
var scale = Math.random() * 0.5 + 0.5;
bubbleGraphics.scale.set(scale, scale);
// Set bubble speed
self.speed = -3;
// Initialize colliding property
self.colliding = false;
// This is automatically called every game tick, if the bubble is attached!
self.update = function () {
// Move the bubble upwards and sideways
self.y += self.speed;
self.x += Math.sin(LK.ticks / 10) * 0.1;
// Reset the position of the bubble when it reaches the top
if (self.y <= 0) {
self.y = 2732;
}
// Check if the bubble is colliding with an obstacle using spatial hash
var cellSize = 150;
var hashX = Math.floor(self.x / cellSize);
var hashY = Math.floor(self.y / cellSize);
var hashKey = hashX + ',' + hashY;
if (spatialHash[hashKey]) {
for (var i = 0; i < spatialHash[hashKey].length; i++) {
var obstacle = spatialHash[hashKey][i];
if (self.intersects(obstacle)) {
// Bring the bubble to the top of the z axis
game.setChildIndex(self, game.children.length - 1);
self.colliding = true;
} else {
self.collidingWithShield = false;
self.colliding = false;
}
}
} else {
self.colliding = false;
}
};
});
// Diver class
var Diver = Container.expand(function () {
var self = Container.call(this);
var diverGraphics = self.attachAsset('diver', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.7,
scaleY: 0.7
});
// Add an invisible hitbox with smaller dimensions
var hitbox = self.attachAsset('shape', {
width: 200,
// Smaller width
height: 260,
// Increased height by 30%
// Smaller height
color: 0x000000,
alpha: 0 // Invisible
});
// Add a sideways movement to the diver
self.movement = 0;
self.direction = 1;
self.update = function () {
self.movement += self.direction * 0.03;
if (self.movement > 0.5 || self.movement < -0.5) {
self.direction *= -1;
}
self.x += self.movement;
};
// Center the hitbox on the diver
hitbox.anchor.set(0.5, 0.5);
// Add flippers to the diver
var leftFlipper = self.addChild(new Flipper());
leftFlipper.x = -50;
leftFlipper.depth = -1;
var rightFlipper = self.addChild(new Flipper());
rightFlipper.x = 60;
rightFlipper.depth = -1;
});
// Flipper class
var Flipper = Container.expand(function () {
var self = Container.call(this);
var flipperGraphics = self.attachAsset('flippers', {
anchorX: 0.5,
anchorY: 1.0,
scaleX: 0.7,
scaleY: 0.7
});
// Set flipper movement
self.movement = 0;
self.direction = 1;
// This is automatically called every game tick, if the flipper is attached!
self.update = function () {
// Move the flipper subtly to simulate flipping
self.movement += self.direction * 0.03;
if (self.movement > 0.5 || self.movement < -0.5) {
self.direction *= -1;
}
self.rotation = self.movement;
};
});
// Obstacle1 class
var Obstacle1 = Container.expand(function () {
var self = Container.call(this);
var obstacle1Graphics = self.attachAsset('obstacle1', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: Math.random() < 0.5 ? 0.7 : -0.7,
// Randomly mirror horizontally
scaleY: 0.7
});
// Set obstacle1 speed
self.speed = -5;
self.originalSpeedX = self.speed;
// This is automatically called every game tick, if the obstacle1 is attached!
self.update = function () {
// Rotate obstacle1 on its axis
self.rotation += 0.05;
// Check if the obstacle is colliding with the shield
if (self.intersects(shield, {
tolerance: 10
})) {
if (!self.collidingWithShield) {
LK.getSound('bubble').play();
self.collidingWithShield = true;
}
// Calculate the direction vector between the shield and the obstacle
var dx = self.x - shield.x;
var dy = self.y - shield.y;
var distance = Math.sqrt(dx * dx + dy * dy);
// Normalize the direction vector
dx /= distance;
dy /= distance;
// Push the obstacle away from the shield
self.x += dx * 5;
self.y += dy * 5;
} else {
self.collidingWithShield = false;
self.speed = self.originalSpeedX;
}
// Check for collision with diver
if (self.intersects(diver.children.find(function (child) {
return child.alpha === 0;
}), {
tolerance: 10
})) {
// Flash screen red for 1 second (1000ms) to show game over
LK.effects.flashScreen(0xff0000, 1000);
// Show game over. The game will be automatically paused while game over is showing.
LK.showGameOver();
}
// Update spatial hash
var oldHashX = Math.floor((self.x - self.speed * speedMultiplier) / cellSize);
var oldHashY = Math.floor((self.y - self.speed * speedMultiplier) / cellSize);
var newHashX = Math.floor(self.x / cellSize);
var newHashY = Math.floor(self.y / cellSize);
var oldHashKey = oldHashX + ',' + oldHashY;
var newHashKey = newHashX + ',' + newHashY;
if (oldHashKey !== newHashKey) {
if (spatialHash[oldHashKey]) {
var index = spatialHash[oldHashKey].indexOf(self);
if (index > -1) {
spatialHash[oldHashKey].splice(index, 1);
}
}
if (!spatialHash[newHashKey]) {
spatialHash[newHashKey] = [];
}
spatialHash[newHashKey].push(self);
}
// Continue moving upwards
self.x += self.waveSpeedX;
self.y += self.speed * speedMultiplier;
self.scale.x = 1 + Math.sin(LK.ticks / 10) * 0.02;
self.scale.y = 1 + Math.sin(LK.ticks / 10) * 0.02;
if (self.y < 0) {
self.destroy();
var index = obstacles.indexOf(self);
if (index > -1) {
obstacles.splice(index, 1);
}
}
// Check if the obstacle is colliding with another obstacle
for (var i = 0; i < obstacles.length; i++) {
var otherObstacle = obstacles[i];
if (self !== otherObstacle && self.intersects(otherObstacle)) {
// Calculate the direction vector between the two obstacles
var dx = self.x - otherObstacle.x;
var dy = self.y - otherObstacle.y;
var distance = Math.sqrt(dx * dx + dy * dy);
// Normalize the direction vector
dx /= distance;
dy /= distance;
// Increase the repulsion force and always push the obstacle to the outside
self.x += dx * 10;
self.y += dy * 10;
}
}
};
});
// Obstacle2 class
var Obstacle2 = Container.expand(function () {
var self = Container.call(this);
var obstacle2Graphics = self.attachAsset('obstacle2', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: Math.random() < 0.5 ? 0.7 : -0.7,
// Randomly mirror horizontally
scaleY: 0.7
});
// Set obstacle2 speed
self.speed = -5;
self.originalSpeedX = self.speed;
// This is automatically called every game tick, if the obstacle2 is attached!
self.update = function () {
// Check if the obstacle is colliding with the shield
if (self.intersects(shield, {
tolerance: 10
})) {
if (!self.collidingWithShield) {
LK.getSound('bubble').play();
self.collidingWithShield = true;
}
// Calculate the direction vector between the shield and the obstacle
var dx = self.x - shield.x;
var dy = self.y - shield.y;
var distance = Math.sqrt(dx * dx + dy * dy);
// Normalize the direction vector
dx /= distance;
dy /= distance;
// Push the obstacle away from the shield
self.x += dx * 5;
self.y += dy * 5;
} else {
self.collidingWithShield = false;
self.speed = self.originalSpeedX;
}
// Check for collision with diver
if (self.intersects(diver.children.find(function (child) {
return child.alpha === 0;
}), {
tolerance: 10
})) {
// Flash screen red for 1 second (1000ms) to show game over
LK.effects.flashScreen(0xff0000, 1000);
// Show game over. The game will be automatically paused while game over is showing.
LK.showGameOver();
}
// Update spatial hash
var oldHashX = Math.floor((self.x - self.speed * speedMultiplier) / cellSize);
var oldHashY = Math.floor((self.y - self.speed * speedMultiplier) / cellSize);
var newHashX = Math.floor(self.x / cellSize);
var newHashY = Math.floor(self.y / cellSize);
var oldHashKey = oldHashX + ',' + oldHashY;
var newHashKey = newHashX + ',' + newHashY;
if (oldHashKey !== newHashKey) {
if (spatialHash[oldHashKey]) {
var index = spatialHash[oldHashKey].indexOf(self);
if (index > -1) {
spatialHash[oldHashKey].splice(index, 1);
}
}
if (!spatialHash[newHashKey]) {
spatialHash[newHashKey] = [];
}
spatialHash[newHashKey].push(self);
}
// Continue moving upwards
self.x += self.waveSpeedX;
self.y += self.speed * speedMultiplier;
// Add wiggly movement to the obstacle
self.scale.x = 1 + Math.sin(LK.ticks / 10) * 0.02;
self.scale.y = 1 + Math.sin(LK.ticks / 10) * 0.02;
if (self.y < 0) {
self.destroy();
var index = obstacles.indexOf(self);
if (index > -1) {
obstacles.splice(index, 1);
}
}
// Check if the obstacle is colliding with another obstacle
for (var i = 0; i < obstacles.length; i++) {
var otherObstacle = obstacles[i];
if (self !== otherObstacle && self.intersects(otherObstacle)) {
// Calculate the direction vector between the two obstacles
var dx = self.x - otherObstacle.x;
var dy = self.y - otherObstacle.y;
var distance = Math.sqrt(dx * dx + dy * dy);
// Normalize the direction vector
dx /= distance;
dy /= distance;
// Increase the repulsion force and always push the obstacle to the outside
self.x += dx * 10;
self.y += dy * 10;
}
}
};
});
// Obstacle3 class
var Obstacle3 = Container.expand(function () {
var self = Container.call(this);
var obstacle3Graphics = self.attachAsset('obstacle3', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: Math.random() < 0.5 ? 0.7 : -0.7,
// Randomly mirror horizontally
scaleY: 0.7
});
// Set obstacle3 speed
self.speed = -5;
self.originalSpeedX = self.speed;
// This is automatically called every game tick, if the obstacle3 is attached!
self.update = function () {
// Check if the obstacle is colliding with the shield
if (self.intersects(shield, {
tolerance: 10
})) {
if (!self.collidingWithShield) {
LK.getSound('bubble').play();
self.collidingWithShield = true;
}
// Calculate the direction vector between the shield and the obstacle
var dx = self.x - shield.x;
var dy = self.y - shield.y;
var distance = Math.sqrt(dx * dx + dy * dy);
// Normalize the direction vector
dx /= distance;
dy /= distance;
// Push the obstacle away from the shield
self.x += dx * 5;
self.y += dy * 5;
} else {
self.collidingWithShield = false;
self.speed = self.originalSpeedX;
}
// Check for collision with diver
if (self.intersects(diver.children.find(function (child) {
return child.alpha === 0;
}), {
tolerance: 10
})) {
// Flash screen red for 1 second (1000ms) to show game over
LK.effects.flashScreen(0xff0000, 1000);
// Show game over. The game will be automatically paused while game over is showing.
LK.showGameOver();
}
// Update spatial hash
var oldHashX = Math.floor((self.x - self.speed * speedMultiplier) / cellSize);
var oldHashY = Math.floor((self.y - self.speed * speedMultiplier) / cellSize);
var newHashX = Math.floor(self.x / cellSize);
var newHashY = Math.floor(self.y / cellSize);
var oldHashKey = oldHashX + ',' + oldHashY;
var newHashKey = newHashX + ',' + newHashY;
if (oldHashKey !== newHashKey) {
if (spatialHash[oldHashKey]) {
var index = spatialHash[oldHashKey].indexOf(self);
if (index > -1) {
spatialHash[oldHashKey].splice(index, 1);
}
}
if (!spatialHash[newHashKey]) {
spatialHash[newHashKey] = [];
}
spatialHash[newHashKey].push(self);
}
// Continue moving upwards
self.x += self.waveSpeedX;
self.y += self.speed * speedMultiplier;
// Add slow spinning effect
self.rotation += 0.01;
// Add unique behavior to obstacle3
self.scale.x = 1 + Math.sin(LK.ticks / 5) * 0.05; // Larger size change
self.scale.y = 1 + Math.sin(LK.ticks / 5) * 0.05;
if (self.y < 0) {
self.destroy();
var index = obstacles.indexOf(self);
if (index > -1) {
obstacles.splice(index, 1);
}
}
// Check if the obstacle is colliding with another obstacle
for (var i = 0; i < obstacles.length; i++) {
var otherObstacle = obstacles[i];
if (self !== otherObstacle && self.intersects(otherObstacle)) {
// Calculate the direction vector between the two obstacles
var dx = self.x - otherObstacle.x;
var dy = self.y - otherObstacle.y;
var distance = Math.sqrt(dx * dx + dy * dy);
// Normalize the direction vector
dx /= distance;
dy /= distance;
// Increase the repulsion force and always push the obstacle to the outside
self.x += dx * 10;
self.y += dy * 10;
}
}
};
});
// Obstacle4 class
var Obstacle4 = Container.expand(function () {
var self = Container.call(this);
var obstacle4Graphics = self.attachAsset('obstacle4', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: Math.random() < 0.5 ? 0.7 : -0.7,
// Randomly mirror horizontally
scaleY: 0.7
});
// Set obstacle4 speed
self.speed = -5;
self.originalSpeedX = self.speed;
// This is automatically called every game tick, if the obstacle4 is attached!
self.update = function () {
// Add up and down movement
self.y += Math.sin(LK.ticks / 20) * 2;
// Check if the obstacle is colliding with the shield
if (self.intersects(shield, {
tolerance: 10
})) {
if (!self.collidingWithShield) {
LK.getSound('bubble').play();
self.collidingWithShield = true;
}
// Calculate the direction vector between the shield and the obstacle
var dx = self.x - shield.x;
var dy = self.y - shield.y;
var distance = Math.sqrt(dx * dx + dy * dy);
// Normalize the direction vector
dx /= distance;
dy /= distance;
// Push the obstacle away from the shield
self.x += dx * 5;
self.y += dy * 5;
} else {
self.collidingWithShield = false;
self.speed = self.originalSpeedX;
}
// Check for collision with diver
if (self.intersects(diver.children.find(function (child) {
return child.alpha === 0;
}), {
tolerance: 10
})) {
// Flash screen red for 1 second (1000ms) to show game over
LK.effects.flashScreen(0xff0000, 1000);
// Show game over. The game will be automatically paused while game over is showing.
LK.showGameOver();
}
// Update spatial hash
var oldHashX = Math.floor((self.x - self.speed * speedMultiplier) / cellSize);
var oldHashY = Math.floor((self.y - self.speed * speedMultiplier) / cellSize);
var newHashX = Math.floor(self.x / cellSize);
var newHashY = Math.floor(self.y / cellSize);
var oldHashKey = oldHashX + ',' + oldHashY;
var newHashKey = newHashX + ',' + newHashY;
if (oldHashKey !== newHashKey) {
if (spatialHash[oldHashKey]) {
var index = spatialHash[oldHashKey].indexOf(self);
if (index > -1) {
spatialHash[oldHashKey].splice(index, 1);
}
}
if (!spatialHash[newHashKey]) {
spatialHash[newHashKey] = [];
}
spatialHash[newHashKey].push(self);
}
// Continue moving upwards
self.x += self.waveSpeedX;
self.y += self.speed * speedMultiplier + Math.sin(LK.ticks / 20) * 2;
self.scale.x = 1 + Math.sin(LK.ticks / 15) * 0.03; // Different size change
self.scale.y = 1 + Math.sin(LK.ticks / 15) * 0.03;
if (self.y < 0) {
self.destroy();
var index = obstacles.indexOf(self);
if (index > -1) {
obstacles.splice(index, 1);
}
}
// Check if the obstacle is colliding with another obstacle
for (var i = 0; i < obstacles.length; i++) {
var otherObstacle = obstacles[i];
if (self !== otherObstacle && self.intersects(otherObstacle)) {
// Calculate the direction vector between the two obstacles
var dx = self.x - otherObstacle.x;
var dy = self.y - otherObstacle.y;
var distance = Math.sqrt(dx * dx + dy * dy);
// Normalize the direction vector
dx /= distance;
dy /= distance;
// Increase the repulsion force and always push the obstacle to the outside
self.x += dx * 10;
self.y += dy * 10;
}
}
};
});
// Obstacle5 class
var Obstacle5 = Container.expand(function () {
var self = Container.call(this);
var obstacle5Graphics = self.attachAsset('obstacle5', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: Math.random() < 0.5 ? 0.7 : -0.7,
// Randomly mirror horizontally
scaleY: 0.7
});
// Set obstacle5 speed
self.speed = -5;
self.originalSpeedX = self.speed;
// This is automatically called every game tick, if the obstacle5 is attached!
self.update = function () {
// Add very small sideways movement
self.x += Math.sin(LK.ticks / 100) * 0.5;
// Check if the obstacle is colliding with the shield
if (self.intersects(shield, {
tolerance: 10
})) {
if (!self.collidingWithShield) {
LK.getSound('bubble').play();
self.collidingWithShield = true;
}
// Calculate the direction vector between the shield and the obstacle
var dx = self.x - shield.x;
var dy = self.y - shield.y;
var distance = Math.sqrt(dx * dx + dy * dy);
// Normalize the direction vector
dx /= distance;
dy /= distance;
// Push the obstacle away from the shield
self.x += dx * 5;
self.y += dy * 5;
} else {
self.collidingWithShield = false;
self.speed = self.originalSpeedX;
}
// Check for collision with diver
if (self.intersects(diver.children.find(function (child) {
return child.alpha === 0;
}), {
tolerance: 10
})) {
// Flash screen red for 1 second (1000ms) to show game over
LK.effects.flashScreen(0xff0000, 1000);
// Show game over. The game will be automatically paused while game over is showing.
LK.showGameOver();
}
// Update spatial hash
var oldHashX = Math.floor((self.x - self.speed * speedMultiplier) / cellSize);
var oldHashY = Math.floor((self.y - self.speed * speedMultiplier) / cellSize);
var newHashX = Math.floor(self.x / cellSize);
var newHashY = Math.floor(self.y / cellSize);
var oldHashKey = oldHashX + ',' + oldHashY;
var newHashKey = newHashX + ',' + newHashY;
if (oldHashKey !== newHashKey) {
if (spatialHash[oldHashKey]) {
var index = spatialHash[oldHashKey].indexOf(self);
if (index > -1) {
spatialHash[oldHashKey].splice(index, 1);
}
}
if (!spatialHash[newHashKey]) {
spatialHash[newHashKey] = [];
}
spatialHash[newHashKey].push(self);
}
// Continue moving upwards
self.x += self.waveSpeedX;
self.y += self.speed * speedMultiplier;
// Add unique behavior to obstacle5
self.scale.x = 1 + Math.sin(LK.ticks / 20) * 0.1; // Increase size change amplitude
self.scale.y = 1 + Math.sin(LK.ticks / 20) * 0.1;
if (self.y < 0) {
self.destroy();
var index = obstacles.indexOf(self);
if (index > -1) {
obstacles.splice(index, 1);
}
}
// Check if the obstacle is colliding with another obstacle
for (var i = 0; i < obstacles.length; i++) {
var otherObstacle = obstacles[i];
if (self !== otherObstacle && self.intersects(otherObstacle)) {
// Calculate the direction vector between the two obstacles
var dx = self.x - otherObstacle.x;
var dy = self.y - otherObstacle.y;
var distance = Math.sqrt(dx * dx + dy * dy);
// Normalize the direction vector
dx /= distance;
dy /= distance;
// Increase the repulsion force and always push the obstacle to the outside
self.x += dx * 10;
self.y += dy * 10;
}
}
};
});
// Obstacle6 class
var Obstacle6 = Container.expand(function () {
var self = Container.call(this);
var obstacle6Graphics = self.attachAsset('obstacle6', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: Math.random() < 0.5 ? 0.7 : -0.7,
// Randomly mirror horizontally
scaleY: 0.7
});
// Set obstacle6 speed
self.speed = -5;
self.originalSpeedX = self.speed;
// This is automatically called every game tick, if the obstacle6 is attached!
self.update = function () {
// Flickering effect
self.alpha = Math.random() * 0.5 + 0.5; // Random alpha between 0.5 and 1
// Fast side-to-side movement
self.x += Math.sin(LK.ticks / 10) * 1; // Further reduced horizontal movement
// Check if the obstacle is colliding with the shield
if (self.intersects(shield, {
tolerance: 10
})) {
if (!self.collidingWithShield) {
LK.getSound('bubble').play();
self.collidingWithShield = true;
}
// Calculate the direction vector between the shield and the obstacle
var dx = self.x - shield.x;
var dy = self.y - shield.y;
var distance = Math.sqrt(dx * dx + dy * dy);
// Normalize the direction vector
dx /= distance;
dy /= distance;
// Push the obstacle away from the shield
self.x += dx * 5;
self.y += dy * 5;
} else {
self.collidingWithShield = false;
self.speed = self.originalSpeedX;
}
// Check for collision with diver
if (self.intersects(diver.children.find(function (child) {
return child.alpha === 0;
}), {
tolerance: 10
})) {
// Flash screen red for 1 second (1000ms) to show game over
LK.effects.flashScreen(0xff0000, 1000);
// Show game over. The game will be automatically paused while game over is showing.
LK.showGameOver();
}
// Update spatial hash
var oldHashX = Math.floor((self.x - self.speed * speedMultiplier) / cellSize);
var oldHashY = Math.floor((self.y - self.speed * speedMultiplier) / cellSize);
var newHashX = Math.floor(self.x / cellSize);
var newHashY = Math.floor(self.y / cellSize);
var oldHashKey = oldHashX + ',' + oldHashY;
var newHashKey = newHashX + ',' + newHashY;
if (oldHashKey !== newHashKey) {
if (spatialHash[oldHashKey]) {
var index = spatialHash[oldHashKey].indexOf(self);
if (index > -1) {
spatialHash[oldHashKey].splice(index, 1);
}
}
if (!spatialHash[newHashKey]) {
spatialHash[newHashKey] = [];
}
spatialHash[newHashKey].push(self);
}
// Continue moving upwards
self.x += self.waveSpeedX;
self.y += self.speed * speedMultiplier;
// Add unique behavior to obstacle6
self.scale.x = 1 + Math.sin(LK.ticks / 25) * 0.05; // Different size change
self.scale.y = 1 + Math.sin(LK.ticks / 25) * 0.05;
self.alpha = Math.random() * 0.5 + 0.5; // Random alpha between 0.5 and 1
self.x += Math.sin(LK.ticks / 5) * 10; // Fast horizontal movement
if (self.y < 0) {
self.destroy();
var index = obstacles.indexOf(self);
if (index > -1) {
obstacles.splice(index, 1);
}
}
// Check if the obstacle is colliding with another obstacle
for (var i = 0; i < obstacles.length; i++) {
var otherObstacle = obstacles[i];
if (self !== otherObstacle && self.intersects(otherObstacle)) {
// Calculate the direction vector between the two obstacles
var dx = self.x - otherObstacle.x;
var dy = self.y - otherObstacle.y;
var distance = Math.sqrt(dx * dx + dy * dy);
// Normalize the direction vector
dx /= distance;
dy /= distance;
// Increase the repulsion force and always push the obstacle to the outside
self.x += dx * 10;
self.y += dy * 10;
}
}
};
});
var PowerUp = Container.expand(function () {
var self = Container.call(this);
var powerUpGraphics = self.attachAsset('powerUp', {
anchorX: 0.5,
anchorY: 0.5
});
self.update = function () {
self.y += 1.6; // Move power-up downwards (reduced by 20%)
self.x += Math.sin(LK.ticks / 20) * 2; // Add pendular movement
// Check if the power-up is colliding with the shield
if (self.intersects(shield, {
tolerance: 10
})) {
if (!self.collidingWithShield) {
LK.getSound('bubble').play();
self.collidingWithShield = true;
}
// Calculate the direction vector between the shield and the power-up
var dx = self.x - shield.x;
var dy = self.y - shield.y;
var distance = Math.sqrt(dx * dx + dy * dy);
// Normalize the direction vector
dx /= distance;
dy /= distance;
// Push the power-up away from the shield
self.x += dx * 5;
self.y += dy * 5;
} else {
self.collidingWithShield = false;
}
if (self.intersects(diver)) {
LK.getSound('powerup').play();
shield.scale.x *= 2;
shield.scale.y *= 2;
LK.setTimeout(function () {
// Start blinking effect after 8 seconds
var blinkInterval = LK.setInterval(function () {
shield.alpha = shield.alpha === 1 ? 0.5 : 1;
if (shield.alpha === 0.5 && !self.shieldOffPlayed) {
LK.getSound('shieldoff').play();
self.shieldOffPlayed = true;
}
}, 60); // Blink every 500ms
// Stop blinking and reset shield size after 10 seconds
LK.setTimeout(function () {
LK.clearInterval(blinkInterval);
shield.alpha = 0.9; // Reset alpha to original value
shield.scale.x /= 2;
shield.scale.y /= 2;
self.shieldOffPlayed = false;
}, 2000); // Blink for 2 seconds
}, 8000); // Start blinking after 8 seconds
self.destroy();
}
};
});
// Shield class
var Shield = Container.expand(function () {
var self = Container.call(this);
var shieldGraphics = self.attachAsset('shield', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.75
});
self.originalAlpha = shieldGraphics.alpha; // Store the original alpha value
self.down = function (x, y, obj) {
dragNode = shield;
};
});
/****
* Initialize Game
****/
// Create a diver instance
//<Assets used in the game will automatically appear here>
var game = new LK.Game({
backgroundColor: 0xADD8E6 //Init game with a softer blue background
});
/****
* Game Code
****/
var wavePositionLabel;
// Function to spawn power-ups every 20 seconds
function spawnPowerUp() {
if (!firstPowerUpSpawned) {
if (LK.ticks < 300) {
// 300 ticks = 5 seconds
return;
}
firstPowerUpSpawned = true;
} else if (LK.ticks - lastPowerUpSpawnTime < 1200) {
// 1200 ticks = 20 seconds
return;
}
var powerUp = game.addChild(new PowerUp());
lastPowerUpSpawnTime = LK.ticks;
do {
powerUp.x = Math.random() * 2048;
} while (diver && Math.abs(powerUp.x - diver.x) < 200);
powerUp.y = -100; // Start offscreen at the top
// Schedule the next power-up spawn
LK.setTimeout(spawnPowerUp, 20000); // 20 seconds
}
// Initial call to spawn the first power-up after 20 seconds
LK.setTimeout(spawnPowerUp, 20000);
var lastBubbleSoundTime = 0;
var lastPowerUpSpawnTime = 0;
var speedMultiplier = 1;
var waveInterval = 6000; // Initial interval of 5 seconds between waves
var firstPowerUpSpawned = false;
// Declare and initialize backgroundMusic variable
var backgroundMusic = LK.getSound('background');
// Play background music on loop when the game starts
LK.on('tick', function () {
if (!backgroundMusic.playing) {
backgroundMusic.play();
}
});
var background1 = game.addChild(new Background());
background1.y = 0;
// Create a shield instance
var shield = game.addChildAt(new Shield(), game.children.length);
// Position the shield at the center of the screen
shield.x = 2048 / 2;
shield.y = 2732 / 2;
// Create a diver instance
var dragNode = null;
var diver = new Diver();
diver.depth = 2;
// Position the diver at the top center of the screen, 200 pixels down from the top
diver.x = 2048 / 2;
diver.y = 500;
// Ensure diver's dimensions are fully initialized before positioning flippers
diver.on('added', function () {
// Position the flippers relative to the diver
diver.children[0].y = diver.height / 2 - 20; // Left flipper
diver.children[1].y = diver.height / 2 - 20; // Right flipper
});
// Position the flippers relative to the diver
diver.children[0].y = diver.height / 2 - 20; // Left flipper
diver.children[0].y = diver.children[0].y; // Right flipper
// Set diver to a higher depth than flippers
diver.depth = 2;
// Create an obstacle1 instance
game.move = function (x, y, obj) {
if (dragNode) {
if (dragNode !== shield) {
shield.x += x - shield.x;
shield.y += y - shield.y;
} else {
dragNode.x = x;
dragNode.y = y;
}
}
if (dragNode === shield) {
shield.x = x;
shield.y = y;
}
};
var obstacles = [];
var spatialHash = {};
game.addChild(diver);
game.setChildIndex(diver, game.children.length - 1);
// Create power-up instance
var powerUp = game.addChild(new PowerUp());
do {
powerUp.x = Math.random() * 2048;
} while (Math.abs(powerUp.x - diver.x) < 200);
powerUp.y = -100; // Start offscreen at the top
// Create bubbles after obstacles
var bubbles = [];
for (var i = 0; i < 20; i++) {
var bubble = new Bubble();
bubble.x = Math.random() * 2048;
bubble.y = Math.random() * 2732;
bubbles.push(bubble);
game.addChildAt(bubble, game.children.length);
}
// Spawn the first wave of obstacles
spawnWave();
;
// Initialize score
var score = LK.getScore();
// Create score text
var depthScoreText = new Text2('Depth:0m', {
size: 70,
fill: "#ffffff",
stroke: "#000000",
strokeThickness: 6,
font: "monospace" // Change font to be more square
});
depthScoreText.anchor.set(0.5, 0.5);
depthScoreText.x = 400;
depthScoreText.y = 100;
LK.gui.top.addChild(depthScoreText);
// Initialize a timer to update the score every second and increase speed multiplier
var scoreUpdateInterval = LK.setInterval(function () {
LK.setScore(LK.getScore() + 1);
if (depthScoreText) {
depthScoreText.setText('Depth:' + LK.getScore() + 'm');
}
speedMultiplier += 0.01; // Increase speed multiplier by 0.02 every second
}, 1000);
game.up = function (x, y, obj) {
dragNode = null;
};
// Check if background music is playing, if not, play it
if (!backgroundMusic.playing) {
backgroundMusic.play();
}
// Update background
background1.update();
// Update bubbles
for (var i = 0; i < bubbles.length; i++) {
bubbles[i].update();
}
// Define the current wave
var currentWave = 0;
var allWavesSpawnedOnce = false;
// Spawn wave function
function spawnWave() {
// Define the layout of the obstacles for each wave
var obstacleLayouts = [{
type: 'line',
grid: ['.....', '.....', '.#.#.', '.....', '.....']
}, {
type: 'triangle',
grid: ['.....', '..#..', '.....', '.#.#.', '.....']
}, {
type: 'square',
grid: ['.....', '.#.#.', '.....', '.#.#.', '.....']
}, {
type: 'circle',
grid: ['.....', '..#..', '.#.#.', '.#.#.', '..#..']
}, {
type: 'cross',
grid: ['.....', '..#..', '.#.#.', '..#..', '.....']
}, {
type: 'hexagon',
grid: ['.....', '..#..', '.#.#.', '.#.#.', '..#..']
}, {
type: 'heptagon',
grid: ['..#..', '.....', '#...#', '.....', '..#..']
}, {
type: 'octagon',
grid: ['.....', '#####', '.....', '.....', '.....']
}, {
type: 'nonagon',
grid: ['#....', '.#....', '..#..', '...#.', '....#']
}, {
type: 'nonagon2',
grid: ['....#', '...#.', '..#..', '.#...', '#....']
}, {
type: 'gon2',
grid: ['#.#.#', '......', '..#..', '.....', '#.#.#']
}, {
type: 'gonn3',
grid: ['#.#.#', '......', '.....', '.....', '#.#.#']
}, {
type: 'decagon',
grid: ['.....', '..#..', '.#.#.', '.#.#.', '..#..']
}];
// Get the layout for the current wave
var layout = obstacleLayouts[currentWave];
if (!layout) {
console.error('Error: layout is undefined. Check the obstacleLayouts array.');
return;
}
var layoutPositions = [];
layout.grid.forEach(function (row, rowIndex) {
row.split('').forEach(function (cell, colIndex) {
if (cell === '#') {
layoutPositions.push({
x: colIndex,
y: rowIndex
});
}
});
});
// Randomly choose an obstacle type for the entire wave
var obstacleTypes = [Obstacle1, Obstacle2, Obstacle3, Obstacle4, Obstacle5, Obstacle6];
var obstacleType = obstacleTypes[Math.floor(Math.random() * obstacleTypes.length)];
// Randomly choose one of the three starting x positions for the entire wave
var startXPositions = [{
position: 2048 / 4.5,
label: 'left'
}, {
position: 2048 / 1.08,
label: 'right'
}, {
position: 2048 / 1.9,
label: 'center'
}];
var randomStart = startXPositions[Math.floor(Math.random() * startXPositions.length)];
var randomStartX = randomStart.position;
wavePositionLabel = randomStart.label;
console.log('Wave starting position:', wavePositionLabel);
console.log('Wave starting position:', wavePositionLabel);
// Generate a random spacing multiplier between 1 and 2 for the current wave
var spacingMultiplier = 1 + Math.random();
layoutPositions.forEach(function (position) {
var obstacle = game.addChild(new obstacleType());
// Position the obstacles according to the layout, using the grid for positioning
obstacle.x = randomStartX + (position.x - gridSize / 2) * cellSize * spacingMultiplier;
obstacle.y = 2732 + position.y * cellSize * spacingMultiplier; // Spawn obstacles offscreen at the bottom
obstacle.waveSpeedX = wavePositionLabel === 'right' ? -1.5 : wavePositionLabel === 'left' ? 1.5 : 0;
obstacles.push(obstacle);
});
currentWave++;
if (currentWave >= obstacleLayouts.length) {
allWavesSpawnedOnce = true;
currentWave = 0;
}
if (allWavesSpawnedOnce) {
currentWave = Math.floor(Math.random() * (obstacleLayouts.length - 3)) + 3;
}
// Add interval of wait between waves, decreasing over time
var waveInterval = Math.max(1000, 5000 - LK.getScore() * 10); // Minimum interval of 1 second
LK.setTimeout(function () {
spawnWave();
}, waveInterval);
}
// Define the grid size and the size of each cell in the grid
var gridSize = 5;
var cellSize = 150;
// Call the spawn wave function every 1 second
// Initial call to spawn the first wave
spawnWave();
;
8bit. cartoon. jellyfish.. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
empty 8 bit cartoon white circle. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
cartoon. 8-bit. octopus. colorful.. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
cartoon. 8-bit. sea urchin. colorful. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
cartoon 8bit stingray. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.