/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ // Coin var Coin = Container.expand(function () { var self = Container.call(this); self.lane = 1; self.collected = false; self.speed = 0; self.attachAsset('coin', { anchorX: 0.5, anchorY: 0.5 }); self.update = function () { self.y += self.speed; }; return self; }); // Obstacle base class var Obstacle = Container.expand(function () { var self = Container.call(this); self.type = 'barrier'; // default self.lane = 1; self.passed = false; self.speed = 0; self.update = function () { self.y += self.speed; }; return self; }); // Train var Train = Obstacle.expand(function () { var self = Obstacle.call(this); self.type = 'train'; self.attachAsset('train', { anchorX: 0.5, anchorY: 1 }); return self; }); // Sign (slide under) var Sign = Obstacle.expand(function () { var self = Obstacle.call(this); self.type = 'sign'; self.attachAsset('sign', { anchorX: 0.5, anchorY: 1 }); return self; }); // Barrier var Barrier = Obstacle.expand(function () { var self = Obstacle.call(this); self.type = 'barrier'; self.attachAsset('barrier', { anchorX: 0.5, anchorY: 1 }); return self; }); // Runner class var Runner = Container.expand(function () { var self = Container.call(this); var runnerSprite = self.attachAsset('runner', { anchorX: 0.5, anchorY: 1 }); self.lane = 1; // 0: left, 1: center, 2: right self.isJumping = false; self.isSliding = false; self.jumpY = 0; self.slideTimer = 0; // Jump action self.jump = function () { if (self.isJumping || self.isSliding) return; self.isJumping = true; // Animate jump: up then down tween(self, { jumpY: -320 }, { duration: 260, easing: tween.cubicOut, onFinish: function onFinish() { tween(self, { jumpY: 0 }, { duration: 320, easing: tween.cubicIn, onFinish: function onFinish() { self.isJumping = false; } }); } }); }; // Slide action self.slide = function () { if (self.isSliding || self.isJumping) return; self.isSliding = true; self.slideTimer = 24; // ~0.4s at 60fps tween(runnerSprite, { height: 120 }, { duration: 80, easing: tween.linear }); }; // Lane change self.moveLane = function (dir) { if (self.isJumping || self.isSliding) return; var newLane = self.lane + dir; if (newLane < 0 || newLane > 2) return; self.lane = newLane; var targetX = lanesX[self.lane]; tween(self, { x: targetX }, { duration: 120, easing: tween.cubicOut }); }; // Update per frame self.update = function () { // Slide timer if (self.isSliding) { self.slideTimer--; if (self.slideTimer <= 0) { self.isSliding = false; tween(runnerSprite, { height: 240 }, { duration: 80, easing: tween.linear }); } } // Apply jumpY offset self.y = runnerBaseY + self.jumpY; }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x222831 }); /**** * Game Code ****/ // Coin // Obstacle: Sign (slide under) // Obstacle: Train // Obstacle: Barrier // Lane ground // Character: The runner // Lane positions (3 lanes) var lanesX = [2048 / 2 - 320, // left 2048 / 2, // center 2048 / 2 + 320 // right ]; var runnerBaseY = 2732 - 420; // Y position for runner standing on ground // Add lane backgrounds for (var i = 0; i < 3; i++) { var lane = LK.getAsset('lane', { anchorX: 0.5, anchorY: 1, x: lanesX[i], y: 2732 }); game.addChild(lane); } // Create runner var runner = new Runner(); runner.x = lanesX[1]; runner.y = runnerBaseY; game.addChild(runner); // Score and coins var score = 0; var coins = 0; var scoreTxt = new Text2('0', { size: 120, fill: "#fff" }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); var coinTxt = new Text2('0', { size: 80, fill: 0xFFE066 }); coinTxt.anchor.set(1, 0); LK.gui.topRight.addChild(coinTxt); // Game state var obstacles = []; var coinsArr = []; var gameSpeed = 18; // pixels per frame var spawnTimer = 0; var coinSpawnTimer = 0; var ticks = 0; var lastTouch = { x: 0, y: 0 }; var swipeThreshold = 80; // px var swipeTime = 18; // frames // Touch/Swipe controls var touchStartX = 0, touchStartY = 0, touchStartTick = 0; game.down = function (x, y, obj) { touchStartX = x; touchStartY = y; touchStartTick = LK.ticks; lastTouch.x = x; lastTouch.y = y; }; game.up = function (x, y, obj) { var dx = x - touchStartX; var dy = y - touchStartY; var dt = LK.ticks - touchStartTick; if (dt > swipeTime) return; // too slow if (Math.abs(dx) > Math.abs(dy)) { // Horizontal swipe if (dx > swipeThreshold) { runner.moveLane(1); // right } else if (dx < -swipeThreshold) { runner.moveLane(-1); // left } } else { // Vertical swipe if (dy < -swipeThreshold) { runner.jump(); } else if (dy > swipeThreshold) { runner.slide(); } } }; game.move = function (x, y, obj) { lastTouch.x = x; lastTouch.y = y; }; // Main update loop game.update = function () { ticks++; // Increase speed over time if (ticks % 180 === 0 && gameSpeed < 38) { gameSpeed += 1.2; } // Spawn obstacles spawnTimer--; if (spawnTimer <= 0) { spawnTimer = 54 + Math.floor(Math.random() * 36); // 0.9-1.5s var typeRand = Math.random(); var lane = Math.floor(Math.random() * 3); var obs; if (typeRand < 0.18) { obs = new Train(); } else if (typeRand < 0.48) { obs = new Barrier(); } else { obs = new Sign(); } obs.lane = lane; obs.x = lanesX[lane]; obs.y = -40; obs.speed = gameSpeed; obstacles.push(obs); game.addChild(obs); } // Spawn coins coinSpawnTimer--; if (coinSpawnTimer <= 0) { coinSpawnTimer = 36 + Math.floor(Math.random() * 36); // 0.6-1.2s var lane = Math.floor(Math.random() * 3); var coin = new Coin(); coin.lane = lane; coin.x = lanesX[lane]; coin.y = -60; coin.speed = gameSpeed; coinsArr.push(coin); game.addChild(coin); } // Update runner runner.update(); // Update obstacles for (var i = obstacles.length - 1; i >= 0; i--) { var obs = obstacles[i]; obs.update(); // Remove if off screen if (obs.y > 2732 + 200) { obs.destroy(); obstacles.splice(i, 1); continue; } // Collision detection if (!obs.passed && Math.abs(obs.y - runner.y) < 120 && obs.lane === runner.lane) { if (obs.type === 'barrier') { if (!runner.isJumping) { LK.effects.flashScreen(0xff0000, 800); LK.showGameOver(); return; } } else if (obs.type === 'sign') { if (!runner.isSliding) { LK.effects.flashScreen(0xff0000, 800); LK.showGameOver(); return; } } else if (obs.type === 'train') { // Train: always game over LK.effects.flashScreen(0xff0000, 800); LK.showGameOver(); return; } obs.passed = true; score += 10; scoreTxt.setText(score); } else if (!obs.passed && obs.y > runner.y + 60) { obs.passed = true; score += 2; scoreTxt.setText(score); } } // Update coins for (var i = coinsArr.length - 1; i >= 0; i--) { var coin = coinsArr[i]; coin.update(); // Remove if off screen if (coin.y > 2732 + 100) { coin.destroy(); coinsArr.splice(i, 1); continue; } // Collect coin if (!coin.collected && Math.abs(coin.y - runner.y + 60) < 100 && coin.lane === runner.lane && !runner.isSliding) { coin.collected = true; coins++; coinTxt.setText(coins); coin.destroy(); coinsArr.splice(i, 1); } } };
===================================================================
--- original.js
+++ change.js
@@ -1,6 +1,352 @@
-/****
+/****
+* Plugins
+****/
+var tween = LK.import("@upit/tween.v1");
+
+/****
+* Classes
+****/
+// Coin
+var Coin = Container.expand(function () {
+ var self = Container.call(this);
+ self.lane = 1;
+ self.collected = false;
+ self.speed = 0;
+ self.attachAsset('coin', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.update = function () {
+ self.y += self.speed;
+ };
+ return self;
+});
+// Obstacle base class
+var Obstacle = Container.expand(function () {
+ var self = Container.call(this);
+ self.type = 'barrier'; // default
+ self.lane = 1;
+ self.passed = false;
+ self.speed = 0;
+ self.update = function () {
+ self.y += self.speed;
+ };
+ return self;
+});
+// Train
+var Train = Obstacle.expand(function () {
+ var self = Obstacle.call(this);
+ self.type = 'train';
+ self.attachAsset('train', {
+ anchorX: 0.5,
+ anchorY: 1
+ });
+ return self;
+});
+// Sign (slide under)
+var Sign = Obstacle.expand(function () {
+ var self = Obstacle.call(this);
+ self.type = 'sign';
+ self.attachAsset('sign', {
+ anchorX: 0.5,
+ anchorY: 1
+ });
+ return self;
+});
+// Barrier
+var Barrier = Obstacle.expand(function () {
+ var self = Obstacle.call(this);
+ self.type = 'barrier';
+ self.attachAsset('barrier', {
+ anchorX: 0.5,
+ anchorY: 1
+ });
+ return self;
+});
+// Runner class
+var Runner = Container.expand(function () {
+ var self = Container.call(this);
+ var runnerSprite = self.attachAsset('runner', {
+ anchorX: 0.5,
+ anchorY: 1
+ });
+ self.lane = 1; // 0: left, 1: center, 2: right
+ self.isJumping = false;
+ self.isSliding = false;
+ self.jumpY = 0;
+ self.slideTimer = 0;
+ // Jump action
+ self.jump = function () {
+ if (self.isJumping || self.isSliding) return;
+ self.isJumping = true;
+ // Animate jump: up then down
+ tween(self, {
+ jumpY: -320
+ }, {
+ duration: 260,
+ easing: tween.cubicOut,
+ onFinish: function onFinish() {
+ tween(self, {
+ jumpY: 0
+ }, {
+ duration: 320,
+ easing: tween.cubicIn,
+ onFinish: function onFinish() {
+ self.isJumping = false;
+ }
+ });
+ }
+ });
+ };
+ // Slide action
+ self.slide = function () {
+ if (self.isSliding || self.isJumping) return;
+ self.isSliding = true;
+ self.slideTimer = 24; // ~0.4s at 60fps
+ tween(runnerSprite, {
+ height: 120
+ }, {
+ duration: 80,
+ easing: tween.linear
+ });
+ };
+ // Lane change
+ self.moveLane = function (dir) {
+ if (self.isJumping || self.isSliding) return;
+ var newLane = self.lane + dir;
+ if (newLane < 0 || newLane > 2) return;
+ self.lane = newLane;
+ var targetX = lanesX[self.lane];
+ tween(self, {
+ x: targetX
+ }, {
+ duration: 120,
+ easing: tween.cubicOut
+ });
+ };
+ // Update per frame
+ self.update = function () {
+ // Slide timer
+ if (self.isSliding) {
+ self.slideTimer--;
+ if (self.slideTimer <= 0) {
+ self.isSliding = false;
+ tween(runnerSprite, {
+ height: 240
+ }, {
+ duration: 80,
+ easing: tween.linear
+ });
+ }
+ }
+ // Apply jumpY offset
+ self.y = runnerBaseY + self.jumpY;
+ };
+ return self;
+});
+
+/****
* Initialize Game
-****/
+****/
var game = new LK.Game({
- backgroundColor: 0x000000
-});
\ No newline at end of file
+ backgroundColor: 0x222831
+});
+
+/****
+* Game Code
+****/
+// Coin
+// Obstacle: Sign (slide under)
+// Obstacle: Train
+// Obstacle: Barrier
+// Lane ground
+// Character: The runner
+// Lane positions (3 lanes)
+var lanesX = [2048 / 2 - 320,
+// left
+2048 / 2,
+// center
+2048 / 2 + 320 // right
+];
+var runnerBaseY = 2732 - 420; // Y position for runner standing on ground
+// Add lane backgrounds
+for (var i = 0; i < 3; i++) {
+ var lane = LK.getAsset('lane', {
+ anchorX: 0.5,
+ anchorY: 1,
+ x: lanesX[i],
+ y: 2732
+ });
+ game.addChild(lane);
+}
+// Create runner
+var runner = new Runner();
+runner.x = lanesX[1];
+runner.y = runnerBaseY;
+game.addChild(runner);
+// Score and coins
+var score = 0;
+var coins = 0;
+var scoreTxt = new Text2('0', {
+ size: 120,
+ fill: "#fff"
+});
+scoreTxt.anchor.set(0.5, 0);
+LK.gui.top.addChild(scoreTxt);
+var coinTxt = new Text2('0', {
+ size: 80,
+ fill: 0xFFE066
+});
+coinTxt.anchor.set(1, 0);
+LK.gui.topRight.addChild(coinTxt);
+// Game state
+var obstacles = [];
+var coinsArr = [];
+var gameSpeed = 18; // pixels per frame
+var spawnTimer = 0;
+var coinSpawnTimer = 0;
+var ticks = 0;
+var lastTouch = {
+ x: 0,
+ y: 0
+};
+var swipeThreshold = 80; // px
+var swipeTime = 18; // frames
+// Touch/Swipe controls
+var touchStartX = 0,
+ touchStartY = 0,
+ touchStartTick = 0;
+game.down = function (x, y, obj) {
+ touchStartX = x;
+ touchStartY = y;
+ touchStartTick = LK.ticks;
+ lastTouch.x = x;
+ lastTouch.y = y;
+};
+game.up = function (x, y, obj) {
+ var dx = x - touchStartX;
+ var dy = y - touchStartY;
+ var dt = LK.ticks - touchStartTick;
+ if (dt > swipeTime) return; // too slow
+ if (Math.abs(dx) > Math.abs(dy)) {
+ // Horizontal swipe
+ if (dx > swipeThreshold) {
+ runner.moveLane(1); // right
+ } else if (dx < -swipeThreshold) {
+ runner.moveLane(-1); // left
+ }
+ } else {
+ // Vertical swipe
+ if (dy < -swipeThreshold) {
+ runner.jump();
+ } else if (dy > swipeThreshold) {
+ runner.slide();
+ }
+ }
+};
+game.move = function (x, y, obj) {
+ lastTouch.x = x;
+ lastTouch.y = y;
+};
+// Main update loop
+game.update = function () {
+ ticks++;
+ // Increase speed over time
+ if (ticks % 180 === 0 && gameSpeed < 38) {
+ gameSpeed += 1.2;
+ }
+ // Spawn obstacles
+ spawnTimer--;
+ if (spawnTimer <= 0) {
+ spawnTimer = 54 + Math.floor(Math.random() * 36); // 0.9-1.5s
+ var typeRand = Math.random();
+ var lane = Math.floor(Math.random() * 3);
+ var obs;
+ if (typeRand < 0.18) {
+ obs = new Train();
+ } else if (typeRand < 0.48) {
+ obs = new Barrier();
+ } else {
+ obs = new Sign();
+ }
+ obs.lane = lane;
+ obs.x = lanesX[lane];
+ obs.y = -40;
+ obs.speed = gameSpeed;
+ obstacles.push(obs);
+ game.addChild(obs);
+ }
+ // Spawn coins
+ coinSpawnTimer--;
+ if (coinSpawnTimer <= 0) {
+ coinSpawnTimer = 36 + Math.floor(Math.random() * 36); // 0.6-1.2s
+ var lane = Math.floor(Math.random() * 3);
+ var coin = new Coin();
+ coin.lane = lane;
+ coin.x = lanesX[lane];
+ coin.y = -60;
+ coin.speed = gameSpeed;
+ coinsArr.push(coin);
+ game.addChild(coin);
+ }
+ // Update runner
+ runner.update();
+ // Update obstacles
+ for (var i = obstacles.length - 1; i >= 0; i--) {
+ var obs = obstacles[i];
+ obs.update();
+ // Remove if off screen
+ if (obs.y > 2732 + 200) {
+ obs.destroy();
+ obstacles.splice(i, 1);
+ continue;
+ }
+ // Collision detection
+ if (!obs.passed && Math.abs(obs.y - runner.y) < 120 && obs.lane === runner.lane) {
+ if (obs.type === 'barrier') {
+ if (!runner.isJumping) {
+ LK.effects.flashScreen(0xff0000, 800);
+ LK.showGameOver();
+ return;
+ }
+ } else if (obs.type === 'sign') {
+ if (!runner.isSliding) {
+ LK.effects.flashScreen(0xff0000, 800);
+ LK.showGameOver();
+ return;
+ }
+ } else if (obs.type === 'train') {
+ // Train: always game over
+ LK.effects.flashScreen(0xff0000, 800);
+ LK.showGameOver();
+ return;
+ }
+ obs.passed = true;
+ score += 10;
+ scoreTxt.setText(score);
+ } else if (!obs.passed && obs.y > runner.y + 60) {
+ obs.passed = true;
+ score += 2;
+ scoreTxt.setText(score);
+ }
+ }
+ // Update coins
+ for (var i = coinsArr.length - 1; i >= 0; i--) {
+ var coin = coinsArr[i];
+ coin.update();
+ // Remove if off screen
+ if (coin.y > 2732 + 100) {
+ coin.destroy();
+ coinsArr.splice(i, 1);
+ continue;
+ }
+ // Collect coin
+ if (!coin.collected && Math.abs(coin.y - runner.y + 60) < 100 && coin.lane === runner.lane && !runner.isSliding) {
+ coin.collected = true;
+ coins++;
+ coinTxt.setText(coins);
+ coin.destroy();
+ coinsArr.splice(i, 1);
+ }
+ }
+};
\ No newline at end of file