/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ var Goalkeeper = Container.expand(function () { var self = Container.call(this); var keeperGraphics = self.attachAsset('goalkeeper', { anchorX: 0.5, anchorY: 1.0 }); self.minX = 0; self.maxX = 0; self.isDiving = false; self.dive = function (direction) { if (!self.isDiving) { self.isDiving = true; var targetX = direction > 0 ? self.maxX : self.minX; tween(self, { x: targetX, scaleX: direction > 0 ? 1.2 : -1.2 }, { duration: 300, easing: tween.easeOut, onFinish: function onFinish() { tween(self, { scaleX: 1 }, { duration: 200 }); self.isDiving = false; } }); } }; return self; }); var SoccerBall = Container.expand(function () { var self = Container.call(this); var ballGraphics = self.attachAsset('soccerBall', { anchorX: 0.5, anchorY: 0.5 }); self.speedX = 0; self.speedY = 0; self.isActive = true; self.update = function () { if (self.isActive) { self.x += self.speedX; self.y += self.speedY; } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x4CAF50 }); /**** * Game Code ****/ // Game variables var goalkeeper; var soccerBalls = []; var goalsAllowed = 0; var maxGoals = 5; var consecutiveSaves = 0; var ballSpawnCounter = 0; var ballSpawnRate = 120; // frames between balls var gameSpeed = 1; var isDragging = false; // Create goal structure var goalBackground = game.addChild(LK.getAsset('goal', { anchorX: 0.5, anchorY: 1.0, alpha: 0.3 })); goalBackground.x = 2048 / 2; goalBackground.y = 2732 - 200; // Goal posts var leftPost = game.addChild(LK.getAsset('goalPost', { anchorX: 0.5, anchorY: 1.0 })); leftPost.x = 2048 / 2 - 400; leftPost.y = 2732 - 200; var rightPost = game.addChild(LK.getAsset('goalPost', { anchorX: 0.5, anchorY: 1.0 })); rightPost.x = 2048 / 2 + 400; rightPost.y = 2732 - 200; // Goal line var goalLine = game.addChild(LK.getAsset('goalLine', { anchorX: 0.5, anchorY: 0.5 })); goalLine.x = 2048 / 2; goalLine.y = 2732 - 200; // Create goalkeeper goalkeeper = game.addChild(new Goalkeeper()); goalkeeper.x = 2048 / 2; goalkeeper.y = 2732 - 200; goalkeeper.minX = 2048 / 2 - 350; goalkeeper.maxX = 2048 / 2 + 350; // UI Elements var scoreTxt = new Text2('Score: 0', { size: 80, fill: 0xFFFFFF }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); var goalsTxt = new Text2('Goals: 0/5', { size: 60, fill: 0xFFFFFF }); goalsTxt.anchor.set(1, 0); LK.gui.topRight.addChild(goalsTxt); var streakTxt = new Text2('Saves: 0', { size: 50, fill: 0xFFFF00 }); streakTxt.anchor.set(0, 0); LK.gui.left.addChild(streakTxt); // Touch/drag controls game.down = function (x, y, obj) { isDragging = true; var clampedX = Math.max(goalkeeper.minX, Math.min(goalkeeper.maxX, x)); goalkeeper.x = clampedX; }; game.move = function (x, y, obj) { if (isDragging) { var clampedX = Math.max(goalkeeper.minX, Math.min(goalkeeper.maxX, x)); goalkeeper.x = clampedX; } }; game.up = function (x, y, obj) { isDragging = false; }; // Spawn soccer ball function spawnSoccerBall() { var ball = new SoccerBall(); // Random spawn position along top of screen ball.x = Math.random() * 1848 + 100; ball.y = 100; // Calculate trajectory toward goal var targetX = 2048 / 2 + (Math.random() - 0.5) * 600; var targetY = 2732 - 250; var distance = Math.sqrt(Math.pow(targetX - ball.x, 2) + Math.pow(targetY - ball.y, 2)); var speed = 8 + Math.random() * 4 * gameSpeed; ball.speedX = (targetX - ball.x) / distance * speed; ball.speedY = (targetY - ball.y) / distance * speed; ball.lastY = ball.y; ball.lastActive = true; soccerBalls.push(ball); game.addChild(ball); } // Main game update loop game.update = function () { // Update ball spawn counter ballSpawnCounter++; if (ballSpawnCounter >= ballSpawnRate) { spawnSoccerBall(); ballSpawnCounter = 0; // Increase difficulty over time if (ballSpawnRate > 60) { ballSpawnRate = Math.max(60, ballSpawnRate - 1); } gameSpeed += 0.01; } // Update soccer balls for (var i = soccerBalls.length - 1; i >= 0; i--) { var ball = soccerBalls[i]; if (!ball.isActive) continue; // Check if ball went off screen (missed goal) if (ball.lastY < 2732 - 180 && ball.y >= 2732 - 180 && ball.isActive) { // Check if ball is within goal area if (ball.x > 2048 / 2 - 400 && ball.x < 2048 / 2 + 400) { // Check if goalkeeper saved it if (ball.intersects(goalkeeper)) { // SAVE! ball.isActive = false; LK.setScore(LK.getScore() + 10); consecutiveSaves++; // Bonus points for consecutive saves if (consecutiveSaves > 1) { LK.setScore(LK.getScore() + consecutiveSaves * 5); } // Diving save bonus if (goalkeeper.isDiving) { LK.setScore(LK.getScore() + 20); LK.effects.flashObject(goalkeeper, 0xffff00, 500); } LK.getSound('save').play(); LK.effects.flashObject(ball, 0x00ff00, 300); // Trigger goalkeeper dive animation var direction = ball.x > goalkeeper.x ? 1 : -1; goalkeeper.dive(direction); } else { // GOAL! goalsAllowed++; consecutiveSaves = 0; LK.getSound('goal').play(); LK.effects.flashScreen(0xff0000, 500); if (goalsAllowed >= maxGoals) { LK.getSound('whistle').play(); LK.showGameOver(); return; } } // Remove ball ball.destroy(); soccerBalls.splice(i, 1); continue; } } // Remove balls that go completely off screen if (ball.y > 2732 + 100 || ball.x < -100 || ball.x > 2148) { ball.destroy(); soccerBalls.splice(i, 1); continue; } // Update last position ball.lastY = ball.y; } // Update UI scoreTxt.setText('Score: ' + LK.getScore()); goalsTxt.setText('Goals: ' + goalsAllowed + '/' + maxGoals); streakTxt.setText('Saves: ' + consecutiveSaves); };
===================================================================
--- original.js
+++ change.js
@@ -1,6 +1,237 @@
-/****
+/****
+* Plugins
+****/
+var tween = LK.import("@upit/tween.v1");
+
+/****
+* Classes
+****/
+var Goalkeeper = Container.expand(function () {
+ var self = Container.call(this);
+ var keeperGraphics = self.attachAsset('goalkeeper', {
+ anchorX: 0.5,
+ anchorY: 1.0
+ });
+ self.minX = 0;
+ self.maxX = 0;
+ self.isDiving = false;
+ self.dive = function (direction) {
+ if (!self.isDiving) {
+ self.isDiving = true;
+ var targetX = direction > 0 ? self.maxX : self.minX;
+ tween(self, {
+ x: targetX,
+ scaleX: direction > 0 ? 1.2 : -1.2
+ }, {
+ duration: 300,
+ easing: tween.easeOut,
+ onFinish: function onFinish() {
+ tween(self, {
+ scaleX: 1
+ }, {
+ duration: 200
+ });
+ self.isDiving = false;
+ }
+ });
+ }
+ };
+ return self;
+});
+var SoccerBall = Container.expand(function () {
+ var self = Container.call(this);
+ var ballGraphics = self.attachAsset('soccerBall', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.speedX = 0;
+ self.speedY = 0;
+ self.isActive = true;
+ self.update = function () {
+ if (self.isActive) {
+ self.x += self.speedX;
+ self.y += self.speedY;
+ }
+ };
+ return self;
+});
+
+/****
* Initialize Game
-****/
+****/
var game = new LK.Game({
- backgroundColor: 0x000000
-});
\ No newline at end of file
+ backgroundColor: 0x4CAF50
+});
+
+/****
+* Game Code
+****/
+// Game variables
+var goalkeeper;
+var soccerBalls = [];
+var goalsAllowed = 0;
+var maxGoals = 5;
+var consecutiveSaves = 0;
+var ballSpawnCounter = 0;
+var ballSpawnRate = 120; // frames between balls
+var gameSpeed = 1;
+var isDragging = false;
+// Create goal structure
+var goalBackground = game.addChild(LK.getAsset('goal', {
+ anchorX: 0.5,
+ anchorY: 1.0,
+ alpha: 0.3
+}));
+goalBackground.x = 2048 / 2;
+goalBackground.y = 2732 - 200;
+// Goal posts
+var leftPost = game.addChild(LK.getAsset('goalPost', {
+ anchorX: 0.5,
+ anchorY: 1.0
+}));
+leftPost.x = 2048 / 2 - 400;
+leftPost.y = 2732 - 200;
+var rightPost = game.addChild(LK.getAsset('goalPost', {
+ anchorX: 0.5,
+ anchorY: 1.0
+}));
+rightPost.x = 2048 / 2 + 400;
+rightPost.y = 2732 - 200;
+// Goal line
+var goalLine = game.addChild(LK.getAsset('goalLine', {
+ anchorX: 0.5,
+ anchorY: 0.5
+}));
+goalLine.x = 2048 / 2;
+goalLine.y = 2732 - 200;
+// Create goalkeeper
+goalkeeper = game.addChild(new Goalkeeper());
+goalkeeper.x = 2048 / 2;
+goalkeeper.y = 2732 - 200;
+goalkeeper.minX = 2048 / 2 - 350;
+goalkeeper.maxX = 2048 / 2 + 350;
+// UI Elements
+var scoreTxt = new Text2('Score: 0', {
+ size: 80,
+ fill: 0xFFFFFF
+});
+scoreTxt.anchor.set(0.5, 0);
+LK.gui.top.addChild(scoreTxt);
+var goalsTxt = new Text2('Goals: 0/5', {
+ size: 60,
+ fill: 0xFFFFFF
+});
+goalsTxt.anchor.set(1, 0);
+LK.gui.topRight.addChild(goalsTxt);
+var streakTxt = new Text2('Saves: 0', {
+ size: 50,
+ fill: 0xFFFF00
+});
+streakTxt.anchor.set(0, 0);
+LK.gui.left.addChild(streakTxt);
+// Touch/drag controls
+game.down = function (x, y, obj) {
+ isDragging = true;
+ var clampedX = Math.max(goalkeeper.minX, Math.min(goalkeeper.maxX, x));
+ goalkeeper.x = clampedX;
+};
+game.move = function (x, y, obj) {
+ if (isDragging) {
+ var clampedX = Math.max(goalkeeper.minX, Math.min(goalkeeper.maxX, x));
+ goalkeeper.x = clampedX;
+ }
+};
+game.up = function (x, y, obj) {
+ isDragging = false;
+};
+// Spawn soccer ball
+function spawnSoccerBall() {
+ var ball = new SoccerBall();
+ // Random spawn position along top of screen
+ ball.x = Math.random() * 1848 + 100;
+ ball.y = 100;
+ // Calculate trajectory toward goal
+ var targetX = 2048 / 2 + (Math.random() - 0.5) * 600;
+ var targetY = 2732 - 250;
+ var distance = Math.sqrt(Math.pow(targetX - ball.x, 2) + Math.pow(targetY - ball.y, 2));
+ var speed = 8 + Math.random() * 4 * gameSpeed;
+ ball.speedX = (targetX - ball.x) / distance * speed;
+ ball.speedY = (targetY - ball.y) / distance * speed;
+ ball.lastY = ball.y;
+ ball.lastActive = true;
+ soccerBalls.push(ball);
+ game.addChild(ball);
+}
+// Main game update loop
+game.update = function () {
+ // Update ball spawn counter
+ ballSpawnCounter++;
+ if (ballSpawnCounter >= ballSpawnRate) {
+ spawnSoccerBall();
+ ballSpawnCounter = 0;
+ // Increase difficulty over time
+ if (ballSpawnRate > 60) {
+ ballSpawnRate = Math.max(60, ballSpawnRate - 1);
+ }
+ gameSpeed += 0.01;
+ }
+ // Update soccer balls
+ for (var i = soccerBalls.length - 1; i >= 0; i--) {
+ var ball = soccerBalls[i];
+ if (!ball.isActive) continue;
+ // Check if ball went off screen (missed goal)
+ if (ball.lastY < 2732 - 180 && ball.y >= 2732 - 180 && ball.isActive) {
+ // Check if ball is within goal area
+ if (ball.x > 2048 / 2 - 400 && ball.x < 2048 / 2 + 400) {
+ // Check if goalkeeper saved it
+ if (ball.intersects(goalkeeper)) {
+ // SAVE!
+ ball.isActive = false;
+ LK.setScore(LK.getScore() + 10);
+ consecutiveSaves++;
+ // Bonus points for consecutive saves
+ if (consecutiveSaves > 1) {
+ LK.setScore(LK.getScore() + consecutiveSaves * 5);
+ }
+ // Diving save bonus
+ if (goalkeeper.isDiving) {
+ LK.setScore(LK.getScore() + 20);
+ LK.effects.flashObject(goalkeeper, 0xffff00, 500);
+ }
+ LK.getSound('save').play();
+ LK.effects.flashObject(ball, 0x00ff00, 300);
+ // Trigger goalkeeper dive animation
+ var direction = ball.x > goalkeeper.x ? 1 : -1;
+ goalkeeper.dive(direction);
+ } else {
+ // GOAL!
+ goalsAllowed++;
+ consecutiveSaves = 0;
+ LK.getSound('goal').play();
+ LK.effects.flashScreen(0xff0000, 500);
+ if (goalsAllowed >= maxGoals) {
+ LK.getSound('whistle').play();
+ LK.showGameOver();
+ return;
+ }
+ }
+ // Remove ball
+ ball.destroy();
+ soccerBalls.splice(i, 1);
+ continue;
+ }
+ }
+ // Remove balls that go completely off screen
+ if (ball.y > 2732 + 100 || ball.x < -100 || ball.x > 2148) {
+ ball.destroy();
+ soccerBalls.splice(i, 1);
+ continue;
+ }
+ // Update last position
+ ball.lastY = ball.y;
+ }
+ // Update UI
+ scoreTxt.setText('Score: ' + LK.getScore());
+ goalsTxt.setText('Goals: ' + goalsAllowed + '/' + maxGoals);
+ streakTxt.setText('Saves: ' + consecutiveSaves);
+};
\ No newline at end of file