/**** * 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.