/****
* 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 = 0.8;
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.5;
self.velocity.y = Math.sin(radians) * power * 0.5;
// 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 (wall.width > wall.height) {
// Horizontal wall, 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;
}
} else {
// Vertical wall, 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;
}
}
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: 300,
y: 2000
},
targets: [{
x: 1700,
y: 800
}],
walls: [{
x: 1024,
y: 1500,
width: 800,
height: 40,
rotation: 0
}],
maxShots: 3
});
// Level 2 - Two targets
self.levels.push({
ballStart: {
x: 400,
y: 2000
},
targets: [{
x: 1600,
y: 500
}, {
x: 1000,
y: 1200
}],
walls: [{
x: 1024,
y: 1400,
width: 1000,
height: 40,
rotation: 0
}, {
x: 600,
y: 800,
width: 600,
height: 40,
rotation: 45
}],
maxShots: 4
});
// Level 3 - More complex arrangement
self.levels.push({
ballStart: {
x: 500,
y: 2000
},
targets: [{
x: 800,
y: 500
}, {
x: 1500,
y: 700
}, {
x: 1300,
y: 1400
}],
walls: [{
x: 1024,
y: 1300,
width: 1200,
height: 40,
rotation: 0
}, {
x: 500,
y: 900,
width: 700,
height: 40,
rotation: 30
}, {
x: 1500,
y: 900,
width: 700,
height: 40,
rotation: -30
}, {
x: 1024,
y: 600,
width: 400,
height: 40,
rotation: 90
}],
maxShots: 5
});
};
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 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
};
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;
});
var Wall = Container.expand(function () {
var self = Container.call(this);
var wallGraphic = self.attachAsset('wall', {
anchorX: 0.5,
anchorY: 0.5
});
self.setSize = function (width, height) {
wallGraphic.width = width;
wallGraphic.height = height;
};
self.rotate = function (degrees) {
wallGraphic.rotation = degrees * (Math.PI / 180);
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x222233
});
/****
* Game Code
****/
// Game state variables
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: 70,
fill: 0xFFFFFF
});
scoreText.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreText);
var levelText = new Text2('Level: 1', {
size: 70,
fill: 0xFFFFFF
});
levelText.anchor.set(0, 0);
LK.gui.topRight.addChild(levelText);
levelText.x -= 300; // Offset from right edge
var instructionText = new Text2('Swipe to launch the ball', {
size: 60,
fill: 0xFFFFFF,
alpha: 0.8
});
instructionText.anchor.set(0.5, 0);
instructionText.y = 150;
LK.gui.top.addChild(instructionText);
// Create game objects
var levelManager = new LevelManager();
levelManager.initializeLevels();
var ball = new Ball();
var aimLine = new AimLine();
var powerMeter = new PowerMeter();
var targets = [];
var walls = [];
// Initialize level
function initializeLevel() {
// Clear old objects
for (var i = targets.length - 1; i >= 0; i--) {
game.removeChild(targets[i]);
}
targets = [];
for (var i = walls.length - 1; i >= 0; i--) {
game.removeChild(walls[i]);
}
walls = [];
// 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();
target.x = targetData.x;
target.y = targetData.y;
target.reset();
targets.push(target);
game.addChild(target);
}
// Create walls
for (var i = 0; i < currentLevel.walls.length; i++) {
var wallData = currentLevel.walls[i];
var wall = new Wall();
wall.x = wallData.x;
wall.y = wallData.y;
wall.setSize(wallData.width, wallData.height);
wall.rotate(wallData.rotation);
walls.push(wall);
game.addChild(wall);
}
// 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;
// Update UI
scoreText.setText('Shots: ' + shotsUsed + ' / ' + currentLevel.maxShots);
levelText.setText('Level: ' + levelManager.currentLevel);
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 = startX - x;
var dy = startY - y;
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 * 0.5);
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 = startX - x;
var dy = startY - y;
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 + ' / ' + currentLevel.maxShots);
// Check if we've used all shots
if (shotsUsed >= currentLevel.maxShots && targetsHit < totalTargets) {
// Will check for level fail in the update loop
}
}
}
// 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);
// Advance to next level after delay
LK.setTimeout(function () {
game.removeChild(completeText);
var hasNextLevel = levelManager.advanceLevel();
if (hasNextLevel) {
initializeLevel();
} else {
// 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);
}
// Check for level failure (out of shots)
if (gameActive && shotsUsed >= levelManager.getCurrentLevel().maxShots && targetsHit < totalTargets && !ball.moving) {
gameActive = false;
// Show level failed message
var failedText = new Text2('Out of shots!\nTry again.', {
size: 100,
fill: 0xFF3333
});
failedText.anchor.set(0.5, 0.5);
failedText.x = 1024;
failedText.y = 1366;
game.addChild(failedText);
// Flash screen red
LK.effects.flashScreen(0xFF3333, 1000);
// Restart level after delay
LK.setTimeout(function () {
game.removeChild(failedText);
initializeLevel();
}, 2000);
}
// Update all game objects
if (ball.moving) {
ball.update();
// Check for collisions with walls
for (var i = 0; i < walls.length; i++) {
if (ball.intersects(walls[i])) {
ball.bounceOffWall(walls[i]);
}
}
// Check for collisions with targets
for (var i = 0; i < targets.length; i++) {
if (!targets[i].hit && targets[i].intersects(ball)) {
if (targets[i].onHit()) {
targetsHit++;
}
}
}
}
// Update targets (for any that have movement)
for (var i = 0; i < targets.length; i++) {
targets[i].update();
}
}; ===================================================================
--- original.js
+++ change.js
@@ -1,6 +1,616 @@
-/****
+/****
+* 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 = 0.8;
+ 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.5;
+ self.velocity.y = Math.sin(radians) * power * 0.5;
+ // 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 (wall.width > wall.height) {
+ // Horizontal wall, 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;
+ }
+ } else {
+ // Vertical wall, 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;
+ }
+ }
+ 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: 300,
+ y: 2000
+ },
+ targets: [{
+ x: 1700,
+ y: 800
+ }],
+ walls: [{
+ x: 1024,
+ y: 1500,
+ width: 800,
+ height: 40,
+ rotation: 0
+ }],
+ maxShots: 3
+ });
+ // Level 2 - Two targets
+ self.levels.push({
+ ballStart: {
+ x: 400,
+ y: 2000
+ },
+ targets: [{
+ x: 1600,
+ y: 500
+ }, {
+ x: 1000,
+ y: 1200
+ }],
+ walls: [{
+ x: 1024,
+ y: 1400,
+ width: 1000,
+ height: 40,
+ rotation: 0
+ }, {
+ x: 600,
+ y: 800,
+ width: 600,
+ height: 40,
+ rotation: 45
+ }],
+ maxShots: 4
+ });
+ // Level 3 - More complex arrangement
+ self.levels.push({
+ ballStart: {
+ x: 500,
+ y: 2000
+ },
+ targets: [{
+ x: 800,
+ y: 500
+ }, {
+ x: 1500,
+ y: 700
+ }, {
+ x: 1300,
+ y: 1400
+ }],
+ walls: [{
+ x: 1024,
+ y: 1300,
+ width: 1200,
+ height: 40,
+ rotation: 0
+ }, {
+ x: 500,
+ y: 900,
+ width: 700,
+ height: 40,
+ rotation: 30
+ }, {
+ x: 1500,
+ y: 900,
+ width: 700,
+ height: 40,
+ rotation: -30
+ }, {
+ x: 1024,
+ y: 600,
+ width: 400,
+ height: 40,
+ rotation: 90
+ }],
+ maxShots: 5
+ });
+ };
+ 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 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
+ };
+ 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;
+});
+var Wall = Container.expand(function () {
+ var self = Container.call(this);
+ var wallGraphic = self.attachAsset('wall', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.setSize = function (width, height) {
+ wallGraphic.width = width;
+ wallGraphic.height = height;
+ };
+ self.rotate = function (degrees) {
+ wallGraphic.rotation = degrees * (Math.PI / 180);
+ };
+ return self;
+});
+
+/****
* Initialize Game
-****/
+****/
var game = new LK.Game({
- backgroundColor: 0x000000
-});
\ No newline at end of file
+ backgroundColor: 0x222233
+});
+
+/****
+* Game Code
+****/
+// Game state variables
+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: 70,
+ fill: 0xFFFFFF
+});
+scoreText.anchor.set(0.5, 0);
+LK.gui.top.addChild(scoreText);
+var levelText = new Text2('Level: 1', {
+ size: 70,
+ fill: 0xFFFFFF
+});
+levelText.anchor.set(0, 0);
+LK.gui.topRight.addChild(levelText);
+levelText.x -= 300; // Offset from right edge
+var instructionText = new Text2('Swipe to launch the ball', {
+ size: 60,
+ fill: 0xFFFFFF,
+ alpha: 0.8
+});
+instructionText.anchor.set(0.5, 0);
+instructionText.y = 150;
+LK.gui.top.addChild(instructionText);
+// Create game objects
+var levelManager = new LevelManager();
+levelManager.initializeLevels();
+var ball = new Ball();
+var aimLine = new AimLine();
+var powerMeter = new PowerMeter();
+var targets = [];
+var walls = [];
+// Initialize level
+function initializeLevel() {
+ // Clear old objects
+ for (var i = targets.length - 1; i >= 0; i--) {
+ game.removeChild(targets[i]);
+ }
+ targets = [];
+ for (var i = walls.length - 1; i >= 0; i--) {
+ game.removeChild(walls[i]);
+ }
+ walls = [];
+ // 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();
+ target.x = targetData.x;
+ target.y = targetData.y;
+ target.reset();
+ targets.push(target);
+ game.addChild(target);
+ }
+ // Create walls
+ for (var i = 0; i < currentLevel.walls.length; i++) {
+ var wallData = currentLevel.walls[i];
+ var wall = new Wall();
+ wall.x = wallData.x;
+ wall.y = wallData.y;
+ wall.setSize(wallData.width, wallData.height);
+ wall.rotate(wallData.rotation);
+ walls.push(wall);
+ game.addChild(wall);
+ }
+ // 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;
+ // Update UI
+ scoreText.setText('Shots: ' + shotsUsed + ' / ' + currentLevel.maxShots);
+ levelText.setText('Level: ' + levelManager.currentLevel);
+ 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 = startX - x;
+ var dy = startY - y;
+ 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 * 0.5);
+ 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 = startX - x;
+ var dy = startY - y;
+ 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 + ' / ' + currentLevel.maxShots);
+ // Check if we've used all shots
+ if (shotsUsed >= currentLevel.maxShots && targetsHit < totalTargets) {
+ // Will check for level fail in the update loop
+ }
+ }
+}
+// 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);
+ // Advance to next level after delay
+ LK.setTimeout(function () {
+ game.removeChild(completeText);
+ var hasNextLevel = levelManager.advanceLevel();
+ if (hasNextLevel) {
+ initializeLevel();
+ } else {
+ // 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);
+ }
+ // Check for level failure (out of shots)
+ if (gameActive && shotsUsed >= levelManager.getCurrentLevel().maxShots && targetsHit < totalTargets && !ball.moving) {
+ gameActive = false;
+ // Show level failed message
+ var failedText = new Text2('Out of shots!\nTry again.', {
+ size: 100,
+ fill: 0xFF3333
+ });
+ failedText.anchor.set(0.5, 0.5);
+ failedText.x = 1024;
+ failedText.y = 1366;
+ game.addChild(failedText);
+ // Flash screen red
+ LK.effects.flashScreen(0xFF3333, 1000);
+ // Restart level after delay
+ LK.setTimeout(function () {
+ game.removeChild(failedText);
+ initializeLevel();
+ }, 2000);
+ }
+ // Update all game objects
+ if (ball.moving) {
+ ball.update();
+ // Check for collisions with walls
+ for (var i = 0; i < walls.length; i++) {
+ if (ball.intersects(walls[i])) {
+ ball.bounceOffWall(walls[i]);
+ }
+ }
+ // Check for collisions with targets
+ for (var i = 0; i < targets.length; i++) {
+ if (!targets[i].hit && targets[i].intersects(ball)) {
+ if (targets[i].onHit()) {
+ targetsHit++;
+ }
+ }
+ }
+ }
+ // Update targets (for any that have movement)
+ for (var i = 0; i < targets.length; i++) {
+ targets[i].update();
+ }
+};
\ No newline at end of file