/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Laser Cannon Class
var Cannon = Container.expand(function () {
var self = Container.call(this);
// Base
var base = self.attachAsset('cannonBase', {
anchorX: 0.5,
anchorY: 0.5,
y: 0
});
// Barrel
var barrel = self.attachAsset('cannonBarrel', {
anchorX: 0.5,
anchorY: 1,
y: -80
});
// Glow (for charging)
var glow = self.attachAsset('cannonGlow', {
anchorX: 0.5,
anchorY: 0.5,
y: -80,
alpha: 0
});
self.barrel = barrel;
self.glow = glow;
// Cannon rotation (radians)
self.angle = 0;
// Charging state
self.isCharging = false;
self.chargeTime = 0; // ms
// Set cannon angle (radians)
self.setAngle = function (r) {
self.angle = r;
barrel.rotation = r - Math.PI / 2;
glow.rotation = r - Math.PI / 2;
};
// Start charging
self.startCharge = function () {
self.isCharging = true;
self.chargeTime = 0;
glow.alpha = 0.5;
glow.scaleX = 1;
glow.scaleY = 1;
};
// Stop charging
self.stopCharge = function () {
self.isCharging = false;
glow.alpha = 0;
glow.scaleX = 1;
glow.scaleY = 1;
};
// Update charging visuals
self.updateCharge = function (dt) {
if (self.isCharging) {
self.chargeTime += dt;
var scale = 1 + Math.min(self.chargeTime / 800, 1.5);
glow.scaleX = scale;
glow.scaleY = scale;
glow.alpha = 0.5 + 0.3 * Math.sin(LK.ticks / 6);
}
};
return self;
});
// Enemy Drone Class
var Drone = Container.expand(function () {
var self = Container.call(this);
// Body
var body = self.attachAsset('droneBody', {
anchorX: 0.5,
anchorY: 0.5
});
// Eye
var eye = self.attachAsset('droneEye', {
anchorX: 0.5,
anchorY: 0.5,
y: 0
});
// Movement
self.speed = 3 + Math.random() * 2; // Will be increased by wave
self.waveOffset = Math.random() * Math.PI * 2;
self.waveAmp = 60 + Math.random() * 40;
// For collision
self.radius = 60;
// Update
self.update = function () {
// Sway left/right
self.x += Math.sin(self.y / 180 + self.waveOffset) * 2;
self.y += self.speed;
};
return self;
});
// Explosion Effect
var Explosion = Container.expand(function () {
var self = Container.call(this);
var exp = self.attachAsset('explosion', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.8
});
// Animate and destroy
tween(exp, {
scaleX: 2,
scaleY: 2,
alpha: 0
}, {
duration: 400,
easing: tween.easeOut,
onFinish: function onFinish() {
self.destroy();
}
});
return self;
});
// Laser Beam Class
var LaserBeam = Container.expand(function () {
var self = Container.call(this);
// Beam
var beam = self.attachAsset('laserBeam', {
anchorX: 0.5,
anchorY: 1,
y: 0
});
self.beam = beam;
// Direction (radians)
self.angle = 0;
// Power (1 = normal, >1 = charged)
self.power = 1;
// Speed (pixels per frame)
self.speed = 60;
// Set angle
self.setAngle = function (r) {
self.angle = r;
self.rotation = r - Math.PI / 2;
};
// Set power (affects width/length)
self.setPower = function (p) {
self.power = p;
beam.width = 24 * p;
beam.height = 900 + 300 * (p - 1);
};
// Update
self.update = function () {
self.x += Math.cos(self.angle) * self.speed;
self.y += Math.sin(self.angle) * self.speed;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x181c2a
});
/****
* Game Code
****/
// Sound effects
// Explosion effect
// Enemy Drone
// Laser Beam
// Laser Cannon (player)
// Game constants
var GAME_WIDTH = 2048;
var GAME_HEIGHT = 2732;
var CANNON_Y = GAME_HEIGHT - 180;
var CANNON_X = GAME_WIDTH / 2;
// State
var cannon;
var laserBeams = [];
var drones = [];
var canFire = true;
var fireCooldown = 0;
var lastTouch = {
x: CANNON_X,
y: CANNON_Y - 400
};
var wave = 1;
var spawnTimer = 0;
var spawnInterval = 90; // frames
var scoreTxt;
// Add cannon
cannon = new Cannon();
game.addChild(cannon);
cannon.x = CANNON_X;
cannon.y = CANNON_Y;
cannon.setAngle(-Math.PI / 2);
// Score display
scoreTxt = new Text2('0', {
size: 120,
fill: "#fff"
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Helper: clamp angle to upper half of screen
function clampAngle(r) {
// Only allow aiming between -160deg and -20deg (in radians)
var min = -Math.PI * 0.89; // ~-160deg
var max = -Math.PI * 0.11; // ~-20deg
if (r < min) r = min;
if (r > max) r = max;
return r;
}
// Touch/drag aiming and charging
var isTouching = false;
game.down = function (x, y, obj) {
// Don't allow touch in top 100px (menu)
if (y < 100 && x < 100) return;
isTouching = true;
lastTouch.x = x;
lastTouch.y = y;
// Calculate angle
var dx = x - cannon.x;
var dy = y - cannon.y;
var angle = Math.atan2(dy, dx);
angle = clampAngle(angle);
cannon.setAngle(angle);
cannon.startCharge();
};
game.move = function (x, y, obj) {
if (!isTouching) return;
lastTouch.x = x;
lastTouch.y = y;
var dx = x - cannon.x;
var dy = y - cannon.y;
var angle = Math.atan2(dy, dx);
angle = clampAngle(angle);
cannon.setAngle(angle);
};
game.up = function (x, y, obj) {
if (!isTouching) return;
isTouching = false;
// Fire laser
if (canFire) {
var power = 1 + Math.min(cannon.chargeTime / 800, 1.5); // up to 2.5x
fireLaser(cannon.angle, power);
canFire = false;
fireCooldown = 24; // frames
}
cannon.stopCharge();
};
// Fire laser
function fireLaser(angle, power) {
var laser = new LaserBeam();
laser.x = cannon.x + Math.cos(angle) * 0;
laser.y = cannon.y + Math.sin(angle) * 0;
laser.setAngle(angle);
laser.setPower(power);
laserBeams.push(laser);
game.addChild(laser);
LK.getSound('laserFire').play();
}
// Spawn a drone
function spawnDrone() {
var drone = new Drone();
// Random x, but not too close to edge
var margin = 120;
drone.x = margin + Math.random() * (GAME_WIDTH - margin * 2);
drone.y = -80;
// Increase speed with wave
drone.speed += (wave - 1) * 0.5;
drones.push(drone);
game.addChild(drone);
}
// Destroy drone with explosion
function destroyDrone(drone) {
var exp = new Explosion();
exp.x = drone.x;
exp.y = drone.y;
game.addChild(exp);
LK.getSound('droneExplode').play();
drone.destroy();
}
// Main update loop
game.update = function () {
// Update cannon charging visuals
cannon.updateCharge(16.7);
// Fire cooldown
if (!canFire) {
fireCooldown--;
if (fireCooldown <= 0) canFire = true;
}
// Laser beams update
for (var i = laserBeams.length - 1; i >= 0; i--) {
var l = laserBeams[i];
l.update();
// Remove if off screen
if (l.x < -100 || l.x > GAME_WIDTH + 100 || l.y < -100 || l.y > GAME_HEIGHT + 100) {
l.destroy();
laserBeams.splice(i, 1);
continue;
}
}
// Drones update
for (var j = drones.length - 1; j >= 0; j--) {
var d = drones[j];
d.update();
// Check if reached cannon (game over)
var dx = d.x - cannon.x;
var dy = d.y - cannon.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (d.y > CANNON_Y - 40 && dist < 120) {
// Game over
LK.effects.flashScreen(0xff0000, 1000);
LK.showGameOver();
return;
}
// Remove if off screen
if (d.y > GAME_HEIGHT + 100) {
d.destroy();
drones.splice(j, 1);
continue;
}
}
// Laser-drone collision
for (var i = laserBeams.length - 1; i >= 0; i--) {
var l = laserBeams[i];
var lx = l.x + Math.cos(l.angle) * l.beam.height / 2;
var ly = l.y + Math.sin(l.angle) * l.beam.height / 2;
for (var j = drones.length - 1; j >= 0; j--) {
var d = drones[j];
// Approximate collision: check if laser line passes through drone circle
var dx = d.x - l.x;
var dy = d.y - l.y;
var proj = dx * Math.cos(l.angle) + dy * Math.sin(l.angle);
if (proj > 0 && proj < l.beam.height) {
// Closest point on beam
var px = l.x + Math.cos(l.angle) * proj;
var py = l.y + Math.sin(l.angle) * proj;
var dist = Math.sqrt((d.x - px) * (d.x - px) + (d.y - py) * (d.y - py));
if (dist < d.radius * (0.7 + 0.2 * l.power)) {
// Hit!
destroyDrone(d);
drones.splice(j, 1);
// Score
var addScore = Math.floor(10 * l.power);
LK.setScore(LK.getScore() + addScore);
scoreTxt.setText(LK.getScore());
// Remove laser
l.destroy();
laserBeams.splice(i, 1);
break;
}
}
}
}
// Spawn drones
spawnTimer++;
var interval = Math.max(30, spawnInterval - (wave - 1) * 6);
if (spawnTimer >= interval) {
spawnDrone();
spawnTimer = 0;
}
// Increase wave every 20 drones destroyed
var currentScore = LK.getScore();
var newWave = 1 + Math.floor(currentScore / 200);
if (newWave > wave) {
wave = newWave;
// Flash for new wave
LK.effects.flashScreen(0x44ff44, 400);
}
};
// Play music (if you want to add music, uncomment and set up an asset)
// LK.playMusic('bgmusic'); ===================================================================
--- original.js
+++ change.js
@@ -1,6 +1,372 @@
-/****
+/****
+* Plugins
+****/
+var tween = LK.import("@upit/tween.v1");
+
+/****
+* Classes
+****/
+// Laser Cannon Class
+var Cannon = Container.expand(function () {
+ var self = Container.call(this);
+ // Base
+ var base = self.attachAsset('cannonBase', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ y: 0
+ });
+ // Barrel
+ var barrel = self.attachAsset('cannonBarrel', {
+ anchorX: 0.5,
+ anchorY: 1,
+ y: -80
+ });
+ // Glow (for charging)
+ var glow = self.attachAsset('cannonGlow', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ y: -80,
+ alpha: 0
+ });
+ self.barrel = barrel;
+ self.glow = glow;
+ // Cannon rotation (radians)
+ self.angle = 0;
+ // Charging state
+ self.isCharging = false;
+ self.chargeTime = 0; // ms
+ // Set cannon angle (radians)
+ self.setAngle = function (r) {
+ self.angle = r;
+ barrel.rotation = r - Math.PI / 2;
+ glow.rotation = r - Math.PI / 2;
+ };
+ // Start charging
+ self.startCharge = function () {
+ self.isCharging = true;
+ self.chargeTime = 0;
+ glow.alpha = 0.5;
+ glow.scaleX = 1;
+ glow.scaleY = 1;
+ };
+ // Stop charging
+ self.stopCharge = function () {
+ self.isCharging = false;
+ glow.alpha = 0;
+ glow.scaleX = 1;
+ glow.scaleY = 1;
+ };
+ // Update charging visuals
+ self.updateCharge = function (dt) {
+ if (self.isCharging) {
+ self.chargeTime += dt;
+ var scale = 1 + Math.min(self.chargeTime / 800, 1.5);
+ glow.scaleX = scale;
+ glow.scaleY = scale;
+ glow.alpha = 0.5 + 0.3 * Math.sin(LK.ticks / 6);
+ }
+ };
+ return self;
+});
+// Enemy Drone Class
+var Drone = Container.expand(function () {
+ var self = Container.call(this);
+ // Body
+ var body = self.attachAsset('droneBody', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ // Eye
+ var eye = self.attachAsset('droneEye', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ y: 0
+ });
+ // Movement
+ self.speed = 3 + Math.random() * 2; // Will be increased by wave
+ self.waveOffset = Math.random() * Math.PI * 2;
+ self.waveAmp = 60 + Math.random() * 40;
+ // For collision
+ self.radius = 60;
+ // Update
+ self.update = function () {
+ // Sway left/right
+ self.x += Math.sin(self.y / 180 + self.waveOffset) * 2;
+ self.y += self.speed;
+ };
+ return self;
+});
+// Explosion Effect
+var Explosion = Container.expand(function () {
+ var self = Container.call(this);
+ var exp = self.attachAsset('explosion', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ alpha: 0.8
+ });
+ // Animate and destroy
+ tween(exp, {
+ scaleX: 2,
+ scaleY: 2,
+ alpha: 0
+ }, {
+ duration: 400,
+ easing: tween.easeOut,
+ onFinish: function onFinish() {
+ self.destroy();
+ }
+ });
+ return self;
+});
+// Laser Beam Class
+var LaserBeam = Container.expand(function () {
+ var self = Container.call(this);
+ // Beam
+ var beam = self.attachAsset('laserBeam', {
+ anchorX: 0.5,
+ anchorY: 1,
+ y: 0
+ });
+ self.beam = beam;
+ // Direction (radians)
+ self.angle = 0;
+ // Power (1 = normal, >1 = charged)
+ self.power = 1;
+ // Speed (pixels per frame)
+ self.speed = 60;
+ // Set angle
+ self.setAngle = function (r) {
+ self.angle = r;
+ self.rotation = r - Math.PI / 2;
+ };
+ // Set power (affects width/length)
+ self.setPower = function (p) {
+ self.power = p;
+ beam.width = 24 * p;
+ beam.height = 900 + 300 * (p - 1);
+ };
+ // Update
+ self.update = function () {
+ self.x += Math.cos(self.angle) * self.speed;
+ self.y += Math.sin(self.angle) * self.speed;
+ };
+ return self;
+});
+
+/****
* Initialize Game
-****/
+****/
var game = new LK.Game({
- backgroundColor: 0x000000
-});
\ No newline at end of file
+ backgroundColor: 0x181c2a
+});
+
+/****
+* Game Code
+****/
+// Sound effects
+// Explosion effect
+// Enemy Drone
+// Laser Beam
+// Laser Cannon (player)
+// Game constants
+var GAME_WIDTH = 2048;
+var GAME_HEIGHT = 2732;
+var CANNON_Y = GAME_HEIGHT - 180;
+var CANNON_X = GAME_WIDTH / 2;
+// State
+var cannon;
+var laserBeams = [];
+var drones = [];
+var canFire = true;
+var fireCooldown = 0;
+var lastTouch = {
+ x: CANNON_X,
+ y: CANNON_Y - 400
+};
+var wave = 1;
+var spawnTimer = 0;
+var spawnInterval = 90; // frames
+var scoreTxt;
+// Add cannon
+cannon = new Cannon();
+game.addChild(cannon);
+cannon.x = CANNON_X;
+cannon.y = CANNON_Y;
+cannon.setAngle(-Math.PI / 2);
+// Score display
+scoreTxt = new Text2('0', {
+ size: 120,
+ fill: "#fff"
+});
+scoreTxt.anchor.set(0.5, 0);
+LK.gui.top.addChild(scoreTxt);
+// Helper: clamp angle to upper half of screen
+function clampAngle(r) {
+ // Only allow aiming between -160deg and -20deg (in radians)
+ var min = -Math.PI * 0.89; // ~-160deg
+ var max = -Math.PI * 0.11; // ~-20deg
+ if (r < min) r = min;
+ if (r > max) r = max;
+ return r;
+}
+// Touch/drag aiming and charging
+var isTouching = false;
+game.down = function (x, y, obj) {
+ // Don't allow touch in top 100px (menu)
+ if (y < 100 && x < 100) return;
+ isTouching = true;
+ lastTouch.x = x;
+ lastTouch.y = y;
+ // Calculate angle
+ var dx = x - cannon.x;
+ var dy = y - cannon.y;
+ var angle = Math.atan2(dy, dx);
+ angle = clampAngle(angle);
+ cannon.setAngle(angle);
+ cannon.startCharge();
+};
+game.move = function (x, y, obj) {
+ if (!isTouching) return;
+ lastTouch.x = x;
+ lastTouch.y = y;
+ var dx = x - cannon.x;
+ var dy = y - cannon.y;
+ var angle = Math.atan2(dy, dx);
+ angle = clampAngle(angle);
+ cannon.setAngle(angle);
+};
+game.up = function (x, y, obj) {
+ if (!isTouching) return;
+ isTouching = false;
+ // Fire laser
+ if (canFire) {
+ var power = 1 + Math.min(cannon.chargeTime / 800, 1.5); // up to 2.5x
+ fireLaser(cannon.angle, power);
+ canFire = false;
+ fireCooldown = 24; // frames
+ }
+ cannon.stopCharge();
+};
+// Fire laser
+function fireLaser(angle, power) {
+ var laser = new LaserBeam();
+ laser.x = cannon.x + Math.cos(angle) * 0;
+ laser.y = cannon.y + Math.sin(angle) * 0;
+ laser.setAngle(angle);
+ laser.setPower(power);
+ laserBeams.push(laser);
+ game.addChild(laser);
+ LK.getSound('laserFire').play();
+}
+// Spawn a drone
+function spawnDrone() {
+ var drone = new Drone();
+ // Random x, but not too close to edge
+ var margin = 120;
+ drone.x = margin + Math.random() * (GAME_WIDTH - margin * 2);
+ drone.y = -80;
+ // Increase speed with wave
+ drone.speed += (wave - 1) * 0.5;
+ drones.push(drone);
+ game.addChild(drone);
+}
+// Destroy drone with explosion
+function destroyDrone(drone) {
+ var exp = new Explosion();
+ exp.x = drone.x;
+ exp.y = drone.y;
+ game.addChild(exp);
+ LK.getSound('droneExplode').play();
+ drone.destroy();
+}
+// Main update loop
+game.update = function () {
+ // Update cannon charging visuals
+ cannon.updateCharge(16.7);
+ // Fire cooldown
+ if (!canFire) {
+ fireCooldown--;
+ if (fireCooldown <= 0) canFire = true;
+ }
+ // Laser beams update
+ for (var i = laserBeams.length - 1; i >= 0; i--) {
+ var l = laserBeams[i];
+ l.update();
+ // Remove if off screen
+ if (l.x < -100 || l.x > GAME_WIDTH + 100 || l.y < -100 || l.y > GAME_HEIGHT + 100) {
+ l.destroy();
+ laserBeams.splice(i, 1);
+ continue;
+ }
+ }
+ // Drones update
+ for (var j = drones.length - 1; j >= 0; j--) {
+ var d = drones[j];
+ d.update();
+ // Check if reached cannon (game over)
+ var dx = d.x - cannon.x;
+ var dy = d.y - cannon.y;
+ var dist = Math.sqrt(dx * dx + dy * dy);
+ if (d.y > CANNON_Y - 40 && dist < 120) {
+ // Game over
+ LK.effects.flashScreen(0xff0000, 1000);
+ LK.showGameOver();
+ return;
+ }
+ // Remove if off screen
+ if (d.y > GAME_HEIGHT + 100) {
+ d.destroy();
+ drones.splice(j, 1);
+ continue;
+ }
+ }
+ // Laser-drone collision
+ for (var i = laserBeams.length - 1; i >= 0; i--) {
+ var l = laserBeams[i];
+ var lx = l.x + Math.cos(l.angle) * l.beam.height / 2;
+ var ly = l.y + Math.sin(l.angle) * l.beam.height / 2;
+ for (var j = drones.length - 1; j >= 0; j--) {
+ var d = drones[j];
+ // Approximate collision: check if laser line passes through drone circle
+ var dx = d.x - l.x;
+ var dy = d.y - l.y;
+ var proj = dx * Math.cos(l.angle) + dy * Math.sin(l.angle);
+ if (proj > 0 && proj < l.beam.height) {
+ // Closest point on beam
+ var px = l.x + Math.cos(l.angle) * proj;
+ var py = l.y + Math.sin(l.angle) * proj;
+ var dist = Math.sqrt((d.x - px) * (d.x - px) + (d.y - py) * (d.y - py));
+ if (dist < d.radius * (0.7 + 0.2 * l.power)) {
+ // Hit!
+ destroyDrone(d);
+ drones.splice(j, 1);
+ // Score
+ var addScore = Math.floor(10 * l.power);
+ LK.setScore(LK.getScore() + addScore);
+ scoreTxt.setText(LK.getScore());
+ // Remove laser
+ l.destroy();
+ laserBeams.splice(i, 1);
+ break;
+ }
+ }
+ }
+ }
+ // Spawn drones
+ spawnTimer++;
+ var interval = Math.max(30, spawnInterval - (wave - 1) * 6);
+ if (spawnTimer >= interval) {
+ spawnDrone();
+ spawnTimer = 0;
+ }
+ // Increase wave every 20 drones destroyed
+ var currentScore = LK.getScore();
+ var newWave = 1 + Math.floor(currentScore / 200);
+ if (newWave > wave) {
+ wave = newWave;
+ // Flash for new wave
+ LK.effects.flashScreen(0x44ff44, 400);
+ }
+};
+// Play music (if you want to add music, uncomment and set up an asset)
+// LK.playMusic('bgmusic');
\ No newline at end of file