/****
* Classes
****/
// Ball class
var Ball = Container.expand(function () {
var self = Container.call(this);
var ballGraphics = self.attachAsset('ball', {
anchorX: 0.5,
anchorY: 0.5
});
self["throw"] = function () {
// Throw logic for the ball
};
self.spawn = function () {
// Adjusted spawn logic to exclude top 10% of the screen and area around the basket
var safeSpawnArea = {
xMin: 0,
xMax: 2048,
yMin: 273.2,
// Start from 10% of the screen height to avoid top 10%
yMax: 2732 - 273.2 // Exclude the bottom 10% as well for symmetry
};
var basketSafeZone = {
xMin: basket.x - 150,
// Basket width / 2
yMin: basket.y - 157.005,
// Basket height
xMax: basket.x + 150,
// Basket width / 2
yMax: basket.y + 157.005 // Basket height
};
do {
self.x = Math.random() * (safeSpawnArea.xMax - safeSpawnArea.xMin) + safeSpawnArea.xMin;
self.y = Math.random() * (safeSpawnArea.yMax - safeSpawnArea.yMin) + safeSpawnArea.yMin;
} while (self.x >= basketSafeZone.xMin && self.x <= basketSafeZone.xMax && self.y >= basketSafeZone.yMin && self.y <= basketSafeZone.yMax);
};
});
// Assets will be automatically created based on usage in the code.
// Basket class
var Basket = Container.expand(function () {
var self = Container.call(this);
var basketGraphics = self.attachAsset('basket', {
anchorX: 0.5,
anchorY: 0.5
});
self.drawArrow = function (pos) {
// Calculate the distance and direction of the drag
var dx = pos.x - self.x;
var dy = pos.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
var direction = Math.atan2(dy, dx);
// Remove the previous arrow if it exists
if (self.arrow) {
self.arrow.destroy();
}
// Create a new arrow asset
self.arrow = LK.getAsset('arrow', {
anchorX: 0.0,
// Anchor at the start of the arrow
anchorY: 0.5,
// Center vertically
x: self.x,
y: self.y,
scaleX: Math.min(Math.max(distance / 100, 1), 0.3 * Math.sqrt(2048 * 2048 + 2732 * 2732) / 100),
// Stretch the arrow in the direction of the cursor, but ensure it's at least 1 to allow it to extend outside the screen and not more than 40% of the screen size
scaleY: 1,
rotation: direction
});
// Correctly align the basket's opening with the arrow direction without additional rotation
basketGraphics.rotation = direction;
// Add the arrow to the game
game.addChild(self.arrow);
};
self.move = function () {
// Move the basket
self.x += self.vx;
self.y += self.vy;
// Apply friction
self.vx *= 0.99;
self.vy *= 0.99;
// Check for collision with the edges of the screen and bounce off
if (self.x < 0) {
self.vx = Math.abs(self.vx);
// Correctly adjust the basket's rotation to align with the new direction of movement, ensuring the opening follows the path
basketGraphics.rotation = Math.atan2(self.vy, self.vx);
} else if (self.x > 2048) {
self.vx = -Math.abs(self.vx);
basketGraphics.rotation = Math.atan2(self.vy, self.vx);
}
if (self.y < 0) {
self.vy = Math.abs(self.vy);
// Adjust the basket's rotation to follow the path of reflection, ensuring the opening is correctly aligned
basketGraphics.rotation = Math.atan2(self.vy, self.vx) + Math.PI / 2;
} else if (self.y > 2732) {
self.vy = -Math.abs(self.vy);
basketGraphics.rotation = Math.atan2(self.vy, self.vx) + Math.PI / 2;
}
// Check for collision with obstacles and boostpads, bounce off obstacles, and reflect with increased speed on boostpads
for (var i = 0; i < obstacles.length; i++) {
if (self.intersects(obstacles[i])) {
// Calculate the angle of reflection
var dx = self.x - obstacles[i].x;
var dy = self.y - obstacles[i].y;
var angle = Math.atan2(dy, dx);
// Reflect the velocity
self.vx = Math.cos(angle) * Math.sqrt(self.vx * self.vx + self.vy * self.vy);
self.vy = Math.sin(angle) * Math.sqrt(self.vx * self.vx + self.vy * self.vy);
// Adjust the basket's rotation to follow the path of reflection, ensuring the opening faces the correct direction
basketGraphics.rotation = Math.atan2(self.vy, self.vx);
}
}
for (var j = 0; j < boostpads.length; j++) {
if (self.intersects(boostpads[j])) {
// Calculate the angle of reflection and display 'lightning' asset on collision edge
var dxPad = self.x - boostpads[j].x;
var dyPad = self.y - boostpads[j].y;
var anglePad = Math.atan2(dyPad, dxPad);
// Display 'lightning' asset at the point of collision for half a second
var lightning = LK.getAsset('lightning', {
x: self.x - Math.cos(anglePad) * basketGraphics.width / 2,
y: self.y - Math.sin(anglePad) * basketGraphics.height / 2,
anchorX: 0.5,
anchorY: 0.5
});
game.addChild(lightning);
LK.setTimeout(function () {
lightning.destroy();
}, 500);
// Check if the basket was deflected off another boost pad right before hitting this one
if (!self.deflected) {
// Reflect the velocity and increase speed
self.vx = Math.cos(anglePad) * 1.6 * Math.sqrt(self.vx * self.vx + self.vy * self.vy);
self.vy = Math.sin(anglePad) * 1.6 * Math.sqrt(self.vx * self.vx + self.vy * self.vy);
// Adjust the basket's rotation to follow the path of reflection with increased speed, ensuring the opening faces the correct direction
basketGraphics.rotation = Math.atan2(self.vy, self.vx);
// Mark the basket as having been boosted for double scoring
self.boosted = true;
// Mark the basket as deflected to prevent further acceleration without player interaction
self.deflected = true;
// Reset the deflected flag after a short delay to allow for player interaction
LK.setTimeout(function () {
self.deflected = false;
}, 500); // Delay in milliseconds
} else {
// Simply reflect the velocity without increasing speed
self.vx = Math.cos(anglePad) * Math.sqrt(self.vx * self.vx + self.vy * self.vy);
self.vy = Math.sin(anglePad) * Math.sqrt(self.vx * self.vx + self.vy * self.vy);
// Adjust the basket's rotation to follow the path of reflection, ensuring the opening faces the correct direction
basketGraphics.rotation = Math.atan2(self.vy, self.vx);
}
}
}
};
self.shoot = function (pos) {
// Calculate the distance and direction of the drag
var dx = self.x - pos.x;
var dy = self.y - pos.y;
var distance = Math.sqrt(dx * dx + dy * dy);
var direction = Math.atan2(dy, dx);
// Set the velocity of the basket to go 50% further than the cursor's end location
self.vx = -Math.cos(direction) * distance * 1.5 / 100;
self.vy = -Math.sin(direction) * distance * 1.5 / 100;
};
self.isBallHitByOpening = function (ball) {
// Calculate the angle between the basket's direction and the ball
if (ball) {
var dx = ball.x - self.x;
var dy = ball.y - self.y;
}
var angle = Math.atan2(dy, dx);
// Check if the ball is within the opening angle of the basket
return Math.abs(angle - basketGraphics.rotation) < Math.PI / 4;
};
});
// Boostpad class
var Boostpad = Container.expand(function () {
var self = Container.call(this);
var boostpadGraphics = self.attachAsset('boostPad', {
anchorX: 0.5,
anchorY: 0.5
});
self.positionBoostpad = function () {
do {
self.x = Math.random() * 2048;
self.y = Math.random() * (2732 - 273.2) + 273.2; // Exclude top 10%
} while (self.x >= basketSafeZone.xMin && self.x <= basketSafeZone.xMax && self.y >= basketSafeZone.yMin && self.y <= basketSafeZone.yMax); // Ensure boostpad does not spawn within basket area
};
// Initialize boostPad size change animation
self.animateSize = function () {
var growing = true;
LK.on('tick', function () {
if (growing) {
self.scaleX = Math.min(self.scaleX + 0.01, 1.3);
self.scaleY = Math.min(self.scaleY + 0.01, 1.3);
if (self.scaleX >= 1.3) {
growing = false;
}
} else {
self.scaleX = Math.max(self.scaleX - 0.01, 0.9);
self.scaleY = Math.max(self.scaleY - 0.01, 0.9);
if (self.scaleX <= 0.9) {
growing = true;
}
}
});
};
self.animateSize();
});
// Enemy class
var Enemy = Container.expand(function () {
var self = Container.call(this);
var enemyGraphics = self.attachAsset('enemy', {
anchorX: 0.5,
anchorY: 0.5,
tint: 0xFF0000 // Red color to differentiate enemies
});
self.moveTowardsBasket = function (basket) {
if (LK.ticks > 180) {
// 3 seconds at 60FPS
var dx = basket.x - self.x;
var dy = basket.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
this.speed = this.speed || 2; // Initialize speed if not set
var speed = this.speed; // Use the enemy's current speed
self.x += dx / distance * speed;
self.y += dy / distance * speed;
}
};
});
var Magnet = Container.expand(function () {
var self = Container.call(this);
var magnetGraphics = self.attachAsset('magnet', {
anchorX: 0.5,
anchorY: 0.5
});
self.spawn = function () {
self.x = Math.random() * 2048;
self.y = Math.random() * 2732;
};
});
// MediaKit class for immunity item
var MediaKit = Container.expand(function () {
var self = Container.call(this);
var mediaKitGraphics = self.attachAsset('mediaKit', {
anchorX: 0.5,
anchorY: 0.5
});
self.spawn = function () {
self.x = Math.random() * 2048;
self.y = Math.random() * 2732;
};
});
// Obstacle class
var Obstacle = Container.expand(function () {
var self = Container.call(this);
var sizeMultiplier = Math.random() + 1; // Generates a value between 1.0 and 2.0
var obstacleGraphics = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: sizeMultiplier,
scaleY: sizeMultiplier
});
self.positionObstacle = function () {
do {
self.x = Math.random() * 2048;
self.y = Math.random() * (2732 - 273.2) + 273.2; // Exclude top 10%
} while (self.x >= basketSafeZone.xMin && self.x <= basketSafeZone.xMax && self.y >= basketSafeZone.yMin && self.y <= basketSafeZone.yMax); // Ensure obstacle does not spawn within basket area
};
});
// Revive class for refilling a life
var Revive = Container.expand(function () {
var self = Container.call(this);
var reviveGraphics = self.attachAsset('revive', {
anchorX: 0.5,
anchorY: 0.5
});
self.spawn = function () {
self.x = Math.random() * 2048;
self.y = Math.random() * 2732;
};
});
// SlowDown class for slowing down enemies
var SlowDown = Container.expand(function () {
var self = Container.call(this);
var slowDownGraphics = self.attachAsset('slowDown', {
anchorX: 0.5,
anchorY: 0.5
});
self.spawn = function () {
self.x = Math.random() * 2048;
self.y = Math.random() * 2732;
};
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0xADD8E6 // Init game with light blue background
});
/****
* Game Code
****/
// Check for Magnet collection and trigger magnetism effect
LK.on('tick', function () {
game.children.forEach(function (child) {
if (child instanceof Magnet && basket.intersects(child)) {
child.destroy(); // Remove the Magnet from the game
activateMagnetism();
}
});
});
function activateMagnetism() {
var magnetismEffect = LK.getAsset('magnetismEffect', {
anchorX: 0.5,
anchorY: 0,
x: 1024,
// Center horizontally
y: 100,
// At the top of the screen
alpha: 1.0 // Ensure full visibility
});
game.addChild(magnetismEffect);
basket.magnetismActive = true;
LK.setTimeout(function () {
basket.magnetismActive = false;
magnetismEffect.destroy(); // Remove the magnetismEffect from the game after 5 seconds
}, 5000); // Magnetism lasts for 5 seconds with a radius of 500 pixels
}
// Display starting screen
var startScreen = LK.gui.center.addChild(LK.getAsset('startScreen', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: 0,
alpha: 1.0 // Ensure full visibility
}));
LK.setTimeout(function () {
// Fade out effect over 50ms before destroying the startScreen asset
var fadeOutDuration = 50;
var fadeOutStart = LK.ticks;
LK.on('tick', function fadeOut() {
var elapsed = LK.ticks - fadeOutStart;
if (elapsed < fadeOutDuration) {
startScreen.alpha = 1 - elapsed / fadeOutDuration;
} else {
startScreen.destroy();
LK.off('tick', fadeOut);
}
});
}, 2000); // Start fade out after 2 seconds to complete at 3 seconds
// Check for Revive collection and refill a life if one is missing
LK.on('tick', function () {
game.children.forEach(function (child) {
if (child instanceof Revive && basket.intersects(child)) {
child.destroy(); // Remove the Revive from the game
if (playerLives < 3) {
playerLives++;
heartAssets[playerLives - 1].visible = true; // Refill one life
}
}
});
});
// Spawn Revive at random intervals
LK.setInterval(function () {
var revive = new Revive();
revive.spawn(); // Use the spawn method to set random position
game.addChild(revive);
// Set a timeout to remove the Revive after a certain time if not collected
LK.setTimeout(function () {
if (game.children.includes(revive)) {
revive.destroy();
}
}, 10000); // Revive disappears after 10 seconds if not collected
}, 30000); // Spawn a new Revive every 30 seconds
// Spawn Magnet at random intervals
LK.setInterval(function () {
var magnet = new Magnet();
magnet.spawn(); // Use the spawn method to set random position
game.addChild(magnet);
// Set a timeout to remove the Magnet after a certain time if not collected
LK.setTimeout(function () {
if (game.children.includes(magnet)) {
magnet.destroy();
}
}, 10000); // Magnet disappears after 10 seconds if not collected
}, 20000); // Spawn a new Magnet every 20 seconds
// Spawn SlowDown at random intervals
LK.setInterval(function () {
var slowDown = new SlowDown();
slowDown.spawn(); // Use the spawn method to set random position
game.addChild(slowDown);
// Set a timeout to remove the SlowDown after a certain time if not collected
LK.setTimeout(function () {
if (game.children.includes(slowDown)) {
slowDown.destroy();
}
}, 10000); // SlowDown disappears after 10 seconds if not collected
}, Math.random() * (30000 - 10000) + 10000); // Spawn a new SlowDown at random intervals between 10 and 30 seconds
// Check for SlowDown collection and trigger slow down effect
LK.on('tick', function () {
game.children.forEach(function (child) {
if (child instanceof SlowDown && basket.intersects(child)) {
child.destroy(); // Remove the SlowDown from the game
enemies.forEach(function (enemy) {
enemy.speed *= 0.3; // Slow down enemies by 70%
});
// Reset enemy speed after 5 seconds
LK.setTimeout(function () {
enemies.forEach(function (enemy) {
enemy.speed /= 0.3; // Reset enemy speed
});
}, 5000);
}
});
});
// Check for MediaKit collection and trigger immunity effect
LK.on('tick', function () {
game.children.forEach(function (child) {
if (child instanceof MediaKit && basket.intersects(child)) {
child.destroy(); // Remove the MediaKit from the game
// Override other immunity effects with medikit's immunity if damage was taken shortly before
var currentTime = LK.ticks;
if (basket.lastDamageTime && currentTime - basket.lastDamageTime < 180) {
// Less than 3 seconds before
activateImmunity(5000, true); // Force immunity for 5 seconds, overriding other effects
} else {
// Clear any existing immunity timeout
if (basket.immunityTimeout) {
LK.clearTimeout(basket.immunityTimeout);
}
activateImmunity(ballCollectionResets >= 2 ? 7000 : 5000); // Activate immunity for 7 seconds from the third reset onwards, otherwise 5 seconds
}
}
});
});
function spawnMediaKit() {
var mediaKit = new MediaKit();
mediaKit.spawn(); // Use the spawn method to set random position
game.addChild(mediaKit);
// Set a timeout to remove the MediaKit after a certain time if not collected
LK.setTimeout(function () {
if (game.children.includes(mediaKit)) {
mediaKit.destroy();
}
}, 10000); // MediaKit disappears after 10 seconds if not collected
}
// Spawn MediaKit at random intervals
LK.setInterval(function () {
var mediaKit = new MediaKit();
mediaKit.spawn(); // Use the spawn method to set random position
game.addChild(mediaKit);
// Set a timeout to remove the MediaKit after a certain time if not collected
LK.setTimeout(function () {
if (game.children.includes(mediaKit)) {
mediaKit.destroy();
}
}, 10000); // MediaKit disappears after 10 seconds if not collected
}, Math.random() * (30000 - 10000) + 10000); // Spawn a new MediaKit at random intervals between 10 and 30 seconds
var background = game.addChild(LK.getAsset('background', {
anchorX: 0.0,
anchorY: 0.0,
x: 0,
y: 0,
alpha: 0.5
}));
background.width = 2048;
background.height = 2732;
// Create a text element to display enemy speed percentage
var enemySpeedTxt = new Text2('Enemy Speed: 100%', {
size: 50,
fill: "#ffffff",
weight: 400,
dropShadow: true,
dropShadowColor: "#00000080",
dropShadowBlur: 4,
dropShadowAngle: Math.PI / 6,
dropShadowDistance: 6
});
enemySpeedTxt.anchor.set(0, 0); // Anchor to the top left corner
enemySpeedTxt.x = 40;
enemySpeedTxt.y = 40;
LK.gui.topLeft.addChild(enemySpeedTxt);
// Update the enemy speed display text in the game tick event
LK.on('tick', function () {
var speedPercentage = Math.min(100 + speedIncreaseCount * 15, 175); // Calculate speed percentage, starting at 100% and increasing by 15% per interval, capped at 175%
enemySpeedTxt.setText('Enemy Speed: ' + speedPercentage + '%');
// Existing game tick code...
});
// Initialize game elements
var basket = game.addChild(new Basket());
basket.immunity = false; // Add immunity flag to basket
var immunityAsset = LK.getAsset('immunity', {
anchorX: 0.5,
anchorY: 0.0,
x: 1024,
y: 100,
// Move down 100 pixels
scaleX: 1.5,
// Make it even bigger
scaleY: 1.5,
// Make it even bigger
alpha: 1.0
});
immunityAsset.visible = false; // Initially hide the immunity asset
game.addChild(immunityAsset);
// Function to activate basket immunity
function activateImmunity() {
var duration = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 2000;
// Default duration is 2000ms
basket.immunity = true;
immunityAsset.visible = true;
LK.setTimeout(function () {
basket.immunity = false;
immunityAsset.visible = false;
}, duration); // Immunity duration is now variable
}
basket.x = 1024; // Center horizontally
basket.y = 2732 - 2732 / 4; // Position 1/4 of the screen size away from the bottom
basket.visible = true; // Ensure the basket is always visible
var balls = [];
for (var i = 0; i < 10; i++) {
var ball = game.addChild(new Ball());
ball.spawn();
balls.push(ball);
}
var obstacles = [];
var boostpads = []; // Array to store boostpad instances
var enemies = []; // Array to store enemy instances
// Create obstacles, boostpads, and enemies at random positions
// Define safe zone around basket spawn point
var safeZone = {
x: basket.x - 400,
y: basket.y - 400,
width: 800,
height: 800
};
// Define basketSafeZone globally to fix ReferenceError
var basketSafeZone = {
xMin: basket.x - 150,
// Basket width / 2
yMin: basket.y - 157.005,
// Basket height
xMax: basket.x + 150,
// Basket width / 2
yMax: basket.y + 157.005 // Basket height
};
// Start with only one enemy at the beginning of the game
var enemy = game.addChild(new Enemy());
do {
enemy.x = Math.random() * 2048;
enemy.y = Math.random() * 2732;
} while (enemy.intersects(safeZone)); // Ensure enemy does not spawn within safe zone
enemies.push(enemy);
for (var i = 0; i < 5; i++) {
var obstacle = game.addChild(new Obstacle());
do {
obstacle.x = Math.random() * 2048;
obstacle.y = Math.random() * (2732 - 400) + 200; // Avoid placing too close to the bottom
} while (obstacle.intersects(safeZone)); // Ensure obstacle does not spawn within safe zone
obstacles.push(obstacle);
}
// Limit the creation of boostpads to a maximum of three
for (var i = 0; i < 3; i++) {
var boostpad = game.addChild(new Boostpad());
do {
boostpad.x = Math.random() * 2048;
boostpad.y = Math.random() * 2732;
var tooClose = balls.some(function (ball) {
var dx = boostpad.x - ball.x;
var dy = boostpad.y - ball.y;
return Math.sqrt(dx * dx + dy * dy) < 2048 / 10;
});
} while (boostpad.intersects(safeZone) || tooClose); // Ensure boostpad does not spawn within safe zone or too close to balls
boostpads.push(boostpad);
}
// Initialize enemy speed increase factor and timer
var enemySpeedIncreaseFactor = 1.15; // 15% speed increase
var enemySpeedIncreaseInterval = 10000; // Increase speed every 10 seconds
var speedIncreaseCount = 0; // Initialize speed increase count
LK.setInterval(function () {
// Cap the speed increase at 175%
if (speedIncreaseCount * 15 < 75) {
enemies.forEach(function (enemy) {
enemy.speed *= enemySpeedIncreaseFactor;
});
speedIncreaseCount++;
}
}, enemySpeedIncreaseInterval);
// Function to spawn a new ball
function spawnBall() {
var ball = new Ball();
ball.x = 1024; // Start from the center horizontally
ball.y = 2732 - 150; // Start a little above the basket
balls.push(ball);
game.addChild(ball);
}
// Touch event to throw a ball
var initialPos;
game.on('down', function (obj) {
var event = obj.event;
initialPos = event.getLocalPosition(game);
if (LK.ticks > 180) {
// 3 seconds at 60FPS
basket.shoot(initialPos);
}
});
game.on('move', function (obj) {
var event = obj.event;
var pos = event.getLocalPosition(game);
basket.drawArrow(pos);
});
// Game tick event
LK.on('tick', function () {
// Move enemies towards the basket and check for collision
for (var j = enemies.length - 1; j >= 0; j--) {
enemies[j].moveTowardsBasket(basket);
if (!basket.immunity && enemies[j].intersects(basket)) {
playerLives--;
heartAssets[playerLives].visible = false; // Hide one heart asset
if (playerLives <= 0) {
LK.effects.flashScreen(0xff0000, 1000);
LK.showGameOver();
} else {
// Flash screen red for half a second when losing a life
LK.effects.flashScreen(0xff0000, 500);
// Temporarily activate immunity after losing a life
activateImmunity(3000);
}
}
}
// Update balls
for (var i = balls.length - 1; i >= 0; i--) {
balls[i]["throw"]();
basket.move();
// Check for collision with basket
var distanceToBall = Math.sqrt(Math.pow(balls[i].x - basket.x, 2) + Math.pow(balls[i].y - basket.y, 2));
if (balls[i].intersects(basket) && basket.isBallHitByOpening(balls[i]) || basket.magnetismActive && distanceToBall <= 500) {
// Display 'poof' asset at the ball's position upon collision
var poof = LK.getAsset('poof', {
x: balls[i].x,
y: balls[i].y,
anchorX: 0.5,
anchorY: 0.5
});
game.addChild(poof);
LK.setTimeout(function () {
poof.destroy();
}, 500); // Display for half a second
balls[i].destroy();
balls.splice(i, 1);
// Increase the score and update the score counter
score++;
// Check if all balls are collected
if (balls.length === 0) {
// Reset obstacles, boostpads, and enemies
obstacles.forEach(function (obstacle) {
obstacle.destroy();
});
obstacles = [];
boostpads.forEach(function (boostpad) {
boostpad.destroy();
});
boostpads = [];
enemies.forEach(function (enemy) {
enemy.destroy();
});
enemies = [];
// Increment ball collection reset counter and activate immunity
ballCollectionResets++;
activateImmunity();
// Update wave counter text
waveTxt.setText('Wave: ' + (ballCollectionResets + 1));
// Spawn new set of balls, obstacles, boostpads, and enemies
for (var i = 0; i < 10; i++) {
var newBall = game.addChild(new Ball());
newBall.spawn();
balls.push(newBall);
}
// Adjust the number of enemies based on the number of times the game has been reset, capped at 5
var enemyCount = Math.min(ballCollectionResets + 1, 5);
for (var i = 0; i < 5; i++) {
var newObstacle = game.addChild(new Obstacle());
newObstacle.positionObstacle();
obstacles.push(newObstacle);
var newBoostpad = game.addChild(new Boostpad());
newBoostpad.positionBoostpad();
boostpads.push(newBoostpad);
}
for (var i = 0; i < enemyCount; i++) {
var newEnemy = game.addChild(new Enemy());
newEnemy.x = Math.random() * 2048;
newEnemy.y = Math.random() * 2732;
enemies.push(newEnemy);
}
}
// Check if the basket was boosted and the ball was hit in the same shot
if (basket.boosted && basket.isBallHitByOpening(balls[i])) {
score++; // Additional score for boosted basket
// Display bonus asset for one second in the top left corner when a bonus is hit
var bonusAsset = LK.getAsset('bonus', {
x: 1024,
// Center horizontally
y: 2732 - 150,
// Move to bottom center and then up 50 pixels
anchorX: 0.5,
// Center horizontally
anchorY: 0,
// Anchor at the bottom
scaleX: 3,
// Make it three times as big
scaleY: 3 // Make it three times as big
});
game.addChild(bonusAsset);
LK.setTimeout(function () {
bonusAsset.destroy();
}, 1000);
}
// Reset boosted state after checking for bonus
basket.boosted = false;
LK.setScore(score); // Report the current score to the system
scoreTxt.setText('Score: ' + LK.getScore()); // Update the score display text
}
// Remove balls that are off-screen or collide with obstacles
if (balls[i] && (balls[i].y < 0 || obstacles.some(function (obstacle) {
return balls[i].intersects(obstacle);
}))) {
balls[i].destroy();
balls.splice(i, 1);
}
}
});
// Initialize player lives
var playerLives = 3;
// Initialize heart assets for lives display
var heartAssets = [];
for (var i = 0; i < playerLives; i++) {
var heart = LK.getAsset('heart', {
anchorX: 0,
anchorY: 0,
x: 40 + i * 60,
// Position hearts horizontally with a small gap starting 40px from the left edge
y: enemySpeedTxt.height + 50 // Position hearts 40px below the enemy speed display
});
heartAssets.push(heart);
LK.gui.topLeft.addChild(heart);
}
// Activate basket immunity at game start
activateImmunity();
// Initialize the first ball
spawnBall();
// Initialize ball collection reset counter
var ballCollectionResets = 0;
// Create a score counter
var score = 0;
var scoreTxt = new Text2('Score: 0', {
size: 50,
fill: "#ffffff",
weight: 400,
dropShadow: true,
dropShadowColor: "#00000080",
dropShadowBlur: 4,
dropShadowAngle: Math.PI / 6,
dropShadowDistance: 6
});
scoreTxt.anchor.set(1, 0); // Anchor to the top right corner
scoreTxt.x = -40;
scoreTxt.y = 40;
LK.gui.topRight.addChild(scoreTxt);
// Create a text element to display the current wave of balls
var waveTxt = new Text2('Wave: 1', {
size: 50,
fill: "#ffffff",
weight: 400,
dropShadow: true,
dropShadowColor: "#00000080",
dropShadowBlur: 4,
dropShadowAngle: Math.PI / 6,
dropShadowDistance: 6
});
waveTxt.anchor.set(1, 0); // Anchor to the top right corner, below the score
waveTxt.x = -40;
waveTxt.y = scoreTxt.height + 50; // Position it right below the score text with 40px padding from the top
LK.gui.topRight.addChild(waveTxt); /****
* Classes
****/
// Ball class
var Ball = Container.expand(function () {
var self = Container.call(this);
var ballGraphics = self.attachAsset('ball', {
anchorX: 0.5,
anchorY: 0.5
});
self["throw"] = function () {
// Throw logic for the ball
};
self.spawn = function () {
// Adjusted spawn logic to exclude top 10% of the screen and area around the basket
var safeSpawnArea = {
xMin: 0,
xMax: 2048,
yMin: 273.2,
// Start from 10% of the screen height to avoid top 10%
yMax: 2732 - 273.2 // Exclude the bottom 10% as well for symmetry
};
var basketSafeZone = {
xMin: basket.x - 150,
// Basket width / 2
yMin: basket.y - 157.005,
// Basket height
xMax: basket.x + 150,
// Basket width / 2
yMax: basket.y + 157.005 // Basket height
};
do {
self.x = Math.random() * (safeSpawnArea.xMax - safeSpawnArea.xMin) + safeSpawnArea.xMin;
self.y = Math.random() * (safeSpawnArea.yMax - safeSpawnArea.yMin) + safeSpawnArea.yMin;
} while (self.x >= basketSafeZone.xMin && self.x <= basketSafeZone.xMax && self.y >= basketSafeZone.yMin && self.y <= basketSafeZone.yMax);
};
});
// Assets will be automatically created based on usage in the code.
// Basket class
var Basket = Container.expand(function () {
var self = Container.call(this);
var basketGraphics = self.attachAsset('basket', {
anchorX: 0.5,
anchorY: 0.5
});
self.drawArrow = function (pos) {
// Calculate the distance and direction of the drag
var dx = pos.x - self.x;
var dy = pos.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
var direction = Math.atan2(dy, dx);
// Remove the previous arrow if it exists
if (self.arrow) {
self.arrow.destroy();
}
// Create a new arrow asset
self.arrow = LK.getAsset('arrow', {
anchorX: 0.0,
// Anchor at the start of the arrow
anchorY: 0.5,
// Center vertically
x: self.x,
y: self.y,
scaleX: Math.min(Math.max(distance / 100, 1), 0.3 * Math.sqrt(2048 * 2048 + 2732 * 2732) / 100),
// Stretch the arrow in the direction of the cursor, but ensure it's at least 1 to allow it to extend outside the screen and not more than 40% of the screen size
scaleY: 1,
rotation: direction
});
// Correctly align the basket's opening with the arrow direction without additional rotation
basketGraphics.rotation = direction;
// Add the arrow to the game
game.addChild(self.arrow);
};
self.move = function () {
// Move the basket
self.x += self.vx;
self.y += self.vy;
// Apply friction
self.vx *= 0.99;
self.vy *= 0.99;
// Check for collision with the edges of the screen and bounce off
if (self.x < 0) {
self.vx = Math.abs(self.vx);
// Correctly adjust the basket's rotation to align with the new direction of movement, ensuring the opening follows the path
basketGraphics.rotation = Math.atan2(self.vy, self.vx);
} else if (self.x > 2048) {
self.vx = -Math.abs(self.vx);
basketGraphics.rotation = Math.atan2(self.vy, self.vx);
}
if (self.y < 0) {
self.vy = Math.abs(self.vy);
// Adjust the basket's rotation to follow the path of reflection, ensuring the opening is correctly aligned
basketGraphics.rotation = Math.atan2(self.vy, self.vx) + Math.PI / 2;
} else if (self.y > 2732) {
self.vy = -Math.abs(self.vy);
basketGraphics.rotation = Math.atan2(self.vy, self.vx) + Math.PI / 2;
}
// Check for collision with obstacles and boostpads, bounce off obstacles, and reflect with increased speed on boostpads
for (var i = 0; i < obstacles.length; i++) {
if (self.intersects(obstacles[i])) {
// Calculate the angle of reflection
var dx = self.x - obstacles[i].x;
var dy = self.y - obstacles[i].y;
var angle = Math.atan2(dy, dx);
// Reflect the velocity
self.vx = Math.cos(angle) * Math.sqrt(self.vx * self.vx + self.vy * self.vy);
self.vy = Math.sin(angle) * Math.sqrt(self.vx * self.vx + self.vy * self.vy);
// Adjust the basket's rotation to follow the path of reflection, ensuring the opening faces the correct direction
basketGraphics.rotation = Math.atan2(self.vy, self.vx);
}
}
for (var j = 0; j < boostpads.length; j++) {
if (self.intersects(boostpads[j])) {
// Calculate the angle of reflection and display 'lightning' asset on collision edge
var dxPad = self.x - boostpads[j].x;
var dyPad = self.y - boostpads[j].y;
var anglePad = Math.atan2(dyPad, dxPad);
// Display 'lightning' asset at the point of collision for half a second
var lightning = LK.getAsset('lightning', {
x: self.x - Math.cos(anglePad) * basketGraphics.width / 2,
y: self.y - Math.sin(anglePad) * basketGraphics.height / 2,
anchorX: 0.5,
anchorY: 0.5
});
game.addChild(lightning);
LK.setTimeout(function () {
lightning.destroy();
}, 500);
// Check if the basket was deflected off another boost pad right before hitting this one
if (!self.deflected) {
// Reflect the velocity and increase speed
self.vx = Math.cos(anglePad) * 1.6 * Math.sqrt(self.vx * self.vx + self.vy * self.vy);
self.vy = Math.sin(anglePad) * 1.6 * Math.sqrt(self.vx * self.vx + self.vy * self.vy);
// Adjust the basket's rotation to follow the path of reflection with increased speed, ensuring the opening faces the correct direction
basketGraphics.rotation = Math.atan2(self.vy, self.vx);
// Mark the basket as having been boosted for double scoring
self.boosted = true;
// Mark the basket as deflected to prevent further acceleration without player interaction
self.deflected = true;
// Reset the deflected flag after a short delay to allow for player interaction
LK.setTimeout(function () {
self.deflected = false;
}, 500); // Delay in milliseconds
} else {
// Simply reflect the velocity without increasing speed
self.vx = Math.cos(anglePad) * Math.sqrt(self.vx * self.vx + self.vy * self.vy);
self.vy = Math.sin(anglePad) * Math.sqrt(self.vx * self.vx + self.vy * self.vy);
// Adjust the basket's rotation to follow the path of reflection, ensuring the opening faces the correct direction
basketGraphics.rotation = Math.atan2(self.vy, self.vx);
}
}
}
};
self.shoot = function (pos) {
// Calculate the distance and direction of the drag
var dx = self.x - pos.x;
var dy = self.y - pos.y;
var distance = Math.sqrt(dx * dx + dy * dy);
var direction = Math.atan2(dy, dx);
// Set the velocity of the basket to go 50% further than the cursor's end location
self.vx = -Math.cos(direction) * distance * 1.5 / 100;
self.vy = -Math.sin(direction) * distance * 1.5 / 100;
};
self.isBallHitByOpening = function (ball) {
// Calculate the angle between the basket's direction and the ball
if (ball) {
var dx = ball.x - self.x;
var dy = ball.y - self.y;
}
var angle = Math.atan2(dy, dx);
// Check if the ball is within the opening angle of the basket
return Math.abs(angle - basketGraphics.rotation) < Math.PI / 4;
};
});
// Boostpad class
var Boostpad = Container.expand(function () {
var self = Container.call(this);
var boostpadGraphics = self.attachAsset('boostPad', {
anchorX: 0.5,
anchorY: 0.5
});
self.positionBoostpad = function () {
do {
self.x = Math.random() * 2048;
self.y = Math.random() * (2732 - 273.2) + 273.2; // Exclude top 10%
} while (self.x >= basketSafeZone.xMin && self.x <= basketSafeZone.xMax && self.y >= basketSafeZone.yMin && self.y <= basketSafeZone.yMax); // Ensure boostpad does not spawn within basket area
};
// Initialize boostPad size change animation
self.animateSize = function () {
var growing = true;
LK.on('tick', function () {
if (growing) {
self.scaleX = Math.min(self.scaleX + 0.01, 1.3);
self.scaleY = Math.min(self.scaleY + 0.01, 1.3);
if (self.scaleX >= 1.3) {
growing = false;
}
} else {
self.scaleX = Math.max(self.scaleX - 0.01, 0.9);
self.scaleY = Math.max(self.scaleY - 0.01, 0.9);
if (self.scaleX <= 0.9) {
growing = true;
}
}
});
};
self.animateSize();
});
// Enemy class
var Enemy = Container.expand(function () {
var self = Container.call(this);
var enemyGraphics = self.attachAsset('enemy', {
anchorX: 0.5,
anchorY: 0.5,
tint: 0xFF0000 // Red color to differentiate enemies
});
self.moveTowardsBasket = function (basket) {
if (LK.ticks > 180) {
// 3 seconds at 60FPS
var dx = basket.x - self.x;
var dy = basket.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
this.speed = this.speed || 2; // Initialize speed if not set
var speed = this.speed; // Use the enemy's current speed
self.x += dx / distance * speed;
self.y += dy / distance * speed;
}
};
});
var Magnet = Container.expand(function () {
var self = Container.call(this);
var magnetGraphics = self.attachAsset('magnet', {
anchorX: 0.5,
anchorY: 0.5
});
self.spawn = function () {
self.x = Math.random() * 2048;
self.y = Math.random() * 2732;
};
});
// MediaKit class for immunity item
var MediaKit = Container.expand(function () {
var self = Container.call(this);
var mediaKitGraphics = self.attachAsset('mediaKit', {
anchorX: 0.5,
anchorY: 0.5
});
self.spawn = function () {
self.x = Math.random() * 2048;
self.y = Math.random() * 2732;
};
});
// Obstacle class
var Obstacle = Container.expand(function () {
var self = Container.call(this);
var sizeMultiplier = Math.random() + 1; // Generates a value between 1.0 and 2.0
var obstacleGraphics = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: sizeMultiplier,
scaleY: sizeMultiplier
});
self.positionObstacle = function () {
do {
self.x = Math.random() * 2048;
self.y = Math.random() * (2732 - 273.2) + 273.2; // Exclude top 10%
} while (self.x >= basketSafeZone.xMin && self.x <= basketSafeZone.xMax && self.y >= basketSafeZone.yMin && self.y <= basketSafeZone.yMax); // Ensure obstacle does not spawn within basket area
};
});
// Revive class for refilling a life
var Revive = Container.expand(function () {
var self = Container.call(this);
var reviveGraphics = self.attachAsset('revive', {
anchorX: 0.5,
anchorY: 0.5
});
self.spawn = function () {
self.x = Math.random() * 2048;
self.y = Math.random() * 2732;
};
});
// SlowDown class for slowing down enemies
var SlowDown = Container.expand(function () {
var self = Container.call(this);
var slowDownGraphics = self.attachAsset('slowDown', {
anchorX: 0.5,
anchorY: 0.5
});
self.spawn = function () {
self.x = Math.random() * 2048;
self.y = Math.random() * 2732;
};
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0xADD8E6 // Init game with light blue background
});
/****
* Game Code
****/
// Check for Magnet collection and trigger magnetism effect
LK.on('tick', function () {
game.children.forEach(function (child) {
if (child instanceof Magnet && basket.intersects(child)) {
child.destroy(); // Remove the Magnet from the game
activateMagnetism();
}
});
});
function activateMagnetism() {
var magnetismEffect = LK.getAsset('magnetismEffect', {
anchorX: 0.5,
anchorY: 0,
x: 1024,
// Center horizontally
y: 100,
// At the top of the screen
alpha: 1.0 // Ensure full visibility
});
game.addChild(magnetismEffect);
basket.magnetismActive = true;
LK.setTimeout(function () {
basket.magnetismActive = false;
magnetismEffect.destroy(); // Remove the magnetismEffect from the game after 5 seconds
}, 5000); // Magnetism lasts for 5 seconds with a radius of 500 pixels
}
// Display starting screen
var startScreen = LK.gui.center.addChild(LK.getAsset('startScreen', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: 0,
alpha: 1.0 // Ensure full visibility
}));
LK.setTimeout(function () {
// Fade out effect over 50ms before destroying the startScreen asset
var fadeOutDuration = 50;
var fadeOutStart = LK.ticks;
LK.on('tick', function fadeOut() {
var elapsed = LK.ticks - fadeOutStart;
if (elapsed < fadeOutDuration) {
startScreen.alpha = 1 - elapsed / fadeOutDuration;
} else {
startScreen.destroy();
LK.off('tick', fadeOut);
}
});
}, 2000); // Start fade out after 2 seconds to complete at 3 seconds
// Check for Revive collection and refill a life if one is missing
LK.on('tick', function () {
game.children.forEach(function (child) {
if (child instanceof Revive && basket.intersects(child)) {
child.destroy(); // Remove the Revive from the game
if (playerLives < 3) {
playerLives++;
heartAssets[playerLives - 1].visible = true; // Refill one life
}
}
});
});
// Spawn Revive at random intervals
LK.setInterval(function () {
var revive = new Revive();
revive.spawn(); // Use the spawn method to set random position
game.addChild(revive);
// Set a timeout to remove the Revive after a certain time if not collected
LK.setTimeout(function () {
if (game.children.includes(revive)) {
revive.destroy();
}
}, 10000); // Revive disappears after 10 seconds if not collected
}, 30000); // Spawn a new Revive every 30 seconds
// Spawn Magnet at random intervals
LK.setInterval(function () {
var magnet = new Magnet();
magnet.spawn(); // Use the spawn method to set random position
game.addChild(magnet);
// Set a timeout to remove the Magnet after a certain time if not collected
LK.setTimeout(function () {
if (game.children.includes(magnet)) {
magnet.destroy();
}
}, 10000); // Magnet disappears after 10 seconds if not collected
}, 20000); // Spawn a new Magnet every 20 seconds
// Spawn SlowDown at random intervals
LK.setInterval(function () {
var slowDown = new SlowDown();
slowDown.spawn(); // Use the spawn method to set random position
game.addChild(slowDown);
// Set a timeout to remove the SlowDown after a certain time if not collected
LK.setTimeout(function () {
if (game.children.includes(slowDown)) {
slowDown.destroy();
}
}, 10000); // SlowDown disappears after 10 seconds if not collected
}, Math.random() * (30000 - 10000) + 10000); // Spawn a new SlowDown at random intervals between 10 and 30 seconds
// Check for SlowDown collection and trigger slow down effect
LK.on('tick', function () {
game.children.forEach(function (child) {
if (child instanceof SlowDown && basket.intersects(child)) {
child.destroy(); // Remove the SlowDown from the game
enemies.forEach(function (enemy) {
enemy.speed *= 0.3; // Slow down enemies by 70%
});
// Reset enemy speed after 5 seconds
LK.setTimeout(function () {
enemies.forEach(function (enemy) {
enemy.speed /= 0.3; // Reset enemy speed
});
}, 5000);
}
});
});
// Check for MediaKit collection and trigger immunity effect
LK.on('tick', function () {
game.children.forEach(function (child) {
if (child instanceof MediaKit && basket.intersects(child)) {
child.destroy(); // Remove the MediaKit from the game
// Override other immunity effects with medikit's immunity if damage was taken shortly before
var currentTime = LK.ticks;
if (basket.lastDamageTime && currentTime - basket.lastDamageTime < 180) {
// Less than 3 seconds before
activateImmunity(5000, true); // Force immunity for 5 seconds, overriding other effects
} else {
// Clear any existing immunity timeout
if (basket.immunityTimeout) {
LK.clearTimeout(basket.immunityTimeout);
}
activateImmunity(ballCollectionResets >= 2 ? 7000 : 5000); // Activate immunity for 7 seconds from the third reset onwards, otherwise 5 seconds
}
}
});
});
function spawnMediaKit() {
var mediaKit = new MediaKit();
mediaKit.spawn(); // Use the spawn method to set random position
game.addChild(mediaKit);
// Set a timeout to remove the MediaKit after a certain time if not collected
LK.setTimeout(function () {
if (game.children.includes(mediaKit)) {
mediaKit.destroy();
}
}, 10000); // MediaKit disappears after 10 seconds if not collected
}
// Spawn MediaKit at random intervals
LK.setInterval(function () {
var mediaKit = new MediaKit();
mediaKit.spawn(); // Use the spawn method to set random position
game.addChild(mediaKit);
// Set a timeout to remove the MediaKit after a certain time if not collected
LK.setTimeout(function () {
if (game.children.includes(mediaKit)) {
mediaKit.destroy();
}
}, 10000); // MediaKit disappears after 10 seconds if not collected
}, Math.random() * (30000 - 10000) + 10000); // Spawn a new MediaKit at random intervals between 10 and 30 seconds
var background = game.addChild(LK.getAsset('background', {
anchorX: 0.0,
anchorY: 0.0,
x: 0,
y: 0,
alpha: 0.5
}));
background.width = 2048;
background.height = 2732;
// Create a text element to display enemy speed percentage
var enemySpeedTxt = new Text2('Enemy Speed: 100%', {
size: 50,
fill: "#ffffff",
weight: 400,
dropShadow: true,
dropShadowColor: "#00000080",
dropShadowBlur: 4,
dropShadowAngle: Math.PI / 6,
dropShadowDistance: 6
});
enemySpeedTxt.anchor.set(0, 0); // Anchor to the top left corner
enemySpeedTxt.x = 40;
enemySpeedTxt.y = 40;
LK.gui.topLeft.addChild(enemySpeedTxt);
// Update the enemy speed display text in the game tick event
LK.on('tick', function () {
var speedPercentage = Math.min(100 + speedIncreaseCount * 15, 175); // Calculate speed percentage, starting at 100% and increasing by 15% per interval, capped at 175%
enemySpeedTxt.setText('Enemy Speed: ' + speedPercentage + '%');
// Existing game tick code...
});
// Initialize game elements
var basket = game.addChild(new Basket());
basket.immunity = false; // Add immunity flag to basket
var immunityAsset = LK.getAsset('immunity', {
anchorX: 0.5,
anchorY: 0.0,
x: 1024,
y: 100,
// Move down 100 pixels
scaleX: 1.5,
// Make it even bigger
scaleY: 1.5,
// Make it even bigger
alpha: 1.0
});
immunityAsset.visible = false; // Initially hide the immunity asset
game.addChild(immunityAsset);
// Function to activate basket immunity
function activateImmunity() {
var duration = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 2000;
// Default duration is 2000ms
basket.immunity = true;
immunityAsset.visible = true;
LK.setTimeout(function () {
basket.immunity = false;
immunityAsset.visible = false;
}, duration); // Immunity duration is now variable
}
basket.x = 1024; // Center horizontally
basket.y = 2732 - 2732 / 4; // Position 1/4 of the screen size away from the bottom
basket.visible = true; // Ensure the basket is always visible
var balls = [];
for (var i = 0; i < 10; i++) {
var ball = game.addChild(new Ball());
ball.spawn();
balls.push(ball);
}
var obstacles = [];
var boostpads = []; // Array to store boostpad instances
var enemies = []; // Array to store enemy instances
// Create obstacles, boostpads, and enemies at random positions
// Define safe zone around basket spawn point
var safeZone = {
x: basket.x - 400,
y: basket.y - 400,
width: 800,
height: 800
};
// Define basketSafeZone globally to fix ReferenceError
var basketSafeZone = {
xMin: basket.x - 150,
// Basket width / 2
yMin: basket.y - 157.005,
// Basket height
xMax: basket.x + 150,
// Basket width / 2
yMax: basket.y + 157.005 // Basket height
};
// Start with only one enemy at the beginning of the game
var enemy = game.addChild(new Enemy());
do {
enemy.x = Math.random() * 2048;
enemy.y = Math.random() * 2732;
} while (enemy.intersects(safeZone)); // Ensure enemy does not spawn within safe zone
enemies.push(enemy);
for (var i = 0; i < 5; i++) {
var obstacle = game.addChild(new Obstacle());
do {
obstacle.x = Math.random() * 2048;
obstacle.y = Math.random() * (2732 - 400) + 200; // Avoid placing too close to the bottom
} while (obstacle.intersects(safeZone)); // Ensure obstacle does not spawn within safe zone
obstacles.push(obstacle);
}
// Limit the creation of boostpads to a maximum of three
for (var i = 0; i < 3; i++) {
var boostpad = game.addChild(new Boostpad());
do {
boostpad.x = Math.random() * 2048;
boostpad.y = Math.random() * 2732;
var tooClose = balls.some(function (ball) {
var dx = boostpad.x - ball.x;
var dy = boostpad.y - ball.y;
return Math.sqrt(dx * dx + dy * dy) < 2048 / 10;
});
} while (boostpad.intersects(safeZone) || tooClose); // Ensure boostpad does not spawn within safe zone or too close to balls
boostpads.push(boostpad);
}
// Initialize enemy speed increase factor and timer
var enemySpeedIncreaseFactor = 1.15; // 15% speed increase
var enemySpeedIncreaseInterval = 10000; // Increase speed every 10 seconds
var speedIncreaseCount = 0; // Initialize speed increase count
LK.setInterval(function () {
// Cap the speed increase at 175%
if (speedIncreaseCount * 15 < 75) {
enemies.forEach(function (enemy) {
enemy.speed *= enemySpeedIncreaseFactor;
});
speedIncreaseCount++;
}
}, enemySpeedIncreaseInterval);
// Function to spawn a new ball
function spawnBall() {
var ball = new Ball();
ball.x = 1024; // Start from the center horizontally
ball.y = 2732 - 150; // Start a little above the basket
balls.push(ball);
game.addChild(ball);
}
// Touch event to throw a ball
var initialPos;
game.on('down', function (obj) {
var event = obj.event;
initialPos = event.getLocalPosition(game);
if (LK.ticks > 180) {
// 3 seconds at 60FPS
basket.shoot(initialPos);
}
});
game.on('move', function (obj) {
var event = obj.event;
var pos = event.getLocalPosition(game);
basket.drawArrow(pos);
});
// Game tick event
LK.on('tick', function () {
// Move enemies towards the basket and check for collision
for (var j = enemies.length - 1; j >= 0; j--) {
enemies[j].moveTowardsBasket(basket);
if (!basket.immunity && enemies[j].intersects(basket)) {
playerLives--;
heartAssets[playerLives].visible = false; // Hide one heart asset
if (playerLives <= 0) {
LK.effects.flashScreen(0xff0000, 1000);
LK.showGameOver();
} else {
// Flash screen red for half a second when losing a life
LK.effects.flashScreen(0xff0000, 500);
// Temporarily activate immunity after losing a life
activateImmunity(3000);
}
}
}
// Update balls
for (var i = balls.length - 1; i >= 0; i--) {
balls[i]["throw"]();
basket.move();
// Check for collision with basket
var distanceToBall = Math.sqrt(Math.pow(balls[i].x - basket.x, 2) + Math.pow(balls[i].y - basket.y, 2));
if (balls[i].intersects(basket) && basket.isBallHitByOpening(balls[i]) || basket.magnetismActive && distanceToBall <= 500) {
// Display 'poof' asset at the ball's position upon collision
var poof = LK.getAsset('poof', {
x: balls[i].x,
y: balls[i].y,
anchorX: 0.5,
anchorY: 0.5
});
game.addChild(poof);
LK.setTimeout(function () {
poof.destroy();
}, 500); // Display for half a second
balls[i].destroy();
balls.splice(i, 1);
// Increase the score and update the score counter
score++;
// Check if all balls are collected
if (balls.length === 0) {
// Reset obstacles, boostpads, and enemies
obstacles.forEach(function (obstacle) {
obstacle.destroy();
});
obstacles = [];
boostpads.forEach(function (boostpad) {
boostpad.destroy();
});
boostpads = [];
enemies.forEach(function (enemy) {
enemy.destroy();
});
enemies = [];
// Increment ball collection reset counter and activate immunity
ballCollectionResets++;
activateImmunity();
// Update wave counter text
waveTxt.setText('Wave: ' + (ballCollectionResets + 1));
// Spawn new set of balls, obstacles, boostpads, and enemies
for (var i = 0; i < 10; i++) {
var newBall = game.addChild(new Ball());
newBall.spawn();
balls.push(newBall);
}
// Adjust the number of enemies based on the number of times the game has been reset, capped at 5
var enemyCount = Math.min(ballCollectionResets + 1, 5);
for (var i = 0; i < 5; i++) {
var newObstacle = game.addChild(new Obstacle());
newObstacle.positionObstacle();
obstacles.push(newObstacle);
var newBoostpad = game.addChild(new Boostpad());
newBoostpad.positionBoostpad();
boostpads.push(newBoostpad);
}
for (var i = 0; i < enemyCount; i++) {
var newEnemy = game.addChild(new Enemy());
newEnemy.x = Math.random() * 2048;
newEnemy.y = Math.random() * 2732;
enemies.push(newEnemy);
}
}
// Check if the basket was boosted and the ball was hit in the same shot
if (basket.boosted && basket.isBallHitByOpening(balls[i])) {
score++; // Additional score for boosted basket
// Display bonus asset for one second in the top left corner when a bonus is hit
var bonusAsset = LK.getAsset('bonus', {
x: 1024,
// Center horizontally
y: 2732 - 150,
// Move to bottom center and then up 50 pixels
anchorX: 0.5,
// Center horizontally
anchorY: 0,
// Anchor at the bottom
scaleX: 3,
// Make it three times as big
scaleY: 3 // Make it three times as big
});
game.addChild(bonusAsset);
LK.setTimeout(function () {
bonusAsset.destroy();
}, 1000);
}
// Reset boosted state after checking for bonus
basket.boosted = false;
LK.setScore(score); // Report the current score to the system
scoreTxt.setText('Score: ' + LK.getScore()); // Update the score display text
}
// Remove balls that are off-screen or collide with obstacles
if (balls[i] && (balls[i].y < 0 || obstacles.some(function (obstacle) {
return balls[i].intersects(obstacle);
}))) {
balls[i].destroy();
balls.splice(i, 1);
}
}
});
// Initialize player lives
var playerLives = 3;
// Initialize heart assets for lives display
var heartAssets = [];
for (var i = 0; i < playerLives; i++) {
var heart = LK.getAsset('heart', {
anchorX: 0,
anchorY: 0,
x: 40 + i * 60,
// Position hearts horizontally with a small gap starting 40px from the left edge
y: enemySpeedTxt.height + 50 // Position hearts 40px below the enemy speed display
});
heartAssets.push(heart);
LK.gui.topLeft.addChild(heart);
}
// Activate basket immunity at game start
activateImmunity();
// Initialize the first ball
spawnBall();
// Initialize ball collection reset counter
var ballCollectionResets = 0;
// Create a score counter
var score = 0;
var scoreTxt = new Text2('Score: 0', {
size: 50,
fill: "#ffffff",
weight: 400,
dropShadow: true,
dropShadowColor: "#00000080",
dropShadowBlur: 4,
dropShadowAngle: Math.PI / 6,
dropShadowDistance: 6
});
scoreTxt.anchor.set(1, 0); // Anchor to the top right corner
scoreTxt.x = -40;
scoreTxt.y = 40;
LK.gui.topRight.addChild(scoreTxt);
// Create a text element to display the current wave of balls
var waveTxt = new Text2('Wave: 1', {
size: 50,
fill: "#ffffff",
weight: 400,
dropShadow: true,
dropShadowColor: "#00000080",
dropShadowBlur: 4,
dropShadowAngle: Math.PI / 6,
dropShadowDistance: 6
});
waveTxt.anchor.set(1, 0); // Anchor to the top right corner, below the score
waveTxt.x = -40;
waveTxt.y = scoreTxt.height + 50; // Position it right below the score text with 40px padding from the top
LK.gui.topRight.addChild(waveTxt);
in-game asset. 2d. basketball. blank background. minimalistic flat graphic. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
Single Game Texture. In-Game asset. 2d. Blank background. super simplistic arrow from left to right. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
Single Game Texture. In-Game asset. 2d. flat graphic orange red. Basketball saying "bonus" white font. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
Single Game Texture. In-Game asset. 2d. flat minimalistic graphic. Boost pad with a lightning icon on the top. Top view. Blank background. High contrast. No shadows.. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
in-game asset. 2d. monster head from top view. blank background. minimalistic flat graphic. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
in-game asset. 2d. shield graphic green. blank background. minimalistic flat graphic. Single Game Texture. In-Game asset. 2d. High contrast. No shadows.. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
in-game asset. 2d. flat 2d graphic of a blueish rectangle that looks like the top of a crate. blank background. minimalistic flat graphic. Single Game Texture. In-Game asset. 2d. High contrast. No shadows.. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
in-game asset. yellow lighting bolt. small black outline. blank background. minimalistic flat graphic. Single Game Texture. 2d. Blank background. High contrast. No shadows.. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
in-game asset. 2d. magnet graphic recentgular with text saying "Magnetism". blank background. minimalistic flat graphic. Single Game Texture. In-Game asset. High contrast. No shadows. red and blue. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.