/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1", { currentLevel: 1, highScores: {} }); /**** * Classes ****/ var AimLine = Container.expand(function () { var self = Container.call(this); var line = self.attachAsset('aimLine', { anchorX: 0.5, anchorY: 1, alpha: 0.7 }); self.setAngle = function (degrees) { line.rotation = degrees * (Math.PI / 180); }; self.setLength = function (length) { line.height = length; }; self.hide = function () { self.visible = false; }; self.show = function () { self.visible = true; }; return self; }); var Ball = Container.expand(function () { var self = Container.call(this); var ballGraphic = self.attachAsset('ball', { anchorX: 0.5, anchorY: 0.5 }); self.velocity = { x: 0, y: 0 }; self.moving = false; self.bounceCount = 0; self.friction = 0.98; self.bounceFactor = 1.1; self.maxSpeed = 50; self.launch = function (power, angle) { // Convert angle from degrees to radians var radians = angle * (Math.PI / 180); // Set velocity based on power and angle self.velocity.x = Math.cos(radians) * power * 0.3; self.velocity.y = Math.sin(radians) * power * 0.3; // Clamp velocity to max speed var speed = Math.sqrt(self.velocity.x * self.velocity.x + self.velocity.y * self.velocity.y); if (speed > self.maxSpeed) { var ratio = self.maxSpeed / speed; self.velocity.x *= ratio; self.velocity.y *= ratio; } self.moving = true; self.bounceCount = 0; LK.getSound('launch').play(); }; self.update = function () { if (!self.moving) { return; } // Apply physics self.x += self.velocity.x; self.y += self.velocity.y; // Apply friction self.velocity.x *= self.friction; self.velocity.y *= self.friction; // Check if ball has stopped if (Math.abs(self.velocity.x) < 0.1 && Math.abs(self.velocity.y) < 0.1) { self.velocity.x = 0; self.velocity.y = 0; self.moving = false; } // Check boundaries var halfWidth = ballGraphic.width / 2; var halfHeight = ballGraphic.height / 2; if (self.x < halfWidth) { self.x = halfWidth; self.velocity.x = -self.velocity.x * self.bounceFactor; self.bounceWall(); } else if (self.x > 2048 - halfWidth) { self.x = 2048 - halfWidth; self.velocity.x = -self.velocity.x * self.bounceFactor; self.bounceWall(); } if (self.y < halfHeight) { self.y = halfHeight; self.velocity.y = -self.velocity.y * self.bounceFactor; self.bounceWall(); } else if (self.y > 2732 - halfHeight) { self.y = 2732 - halfHeight; self.velocity.y = -self.velocity.y * self.bounceFactor; self.bounceWall(); } }; self.bounceWall = function () { self.bounceCount++; LK.getSound('bounce').play(); }; self.bounceOffWall = function (wall) { // Calculate the center of the wall var wallCenterX = wall.x; var wallCenterY = wall.y; // Calculate the normal vector from the wall var dx = self.x - wallCenterX; var dy = self.y - wallCenterY; // Determine if collision is mainly horizontal or vertical based on wall dimensions if (Math.abs(dx) > Math.abs(dy)) { // Horizontal collision, bounce horizontally self.velocity.x = -self.velocity.x * self.bounceFactor; // Reposition to avoid sticking if (self.x < wallCenterX) { self.x = wallCenterX - wall.width / 2 - ballGraphic.width / 2; } else { self.x = wallCenterX + wall.width / 2 + ballGraphic.width / 2; } } else { // Vertical collision, bounce vertically self.velocity.y = -self.velocity.y * self.bounceFactor; // Reposition to avoid sticking if (self.y < wallCenterY) { self.y = wallCenterY - wall.height / 2 - ballGraphic.height / 2; } else { self.y = wallCenterY + wall.height / 2 + ballGraphic.height / 2; } } self.bounceWall(); }; return self; }); var LevelManager = Container.expand(function () { var self = Container.call(this); self.currentLevel = storage.currentLevel || 1; self.levels = []; self.initializeLevels = function () { // Level 1 - Simple intro level self.levels.push({ ballStart: { x: 1024, y: 1366 }, targets: Array.from({ length: 50 }, function () { return { x: Math.random() * 2048, y: Math.random() * 1366 }; }), walls: Array.from({ length: 5 }, function () { return { x: Math.random() * 2048, y: Math.random() * 2732 }; }) }); }; self.getCurrentLevel = function () { return self.levels[self.currentLevel - 1] || self.levels[0]; }; self.advanceLevel = function () { if (self.currentLevel < self.levels.length) { self.currentLevel++; storage.currentLevel = self.currentLevel; return true; } return false; }; self.resetLevel = function () { // Just reset the current level (no change in level number) }; self.saveScore = function (level, shots) { var currentHighScore = storage.highScores[level] || 999; if (shots < currentHighScore) { storage.highScores[level] = shots; } }; self.getHighScore = function (level) { return storage.highScores[level] || "-"; }; return self; }); var MovingWall = Container.expand(function () { var self = Container.call(this); var wallGraphic = self.attachAsset('wall', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 20; // Super speed for walls self.direction = 1; // 1 for right, -1 for left self.update = function () { self.x += self.speed * self.direction; if (self.x > 2048 - wallGraphic.width / 2 || self.x < wallGraphic.width / 2) { self.direction *= -1; // Reverse direction } }; return self; }); var PowerMeter = Container.expand(function () { var self = Container.call(this); var background = self.attachAsset('powerMeter', { anchorX: 0.5, anchorY: 1, alpha: 0.3 }); var meter = self.attachAsset('powerMeter', { anchorX: 0.5, anchorY: 1, tint: 0xFF3333 }); self.power = 0; self.maxPower = 100; meter.height = 0; self.setPower = function (percent) { self.power = Math.max(0, Math.min(100, percent)); meter.height = self.power / 100 * background.height; // Change color based on power if (self.power < 33) { meter.tint = 0x33FF33; // Green for low power } else if (self.power < 66) { meter.tint = 0xFFFF33; // Yellow for medium power } else { meter.tint = 0xFF3333; // Red for high power } }; self.hide = function () { self.visible = false; }; self.show = function () { self.visible = true; }; return self; }); var Target = Container.expand(function () { var self = Container.call(this); var targetGraphic = self.attachAsset('target', { anchorX: 0.5, anchorY: 0.5 }); self.active = true; self.hit = false; self.update = function () { // This would be where we'd add movement or animation if needed if (self.x < targetGraphic.width / 2 || self.x > 2048 - targetGraphic.width / 2) { self.velocity.x = -self.velocity.x; } if (self.y < targetGraphic.height / 2 || self.y > 1366 - targetGraphic.height / 2) { self.velocity.y = -self.velocity.y; } self.x += self.velocity.x; self.y += self.velocity.y; }; self.onHit = function () { if (!self.hit && self.active) { self.hit = true; LK.getSound('hitTarget').play(); // Visual feedback tween(targetGraphic, { alpha: 0.3, scaleX: 0.7, scaleY: 0.7 }, { duration: 300, easing: tween.easeOut }); return true; } return false; }; self.reset = function () { self.hit = false; targetGraphic.alpha = 1; tween(targetGraphic, { scaleX: 1, scaleY: 1 }, { duration: 300, easing: tween.bounceOut }); }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x000000 }); /**** * Game Code ****/ var maxShots = 15; // Set the maximum number of shots allowed per level var gameActive = false; var isDragging = false; var startX, startY; var shotsUsed = 0; var targetsHit = 0; var totalTargets = 0; // Create UI elements var scoreText = new Text2('Shots: 0', { size: 50, fill: 0xFFFFFF }); scoreText.anchor.set(0.5, 0); scoreText.x = 1800; scoreText.y = 50; game.addChild(scoreText); // Create UI elements var instructionText = new Text2('', { size: 50, fill: 0xFFFFFF }); instructionText.anchor.set(0.5, 0); instructionText.x = 1024; instructionText.y = 100; game.addChild(instructionText); // Initialize targetsHitDisplay var targetsHitDisplay = new Text2('Targets Hit: 0', { size: 50, fill: 0xFFFFFF }); targetsHitDisplay.anchor.set(0.5, 0); targetsHitDisplay.x = 1800; targetsHitDisplay.y = 100; game.addChild(targetsHitDisplay); var levelManager = new LevelManager(); levelManager.initializeLevels(); var ball = new Ball(); var aimLine = new AimLine(); var powerMeter = new PowerMeter(); var targets = []; // Initialize level function initializeLevel() { // Clear old objects for (var i = targets.length - 1; i >= 0; i--) { game.removeChild(targets[i]); } targets = []; // Get current level data var currentLevel = levelManager.getCurrentLevel(); // Set ball position ball.x = currentLevel.ballStart.x; ball.y = currentLevel.ballStart.y; ball.velocity = { x: 0, y: 0 }; ball.moving = false; // Create targets totalTargets = currentLevel.targets.length; for (var i = 0; i < currentLevel.targets.length; i++) { var targetData = currentLevel.targets[i]; var target = new Target(); // Randomize target position on the upper half of the screen target.x = Math.random() * 2048; target.y = Math.random() * (1366 - target.height / 2); target.reset(); target.velocity = { x: (Math.random() - 0.5) * 20, // Increased horizontal velocity y: (Math.random() - 0.5) * 20 // Increased vertical velocity }; targets.push(target); game.addChild(target); } // Create moving walls for (var i = 0; i < currentLevel.walls.length; i++) { var wallData = currentLevel.walls[i]; var movingWall = new MovingWall(); movingWall.x = wallData.x; movingWall.y = wallData.y; game.addChild(movingWall); } // Set up aiming tools aimLine.x = ball.x; aimLine.y = ball.y; aimLine.hide(); game.addChild(aimLine); powerMeter.x = 100; powerMeter.y = 2600; powerMeter.setPower(0); powerMeter.hide(); game.addChild(powerMeter); // Reset game state shotsUsed = 0; targetsHit = 0; gameActive = true; var maxShots = 15; // Set the maximum number of shots allowed per level // Update UI scoreText.setText('Shots: ' + shotsUsed); var highScore = levelManager.getHighScore(levelManager.currentLevel); instructionText.setText('Best: ' + (highScore === 999 ? "-" : highScore) + ' shots - Swipe to launch'); } // Add ball to game game.addChild(ball); // Start the first level initializeLevel(); // Play background music LK.playMusic('gameMusic', { volume: 0.5 }); // Event handlers function handleDown(x, y, obj) { if (!gameActive || ball.moving) { return; } startX = x; startY = y; isDragging = true; aimLine.x = ball.x; aimLine.y = ball.y; aimLine.show(); powerMeter.show(); powerMeter.setPower(0); } function handleMove(x, y, obj) { if (!isDragging) { return; } // Calculate angle and power var dx = x - startX; var dy = y - startY; var distance = Math.sqrt(dx * dx + dy * dy); var power = Math.min(100, distance / 10); var angle = Math.atan2(-dy, -dx) * (180 / Math.PI); // Update visual aids aimLine.setAngle(angle); aimLine.setLength(distance); powerMeter.setPower(power); } function handleUp(x, y, obj) { if (!isDragging) { return; } isDragging = false; aimLine.hide(); powerMeter.hide(); if (!gameActive || ball.moving) { return; } // Calculate launch parameters var dx = x - startX; var dy = y - startY; var distance = Math.sqrt(dx * dx + dy * dy); // Only launch if the swipe was long enough if (distance > 20) { var power = Math.min(100, distance / 10); var angle = Math.atan2(-dy, -dx) * (180 / Math.PI); // Launch the ball ball.launch(power, angle); shotsUsed++; // Update UI var currentLevel = levelManager.getCurrentLevel(); scoreText.setText('Shots: ' + shotsUsed); } } // Attach event handlers game.down = handleDown; game.move = handleMove; game.up = handleUp; // Main update loop game.update = function () { // Check for level completion if (gameActive && targetsHit === totalTargets) { // Level completed gameActive = false; levelManager.saveScore(levelManager.currentLevel, shotsUsed); // Show level complete message var completeText = new Text2('Level Complete!', { size: 120, fill: 0xFFFF00 }); completeText.anchor.set(0.5, 0.5); completeText.x = 1024; completeText.y = 1366; game.addChild(completeText); // Play level complete sound LK.getSound('levelComplete').play(); // Flash screen for effect LK.effects.flashScreen(0x33FF33, 1000); // End game after delay LK.setTimeout(function () { game.removeChild(completeText); // Game complete var gameCompleteText = new Text2('Game Complete!\nCongratulations!', { size: 100, fill: 0xFFFF00 }); gameCompleteText.anchor.set(0.5, 0.5); gameCompleteText.x = 1024; gameCompleteText.y = 1366; game.addChild(gameCompleteText); // Show you win screen LK.showYouWin(); }, 2000); } // Removed level failure check based on shot limit // Update all game objects if (ball.moving) { ball.update(); // Check for collisions with targets var _loop = function _loop() { if (!targets[i].hit && targets[i].intersects(ball)) { if (targets[i].onHit()) { var updateScoreDisplay = function updateScoreDisplay(targetsHit) { scoreText.setText('Targets Hit: ' + targetsHit); }; targetsHit++; updateScoreDisplay(targetsHit); // Update score display targetsHitDisplay.setText('Targets Hit: ' + targetsHit); // Update targets hit display } } }; for (var i = 0; i < targets.length; i++) { _loop(); } // Check for collisions with moving walls for (var i = 0; i < game.children.length; i++) { if (game.children[i] instanceof MovingWall) { if (ball.intersects(game.children[i])) { ball.bounceOffWall(game.children[i]); } } } } // Update targets (for any that have movement) for (var i = 0; i < targets.length; i++) { targets[i].update(); } // Update moving walls for (var i = 0; i < game.children.length; i++) { if (game.children[i] instanceof MovingWall) { game.children[i].update(); } } };
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
currentLevel: 1,
highScores: {}
});
/****
* Classes
****/
var AimLine = Container.expand(function () {
var self = Container.call(this);
var line = self.attachAsset('aimLine', {
anchorX: 0.5,
anchorY: 1,
alpha: 0.7
});
self.setAngle = function (degrees) {
line.rotation = degrees * (Math.PI / 180);
};
self.setLength = function (length) {
line.height = length;
};
self.hide = function () {
self.visible = false;
};
self.show = function () {
self.visible = true;
};
return self;
});
var Ball = Container.expand(function () {
var self = Container.call(this);
var ballGraphic = self.attachAsset('ball', {
anchorX: 0.5,
anchorY: 0.5
});
self.velocity = {
x: 0,
y: 0
};
self.moving = false;
self.bounceCount = 0;
self.friction = 0.98;
self.bounceFactor = 1.1;
self.maxSpeed = 50;
self.launch = function (power, angle) {
// Convert angle from degrees to radians
var radians = angle * (Math.PI / 180);
// Set velocity based on power and angle
self.velocity.x = Math.cos(radians) * power * 0.3;
self.velocity.y = Math.sin(radians) * power * 0.3;
// Clamp velocity to max speed
var speed = Math.sqrt(self.velocity.x * self.velocity.x + self.velocity.y * self.velocity.y);
if (speed > self.maxSpeed) {
var ratio = self.maxSpeed / speed;
self.velocity.x *= ratio;
self.velocity.y *= ratio;
}
self.moving = true;
self.bounceCount = 0;
LK.getSound('launch').play();
};
self.update = function () {
if (!self.moving) {
return;
}
// Apply physics
self.x += self.velocity.x;
self.y += self.velocity.y;
// Apply friction
self.velocity.x *= self.friction;
self.velocity.y *= self.friction;
// Check if ball has stopped
if (Math.abs(self.velocity.x) < 0.1 && Math.abs(self.velocity.y) < 0.1) {
self.velocity.x = 0;
self.velocity.y = 0;
self.moving = false;
}
// Check boundaries
var halfWidth = ballGraphic.width / 2;
var halfHeight = ballGraphic.height / 2;
if (self.x < halfWidth) {
self.x = halfWidth;
self.velocity.x = -self.velocity.x * self.bounceFactor;
self.bounceWall();
} else if (self.x > 2048 - halfWidth) {
self.x = 2048 - halfWidth;
self.velocity.x = -self.velocity.x * self.bounceFactor;
self.bounceWall();
}
if (self.y < halfHeight) {
self.y = halfHeight;
self.velocity.y = -self.velocity.y * self.bounceFactor;
self.bounceWall();
} else if (self.y > 2732 - halfHeight) {
self.y = 2732 - halfHeight;
self.velocity.y = -self.velocity.y * self.bounceFactor;
self.bounceWall();
}
};
self.bounceWall = function () {
self.bounceCount++;
LK.getSound('bounce').play();
};
self.bounceOffWall = function (wall) {
// Calculate the center of the wall
var wallCenterX = wall.x;
var wallCenterY = wall.y;
// Calculate the normal vector from the wall
var dx = self.x - wallCenterX;
var dy = self.y - wallCenterY;
// Determine if collision is mainly horizontal or vertical based on wall dimensions
if (Math.abs(dx) > Math.abs(dy)) {
// Horizontal collision, bounce horizontally
self.velocity.x = -self.velocity.x * self.bounceFactor;
// Reposition to avoid sticking
if (self.x < wallCenterX) {
self.x = wallCenterX - wall.width / 2 - ballGraphic.width / 2;
} else {
self.x = wallCenterX + wall.width / 2 + ballGraphic.width / 2;
}
} else {
// Vertical collision, bounce vertically
self.velocity.y = -self.velocity.y * self.bounceFactor;
// Reposition to avoid sticking
if (self.y < wallCenterY) {
self.y = wallCenterY - wall.height / 2 - ballGraphic.height / 2;
} else {
self.y = wallCenterY + wall.height / 2 + ballGraphic.height / 2;
}
}
self.bounceWall();
};
return self;
});
var LevelManager = Container.expand(function () {
var self = Container.call(this);
self.currentLevel = storage.currentLevel || 1;
self.levels = [];
self.initializeLevels = function () {
// Level 1 - Simple intro level
self.levels.push({
ballStart: {
x: 1024,
y: 1366
},
targets: Array.from({
length: 50
}, function () {
return {
x: Math.random() * 2048,
y: Math.random() * 1366
};
}),
walls: Array.from({
length: 5
}, function () {
return {
x: Math.random() * 2048,
y: Math.random() * 2732
};
})
});
};
self.getCurrentLevel = function () {
return self.levels[self.currentLevel - 1] || self.levels[0];
};
self.advanceLevel = function () {
if (self.currentLevel < self.levels.length) {
self.currentLevel++;
storage.currentLevel = self.currentLevel;
return true;
}
return false;
};
self.resetLevel = function () {
// Just reset the current level (no change in level number)
};
self.saveScore = function (level, shots) {
var currentHighScore = storage.highScores[level] || 999;
if (shots < currentHighScore) {
storage.highScores[level] = shots;
}
};
self.getHighScore = function (level) {
return storage.highScores[level] || "-";
};
return self;
});
var MovingWall = Container.expand(function () {
var self = Container.call(this);
var wallGraphic = self.attachAsset('wall', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 20; // Super speed for walls
self.direction = 1; // 1 for right, -1 for left
self.update = function () {
self.x += self.speed * self.direction;
if (self.x > 2048 - wallGraphic.width / 2 || self.x < wallGraphic.width / 2) {
self.direction *= -1; // Reverse direction
}
};
return self;
});
var PowerMeter = Container.expand(function () {
var self = Container.call(this);
var background = self.attachAsset('powerMeter', {
anchorX: 0.5,
anchorY: 1,
alpha: 0.3
});
var meter = self.attachAsset('powerMeter', {
anchorX: 0.5,
anchorY: 1,
tint: 0xFF3333
});
self.power = 0;
self.maxPower = 100;
meter.height = 0;
self.setPower = function (percent) {
self.power = Math.max(0, Math.min(100, percent));
meter.height = self.power / 100 * background.height;
// Change color based on power
if (self.power < 33) {
meter.tint = 0x33FF33; // Green for low power
} else if (self.power < 66) {
meter.tint = 0xFFFF33; // Yellow for medium power
} else {
meter.tint = 0xFF3333; // Red for high power
}
};
self.hide = function () {
self.visible = false;
};
self.show = function () {
self.visible = true;
};
return self;
});
var Target = Container.expand(function () {
var self = Container.call(this);
var targetGraphic = self.attachAsset('target', {
anchorX: 0.5,
anchorY: 0.5
});
self.active = true;
self.hit = false;
self.update = function () {
// This would be where we'd add movement or animation if needed
if (self.x < targetGraphic.width / 2 || self.x > 2048 - targetGraphic.width / 2) {
self.velocity.x = -self.velocity.x;
}
if (self.y < targetGraphic.height / 2 || self.y > 1366 - targetGraphic.height / 2) {
self.velocity.y = -self.velocity.y;
}
self.x += self.velocity.x;
self.y += self.velocity.y;
};
self.onHit = function () {
if (!self.hit && self.active) {
self.hit = true;
LK.getSound('hitTarget').play();
// Visual feedback
tween(targetGraphic, {
alpha: 0.3,
scaleX: 0.7,
scaleY: 0.7
}, {
duration: 300,
easing: tween.easeOut
});
return true;
}
return false;
};
self.reset = function () {
self.hit = false;
targetGraphic.alpha = 1;
tween(targetGraphic, {
scaleX: 1,
scaleY: 1
}, {
duration: 300,
easing: tween.bounceOut
});
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000000
});
/****
* Game Code
****/
var maxShots = 15; // Set the maximum number of shots allowed per level
var gameActive = false;
var isDragging = false;
var startX, startY;
var shotsUsed = 0;
var targetsHit = 0;
var totalTargets = 0;
// Create UI elements
var scoreText = new Text2('Shots: 0', {
size: 50,
fill: 0xFFFFFF
});
scoreText.anchor.set(0.5, 0);
scoreText.x = 1800;
scoreText.y = 50;
game.addChild(scoreText);
// Create UI elements
var instructionText = new Text2('', {
size: 50,
fill: 0xFFFFFF
});
instructionText.anchor.set(0.5, 0);
instructionText.x = 1024;
instructionText.y = 100;
game.addChild(instructionText);
// Initialize targetsHitDisplay
var targetsHitDisplay = new Text2('Targets Hit: 0', {
size: 50,
fill: 0xFFFFFF
});
targetsHitDisplay.anchor.set(0.5, 0);
targetsHitDisplay.x = 1800;
targetsHitDisplay.y = 100;
game.addChild(targetsHitDisplay);
var levelManager = new LevelManager();
levelManager.initializeLevels();
var ball = new Ball();
var aimLine = new AimLine();
var powerMeter = new PowerMeter();
var targets = [];
// Initialize level
function initializeLevel() {
// Clear old objects
for (var i = targets.length - 1; i >= 0; i--) {
game.removeChild(targets[i]);
}
targets = [];
// Get current level data
var currentLevel = levelManager.getCurrentLevel();
// Set ball position
ball.x = currentLevel.ballStart.x;
ball.y = currentLevel.ballStart.y;
ball.velocity = {
x: 0,
y: 0
};
ball.moving = false;
// Create targets
totalTargets = currentLevel.targets.length;
for (var i = 0; i < currentLevel.targets.length; i++) {
var targetData = currentLevel.targets[i];
var target = new Target();
// Randomize target position on the upper half of the screen
target.x = Math.random() * 2048;
target.y = Math.random() * (1366 - target.height / 2);
target.reset();
target.velocity = {
x: (Math.random() - 0.5) * 20,
// Increased horizontal velocity
y: (Math.random() - 0.5) * 20 // Increased vertical velocity
};
targets.push(target);
game.addChild(target);
}
// Create moving walls
for (var i = 0; i < currentLevel.walls.length; i++) {
var wallData = currentLevel.walls[i];
var movingWall = new MovingWall();
movingWall.x = wallData.x;
movingWall.y = wallData.y;
game.addChild(movingWall);
}
// Set up aiming tools
aimLine.x = ball.x;
aimLine.y = ball.y;
aimLine.hide();
game.addChild(aimLine);
powerMeter.x = 100;
powerMeter.y = 2600;
powerMeter.setPower(0);
powerMeter.hide();
game.addChild(powerMeter);
// Reset game state
shotsUsed = 0;
targetsHit = 0;
gameActive = true;
var maxShots = 15; // Set the maximum number of shots allowed per level
// Update UI
scoreText.setText('Shots: ' + shotsUsed);
var highScore = levelManager.getHighScore(levelManager.currentLevel);
instructionText.setText('Best: ' + (highScore === 999 ? "-" : highScore) + ' shots - Swipe to launch');
}
// Add ball to game
game.addChild(ball);
// Start the first level
initializeLevel();
// Play background music
LK.playMusic('gameMusic', {
volume: 0.5
});
// Event handlers
function handleDown(x, y, obj) {
if (!gameActive || ball.moving) {
return;
}
startX = x;
startY = y;
isDragging = true;
aimLine.x = ball.x;
aimLine.y = ball.y;
aimLine.show();
powerMeter.show();
powerMeter.setPower(0);
}
function handleMove(x, y, obj) {
if (!isDragging) {
return;
}
// Calculate angle and power
var dx = x - startX;
var dy = y - startY;
var distance = Math.sqrt(dx * dx + dy * dy);
var power = Math.min(100, distance / 10);
var angle = Math.atan2(-dy, -dx) * (180 / Math.PI);
// Update visual aids
aimLine.setAngle(angle);
aimLine.setLength(distance);
powerMeter.setPower(power);
}
function handleUp(x, y, obj) {
if (!isDragging) {
return;
}
isDragging = false;
aimLine.hide();
powerMeter.hide();
if (!gameActive || ball.moving) {
return;
}
// Calculate launch parameters
var dx = x - startX;
var dy = y - startY;
var distance = Math.sqrt(dx * dx + dy * dy);
// Only launch if the swipe was long enough
if (distance > 20) {
var power = Math.min(100, distance / 10);
var angle = Math.atan2(-dy, -dx) * (180 / Math.PI);
// Launch the ball
ball.launch(power, angle);
shotsUsed++;
// Update UI
var currentLevel = levelManager.getCurrentLevel();
scoreText.setText('Shots: ' + shotsUsed);
}
}
// Attach event handlers
game.down = handleDown;
game.move = handleMove;
game.up = handleUp;
// Main update loop
game.update = function () {
// Check for level completion
if (gameActive && targetsHit === totalTargets) {
// Level completed
gameActive = false;
levelManager.saveScore(levelManager.currentLevel, shotsUsed);
// Show level complete message
var completeText = new Text2('Level Complete!', {
size: 120,
fill: 0xFFFF00
});
completeText.anchor.set(0.5, 0.5);
completeText.x = 1024;
completeText.y = 1366;
game.addChild(completeText);
// Play level complete sound
LK.getSound('levelComplete').play();
// Flash screen for effect
LK.effects.flashScreen(0x33FF33, 1000);
// End game after delay
LK.setTimeout(function () {
game.removeChild(completeText);
// Game complete
var gameCompleteText = new Text2('Game Complete!\nCongratulations!', {
size: 100,
fill: 0xFFFF00
});
gameCompleteText.anchor.set(0.5, 0.5);
gameCompleteText.x = 1024;
gameCompleteText.y = 1366;
game.addChild(gameCompleteText);
// Show you win screen
LK.showYouWin();
}, 2000);
}
// Removed level failure check based on shot limit
// Update all game objects
if (ball.moving) {
ball.update();
// Check for collisions with targets
var _loop = function _loop() {
if (!targets[i].hit && targets[i].intersects(ball)) {
if (targets[i].onHit()) {
var updateScoreDisplay = function updateScoreDisplay(targetsHit) {
scoreText.setText('Targets Hit: ' + targetsHit);
};
targetsHit++;
updateScoreDisplay(targetsHit); // Update score display
targetsHitDisplay.setText('Targets Hit: ' + targetsHit); // Update targets hit display
}
}
};
for (var i = 0; i < targets.length; i++) {
_loop();
}
// Check for collisions with moving walls
for (var i = 0; i < game.children.length; i++) {
if (game.children[i] instanceof MovingWall) {
if (ball.intersects(game.children[i])) {
ball.bounceOffWall(game.children[i]);
}
}
}
}
// Update targets (for any that have movement)
for (var i = 0; i < targets.length; i++) {
targets[i].update();
}
// Update moving walls
for (var i = 0; i < game.children.length; i++) {
if (game.children[i] instanceof MovingWall) {
game.children[i].update();
}
}
};