User prompt
Render player1 in front of basketball
User prompt
Move shotbar up 400
User prompt
Add player1 to bottom of screen
User prompt
Make yellow flash change colours on made baskets āŖš” Consider importing and using the following plugins: @upit/tween.v1
User prompt
Rotate shotbars 180° āŖš” Consider importing and using the following plugins: @upit/tween.v1
User prompt
Make shotbar ball go upwards first āŖš” Consider importing and using the following plugins: @upit/tween.v1
User prompt
Make shotbars vertical
User prompt
Keep changing colours on made baskets āŖš” Consider importing and using the following plugins: @upit/tween.v1
User prompt
When colour changes make it stay the new colour untill next basket then change it to a new colour āŖš” Consider importing and using the following plugins: @upit/tween.v1
User prompt
Make them change to a different colour every basket āŖš” Consider importing and using the following plugins: @upit/tween.v1
User prompt
Make backboard change colour when basket goes in āŖš” Consider importing and using the following plugins: @upit/tween.v1
User prompt
Add a ball for backboard 2 and 3
User prompt
Add shotbars for backboard 2 and 3
User prompt
Add shotbars for backboard 2 and 3
User prompt
Move backboard 2 left 50
User prompt
Move backboard 3 right 350
User prompt
Copy everything and add to right of backboard
User prompt
Move backboard 2 left 300
User prompt
Copy everything and add to left of backboard
User prompt
Make background high definition
User prompt
Move everything left 10
User prompt
Move everything left 10
User prompt
Move everything right 120
User prompt
Move everything right 300
User prompt
Simplify perfect shot logic to guarantee scoring with direct trajectory calculation
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ var Basketball = Container.expand(function () { var self = Container.call(this); var ballGraphics = self.attachAsset('basketball', { anchorX: 0.5, anchorY: 0.5 }); // Set z-index to render behind net and hoop ballGraphics.zIndex = -1; self.velocityX = 0; self.velocityY = 0; self.gravity = 0.5; self.bounceDecay = 0.7; self.hasScored = false; self.isActive = true; self.update = function () { if (!self.isActive) return; // Handle perfect shot trajectory override if (self.isPerfectShot && self.perfectShotTarget && self.perfectShotTime < self.perfectShotDuration) { // Use direct linear interpolation for perfect shot to guarantee scoring var progress = self.perfectShotTime / self.perfectShotDuration; var startX = 1024; var startY = 2500; var targetX = self.perfectShotTarget.x; var targetY = self.perfectShotTarget.y; // Linear interpolation from start to target self.x = startX + (targetX - startX) * progress; self.y = startY + (targetY - startY) * progress; self.perfectShotTime++; // Once we reach the target, let normal physics take over for the swish if (self.perfectShotTime >= self.perfectShotDuration) { self.velocityX = 0; self.velocityY = 8; // Strong downward velocity for swish self.perfectShotTarget = null; // Clear override } } else { // Normal physics self.velocityY += self.gravity; self.x += self.velocityX; self.y += self.velocityY; } // Check hoop collision if (hoop) { var hoopX = hoop.x; var hoopY = hoop.y - 450; // Adjust for hoop position within container var relativeX = self.x - hoopX; var relativeY = self.y - hoopY; // Check for scoring through hoop first (ball going through net area) // Increased scoring area width to account for larger basketball and ensure proper detection // Only allow scoring if ball is coming from above the rim (self.y < hoopY) if (Math.abs(relativeX) <= 80 && relativeY >= -20 && relativeY <= 60 && self.velocityY > 0 && !self.hasScored && self.y < hoopY) { // Ball is going through hoop - animate net and score self.hasScored = true; self.isActive = false; // Set ball to render behind net and hoop ballGraphics.zIndex = -2; // Create smooth swish animation with multiple stages var swishX = hoopX + (Math.random() - 0.5) * 15; // Slight horizontal variation // Stage 1: Ball enters net with slight deceleration tween(self, { y: self.y + 30, x: swishX, scaleX: 0.95, scaleY: 1.05 }, { duration: 150, easing: tween.easeOut, onFinish: function onFinish() { // Stage 2: Ball moves through net with wobble tween(self, { y: self.y + 60, x: swishX + (Math.random() - 0.5) * 8, scaleX: 1.0, scaleY: 1.0, rotation: self.rotation + 0.3 }, { duration: 200, easing: tween.easeInOut, onFinish: function onFinish() { // Stage 3: Ball exits net and falls naturally tween(self, { y: self.y + 80, x: swishX + (Math.random() - 0.5) * 12, rotation: self.rotation + 0.5 }, { duration: 300, easing: tween.easeIn }); } }); } }); // Animate net pulsate tween(hoop.net, { scaleX: 1.8, scaleY: 1.8 }, { duration: 200, easing: tween.easeOut, onFinish: function onFinish() { tween(hoop.net, { scaleX: 1.5, scaleY: 1.5 }, { duration: 200, easing: tween.easeIn }); } }); // Score the basket currentStreak++; var points = 10 * currentStreak; if (self.isPerfectShot) { points *= 2; LK.effects.flashScreen(0xFFD700, 400); } LK.setScore(LK.getScore() + points); LK.getSound('swish').play(); scoreTxt.setText('Score: ' + LK.getScore()); streakTxt.setText('Streak: ' + currentStreak); LK.effects.flashObject(hoop, self.isPerfectShot ? 0xFFD700 : 0x00FF00, 300); return; } // Check if ball is hitting the hoop rim (only sides and front/back, not the opening) if (relativeX >= -160 && relativeX <= 160 && relativeY >= -40 && relativeY <= 40) { // Only bounce if hitting the sides of the rim or coming from wrong angle if (Math.abs(relativeX) > 120) { // Hit the sides of the rim self.velocityX = -self.velocityX * self.bounceDecay; if (relativeX < 0) { self.x = hoopX - 160; } else { self.x = hoopX + 160; } LK.getSound('bounce').play(); } else if (relativeY >= -40 && relativeY <= -20 && self.velocityY > 0 && Math.abs(relativeX) > 60) { // Hit the front/back edge of the rim (not the center opening) - only when going down self.velocityY = -Math.abs(self.velocityY) * self.bounceDecay; self.y = hoopY - 40; self.velocityX *= 0.8; // Reduce horizontal velocity slightly LK.getSound('bounce').play(); } } // Check if ball is resting on the rim edges (not center opening) if (Math.abs(relativeX) >= 60 && Math.abs(relativeX) <= 120 && relativeY >= -45 && relativeY <= -35 && Math.abs(self.velocityY) < 2 && Math.abs(self.velocityX) < 3) { // Ball is resting on rim edge, make it roll into the hoop self.isActive = false; // Stop normal physics self.hasScored = true; // Mark as scored // Set ball to render behind net and hoop ballGraphics.zIndex = -2; // Animate rolling into hoop with smooth swish tween(self, { x: hoopX, y: hoopY + 20, rotation: self.rotation + Math.PI * 1.5, scaleX: 0.95, scaleY: 1.05 }, { duration: 800, easing: tween.easeOut, onFinish: function onFinish() { // Second stage: ball goes through net tween(self, { y: hoopY + 60, x: hoopX + (Math.random() - 0.5) * 10, rotation: self.rotation + Math.PI * 0.5, scaleX: 1.0, scaleY: 1.0 }, { duration: 400, easing: tween.easeInOut, onFinish: function onFinish() { // Third stage: ball exits net and falls naturally tween(self, { y: hoopY + 100, x: hoopX + (Math.random() - 0.5) * 15, rotation: self.rotation + Math.PI * 0.3 }, { duration: 300, easing: tween.easeIn }); } }); // Animate net pulsate tween(hoop.net, { scaleX: 1.8, scaleY: 1.8 }, { duration: 200, easing: tween.easeOut, onFinish: function onFinish() { tween(hoop.net, { scaleX: 1.5, scaleY: 1.5 }, { duration: 200, easing: tween.easeIn }); } }); // Score the basket currentStreak++; var points = 10 * currentStreak; LK.setScore(LK.getScore() + points); // Play swish sound LK.getSound('swish').play(); // Update displays scoreTxt.setText('Score: ' + LK.getScore()); streakTxt.setText('Streak: ' + currentStreak); // Visual feedback LK.effects.flashObject(hoop, 0x00FF00, 300); } }); } } // Ground collision removed - ball can fall through // Remove if off screen if (self.x < -100 || self.x > 2148 || self.y > 2800) { self.isActive = false; } }; return self; }); var Hoop = Container.expand(function () { var self = Container.call(this); var backboard = self.attachAsset('backboard', { anchorX: 0.5, anchorY: 1, scaleX: 1.3, scaleY: 1.3 }); backboard.y = -15; var hoop = self.attachAsset('hoop', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.2, scaleY: 1.2 }); hoop.y = -450; // Set z-index to render in front of basketball hoop.zIndex = 1; var net = self.attachAsset('net', { anchorX: 0.5, anchorY: 0, scaleX: 1.5, scaleY: 1.5 }); net.y = -425; net.alpha = 0.8; // Set z-index to render in front of basketball net.zIndex = 2; // Store net reference for animation access self.net = net; self.hoopBounds = { left: -108, right: 108, top: -24, bottom: 24 }; // Enable z-index sorting for proper rendering order self.sortableChildren = true; return self; }); var ShotBar = Container.expand(function () { var self = Container.call(this); // Background bar var bgBar = self.attachAsset('shotBarBg', { anchorX: 0.5, anchorY: 0.5 }); // Green zone var greenZone = self.attachAsset('shotBarGreen', { anchorX: 0.5, anchorY: 0.5 }); greenZone.x = 0; // Start at center, will move // Moving basketball indicator var indicator = self.attachAsset('basketball', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.6, scaleY: 0.6 }); self.isActive = false; self.isMoving = false; self.moveDirection = 1; // 1 for right, -1 for left self.moveSpeed = 8; self.maxDistance = 240; // Half of bar width minus indicator size self.perfectShot = false; self.startMoving = function () { self.isActive = true; self.isMoving = true; self.perfectShot = false; // Position green zone randomly greenZone.x = (Math.random() - 0.5) * 360; // Random position within bar // Reset indicator position indicator.x = -self.maxDistance; self.moveDirection = 1; self.visible = true; }; self.stopMoving = function () { self.isMoving = false; // Check if indicator is within green zone var greenLeft = greenZone.x - 60; var greenRight = greenZone.x + 60; self.perfectShot = indicator.x >= greenLeft && indicator.x <= greenRight; // Hide shot bar after a short delay var self_ref = self; LK.setTimeout(function () { self_ref.visible = false; self_ref.isActive = false; }, 200); return self.perfectShot; }; self.update = function () { if (!self.isMoving) return; // Move indicator back and forth indicator.x += self.moveSpeed * self.moveDirection; // Bounce off edges if (indicator.x >= self.maxDistance) { indicator.x = self.maxDistance; self.moveDirection = -1; } else if (indicator.x <= -self.maxDistance) { indicator.x = -self.maxDistance; self.moveDirection = 1; } }; self.visible = false; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x87CEEB }); /**** * Game Code ****/ var basketballs = []; var hoop = null; var ground = null; var scoreTxt = null; var streakTxt = null; var currentStreak = 0; var swipeStartX = 0; var swipeStartY = 0; var swipeStartTime = 0; var isSwipeStarted = false; var lastShotTime = 0; var musicNotes = ['note1', 'note2', 'note3', 'note4', 'note5']; var currentNoteIndex = 0; var shotBar = null; var isChargingShot = false; // Enable z-index sorting for proper rendering order game.sortableChildren = true; // Add background var background = game.addChild(LK.getAsset('Background', { anchorX: 0, anchorY: 0 })); background.x = 0; background.y = 0; // Set background to render behind everything background.zIndex = -10; // Ground removed - no longer needed // Create hoop hoop = game.addChild(new Hoop()); hoop.x = 1024; hoop.y = 1370; // Create score display scoreTxt = new Text2('Score: 0', { size: 80, fill: 0xFFFFFF }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); // Create streak display streakTxt = new Text2('Streak: 0', { size: 60, fill: 0xFFD700 }); streakTxt.anchor.set(0.5, 0); streakTxt.y = 100; LK.gui.top.addChild(streakTxt); // Create shot bar shotBar = game.addChild(new ShotBar()); shotBar.x = 1024; shotBar.y = 2200; function createBasketball(startX, startY, velocityX, velocityY) { var ball = new Basketball(); ball.x = startX; ball.y = startY; ball.velocityX = velocityX; ball.velocityY = velocityY; ball.isPerfectShot = false; basketballs.push(ball); game.addChild(ball); return ball; } function checkBasketScore(ball) { // Scoring is now handled in Basketball class update method // This function is kept for compatibility but does nothing return; } game.down = function (x, y, obj) { if (LK.ticks - lastShotTime < 60) return; // Prevent rapid firing if (shotBar.isActive) { // Stop the shot bar and check for perfect shot var isPerfect = shotBar.stopMoving(); isChargingShot = false; // Calculate shooting parameters var startX = 1024; var startY = 2500; var velocityX = 0; var velocityY = -22; // Base upward velocity - increased power to shoot 200 higher // Force perfect shot if stopped in green zone if (isPerfect || shotBar.perfectShot) { // Perfect shot - direct trajectory to hoop center for guaranteed score var targetX = hoop.x; var targetY = hoop.y - 450; // Target the exact hoop scoring area // Create perfect shot basketball var ball = createBasketball(startX, startY, 0, -25); ball.isPerfectShot = true; ball.perfectShotTarget = { x: targetX, y: targetY }; ball.perfectShotTime = 0; ball.perfectShotDuration = 60; // Shorter, more direct time to reach hoop // Visual feedback for perfect shot LK.effects.flashScreen(0x00FF00, 200); // Add tween animation to ensure ball goes straight in tween(ball, { tint: 0xFFD700 }, { duration: 300, onFinish: function onFinish() { tween(ball, { tint: 0xFFFFFF }, { duration: 300 }); } }); // Add vertical rotation animation tween(ball, { rotation: ball.rotation + Math.PI * 4 }, { duration: 1500, easing: tween.easeOut }); } else { // Regular shot with some randomness velocityX = (Math.random() - 0.5) * 8; velocityY = -19 - Math.random() * 6; // Increased base power to shoot 200 higher var ball = createBasketball(startX, startY, velocityX, velocityY); // Add vertical rotation animation for regular shot tween(ball, { rotation: ball.rotation + Math.PI * 3 }, { duration: 1200, easing: tween.easeOut }); } lastShotTime = LK.ticks; } else { // Start charging shot isChargingShot = true; shotBar.startMoving(); swipeStartX = x; swipeStartY = y; swipeStartTime = LK.ticks; } }; game.up = function (x, y, obj) { // Shot bar system handles shooting now, remove swipe-based shooting }; game.update = function () { // Update basketballs for (var i = basketballs.length - 1; i >= 0; i--) { var ball = basketballs[i]; if (!ball.isActive) { ball.destroy(); basketballs.splice(i, 1); continue; } // Check for scoring checkBasketScore(ball); // Check collision with other basketballs for (var j = i + 1; j < basketballs.length; j++) { var otherBall = basketballs[j]; if (!otherBall.isActive) continue; var dx = ball.x - otherBall.x; var dy = ball.y - otherBall.y; var distance = Math.sqrt(dx * dx + dy * dy); var minDistance = 180; // Combined radius of two basketballs (adjusted for bigger size) if (distance < minDistance && distance > 0) { // Calculate collision normal var normalX = dx / distance; var normalY = dy / distance; // Separate balls to prevent overlap var overlap = minDistance - distance; var separationX = normalX * overlap * 0.5; var separationY = normalY * overlap * 0.5; ball.x += separationX; ball.y += separationY; otherBall.x -= separationX; otherBall.y -= separationY; // Calculate relative velocity var relativeVelX = ball.velocityX - otherBall.velocityX; var relativeVelY = ball.velocityY - otherBall.velocityY; // Calculate relative velocity along collision normal var relativeSpeed = relativeVelX * normalX + relativeVelY * normalY; // Only resolve if objects are moving towards each other if (relativeSpeed > 0) continue; // Calculate impulse scalar (assuming equal mass) var impulse = -2 * relativeSpeed / 2; var impulseX = impulse * normalX; var impulseY = impulse * normalY; // Apply impulse with bounce decay var bounceDecay = 0.8; ball.velocityX += impulseX * bounceDecay; ball.velocityY += impulseY * bounceDecay; otherBall.velocityX -= impulseX * bounceDecay; otherBall.velocityY -= impulseY * bounceDecay; // Play bounce sound LK.getSound('bounce').play(); } } } // Reset streak if no balls scored recently if (basketballs.length === 0 && LK.ticks - lastShotTime > 180) { if (currentStreak > 0) { currentStreak = 0; streakTxt.setText('Streak: 0'); currentNoteIndex = 0; // Reset musical progression } } // Check win condition if (LK.getScore() >= 500) { LK.showYouWin(); } }; // Start background music LK.playMusic('backgroundMusic');
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Basketball = Container.expand(function () {
var self = Container.call(this);
var ballGraphics = self.attachAsset('basketball', {
anchorX: 0.5,
anchorY: 0.5
});
// Set z-index to render behind net and hoop
ballGraphics.zIndex = -1;
self.velocityX = 0;
self.velocityY = 0;
self.gravity = 0.5;
self.bounceDecay = 0.7;
self.hasScored = false;
self.isActive = true;
self.update = function () {
if (!self.isActive) return;
// Handle perfect shot trajectory override
if (self.isPerfectShot && self.perfectShotTarget && self.perfectShotTime < self.perfectShotDuration) {
// Use direct linear interpolation for perfect shot to guarantee scoring
var progress = self.perfectShotTime / self.perfectShotDuration;
var startX = 1024;
var startY = 2500;
var targetX = self.perfectShotTarget.x;
var targetY = self.perfectShotTarget.y;
// Linear interpolation from start to target
self.x = startX + (targetX - startX) * progress;
self.y = startY + (targetY - startY) * progress;
self.perfectShotTime++;
// Once we reach the target, let normal physics take over for the swish
if (self.perfectShotTime >= self.perfectShotDuration) {
self.velocityX = 0;
self.velocityY = 8; // Strong downward velocity for swish
self.perfectShotTarget = null; // Clear override
}
} else {
// Normal physics
self.velocityY += self.gravity;
self.x += self.velocityX;
self.y += self.velocityY;
}
// Check hoop collision
if (hoop) {
var hoopX = hoop.x;
var hoopY = hoop.y - 450; // Adjust for hoop position within container
var relativeX = self.x - hoopX;
var relativeY = self.y - hoopY;
// Check for scoring through hoop first (ball going through net area)
// Increased scoring area width to account for larger basketball and ensure proper detection
// Only allow scoring if ball is coming from above the rim (self.y < hoopY)
if (Math.abs(relativeX) <= 80 && relativeY >= -20 && relativeY <= 60 && self.velocityY > 0 && !self.hasScored && self.y < hoopY) {
// Ball is going through hoop - animate net and score
self.hasScored = true;
self.isActive = false;
// Set ball to render behind net and hoop
ballGraphics.zIndex = -2;
// Create smooth swish animation with multiple stages
var swishX = hoopX + (Math.random() - 0.5) * 15; // Slight horizontal variation
// Stage 1: Ball enters net with slight deceleration
tween(self, {
y: self.y + 30,
x: swishX,
scaleX: 0.95,
scaleY: 1.05
}, {
duration: 150,
easing: tween.easeOut,
onFinish: function onFinish() {
// Stage 2: Ball moves through net with wobble
tween(self, {
y: self.y + 60,
x: swishX + (Math.random() - 0.5) * 8,
scaleX: 1.0,
scaleY: 1.0,
rotation: self.rotation + 0.3
}, {
duration: 200,
easing: tween.easeInOut,
onFinish: function onFinish() {
// Stage 3: Ball exits net and falls naturally
tween(self, {
y: self.y + 80,
x: swishX + (Math.random() - 0.5) * 12,
rotation: self.rotation + 0.5
}, {
duration: 300,
easing: tween.easeIn
});
}
});
}
});
// Animate net pulsate
tween(hoop.net, {
scaleX: 1.8,
scaleY: 1.8
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(hoop.net, {
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 200,
easing: tween.easeIn
});
}
});
// Score the basket
currentStreak++;
var points = 10 * currentStreak;
if (self.isPerfectShot) {
points *= 2;
LK.effects.flashScreen(0xFFD700, 400);
}
LK.setScore(LK.getScore() + points);
LK.getSound('swish').play();
scoreTxt.setText('Score: ' + LK.getScore());
streakTxt.setText('Streak: ' + currentStreak);
LK.effects.flashObject(hoop, self.isPerfectShot ? 0xFFD700 : 0x00FF00, 300);
return;
}
// Check if ball is hitting the hoop rim (only sides and front/back, not the opening)
if (relativeX >= -160 && relativeX <= 160 && relativeY >= -40 && relativeY <= 40) {
// Only bounce if hitting the sides of the rim or coming from wrong angle
if (Math.abs(relativeX) > 120) {
// Hit the sides of the rim
self.velocityX = -self.velocityX * self.bounceDecay;
if (relativeX < 0) {
self.x = hoopX - 160;
} else {
self.x = hoopX + 160;
}
LK.getSound('bounce').play();
} else if (relativeY >= -40 && relativeY <= -20 && self.velocityY > 0 && Math.abs(relativeX) > 60) {
// Hit the front/back edge of the rim (not the center opening) - only when going down
self.velocityY = -Math.abs(self.velocityY) * self.bounceDecay;
self.y = hoopY - 40;
self.velocityX *= 0.8; // Reduce horizontal velocity slightly
LK.getSound('bounce').play();
}
}
// Check if ball is resting on the rim edges (not center opening)
if (Math.abs(relativeX) >= 60 && Math.abs(relativeX) <= 120 && relativeY >= -45 && relativeY <= -35 && Math.abs(self.velocityY) < 2 && Math.abs(self.velocityX) < 3) {
// Ball is resting on rim edge, make it roll into the hoop
self.isActive = false; // Stop normal physics
self.hasScored = true; // Mark as scored
// Set ball to render behind net and hoop
ballGraphics.zIndex = -2;
// Animate rolling into hoop with smooth swish
tween(self, {
x: hoopX,
y: hoopY + 20,
rotation: self.rotation + Math.PI * 1.5,
scaleX: 0.95,
scaleY: 1.05
}, {
duration: 800,
easing: tween.easeOut,
onFinish: function onFinish() {
// Second stage: ball goes through net
tween(self, {
y: hoopY + 60,
x: hoopX + (Math.random() - 0.5) * 10,
rotation: self.rotation + Math.PI * 0.5,
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 400,
easing: tween.easeInOut,
onFinish: function onFinish() {
// Third stage: ball exits net and falls naturally
tween(self, {
y: hoopY + 100,
x: hoopX + (Math.random() - 0.5) * 15,
rotation: self.rotation + Math.PI * 0.3
}, {
duration: 300,
easing: tween.easeIn
});
}
});
// Animate net pulsate
tween(hoop.net, {
scaleX: 1.8,
scaleY: 1.8
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(hoop.net, {
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 200,
easing: tween.easeIn
});
}
});
// Score the basket
currentStreak++;
var points = 10 * currentStreak;
LK.setScore(LK.getScore() + points);
// Play swish sound
LK.getSound('swish').play();
// Update displays
scoreTxt.setText('Score: ' + LK.getScore());
streakTxt.setText('Streak: ' + currentStreak);
// Visual feedback
LK.effects.flashObject(hoop, 0x00FF00, 300);
}
});
}
}
// Ground collision removed - ball can fall through
// Remove if off screen
if (self.x < -100 || self.x > 2148 || self.y > 2800) {
self.isActive = false;
}
};
return self;
});
var Hoop = Container.expand(function () {
var self = Container.call(this);
var backboard = self.attachAsset('backboard', {
anchorX: 0.5,
anchorY: 1,
scaleX: 1.3,
scaleY: 1.3
});
backboard.y = -15;
var hoop = self.attachAsset('hoop', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.2,
scaleY: 1.2
});
hoop.y = -450;
// Set z-index to render in front of basketball
hoop.zIndex = 1;
var net = self.attachAsset('net', {
anchorX: 0.5,
anchorY: 0,
scaleX: 1.5,
scaleY: 1.5
});
net.y = -425;
net.alpha = 0.8;
// Set z-index to render in front of basketball
net.zIndex = 2;
// Store net reference for animation access
self.net = net;
self.hoopBounds = {
left: -108,
right: 108,
top: -24,
bottom: 24
};
// Enable z-index sorting for proper rendering order
self.sortableChildren = true;
return self;
});
var ShotBar = Container.expand(function () {
var self = Container.call(this);
// Background bar
var bgBar = self.attachAsset('shotBarBg', {
anchorX: 0.5,
anchorY: 0.5
});
// Green zone
var greenZone = self.attachAsset('shotBarGreen', {
anchorX: 0.5,
anchorY: 0.5
});
greenZone.x = 0; // Start at center, will move
// Moving basketball indicator
var indicator = self.attachAsset('basketball', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.6,
scaleY: 0.6
});
self.isActive = false;
self.isMoving = false;
self.moveDirection = 1; // 1 for right, -1 for left
self.moveSpeed = 8;
self.maxDistance = 240; // Half of bar width minus indicator size
self.perfectShot = false;
self.startMoving = function () {
self.isActive = true;
self.isMoving = true;
self.perfectShot = false;
// Position green zone randomly
greenZone.x = (Math.random() - 0.5) * 360; // Random position within bar
// Reset indicator position
indicator.x = -self.maxDistance;
self.moveDirection = 1;
self.visible = true;
};
self.stopMoving = function () {
self.isMoving = false;
// Check if indicator is within green zone
var greenLeft = greenZone.x - 60;
var greenRight = greenZone.x + 60;
self.perfectShot = indicator.x >= greenLeft && indicator.x <= greenRight;
// Hide shot bar after a short delay
var self_ref = self;
LK.setTimeout(function () {
self_ref.visible = false;
self_ref.isActive = false;
}, 200);
return self.perfectShot;
};
self.update = function () {
if (!self.isMoving) return;
// Move indicator back and forth
indicator.x += self.moveSpeed * self.moveDirection;
// Bounce off edges
if (indicator.x >= self.maxDistance) {
indicator.x = self.maxDistance;
self.moveDirection = -1;
} else if (indicator.x <= -self.maxDistance) {
indicator.x = -self.maxDistance;
self.moveDirection = 1;
}
};
self.visible = false;
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87CEEB
});
/****
* Game Code
****/
var basketballs = [];
var hoop = null;
var ground = null;
var scoreTxt = null;
var streakTxt = null;
var currentStreak = 0;
var swipeStartX = 0;
var swipeStartY = 0;
var swipeStartTime = 0;
var isSwipeStarted = false;
var lastShotTime = 0;
var musicNotes = ['note1', 'note2', 'note3', 'note4', 'note5'];
var currentNoteIndex = 0;
var shotBar = null;
var isChargingShot = false;
// Enable z-index sorting for proper rendering order
game.sortableChildren = true;
// Add background
var background = game.addChild(LK.getAsset('Background', {
anchorX: 0,
anchorY: 0
}));
background.x = 0;
background.y = 0;
// Set background to render behind everything
background.zIndex = -10;
// Ground removed - no longer needed
// Create hoop
hoop = game.addChild(new Hoop());
hoop.x = 1024;
hoop.y = 1370;
// Create score display
scoreTxt = new Text2('Score: 0', {
size: 80,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Create streak display
streakTxt = new Text2('Streak: 0', {
size: 60,
fill: 0xFFD700
});
streakTxt.anchor.set(0.5, 0);
streakTxt.y = 100;
LK.gui.top.addChild(streakTxt);
// Create shot bar
shotBar = game.addChild(new ShotBar());
shotBar.x = 1024;
shotBar.y = 2200;
function createBasketball(startX, startY, velocityX, velocityY) {
var ball = new Basketball();
ball.x = startX;
ball.y = startY;
ball.velocityX = velocityX;
ball.velocityY = velocityY;
ball.isPerfectShot = false;
basketballs.push(ball);
game.addChild(ball);
return ball;
}
function checkBasketScore(ball) {
// Scoring is now handled in Basketball class update method
// This function is kept for compatibility but does nothing
return;
}
game.down = function (x, y, obj) {
if (LK.ticks - lastShotTime < 60) return; // Prevent rapid firing
if (shotBar.isActive) {
// Stop the shot bar and check for perfect shot
var isPerfect = shotBar.stopMoving();
isChargingShot = false;
// Calculate shooting parameters
var startX = 1024;
var startY = 2500;
var velocityX = 0;
var velocityY = -22; // Base upward velocity - increased power to shoot 200 higher
// Force perfect shot if stopped in green zone
if (isPerfect || shotBar.perfectShot) {
// Perfect shot - direct trajectory to hoop center for guaranteed score
var targetX = hoop.x;
var targetY = hoop.y - 450; // Target the exact hoop scoring area
// Create perfect shot basketball
var ball = createBasketball(startX, startY, 0, -25);
ball.isPerfectShot = true;
ball.perfectShotTarget = {
x: targetX,
y: targetY
};
ball.perfectShotTime = 0;
ball.perfectShotDuration = 60; // Shorter, more direct time to reach hoop
// Visual feedback for perfect shot
LK.effects.flashScreen(0x00FF00, 200);
// Add tween animation to ensure ball goes straight in
tween(ball, {
tint: 0xFFD700
}, {
duration: 300,
onFinish: function onFinish() {
tween(ball, {
tint: 0xFFFFFF
}, {
duration: 300
});
}
});
// Add vertical rotation animation
tween(ball, {
rotation: ball.rotation + Math.PI * 4
}, {
duration: 1500,
easing: tween.easeOut
});
} else {
// Regular shot with some randomness
velocityX = (Math.random() - 0.5) * 8;
velocityY = -19 - Math.random() * 6; // Increased base power to shoot 200 higher
var ball = createBasketball(startX, startY, velocityX, velocityY);
// Add vertical rotation animation for regular shot
tween(ball, {
rotation: ball.rotation + Math.PI * 3
}, {
duration: 1200,
easing: tween.easeOut
});
}
lastShotTime = LK.ticks;
} else {
// Start charging shot
isChargingShot = true;
shotBar.startMoving();
swipeStartX = x;
swipeStartY = y;
swipeStartTime = LK.ticks;
}
};
game.up = function (x, y, obj) {
// Shot bar system handles shooting now, remove swipe-based shooting
};
game.update = function () {
// Update basketballs
for (var i = basketballs.length - 1; i >= 0; i--) {
var ball = basketballs[i];
if (!ball.isActive) {
ball.destroy();
basketballs.splice(i, 1);
continue;
}
// Check for scoring
checkBasketScore(ball);
// Check collision with other basketballs
for (var j = i + 1; j < basketballs.length; j++) {
var otherBall = basketballs[j];
if (!otherBall.isActive) continue;
var dx = ball.x - otherBall.x;
var dy = ball.y - otherBall.y;
var distance = Math.sqrt(dx * dx + dy * dy);
var minDistance = 180; // Combined radius of two basketballs (adjusted for bigger size)
if (distance < minDistance && distance > 0) {
// Calculate collision normal
var normalX = dx / distance;
var normalY = dy / distance;
// Separate balls to prevent overlap
var overlap = minDistance - distance;
var separationX = normalX * overlap * 0.5;
var separationY = normalY * overlap * 0.5;
ball.x += separationX;
ball.y += separationY;
otherBall.x -= separationX;
otherBall.y -= separationY;
// Calculate relative velocity
var relativeVelX = ball.velocityX - otherBall.velocityX;
var relativeVelY = ball.velocityY - otherBall.velocityY;
// Calculate relative velocity along collision normal
var relativeSpeed = relativeVelX * normalX + relativeVelY * normalY;
// Only resolve if objects are moving towards each other
if (relativeSpeed > 0) continue;
// Calculate impulse scalar (assuming equal mass)
var impulse = -2 * relativeSpeed / 2;
var impulseX = impulse * normalX;
var impulseY = impulse * normalY;
// Apply impulse with bounce decay
var bounceDecay = 0.8;
ball.velocityX += impulseX * bounceDecay;
ball.velocityY += impulseY * bounceDecay;
otherBall.velocityX -= impulseX * bounceDecay;
otherBall.velocityY -= impulseY * bounceDecay;
// Play bounce sound
LK.getSound('bounce').play();
}
}
}
// Reset streak if no balls scored recently
if (basketballs.length === 0 && LK.ticks - lastShotTime > 180) {
if (currentStreak > 0) {
currentStreak = 0;
streakTxt.setText('Streak: 0');
currentNoteIndex = 0; // Reset musical progression
}
}
// Check win condition
if (LK.getScore() >= 500) {
LK.showYouWin();
}
};
// Start background music
LK.playMusic('backgroundMusic');
Make picture high definition
Remove everything but net
Remove basketball rings and backboards from picture
Shiny black rectangle frame. In-Game asset. 2d. High contrast. No shadows
Neon green basketball. In-Game asset. 2d. High contrast. No shadows
Change to black warriors uniform
Change to black warriors uniform
Padlock button that says *locked* Purchase for: $100. In-Game asset. 2d. High contrast. No shadows
Remove words "with basketball"
Number 1
Number 2
Number 3
Number 4
Number 5
Number 6
Number 7
Number 8
Make it say $HOP in big letters across the ball
Change it to say Rhythm
Make a shop backdrop with display shelves and framed areas to place items
Remove ball and put his hands down like he just caught a pass
Remove ball and fix hands
Record. In-Game asset. 2d. High contrast. No shadows
Make the net look like it's on fire
1
Sound effect
2
Sound effect
3
Sound effect
swish
Sound effect
bounce
Sound effect
backgroundMusic
Music
Makeaswish
Sound effect
Title
Music
Second
Music
Third
Music
Fourth
Music
Cash
Sound effect
Hypersonic
Music
swim
Music
Sunrise
Music
Onfire
Sound effect
Speedup
Sound effect