User prompt
It is still too heavy
User prompt
Make the ball more easier to throw
User prompt
The basketball is too heavy, make it easier to throw
User prompt
Generate the first version of the source code for the game Basketball Hoop Shpt ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Basketball Hoop Shot
Initial prompt
A game where you aim a basketball and try to shoot into the hoop
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ var Basketball = Container.expand(function () { var self = Container.call(this); // Visual components var ball = self.attachAsset('basketball', { anchorX: 0.5, anchorY: 0.5 }); var lines = self.attachAsset('basketballLines', { anchorX: 0.5, anchorY: 0.5, alpha: 0.3 }); // Physics properties self.velocityX = 0; self.velocityY = 0; self.gravity = 0.5; self.bounce = 0.7; self.isMoving = false; self.hasScored = false; self.hasThroughNet = false; // Initialize last positions for collision detection self.lastX = 0; self.lastY = 0; self.update = function () { if (self.isMoving) { // Store last position self.lastX = self.x; self.lastY = self.y; // Apply physics self.velocityY += self.gravity; self.x += self.velocityX; self.y += self.velocityY; // Rotate ball based on movement ball.rotation += self.velocityX * 0.02; // Check boundaries if (self.x < 40 || self.x > 2008) { self.velocityX *= -self.bounce; self.x = self.x < 40 ? 40 : 2008; } if (self.y < 40) { self.y = 40; self.velocityY *= -self.bounce; } if (self.y > 2692) { self.y = 2692; self.velocityY *= -self.bounce; self.velocityX *= 0.9; // Friction if (Math.abs(self.velocityY) < 2) { self.isMoving = false; self.velocityX = 0; self.velocityY = 0; } } } }; self.shoot = function (powerX, powerY) { self.velocityX = powerX; self.velocityY = powerY; self.isMoving = true; self.hasScored = false; self.hasThroughNet = false; LK.getSound('shoot').play(); }; self.reset = function () { self.x = 1024; self.y = 2400; self.velocityX = 0; self.velocityY = 0; self.isMoving = false; self.hasScored = false; self.hasThroughNet = false; ball.rotation = 0; }; return self; }); var Coin = Container.expand(function () { var self = Container.call(this); // Visual component var coinGraphics = self.attachAsset('coin', { anchorX: 0.5, anchorY: 0.5 }); // Properties self.hasBeenHit = false; self.lastX = 0; self.lastY = 0; self.update = function () { // Store last position for collision detection self.lastX = self.x; self.lastY = self.y; }; self.startFloating = function () { // Create continuous sine wave floating animation var floatUp = function floatUp() { tween(self, { y: self.y - 20 }, { duration: 2000, easing: tween.easeInOut, onFinish: floatDown }); }; var floatDown = function floatDown() { tween(self, { y: self.y + 20 }, { duration: 2000, easing: tween.easeInOut, onFinish: floatUp }); }; floatUp(); }; self.checkCollision = function (ball) { // Check if ball intersects with coin if (ball.intersects(self) && !self.hasBeenHit) { self.hasBeenHit = true; // Play coin collect sound LK.getSound('coinCollect').play(); // Animate coin collection tween(self, { scaleX: 0, scaleY: 0, alpha: 0 }, { duration: 300, easing: tween.easeOut }); return true; } return false; }; self.moveToNewPosition = function () { // Move to new random position var newX = 200 + Math.random() * 1648; // Random X between 200 and 1848 var newY = 400 + Math.random() * 1200; // Random Y between 400 and 1600 self.x = newX; self.y = newY; self.hasBeenHit = false; self.scaleX = 1; self.scaleY = 1; self.alpha = 1; // Start floating animation self.startFloating(); }; return self; }); var Hoop = Container.expand(function () { var self = Container.call(this); // Backboard var backboard = self.attachAsset('backboard', { anchorX: 0.5, anchorY: 0.5, x: 100, y: 0 }); // Hoop rim var rim = self.attachAsset('hoop', { anchorX: 0.5, anchorY: 0.5, y: 50 }); // Net var net = self.attachAsset('net', { anchorX: 0.5, anchorY: 0, y: 70, alpha: 0.6 }); // Scoring zone (invisible) self.scoringZone = { x: -90, y: 45, width: 180, height: 30 }; self.checkScore = function (ball) { // Define scoring zone boundaries var zoneLeft = self.x + self.scoringZone.x; var zoneRight = self.x + self.scoringZone.x + self.scoringZone.width; var zoneTop = self.y + self.scoringZone.y; var zoneBottom = self.y + self.scoringZone.y + self.scoringZone.height; // Check if ball is currently in zone var ballInZone = ball.x >= zoneLeft && ball.x <= zoneRight && ball.y >= zoneTop && ball.y <= zoneBottom; // Check if ball's trajectory crossed through the scoring zone from above var crossedFromAbove = false; if (ball.lastY < zoneTop && ball.y >= zoneTop && ball.velocityY > 0) { // Calculate where the ball was when it crossed the top of the zone var timeToZone = (zoneTop - ball.lastY) / (ball.y - ball.lastY); var crossX = ball.lastX + (ball.x - ball.lastX) * timeToZone; // Check if the crossing point is within the horizontal bounds if (crossX >= zoneLeft && crossX <= zoneRight) { crossedFromAbove = true; } } // Score if ball crossed from above or is in zone moving downward if ((ballInZone || crossedFromAbove) && ball.velocityY > 0 && !ball.hasScored) { ball.hasThroughNet = true; ball.hasScored = true; // Make ball bounce out of the net ball.velocityY = -Math.abs(ball.velocityY) * 0.3; // Reverse and reduce Y velocity ball.velocityX *= 0.7; // Reduce X velocity slightly // Animate net tween(net, { scaleY: 1.2 }, { duration: 200, onFinish: function onFinish() { tween(net, { scaleY: 1 }, { duration: 200 }); } }); LK.getSound('score').play(); return true; } return false; }; return self; }); /**** * Initialize Game ****/ // Game variables var game = new LK.Game({ backgroundColor: 0x87CEEB // Sky blue background }); /**** * Game Code ****/ //Minimalistic tween library for animations // Sounds // Trajectory line // Hoop assets // Basketball assets // Game variables var basketball = null; var hoop = null; var isDragging = false; var dragStartX = 0; var dragStartY = 0; var aimArrow = null; var score = 0; var scoreTxt = null; var hasJustScored = false; var coins = []; var numCoins = 3; var shots = 10; var shotsTxt = null; // Add single background var background = game.addChild(LK.getAsset('background', { anchorX: 0, anchorY: 0, x: 0, y: 0 })); // Initialize game elements basketball = game.addChild(new Basketball()); basketball.reset(); hoop = game.addChild(new Hoop()); hoop.x = 1024; hoop.y = 800; // Score display scoreTxt = new Text2('Score: 0', { size: 80, fill: 0xFFFFFF }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); // Shots counter display shotsTxt = new Text2('Shots: 10', { size: 80, fill: 0xFFFFFF }); shotsTxt.anchor.set(0.5, 0); shotsTxt.x = 0; shotsTxt.y = 100; LK.gui.top.addChild(shotsTxt); // Aim arrow aimArrow = game.addChild(LK.getAsset('aimArrow', { anchorX: 0.5, anchorY: 0.5, alpha: 0 })); // Initialize coins for (var i = 0; i < numCoins; i++) { var coin = game.addChild(new Coin()); coin.moveToNewPosition(); coins.push(coin); } function updateAimLine(startX, startY, endX, endY) { var deltaX = endX - startX; var deltaY = endY - startY; var distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY); // Position arrow at finger position (slightly below finger for visibility) aimArrow.x = endX; aimArrow.y = endY + 60; // Rotate arrow to point in shooting direction (opposite of drag direction) aimArrow.rotation = Math.atan2(deltaY, deltaX); // Show arrow when dragging aimArrow.alpha = isDragging ? 0.8 : 0; } function hideAimLine() { aimArrow.alpha = 0; } // Game input handling game.down = function (x, y, obj) { if (!basketball.isMoving) { // Check if touch is near basketball var dx = x - basketball.x; var dy = y - basketball.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < 100) { isDragging = true; dragStartX = x; dragStartY = y; } } }; game.move = function (x, y, obj) { if (isDragging) { updateAimLine(basketball.x, basketball.y, x, y); } }; game.up = function (x, y, obj) { if (isDragging) { isDragging = false; hideAimLine(); // Calculate shooting power based on drag distance var deltaX = x - dragStartX; var deltaY = y - dragStartY; var distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY); var powerMultiplier = Math.min(distance / 100, 1) * 28.8; var powerX = deltaX * powerMultiplier; var powerY = deltaY * powerMultiplier; // Limit power var maxPower = 90; var power = Math.sqrt(powerX * powerX + powerY * powerY); if (power > maxPower) { powerX = powerX / power * maxPower; powerY = powerY / power * maxPower; } basketball.shoot(powerX, powerY); // Decrease shots counter shots--; shotsTxt.setText('Shots: ' + shots); } }; // Main game loop game.update = function () { // Check for scoring if (basketball.isMoving && hoop.checkScore(basketball)) { score += 5; scoreTxt.setText('Score: ' + score); LK.setScore(score); hasJustScored = true; } // Check coin collisions for (var i = 0; i < coins.length; i++) { if (coins[i].checkCollision(basketball)) { score += 3; scoreTxt.setText('Score: ' + score); LK.setScore(score); } } // Reset ball if it goes off screen or stops moving if (!basketball.isMoving && (basketball.y > 2500 || basketball.x < -100 || basketball.x > 2148)) { LK.setTimeout(function () { basketball.reset(); // Teleport hoop, net, and backboard to a new random position when ball resets after scoring if (hasJustScored) { var newX = 300 + Math.random() * 1448; // Random X between 300 and 1748 var newY = 600 + Math.random() * 400; // Random Y between 600 and 1000 hoop.x = newX; hoop.y = newY; // Move all coins to new positions for (var i = 0; i < coins.length; i++) { coins[i].moveToNewPosition(); } hasJustScored = false; // Reset the flag } // Check for game over after ball reset if (shots <= 0) { LK.showGameOver(); } }, 1000); } };
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Basketball = Container.expand(function () {
var self = Container.call(this);
// Visual components
var ball = self.attachAsset('basketball', {
anchorX: 0.5,
anchorY: 0.5
});
var lines = self.attachAsset('basketballLines', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.3
});
// Physics properties
self.velocityX = 0;
self.velocityY = 0;
self.gravity = 0.5;
self.bounce = 0.7;
self.isMoving = false;
self.hasScored = false;
self.hasThroughNet = false;
// Initialize last positions for collision detection
self.lastX = 0;
self.lastY = 0;
self.update = function () {
if (self.isMoving) {
// Store last position
self.lastX = self.x;
self.lastY = self.y;
// Apply physics
self.velocityY += self.gravity;
self.x += self.velocityX;
self.y += self.velocityY;
// Rotate ball based on movement
ball.rotation += self.velocityX * 0.02;
// Check boundaries
if (self.x < 40 || self.x > 2008) {
self.velocityX *= -self.bounce;
self.x = self.x < 40 ? 40 : 2008;
}
if (self.y < 40) {
self.y = 40;
self.velocityY *= -self.bounce;
}
if (self.y > 2692) {
self.y = 2692;
self.velocityY *= -self.bounce;
self.velocityX *= 0.9; // Friction
if (Math.abs(self.velocityY) < 2) {
self.isMoving = false;
self.velocityX = 0;
self.velocityY = 0;
}
}
}
};
self.shoot = function (powerX, powerY) {
self.velocityX = powerX;
self.velocityY = powerY;
self.isMoving = true;
self.hasScored = false;
self.hasThroughNet = false;
LK.getSound('shoot').play();
};
self.reset = function () {
self.x = 1024;
self.y = 2400;
self.velocityX = 0;
self.velocityY = 0;
self.isMoving = false;
self.hasScored = false;
self.hasThroughNet = false;
ball.rotation = 0;
};
return self;
});
var Coin = Container.expand(function () {
var self = Container.call(this);
// Visual component
var coinGraphics = self.attachAsset('coin', {
anchorX: 0.5,
anchorY: 0.5
});
// Properties
self.hasBeenHit = false;
self.lastX = 0;
self.lastY = 0;
self.update = function () {
// Store last position for collision detection
self.lastX = self.x;
self.lastY = self.y;
};
self.startFloating = function () {
// Create continuous sine wave floating animation
var floatUp = function floatUp() {
tween(self, {
y: self.y - 20
}, {
duration: 2000,
easing: tween.easeInOut,
onFinish: floatDown
});
};
var floatDown = function floatDown() {
tween(self, {
y: self.y + 20
}, {
duration: 2000,
easing: tween.easeInOut,
onFinish: floatUp
});
};
floatUp();
};
self.checkCollision = function (ball) {
// Check if ball intersects with coin
if (ball.intersects(self) && !self.hasBeenHit) {
self.hasBeenHit = true;
// Play coin collect sound
LK.getSound('coinCollect').play();
// Animate coin collection
tween(self, {
scaleX: 0,
scaleY: 0,
alpha: 0
}, {
duration: 300,
easing: tween.easeOut
});
return true;
}
return false;
};
self.moveToNewPosition = function () {
// Move to new random position
var newX = 200 + Math.random() * 1648; // Random X between 200 and 1848
var newY = 400 + Math.random() * 1200; // Random Y between 400 and 1600
self.x = newX;
self.y = newY;
self.hasBeenHit = false;
self.scaleX = 1;
self.scaleY = 1;
self.alpha = 1;
// Start floating animation
self.startFloating();
};
return self;
});
var Hoop = Container.expand(function () {
var self = Container.call(this);
// Backboard
var backboard = self.attachAsset('backboard', {
anchorX: 0.5,
anchorY: 0.5,
x: 100,
y: 0
});
// Hoop rim
var rim = self.attachAsset('hoop', {
anchorX: 0.5,
anchorY: 0.5,
y: 50
});
// Net
var net = self.attachAsset('net', {
anchorX: 0.5,
anchorY: 0,
y: 70,
alpha: 0.6
});
// Scoring zone (invisible)
self.scoringZone = {
x: -90,
y: 45,
width: 180,
height: 30
};
self.checkScore = function (ball) {
// Define scoring zone boundaries
var zoneLeft = self.x + self.scoringZone.x;
var zoneRight = self.x + self.scoringZone.x + self.scoringZone.width;
var zoneTop = self.y + self.scoringZone.y;
var zoneBottom = self.y + self.scoringZone.y + self.scoringZone.height;
// Check if ball is currently in zone
var ballInZone = ball.x >= zoneLeft && ball.x <= zoneRight && ball.y >= zoneTop && ball.y <= zoneBottom;
// Check if ball's trajectory crossed through the scoring zone from above
var crossedFromAbove = false;
if (ball.lastY < zoneTop && ball.y >= zoneTop && ball.velocityY > 0) {
// Calculate where the ball was when it crossed the top of the zone
var timeToZone = (zoneTop - ball.lastY) / (ball.y - ball.lastY);
var crossX = ball.lastX + (ball.x - ball.lastX) * timeToZone;
// Check if the crossing point is within the horizontal bounds
if (crossX >= zoneLeft && crossX <= zoneRight) {
crossedFromAbove = true;
}
}
// Score if ball crossed from above or is in zone moving downward
if ((ballInZone || crossedFromAbove) && ball.velocityY > 0 && !ball.hasScored) {
ball.hasThroughNet = true;
ball.hasScored = true;
// Make ball bounce out of the net
ball.velocityY = -Math.abs(ball.velocityY) * 0.3; // Reverse and reduce Y velocity
ball.velocityX *= 0.7; // Reduce X velocity slightly
// Animate net
tween(net, {
scaleY: 1.2
}, {
duration: 200,
onFinish: function onFinish() {
tween(net, {
scaleY: 1
}, {
duration: 200
});
}
});
LK.getSound('score').play();
return true;
}
return false;
};
return self;
});
/****
* Initialize Game
****/
// Game variables
var game = new LK.Game({
backgroundColor: 0x87CEEB // Sky blue background
});
/****
* Game Code
****/
//Minimalistic tween library for animations
// Sounds
// Trajectory line
// Hoop assets
// Basketball assets
// Game variables
var basketball = null;
var hoop = null;
var isDragging = false;
var dragStartX = 0;
var dragStartY = 0;
var aimArrow = null;
var score = 0;
var scoreTxt = null;
var hasJustScored = false;
var coins = [];
var numCoins = 3;
var shots = 10;
var shotsTxt = null;
// Add single background
var background = game.addChild(LK.getAsset('background', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0
}));
// Initialize game elements
basketball = game.addChild(new Basketball());
basketball.reset();
hoop = game.addChild(new Hoop());
hoop.x = 1024;
hoop.y = 800;
// Score display
scoreTxt = new Text2('Score: 0', {
size: 80,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Shots counter display
shotsTxt = new Text2('Shots: 10', {
size: 80,
fill: 0xFFFFFF
});
shotsTxt.anchor.set(0.5, 0);
shotsTxt.x = 0;
shotsTxt.y = 100;
LK.gui.top.addChild(shotsTxt);
// Aim arrow
aimArrow = game.addChild(LK.getAsset('aimArrow', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0
}));
// Initialize coins
for (var i = 0; i < numCoins; i++) {
var coin = game.addChild(new Coin());
coin.moveToNewPosition();
coins.push(coin);
}
function updateAimLine(startX, startY, endX, endY) {
var deltaX = endX - startX;
var deltaY = endY - startY;
var distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
// Position arrow at finger position (slightly below finger for visibility)
aimArrow.x = endX;
aimArrow.y = endY + 60;
// Rotate arrow to point in shooting direction (opposite of drag direction)
aimArrow.rotation = Math.atan2(deltaY, deltaX);
// Show arrow when dragging
aimArrow.alpha = isDragging ? 0.8 : 0;
}
function hideAimLine() {
aimArrow.alpha = 0;
}
// Game input handling
game.down = function (x, y, obj) {
if (!basketball.isMoving) {
// Check if touch is near basketball
var dx = x - basketball.x;
var dy = y - basketball.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 100) {
isDragging = true;
dragStartX = x;
dragStartY = y;
}
}
};
game.move = function (x, y, obj) {
if (isDragging) {
updateAimLine(basketball.x, basketball.y, x, y);
}
};
game.up = function (x, y, obj) {
if (isDragging) {
isDragging = false;
hideAimLine();
// Calculate shooting power based on drag distance
var deltaX = x - dragStartX;
var deltaY = y - dragStartY;
var distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
var powerMultiplier = Math.min(distance / 100, 1) * 28.8;
var powerX = deltaX * powerMultiplier;
var powerY = deltaY * powerMultiplier;
// Limit power
var maxPower = 90;
var power = Math.sqrt(powerX * powerX + powerY * powerY);
if (power > maxPower) {
powerX = powerX / power * maxPower;
powerY = powerY / power * maxPower;
}
basketball.shoot(powerX, powerY);
// Decrease shots counter
shots--;
shotsTxt.setText('Shots: ' + shots);
}
};
// Main game loop
game.update = function () {
// Check for scoring
if (basketball.isMoving && hoop.checkScore(basketball)) {
score += 5;
scoreTxt.setText('Score: ' + score);
LK.setScore(score);
hasJustScored = true;
}
// Check coin collisions
for (var i = 0; i < coins.length; i++) {
if (coins[i].checkCollision(basketball)) {
score += 3;
scoreTxt.setText('Score: ' + score);
LK.setScore(score);
}
}
// Reset ball if it goes off screen or stops moving
if (!basketball.isMoving && (basketball.y > 2500 || basketball.x < -100 || basketball.x > 2148)) {
LK.setTimeout(function () {
basketball.reset();
// Teleport hoop, net, and backboard to a new random position when ball resets after scoring
if (hasJustScored) {
var newX = 300 + Math.random() * 1448; // Random X between 300 and 1748
var newY = 600 + Math.random() * 400; // Random Y between 600 and 1000
hoop.x = newX;
hoop.y = newY;
// Move all coins to new positions
for (var i = 0; i < coins.length; i++) {
coins[i].moveToNewPosition();
}
hasJustScored = false; // Reset the flag
}
// Check for game over after ball reset
if (shots <= 0) {
LK.showGameOver();
}
}, 1000);
}
};
Basketball 2d 2d facing the front of the camera In-Game asset. 2d. High contrast.
Silver coin. In-Game asset. 2d. High contrast. No shadows
Basketball net. Just the net not the hoop side view 2d 2d side view just the not the hoop or backboard In-Game asset. 2d. High contrast. No shadows
Black arrow pointing up. In-Game asset. 2d. High contrast. No shadows