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();