Code edit (1 edits merged)
Please save this source code
User prompt
Slam Dunk Challenge
Initial prompt
I want a game and in that game you are playing basketball. You are boy and you want to score in the basket. You have to pass all the levels which are 10 and beat the last one. It gets more difficult with each level.
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1", { level: 1, highScores: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0] }); /**** * Classes ****/ var AimingSystem = Container.expand(function () { var self = Container.call(this); // Create the aim arrow var arrow = self.attachAsset('aimArrow', { anchorX: 0, anchorY: 0.5, x: 0, y: 0 }); // Create power meter background var powerMeter = self.attachAsset('powerMeter', { anchorX: 0.5, anchorY: 1, x: 0, y: 0 }); // Create power indicator var powerIndicator = self.attachAsset('powerIndicator', { anchorX: 0.5, anchorY: 0.5, x: 0, y: -powerMeter.height + 10 }); self.visible = false; self.angle = -45; self.power = 0; self.powerIncreasing = true; self.powerSpeed = 2; self.maxPower = 100; // Position offset from power meter to arrow var offsetX = 100; self.setPosition = function (x, y) { self.x = x; self.y = y; powerMeter.x = x - offsetX; powerMeter.y = y; }; self.setAngle = function (angle) { self.angle = angle; arrow.rotation = angle * Math.PI / 180; }; self.setPower = function (power) { self.power = power; var normalizedPower = power / self.maxPower; powerIndicator.y = -powerMeter.height * normalizedPower + 10; }; self.startPowerPhase = function () { self.power = 0; self.powerIncreasing = true; self.visible = true; }; self.update = function () { if (gameState === "power" && self.visible) { if (self.powerIncreasing) { self.power += self.powerSpeed; if (self.power >= self.maxPower) { self.power = self.maxPower; self.powerIncreasing = false; } } else { self.power -= self.powerSpeed; if (self.power <= 0) { self.power = 0; self.powerIncreasing = true; } } self.setPower(self.power); } }; return self; }); var BasketHoop = Container.expand(function () { var self = Container.call(this); // Create backboard var backboard = self.attachAsset('backboard', { anchorX: 0.5, anchorY: 0, x: 0, y: 0 }); // Create rim var hoop = self.attachAsset('hoop', { anchorX: 0.5, anchorY: 0, x: 0, y: backboard.height + 20 }); // Create net self.net = self.attachAsset('net', { anchorX: 0.5, anchorY: 0, x: 0, y: backboard.height + 20 + hoop.height / 2, alpha: 0.5 }); // For hoop movement self.originalX = 0; self.originalY = 0; self.moveSpeed = 0; self.moveRange = 0; self.moveDir = 1; self.setMoving = function (speed, range) { self.moveSpeed = speed; self.moveRange = range; self.originalX = self.x; }; self.update = function () { if (self.moveSpeed > 0) { self.x += self.moveSpeed * self.moveDir; if (self.x > self.originalX + self.moveRange) { self.x = self.originalX + self.moveRange; self.moveDir = -1; } else if (self.x < self.originalX - self.moveRange) { self.x = self.originalX - self.moveRange; self.moveDir = 1; } } }; return self; }); var Basketball = Container.expand(function () { var self = Container.call(this); var ball = self.attachAsset('ball', { anchorX: 0.5, anchorY: 0.5 }); var ballShine = self.attachAsset('ballShine', { anchorX: 0.5, anchorY: 0.5, x: -20, y: -20 }); self.velocity = { x: 0, y: 0 }; self.gravity = 0.5; self.bounceDecay = 0.65; self.friction = 0.98; self.active = false; self.scored = false; self.update = function () { if (!self.active) { return; } // Apply physics self.velocity.y += self.gravity; self.x += self.velocity.x; self.y += self.velocity.y; // Apply wind if present if (currentLevel.wind) { self.velocity.x += currentLevel.wind / 50; } // Ball rotation based on horizontal movement ball.rotation += self.velocity.x / 30; // Check floor collision if (self.y > floorY - ball.height / 2) { self.y = floorY - ball.height / 2; self.velocity.y = -self.velocity.y * self.bounceDecay; self.velocity.x *= self.friction; LK.getSound('bounce').play(); // Stop ball if it's bounced enough and is slow if (Math.abs(self.velocity.y) < 2 && Math.abs(self.velocity.x) < 1) { self.active = false; shotsRemaining--; updateShotsText(); if (shotsRemaining <= 0 && !levelComplete) { LK.setTimeout(function () { if (!levelComplete) { LK.showGameOver(); } }, 1500); } else if (!levelComplete) { resetShot(); } } } // Check wall collisions if (self.x < ball.width / 2) { self.x = ball.width / 2; self.velocity.x = -self.velocity.x * self.bounceDecay; LK.getSound('bounce').play(); } else if (self.x > 2048 - ball.width / 2) { self.x = 2048 - ball.width / 2; self.velocity.x = -self.velocity.x * self.bounceDecay; LK.getSound('bounce').play(); } // Check obstacle collisions for (var i = 0; i < obstacles.length; i++) { if (self.intersects(obstacles[i])) { // Basic collision response var dx = self.x - obstacles[i].x; var dy = self.y - obstacles[i].y; var dist = Math.sqrt(dx * dx + dy * dy); var nx = dx / dist; var ny = dy / dist; // Push ball away from obstacle self.x += nx * 5; self.y += ny * 5; // Reflect velocity var dotProduct = self.velocity.x * nx + self.velocity.y * ny; self.velocity.x = (self.velocity.x - 2 * dotProduct * nx) * self.bounceDecay; self.velocity.y = (self.velocity.y - 2 * dotProduct * ny) * self.bounceDecay; LK.getSound('bounce').play(); } } // Check defenders for (var i = 0; i < defenders.length; i++) { if (self.intersects(defenders[i])) { // Simplified collision with defenders - just bounce back self.velocity.x = -self.velocity.x * self.bounceDecay; self.velocity.y = -self.velocity.y * self.bounceDecay; LK.getSound('bounce').play(); } } // Check hoop scoring if (!self.scored && self.intersects(basketHoop.net)) { // Ball position relative to hoop var ballToHoop = self.toLocal(basketHoop.net.position, basketHoop); // Only count if the ball is going down and is near the center of the hoop if (self.velocity.y > 0 && Math.abs(ballToHoop.x) < basketHoop.net.width / 4) { self.scored = true; levelScore++; LK.setScore(LK.getScore() + 100); updateScoreText(); LK.getSound('swish').play(); // Check if level is complete if (levelScore >= currentLevel.requiredScores) { levelComplete = true; // Update high score if necessary var highScores = storage.highScores; if (LK.getScore() > highScores[currentLevelIndex]) { highScores[currentLevelIndex] = LK.getScore(); storage.highScores = highScores; } // Advance to next level currentLevelIndex++; if (currentLevelIndex < levels.length) { LK.setTimeout(function () { levelTitleText.setText("LEVEL " + (currentLevelIndex + 1) + " COMPLETE!"); LK.effects.flashScreen(0x27ae60, 1000); LK.getSound('levelUp').play(); LK.setTimeout(function () { loadLevel(currentLevelIndex); }, 2000); }, 1000); } else { // Game completed LK.setTimeout(function () { levelTitleText.setText("GAME COMPLETED!"); LK.effects.flashScreen(0x27ae60, 1000); LK.getSound('levelUp').play(); LK.setTimeout(function () { LK.showYouWin(); }, 2000); }, 1000); } } else { // Continue level with next shot LK.setTimeout(function () { if (!levelComplete) { resetShot(); } }, 1500); } } } }; return self; }); var Defender = Container.expand(function () { var self = Container.call(this); // Create defender body var body = self.attachAsset('player', { anchorX: 0.5, anchorY: 1, x: 0, y: 0, tint: 0xe74c3c }); // Create defender head var head = self.attachAsset('playerHead', { anchorX: 0.5, anchorY: 1, x: 0, y: -body.height, tint: 0xe74c3c }); // For defender movement self.originalX = 0; self.moveSpeed = 0; self.moveRange = 0; self.moveDir = 1; self.setMoving = function (speed, range) { self.moveSpeed = speed; self.moveRange = range; self.originalX = self.x; }; self.update = function () { if (self.moveSpeed > 0) { self.x += self.moveSpeed * self.moveDir; if (self.x > self.originalX + self.moveRange) { self.x = self.originalX + self.moveRange; self.moveDir = -1; } else if (self.x < self.originalX - self.moveRange) { self.x = self.originalX - self.moveRange; self.moveDir = 1; } } }; return self; }); var Player = Container.expand(function () { var self = Container.call(this); // Create player body var body = self.attachAsset('player', { anchorX: 0.5, anchorY: 1, x: 0, y: 0 }); // Create player head var head = self.attachAsset('playerHead', { anchorX: 0.5, anchorY: 1, x: 0, y: -body.height }); self.canShoot = true; self.down = function (x, y, obj) { if (gameState === "aiming" && self.canShoot) { startAiming(self.x, self.y - body.height / 2); } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x3498db }); /**** * Game Code ****/ // Game state management var gameState = "start"; // "start", "aiming", "power", "shooting" var currentLevelIndex = storage.level - 1; var currentLevel; var levels = []; var floorY = 2600; var levelComplete = false; var levelScore = 0; var shotsRemaining = 5; // Game elements var basketball; var basketHoop; var player; var aimingSystem; var obstacles = []; var defenders = []; // UI elements var levelTitleText; var scoreText; var shotsText; var windText; var levelInfoText; // Level definitions function initLevels() { levels = [{ title: "Rookie Shot", description: "Make simple shots to learn the basics", hoopX: 1600, hoopY: 1600, playerX: 400, playerY: floorY, requiredScores: 3, shotsAllowed: 5, movingHoop: false, wind: 0, obstacles: [], defenders: [] }, { title: "Side Angle", description: "Shoot from the side", hoopX: 1700, hoopY: 1600, playerX: 300, playerY: floorY, requiredScores: 3, shotsAllowed: 5, movingHoop: false, wind: 0, obstacles: [], defenders: [] }, { title: "Moving Target", description: "Hit a moving basket", hoopX: 1500, hoopY: 1600, playerX: 400, playerY: floorY, requiredScores: 3, shotsAllowed: 6, movingHoop: true, hoopSpeed: 3, hoopRange: 300, wind: 0, obstacles: [], defenders: [] }, { title: "Obstacle Course", description: "Navigate around obstacles", hoopX: 1600, hoopY: 1600, playerX: 400, playerY: floorY, requiredScores: 2, shotsAllowed: 5, movingHoop: false, wind: 0, obstacles: [{ x: 1000, y: 2000, width: 100, height: 100 }], defenders: [] }, { title: "Defender Pressure", description: "Shoot past defenders", hoopX: 1600, hoopY: 1600, playerX: 400, playerY: floorY, requiredScores: 2, shotsAllowed: 5, movingHoop: false, wind: 0, obstacles: [], defenders: [{ x: 1000, y: floorY, speed: 0, range: 0 }] }, { title: "Windy Day", description: "Account for wind when shooting", hoopX: 1600, hoopY: 1600, playerX: 400, playerY: floorY, requiredScores: 2, shotsAllowed: 6, movingHoop: false, wind: 1.5, obstacles: [], defenders: [] }, { title: "Moving Defenders", description: "Time your shots carefully", hoopX: 1600, hoopY: 1600, playerX: 400, playerY: floorY, requiredScores: 2, shotsAllowed: 5, movingHoop: false, wind: 0, obstacles: [], defenders: [{ x: 800, y: floorY, speed: 4, range: 200 }, { x: 1200, y: floorY, speed: 3, range: 150 }] }, { title: "Complex Challenge", description: "Wind, moving hoop, and defenders", hoopX: 1600, hoopY: 1600, playerX: 400, playerY: floorY, requiredScores: 2, shotsAllowed: 6, movingHoop: true, hoopSpeed: 2, hoopRange: 200, wind: 1, obstacles: [], defenders: [{ x: 1000, y: floorY, speed: 3, range: 200 }] }, { title: "Obstacle Maze", description: "Navigate through multiple obstacles", hoopX: 1600, hoopY: 1600, playerX: 400, playerY: floorY, requiredScores: 2, shotsAllowed: 6, movingHoop: false, wind: 0.5, obstacles: [{ x: 800, y: 2000, width: 100, height: 100 }, { x: 1200, y: 1800, width: 100, height: 100 }], defenders: [] }, { title: "Championship", description: "Use all your skills for the final challenge", hoopX: 1600, hoopY: 1500, playerX: 400, playerY: floorY, requiredScores: 3, shotsAllowed: 5, movingHoop: true, hoopSpeed: 4, hoopRange: 300, wind: 1.2, obstacles: [{ x: 900, y: 2000, width: 100, height: 100 }], defenders: [{ x: 1200, y: floorY, speed: 5, range: 250 }] }]; } // Function to load a specific level function loadLevel(levelIndex) { // Clear previous level objects clearLevel(); // Set current level currentLevel = levels[levelIndex]; storage.level = levelIndex + 1; // Reset level state levelComplete = false; levelScore = 0; shotsRemaining = currentLevel.shotsAllowed; // Create floor var floor = game.addChild(LK.getAsset('floor', { anchorX: 0, anchorY: 0, x: 0, y: floorY })); // Create basketball hoop basketHoop = game.addChild(new BasketHoop()); basketHoop.x = currentLevel.hoopX; basketHoop.y = currentLevel.hoopY; if (currentLevel.movingHoop) { basketHoop.setMoving(currentLevel.hoopSpeed, currentLevel.hoopRange); } // Create player player = game.addChild(new Player()); player.x = currentLevel.playerX; player.y = currentLevel.playerY; // Create obstacles for (var i = 0; i < currentLevel.obstacles.length; i++) { var obstacleData = currentLevel.obstacles[i]; var obstacle = game.addChild(LK.getAsset('obstacle', { anchorX: 0.5, anchorY: 0.5, x: obstacleData.x, y: obstacleData.y })); obstacles.push(obstacle); } // Create defenders for (var i = 0; i < currentLevel.defenders.length; i++) { var defenderData = currentLevel.defenders[i]; var defender = game.addChild(new Defender()); defender.x = defenderData.x; defender.y = defenderData.y; if (defenderData.speed > 0) { defender.setMoving(defenderData.speed, defenderData.range); } defenders.push(defender); } // Create basketball basketball = game.addChild(new Basketball()); resetShot(); // Create aiming system aimingSystem = game.addChild(new AimingSystem()); aimingSystem.visible = false; // Update UI levelTitleText.setText("LEVEL " + (levelIndex + 1) + ": " + currentLevel.title); updateShotsText(); updateWindText(); levelInfoText.setText(currentLevel.description); // Reset game state gameState = "start"; // Show level intro effect LK.effects.flashScreen(0x3498db, 1000); } // Function to clear current level objects function clearLevel() { if (basketball) { basketball.destroy(); basketball = null; } if (basketHoop) { basketHoop.destroy(); basketHoop = null; } if (player) { player.destroy(); player = null; } if (aimingSystem) { aimingSystem.destroy(); aimingSystem = null; } // Clear obstacles for (var i = 0; i < obstacles.length; i++) { obstacles[i].destroy(); } obstacles = []; // Clear defenders for (var i = 0; i < defenders.length; i++) { defenders[i].destroy(); } defenders = []; } // Function to reset shot function resetShot() { basketball.x = player.x; basketball.y = player.y - 150; basketball.velocity.x = 0; basketball.velocity.y = 0; basketball.active = false; basketball.scored = false; gameState = "start"; // Make sure aiming system is hidden if (aimingSystem) { aimingSystem.visible = false; } } // Function to start aiming function startAiming(x, y) { gameState = "aiming"; aimingSystem.setPosition(x, y); aimingSystem.visible = true; } // Function to shoot the ball function shootBall() { var angle = aimingSystem.angle; var power = aimingSystem.power / 20; // Scale power appropriately basketball.velocity.x = Math.cos(angle * Math.PI / 180) * power; basketball.velocity.y = Math.sin(angle * Math.PI / 180) * power; basketball.active = true; gameState = "shooting"; aimingSystem.visible = false; } // Setup UI function setupUI() { // Level title text levelTitleText = new Text2("LEVEL 1", { size: 80, fill: 0xFFFFFF }); levelTitleText.anchor.set(0.5, 0); LK.gui.top.addChild(levelTitleText); // Score text scoreText = new Text2("SCORE: 0", { size: 60, fill: 0xFFFFFF }); scoreText.anchor.set(0, 0); scoreText.x = 150; LK.gui.topRight.addChild(scoreText); // Shots text shotsText = new Text2("SHOTS: 5", { size: 60, fill: 0xFFFFFF }); shotsText.anchor.set(0, 0); shotsText.x = 150; shotsText.y = 80; LK.gui.topRight.addChild(shotsText); // Wind text windText = new Text2("WIND: 0", { size: 60, fill: 0xFFFFFF }); windText.anchor.set(0, 0); windText.x = 150; windText.y = 160; LK.gui.topRight.addChild(windText); // Level info text levelInfoText = new Text2("Make simple shots to learn the basics", { size: 40, fill: 0xFFFFFF }); levelInfoText.anchor.set(0.5, 0); levelInfoText.y = 100; LK.gui.top.addChild(levelInfoText); } // Update UI helper functions function updateScoreText() { scoreText.setText("SCORE: " + LK.getScore()); } function updateShotsText() { shotsText.setText("SHOTS: " + shotsRemaining); } function updateWindText() { if (currentLevel && currentLevel.wind) { var direction = currentLevel.wind > 0 ? "→" : "←"; var strength = Math.abs(currentLevel.wind); var windStr = ""; for (var i = 0; i < Math.ceil(strength); i++) { windStr += direction; } windText.setText("WIND: " + windStr); } else { windText.setText("WIND: NONE"); } } // Input handling game.down = function (x, y, obj) { if (gameState === "aiming") { gameState = "power"; aimingSystem.startPowerPhase(); } else if (gameState === "power") { gameState = "shooting"; shootBall(); } else if (gameState === "start" && player && player.canShoot) { startAiming(player.x, player.y - 150); } }; game.move = function (x, y, obj) { if (gameState === "aiming" && aimingSystem && aimingSystem.visible) { // Calculate angle based on mouse position relative to player var dx = x - player.x; var dy = y - player.y; var angle = Math.atan2(dy, dx) * 180 / Math.PI; // Constrain angle for shooting upward only if (angle > 0) { angle = 0; } if (angle < -90) { angle = -90; } aimingSystem.setAngle(angle); } }; // Game update loop game.update = function () { // Update game objects if (basketball) { basketball.update(); } if (basketHoop) { basketHoop.update(); } if (aimingSystem) { aimingSystem.update(); } // Update defenders for (var i = 0; i < defenders.length; i++) { defenders[i].update(); } }; // Initialize game function initGame() { // Initialize levels initLevels(); // Setup UI setupUI(); // Reset score LK.setScore(0); updateScoreText(); // Load first level loadLevel(currentLevelIndex); // Play background music LK.playMusic('gameMusic'); } // Start the game initGame();
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
level: 1,
highScores: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
});
/****
* Classes
****/
var AimingSystem = Container.expand(function () {
var self = Container.call(this);
// Create the aim arrow
var arrow = self.attachAsset('aimArrow', {
anchorX: 0,
anchorY: 0.5,
x: 0,
y: 0
});
// Create power meter background
var powerMeter = self.attachAsset('powerMeter', {
anchorX: 0.5,
anchorY: 1,
x: 0,
y: 0
});
// Create power indicator
var powerIndicator = self.attachAsset('powerIndicator', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: -powerMeter.height + 10
});
self.visible = false;
self.angle = -45;
self.power = 0;
self.powerIncreasing = true;
self.powerSpeed = 2;
self.maxPower = 100;
// Position offset from power meter to arrow
var offsetX = 100;
self.setPosition = function (x, y) {
self.x = x;
self.y = y;
powerMeter.x = x - offsetX;
powerMeter.y = y;
};
self.setAngle = function (angle) {
self.angle = angle;
arrow.rotation = angle * Math.PI / 180;
};
self.setPower = function (power) {
self.power = power;
var normalizedPower = power / self.maxPower;
powerIndicator.y = -powerMeter.height * normalizedPower + 10;
};
self.startPowerPhase = function () {
self.power = 0;
self.powerIncreasing = true;
self.visible = true;
};
self.update = function () {
if (gameState === "power" && self.visible) {
if (self.powerIncreasing) {
self.power += self.powerSpeed;
if (self.power >= self.maxPower) {
self.power = self.maxPower;
self.powerIncreasing = false;
}
} else {
self.power -= self.powerSpeed;
if (self.power <= 0) {
self.power = 0;
self.powerIncreasing = true;
}
}
self.setPower(self.power);
}
};
return self;
});
var BasketHoop = Container.expand(function () {
var self = Container.call(this);
// Create backboard
var backboard = self.attachAsset('backboard', {
anchorX: 0.5,
anchorY: 0,
x: 0,
y: 0
});
// Create rim
var hoop = self.attachAsset('hoop', {
anchorX: 0.5,
anchorY: 0,
x: 0,
y: backboard.height + 20
});
// Create net
self.net = self.attachAsset('net', {
anchorX: 0.5,
anchorY: 0,
x: 0,
y: backboard.height + 20 + hoop.height / 2,
alpha: 0.5
});
// For hoop movement
self.originalX = 0;
self.originalY = 0;
self.moveSpeed = 0;
self.moveRange = 0;
self.moveDir = 1;
self.setMoving = function (speed, range) {
self.moveSpeed = speed;
self.moveRange = range;
self.originalX = self.x;
};
self.update = function () {
if (self.moveSpeed > 0) {
self.x += self.moveSpeed * self.moveDir;
if (self.x > self.originalX + self.moveRange) {
self.x = self.originalX + self.moveRange;
self.moveDir = -1;
} else if (self.x < self.originalX - self.moveRange) {
self.x = self.originalX - self.moveRange;
self.moveDir = 1;
}
}
};
return self;
});
var Basketball = Container.expand(function () {
var self = Container.call(this);
var ball = self.attachAsset('ball', {
anchorX: 0.5,
anchorY: 0.5
});
var ballShine = self.attachAsset('ballShine', {
anchorX: 0.5,
anchorY: 0.5,
x: -20,
y: -20
});
self.velocity = {
x: 0,
y: 0
};
self.gravity = 0.5;
self.bounceDecay = 0.65;
self.friction = 0.98;
self.active = false;
self.scored = false;
self.update = function () {
if (!self.active) {
return;
}
// Apply physics
self.velocity.y += self.gravity;
self.x += self.velocity.x;
self.y += self.velocity.y;
// Apply wind if present
if (currentLevel.wind) {
self.velocity.x += currentLevel.wind / 50;
}
// Ball rotation based on horizontal movement
ball.rotation += self.velocity.x / 30;
// Check floor collision
if (self.y > floorY - ball.height / 2) {
self.y = floorY - ball.height / 2;
self.velocity.y = -self.velocity.y * self.bounceDecay;
self.velocity.x *= self.friction;
LK.getSound('bounce').play();
// Stop ball if it's bounced enough and is slow
if (Math.abs(self.velocity.y) < 2 && Math.abs(self.velocity.x) < 1) {
self.active = false;
shotsRemaining--;
updateShotsText();
if (shotsRemaining <= 0 && !levelComplete) {
LK.setTimeout(function () {
if (!levelComplete) {
LK.showGameOver();
}
}, 1500);
} else if (!levelComplete) {
resetShot();
}
}
}
// Check wall collisions
if (self.x < ball.width / 2) {
self.x = ball.width / 2;
self.velocity.x = -self.velocity.x * self.bounceDecay;
LK.getSound('bounce').play();
} else if (self.x > 2048 - ball.width / 2) {
self.x = 2048 - ball.width / 2;
self.velocity.x = -self.velocity.x * self.bounceDecay;
LK.getSound('bounce').play();
}
// Check obstacle collisions
for (var i = 0; i < obstacles.length; i++) {
if (self.intersects(obstacles[i])) {
// Basic collision response
var dx = self.x - obstacles[i].x;
var dy = self.y - obstacles[i].y;
var dist = Math.sqrt(dx * dx + dy * dy);
var nx = dx / dist;
var ny = dy / dist;
// Push ball away from obstacle
self.x += nx * 5;
self.y += ny * 5;
// Reflect velocity
var dotProduct = self.velocity.x * nx + self.velocity.y * ny;
self.velocity.x = (self.velocity.x - 2 * dotProduct * nx) * self.bounceDecay;
self.velocity.y = (self.velocity.y - 2 * dotProduct * ny) * self.bounceDecay;
LK.getSound('bounce').play();
}
}
// Check defenders
for (var i = 0; i < defenders.length; i++) {
if (self.intersects(defenders[i])) {
// Simplified collision with defenders - just bounce back
self.velocity.x = -self.velocity.x * self.bounceDecay;
self.velocity.y = -self.velocity.y * self.bounceDecay;
LK.getSound('bounce').play();
}
}
// Check hoop scoring
if (!self.scored && self.intersects(basketHoop.net)) {
// Ball position relative to hoop
var ballToHoop = self.toLocal(basketHoop.net.position, basketHoop);
// Only count if the ball is going down and is near the center of the hoop
if (self.velocity.y > 0 && Math.abs(ballToHoop.x) < basketHoop.net.width / 4) {
self.scored = true;
levelScore++;
LK.setScore(LK.getScore() + 100);
updateScoreText();
LK.getSound('swish').play();
// Check if level is complete
if (levelScore >= currentLevel.requiredScores) {
levelComplete = true;
// Update high score if necessary
var highScores = storage.highScores;
if (LK.getScore() > highScores[currentLevelIndex]) {
highScores[currentLevelIndex] = LK.getScore();
storage.highScores = highScores;
}
// Advance to next level
currentLevelIndex++;
if (currentLevelIndex < levels.length) {
LK.setTimeout(function () {
levelTitleText.setText("LEVEL " + (currentLevelIndex + 1) + " COMPLETE!");
LK.effects.flashScreen(0x27ae60, 1000);
LK.getSound('levelUp').play();
LK.setTimeout(function () {
loadLevel(currentLevelIndex);
}, 2000);
}, 1000);
} else {
// Game completed
LK.setTimeout(function () {
levelTitleText.setText("GAME COMPLETED!");
LK.effects.flashScreen(0x27ae60, 1000);
LK.getSound('levelUp').play();
LK.setTimeout(function () {
LK.showYouWin();
}, 2000);
}, 1000);
}
} else {
// Continue level with next shot
LK.setTimeout(function () {
if (!levelComplete) {
resetShot();
}
}, 1500);
}
}
}
};
return self;
});
var Defender = Container.expand(function () {
var self = Container.call(this);
// Create defender body
var body = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 1,
x: 0,
y: 0,
tint: 0xe74c3c
});
// Create defender head
var head = self.attachAsset('playerHead', {
anchorX: 0.5,
anchorY: 1,
x: 0,
y: -body.height,
tint: 0xe74c3c
});
// For defender movement
self.originalX = 0;
self.moveSpeed = 0;
self.moveRange = 0;
self.moveDir = 1;
self.setMoving = function (speed, range) {
self.moveSpeed = speed;
self.moveRange = range;
self.originalX = self.x;
};
self.update = function () {
if (self.moveSpeed > 0) {
self.x += self.moveSpeed * self.moveDir;
if (self.x > self.originalX + self.moveRange) {
self.x = self.originalX + self.moveRange;
self.moveDir = -1;
} else if (self.x < self.originalX - self.moveRange) {
self.x = self.originalX - self.moveRange;
self.moveDir = 1;
}
}
};
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
// Create player body
var body = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 1,
x: 0,
y: 0
});
// Create player head
var head = self.attachAsset('playerHead', {
anchorX: 0.5,
anchorY: 1,
x: 0,
y: -body.height
});
self.canShoot = true;
self.down = function (x, y, obj) {
if (gameState === "aiming" && self.canShoot) {
startAiming(self.x, self.y - body.height / 2);
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x3498db
});
/****
* Game Code
****/
// Game state management
var gameState = "start"; // "start", "aiming", "power", "shooting"
var currentLevelIndex = storage.level - 1;
var currentLevel;
var levels = [];
var floorY = 2600;
var levelComplete = false;
var levelScore = 0;
var shotsRemaining = 5;
// Game elements
var basketball;
var basketHoop;
var player;
var aimingSystem;
var obstacles = [];
var defenders = [];
// UI elements
var levelTitleText;
var scoreText;
var shotsText;
var windText;
var levelInfoText;
// Level definitions
function initLevels() {
levels = [{
title: "Rookie Shot",
description: "Make simple shots to learn the basics",
hoopX: 1600,
hoopY: 1600,
playerX: 400,
playerY: floorY,
requiredScores: 3,
shotsAllowed: 5,
movingHoop: false,
wind: 0,
obstacles: [],
defenders: []
}, {
title: "Side Angle",
description: "Shoot from the side",
hoopX: 1700,
hoopY: 1600,
playerX: 300,
playerY: floorY,
requiredScores: 3,
shotsAllowed: 5,
movingHoop: false,
wind: 0,
obstacles: [],
defenders: []
}, {
title: "Moving Target",
description: "Hit a moving basket",
hoopX: 1500,
hoopY: 1600,
playerX: 400,
playerY: floorY,
requiredScores: 3,
shotsAllowed: 6,
movingHoop: true,
hoopSpeed: 3,
hoopRange: 300,
wind: 0,
obstacles: [],
defenders: []
}, {
title: "Obstacle Course",
description: "Navigate around obstacles",
hoopX: 1600,
hoopY: 1600,
playerX: 400,
playerY: floorY,
requiredScores: 2,
shotsAllowed: 5,
movingHoop: false,
wind: 0,
obstacles: [{
x: 1000,
y: 2000,
width: 100,
height: 100
}],
defenders: []
}, {
title: "Defender Pressure",
description: "Shoot past defenders",
hoopX: 1600,
hoopY: 1600,
playerX: 400,
playerY: floorY,
requiredScores: 2,
shotsAllowed: 5,
movingHoop: false,
wind: 0,
obstacles: [],
defenders: [{
x: 1000,
y: floorY,
speed: 0,
range: 0
}]
}, {
title: "Windy Day",
description: "Account for wind when shooting",
hoopX: 1600,
hoopY: 1600,
playerX: 400,
playerY: floorY,
requiredScores: 2,
shotsAllowed: 6,
movingHoop: false,
wind: 1.5,
obstacles: [],
defenders: []
}, {
title: "Moving Defenders",
description: "Time your shots carefully",
hoopX: 1600,
hoopY: 1600,
playerX: 400,
playerY: floorY,
requiredScores: 2,
shotsAllowed: 5,
movingHoop: false,
wind: 0,
obstacles: [],
defenders: [{
x: 800,
y: floorY,
speed: 4,
range: 200
}, {
x: 1200,
y: floorY,
speed: 3,
range: 150
}]
}, {
title: "Complex Challenge",
description: "Wind, moving hoop, and defenders",
hoopX: 1600,
hoopY: 1600,
playerX: 400,
playerY: floorY,
requiredScores: 2,
shotsAllowed: 6,
movingHoop: true,
hoopSpeed: 2,
hoopRange: 200,
wind: 1,
obstacles: [],
defenders: [{
x: 1000,
y: floorY,
speed: 3,
range: 200
}]
}, {
title: "Obstacle Maze",
description: "Navigate through multiple obstacles",
hoopX: 1600,
hoopY: 1600,
playerX: 400,
playerY: floorY,
requiredScores: 2,
shotsAllowed: 6,
movingHoop: false,
wind: 0.5,
obstacles: [{
x: 800,
y: 2000,
width: 100,
height: 100
}, {
x: 1200,
y: 1800,
width: 100,
height: 100
}],
defenders: []
}, {
title: "Championship",
description: "Use all your skills for the final challenge",
hoopX: 1600,
hoopY: 1500,
playerX: 400,
playerY: floorY,
requiredScores: 3,
shotsAllowed: 5,
movingHoop: true,
hoopSpeed: 4,
hoopRange: 300,
wind: 1.2,
obstacles: [{
x: 900,
y: 2000,
width: 100,
height: 100
}],
defenders: [{
x: 1200,
y: floorY,
speed: 5,
range: 250
}]
}];
}
// Function to load a specific level
function loadLevel(levelIndex) {
// Clear previous level objects
clearLevel();
// Set current level
currentLevel = levels[levelIndex];
storage.level = levelIndex + 1;
// Reset level state
levelComplete = false;
levelScore = 0;
shotsRemaining = currentLevel.shotsAllowed;
// Create floor
var floor = game.addChild(LK.getAsset('floor', {
anchorX: 0,
anchorY: 0,
x: 0,
y: floorY
}));
// Create basketball hoop
basketHoop = game.addChild(new BasketHoop());
basketHoop.x = currentLevel.hoopX;
basketHoop.y = currentLevel.hoopY;
if (currentLevel.movingHoop) {
basketHoop.setMoving(currentLevel.hoopSpeed, currentLevel.hoopRange);
}
// Create player
player = game.addChild(new Player());
player.x = currentLevel.playerX;
player.y = currentLevel.playerY;
// Create obstacles
for (var i = 0; i < currentLevel.obstacles.length; i++) {
var obstacleData = currentLevel.obstacles[i];
var obstacle = game.addChild(LK.getAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.5,
x: obstacleData.x,
y: obstacleData.y
}));
obstacles.push(obstacle);
}
// Create defenders
for (var i = 0; i < currentLevel.defenders.length; i++) {
var defenderData = currentLevel.defenders[i];
var defender = game.addChild(new Defender());
defender.x = defenderData.x;
defender.y = defenderData.y;
if (defenderData.speed > 0) {
defender.setMoving(defenderData.speed, defenderData.range);
}
defenders.push(defender);
}
// Create basketball
basketball = game.addChild(new Basketball());
resetShot();
// Create aiming system
aimingSystem = game.addChild(new AimingSystem());
aimingSystem.visible = false;
// Update UI
levelTitleText.setText("LEVEL " + (levelIndex + 1) + ": " + currentLevel.title);
updateShotsText();
updateWindText();
levelInfoText.setText(currentLevel.description);
// Reset game state
gameState = "start";
// Show level intro effect
LK.effects.flashScreen(0x3498db, 1000);
}
// Function to clear current level objects
function clearLevel() {
if (basketball) {
basketball.destroy();
basketball = null;
}
if (basketHoop) {
basketHoop.destroy();
basketHoop = null;
}
if (player) {
player.destroy();
player = null;
}
if (aimingSystem) {
aimingSystem.destroy();
aimingSystem = null;
}
// Clear obstacles
for (var i = 0; i < obstacles.length; i++) {
obstacles[i].destroy();
}
obstacles = [];
// Clear defenders
for (var i = 0; i < defenders.length; i++) {
defenders[i].destroy();
}
defenders = [];
}
// Function to reset shot
function resetShot() {
basketball.x = player.x;
basketball.y = player.y - 150;
basketball.velocity.x = 0;
basketball.velocity.y = 0;
basketball.active = false;
basketball.scored = false;
gameState = "start";
// Make sure aiming system is hidden
if (aimingSystem) {
aimingSystem.visible = false;
}
}
// Function to start aiming
function startAiming(x, y) {
gameState = "aiming";
aimingSystem.setPosition(x, y);
aimingSystem.visible = true;
}
// Function to shoot the ball
function shootBall() {
var angle = aimingSystem.angle;
var power = aimingSystem.power / 20; // Scale power appropriately
basketball.velocity.x = Math.cos(angle * Math.PI / 180) * power;
basketball.velocity.y = Math.sin(angle * Math.PI / 180) * power;
basketball.active = true;
gameState = "shooting";
aimingSystem.visible = false;
}
// Setup UI
function setupUI() {
// Level title text
levelTitleText = new Text2("LEVEL 1", {
size: 80,
fill: 0xFFFFFF
});
levelTitleText.anchor.set(0.5, 0);
LK.gui.top.addChild(levelTitleText);
// Score text
scoreText = new Text2("SCORE: 0", {
size: 60,
fill: 0xFFFFFF
});
scoreText.anchor.set(0, 0);
scoreText.x = 150;
LK.gui.topRight.addChild(scoreText);
// Shots text
shotsText = new Text2("SHOTS: 5", {
size: 60,
fill: 0xFFFFFF
});
shotsText.anchor.set(0, 0);
shotsText.x = 150;
shotsText.y = 80;
LK.gui.topRight.addChild(shotsText);
// Wind text
windText = new Text2("WIND: 0", {
size: 60,
fill: 0xFFFFFF
});
windText.anchor.set(0, 0);
windText.x = 150;
windText.y = 160;
LK.gui.topRight.addChild(windText);
// Level info text
levelInfoText = new Text2("Make simple shots to learn the basics", {
size: 40,
fill: 0xFFFFFF
});
levelInfoText.anchor.set(0.5, 0);
levelInfoText.y = 100;
LK.gui.top.addChild(levelInfoText);
}
// Update UI helper functions
function updateScoreText() {
scoreText.setText("SCORE: " + LK.getScore());
}
function updateShotsText() {
shotsText.setText("SHOTS: " + shotsRemaining);
}
function updateWindText() {
if (currentLevel && currentLevel.wind) {
var direction = currentLevel.wind > 0 ? "→" : "←";
var strength = Math.abs(currentLevel.wind);
var windStr = "";
for (var i = 0; i < Math.ceil(strength); i++) {
windStr += direction;
}
windText.setText("WIND: " + windStr);
} else {
windText.setText("WIND: NONE");
}
}
// Input handling
game.down = function (x, y, obj) {
if (gameState === "aiming") {
gameState = "power";
aimingSystem.startPowerPhase();
} else if (gameState === "power") {
gameState = "shooting";
shootBall();
} else if (gameState === "start" && player && player.canShoot) {
startAiming(player.x, player.y - 150);
}
};
game.move = function (x, y, obj) {
if (gameState === "aiming" && aimingSystem && aimingSystem.visible) {
// Calculate angle based on mouse position relative to player
var dx = x - player.x;
var dy = y - player.y;
var angle = Math.atan2(dy, dx) * 180 / Math.PI;
// Constrain angle for shooting upward only
if (angle > 0) {
angle = 0;
}
if (angle < -90) {
angle = -90;
}
aimingSystem.setAngle(angle);
}
};
// Game update loop
game.update = function () {
// Update game objects
if (basketball) {
basketball.update();
}
if (basketHoop) {
basketHoop.update();
}
if (aimingSystem) {
aimingSystem.update();
}
// Update defenders
for (var i = 0; i < defenders.length; i++) {
defenders[i].update();
}
};
// Initialize game
function initGame() {
// Initialize levels
initLevels();
// Setup UI
setupUI();
// Reset score
LK.setScore(0);
updateScoreText();
// Load first level
loadLevel(currentLevelIndex);
// Play background music
LK.playMusic('gameMusic');
}
// Start the game
initGame();