/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
// Apple (collectible)
var Apple = Container.expand(function () {
var self = Container.call(this);
var appleSprite = self.attachAsset('apple', {
anchorX: 0.5,
anchorY: 1
});
self.lane = 1;
self.collected = false;
self.update = function () {
// Movement handled by game
};
return self;
});
// Fence (obstacle)
var Fence = Container.expand(function () {
var self = Container.call(this);
var fenceSprite = self.attachAsset('fence', {
anchorX: 0.5,
anchorY: 1
});
self.lane = 1;
self.hit = false;
self.update = function () {};
return self;
});
// Horse (player) class
var Horse = Container.expand(function () {
var self = Container.call(this);
var horseSprite = self.attachAsset('horse', {
anchorX: 0.5,
anchorY: 1
});
self.lane = 1; // 0: left, 1: center, 2: right
self.isJumping = false;
self.jumpY = 0; // Offset for jump animation
self.jumpTween = null;
self.groundY = 0; // Set after adding to game
self.jumpHeight = 320; // How high the horse jumps
self.jumpDuration = 420; // ms
// Start jump if not already jumping
self.jump = function () {
if (self.isJumping) return;
self.isJumping = true;
if (self.jumpTween) tween.stop(self, {
jumpY: true
});
tween(self, {
jumpY: -self.jumpHeight
}, {
duration: self.jumpDuration,
easing: tween.cubicOut,
onFinish: function onFinish() {
tween(self, {
jumpY: 0
}, {
duration: self.jumpDuration,
easing: tween.cubicIn,
onFinish: function onFinish() {
self.isJumping = false;
}
});
}
});
};
// Move to lane (0,1,2)
self.moveToLane = function (lane) {
if (lane < 0) lane = 0;
if (lane > 2) lane = 2;
self.lane = lane;
// Animate x to new lane
var targetX = laneX(lane);
tween(self, {
x: targetX
}, {
duration: 120,
easing: tween.cubicOut
});
};
// Update position for jump
self.update = function () {
self.y = self.groundY + self.jumpY;
};
return self;
});
// Puddle (obstacle)
var Puddle = Container.expand(function () {
var self = Container.call(this);
var puddleSprite = self.attachAsset('puddle', {
anchorX: 0.5,
anchorY: 1
});
self.lane = 1;
self.hit = false;
self.update = function () {};
return self;
});
// Rock (obstacle)
var Rock = Container.expand(function () {
var self = Container.call(this);
var rockSprite = self.attachAsset('rock', {
anchorX: 0.5,
anchorY: 1
});
self.lane = 1;
self.hit = false;
self.update = function () {};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0xA7D36C // Soft green field
});
/****
* Game Code
****/
// Lane marker (for visual lanes) - 8x2732, light gray box
// Puddle (obstacle) - 140x60, blue ellipse
// Fence (obstacle) - 160x40, tan box
// Rock (obstacle) - 120x80, gray ellipse
// Apple (collectible) - 100x100, red ellipse
// Horse (player) - 220x180, brown box
// Lane logic
var laneCount = 3;
var laneWidth = 480; // (2048 - 2*104) / 3 = ~613, but use 480 for margin
var laneMargin = 104; // left/right margin
function laneX(lane) {
return laneMargin + lane * laneWidth + laneWidth / 2;
}
// Ground Y (where horse stands)
var groundY = 2200;
// Game speed (pixels per tick)
var baseSpeed = 16;
var speed = baseSpeed;
var speedIncrease = 0.0007; // per tick
var maxSpeed = 38;
// Arrays for obstacles and apples
var obstacles = [];
var apples = [];
// Score
var score = 0;
// Distance (for speed up)
var distance = 0;
// GUI
var scoreTxt = new Text2('0', {
size: 120,
fill: "#fff"
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Lane markers (visual only)
for (var i = 1; i < laneCount; i++) {
var marker = LK.getAsset('laneMarker', {
anchorX: 0.5,
anchorY: 0,
x: laneMargin + i * laneWidth,
y: 0,
scaleY: 1
});
game.addChild(marker);
}
// Create horse
var horse = new Horse();
horse.x = laneX(1);
horse.y = groundY;
horse.groundY = groundY;
game.addChild(horse);
// Touch/drag controls
var dragStartX = null;
var dragStartY = null;
var dragStartLane = null;
var dragStartTime = null;
var dragActive = false;
function getLaneFromX(x) {
for (var i = 0; i < laneCount; i++) {
var lx = laneX(i);
if (x < lx + laneWidth / 2) return i;
}
return laneCount - 1;
}
// Touch down: record start
game.down = function (x, y, obj) {
dragStartX = x;
dragStartY = y;
dragStartLane = horse.lane;
dragStartTime = LK.ticks;
dragActive = true;
};
// Touch move: if horizontal drag, change lane
game.move = function (x, y, obj) {
if (!dragActive) return;
var dx = x - dragStartX;
var dy = y - dragStartY;
if (Math.abs(dx) > 80 && Math.abs(dx) > Math.abs(dy)) {
// Lane change
if (dx > 0 && horse.lane < laneCount - 1) {
horse.moveToLane(horse.lane + 1);
dragStartX = x;
dragStartLane = horse.lane;
} else if (dx < 0 && horse.lane > 0) {
horse.moveToLane(horse.lane - 1);
dragStartX = x;
dragStartLane = horse.lane;
}
}
};
// Touch up: if short tap or upward swipe, jump
game.up = function (x, y, obj) {
if (!dragActive) return;
var dt = LK.ticks - dragStartTime;
var dx = x - dragStartX;
var dy = y - dragStartY;
if (dt < 30 && Math.abs(dx) < 60 && Math.abs(dy) < 60) {
// Tap: jump
horse.jump();
} else if (dy < -100 && Math.abs(dy) > Math.abs(dx)) {
// Upward swipe: jump
horse.jump();
}
dragActive = false;
};
// Obstacle/Apple spawn logic
var lastObstacleY = 0;
var lastAppleY = 0;
var minObstacleGap = 520;
var minAppleGap = 340;
var obstacleTypes = ['rock', 'fence', 'puddle'];
// Helper: spawn obstacle at y, lane
function spawnObstacle(type, lane, y) {
var obs;
if (type === 'rock') obs = new Rock();else if (type === 'fence') obs = new Fence();else obs = new Puddle();
obs.lane = lane;
obs.x = laneX(lane);
obs.y = y;
game.addChild(obs);
obstacles.push(obs);
}
// Helper: spawn apple at y, lane
function spawnApple(lane, y) {
var apple = new Apple();
apple.lane = lane;
apple.x = laneX(lane);
apple.y = y;
game.addChild(apple);
apples.push(apple);
}
// Main game update
game.update = function () {
// Speed up over time
if (speed < maxSpeed) speed += speedIncrease;
distance += speed;
// Move obstacles/apples down
for (var i = obstacles.length - 1; i >= 0; i--) {
var obs = obstacles[i];
obs.y += speed;
// Remove if off screen
if (obs.y > 2800) {
obs.destroy();
obstacles.splice(i, 1);
continue;
}
// Collision: only if in same lane and not already hit
if (!obs.hit && obs.lane === horse.lane) {
// Fence: must be jumped over
if (obs instanceof Fence) {
if (Math.abs(obs.y - horse.y) < 120 && horse.jumpY > -40) {
// Not high enough: hit
obs.hit = true;
LK.effects.flashScreen(0xff0000, 800);
LK.showGameOver();
return;
}
} else {
// Rock/Puddle: must be jumped or avoided
if (Math.abs(obs.y - horse.y) < 100 && horse.jumpY > -40) {
obs.hit = true;
LK.effects.flashScreen(0xff0000, 800);
LK.showGameOver();
return;
}
}
}
}
for (var i = apples.length - 1; i >= 0; i--) {
var apple = apples[i];
apple.y += speed;
// Remove if off screen
if (apple.y > 2800) {
apple.destroy();
apples.splice(i, 1);
continue;
}
// Collect: same lane, close, not already collected, and not jumping over
if (!apple.collected && apple.lane === horse.lane && Math.abs(apple.y - horse.y) < 120 && horse.jumpY > -120) {
apple.collected = true;
LK.setScore(LK.getScore() + 1);
scoreTxt.setText(LK.getScore());
// Animate apple
tween(apple, {
y: apple.y - 120,
alpha: 0
}, {
duration: 320,
easing: tween.cubicIn,
onFinish: function onFinish() {
apple.destroy();
}
});
apples.splice(i, 1);
}
}
// Spawn obstacles
if (distance - lastObstacleY > minObstacleGap + Math.random() * 320) {
var type = obstacleTypes[Math.floor(Math.random() * obstacleTypes.length)];
var lane = Math.floor(Math.random() * laneCount);
spawnObstacle(type, lane, -180);
lastObstacleY = distance;
}
// Spawn apples
if (distance - lastAppleY > minAppleGap + Math.random() * 220) {
var lane = Math.floor(Math.random() * laneCount);
spawnApple(lane, -120);
lastAppleY = distance;
}
};
// Reset score on game start
LK.setScore(0);
scoreTxt.setText('0'); ===================================================================
--- original.js
+++ change.js
@@ -1,6 +1,341 @@
-/****
+/****
+* Plugins
+****/
+var tween = LK.import("@upit/tween.v1");
+var storage = LK.import("@upit/storage.v1");
+
+/****
+* Classes
+****/
+// Apple (collectible)
+var Apple = Container.expand(function () {
+ var self = Container.call(this);
+ var appleSprite = self.attachAsset('apple', {
+ anchorX: 0.5,
+ anchorY: 1
+ });
+ self.lane = 1;
+ self.collected = false;
+ self.update = function () {
+ // Movement handled by game
+ };
+ return self;
+});
+// Fence (obstacle)
+var Fence = Container.expand(function () {
+ var self = Container.call(this);
+ var fenceSprite = self.attachAsset('fence', {
+ anchorX: 0.5,
+ anchorY: 1
+ });
+ self.lane = 1;
+ self.hit = false;
+ self.update = function () {};
+ return self;
+});
+// Horse (player) class
+var Horse = Container.expand(function () {
+ var self = Container.call(this);
+ var horseSprite = self.attachAsset('horse', {
+ anchorX: 0.5,
+ anchorY: 1
+ });
+ self.lane = 1; // 0: left, 1: center, 2: right
+ self.isJumping = false;
+ self.jumpY = 0; // Offset for jump animation
+ self.jumpTween = null;
+ self.groundY = 0; // Set after adding to game
+ self.jumpHeight = 320; // How high the horse jumps
+ self.jumpDuration = 420; // ms
+ // Start jump if not already jumping
+ self.jump = function () {
+ if (self.isJumping) return;
+ self.isJumping = true;
+ if (self.jumpTween) tween.stop(self, {
+ jumpY: true
+ });
+ tween(self, {
+ jumpY: -self.jumpHeight
+ }, {
+ duration: self.jumpDuration,
+ easing: tween.cubicOut,
+ onFinish: function onFinish() {
+ tween(self, {
+ jumpY: 0
+ }, {
+ duration: self.jumpDuration,
+ easing: tween.cubicIn,
+ onFinish: function onFinish() {
+ self.isJumping = false;
+ }
+ });
+ }
+ });
+ };
+ // Move to lane (0,1,2)
+ self.moveToLane = function (lane) {
+ if (lane < 0) lane = 0;
+ if (lane > 2) lane = 2;
+ self.lane = lane;
+ // Animate x to new lane
+ var targetX = laneX(lane);
+ tween(self, {
+ x: targetX
+ }, {
+ duration: 120,
+ easing: tween.cubicOut
+ });
+ };
+ // Update position for jump
+ self.update = function () {
+ self.y = self.groundY + self.jumpY;
+ };
+ return self;
+});
+// Puddle (obstacle)
+var Puddle = Container.expand(function () {
+ var self = Container.call(this);
+ var puddleSprite = self.attachAsset('puddle', {
+ anchorX: 0.5,
+ anchorY: 1
+ });
+ self.lane = 1;
+ self.hit = false;
+ self.update = function () {};
+ return self;
+});
+// Rock (obstacle)
+var Rock = Container.expand(function () {
+ var self = Container.call(this);
+ var rockSprite = self.attachAsset('rock', {
+ anchorX: 0.5,
+ anchorY: 1
+ });
+ self.lane = 1;
+ self.hit = false;
+ self.update = function () {};
+ return self;
+});
+
+/****
* Initialize Game
-****/
+****/
var game = new LK.Game({
- backgroundColor: 0x000000
-});
\ No newline at end of file
+ backgroundColor: 0xA7D36C // Soft green field
+});
+
+/****
+* Game Code
+****/
+// Lane marker (for visual lanes) - 8x2732, light gray box
+// Puddle (obstacle) - 140x60, blue ellipse
+// Fence (obstacle) - 160x40, tan box
+// Rock (obstacle) - 120x80, gray ellipse
+// Apple (collectible) - 100x100, red ellipse
+// Horse (player) - 220x180, brown box
+// Lane logic
+var laneCount = 3;
+var laneWidth = 480; // (2048 - 2*104) / 3 = ~613, but use 480 for margin
+var laneMargin = 104; // left/right margin
+function laneX(lane) {
+ return laneMargin + lane * laneWidth + laneWidth / 2;
+}
+// Ground Y (where horse stands)
+var groundY = 2200;
+// Game speed (pixels per tick)
+var baseSpeed = 16;
+var speed = baseSpeed;
+var speedIncrease = 0.0007; // per tick
+var maxSpeed = 38;
+// Arrays for obstacles and apples
+var obstacles = [];
+var apples = [];
+// Score
+var score = 0;
+// Distance (for speed up)
+var distance = 0;
+// GUI
+var scoreTxt = new Text2('0', {
+ size: 120,
+ fill: "#fff"
+});
+scoreTxt.anchor.set(0.5, 0);
+LK.gui.top.addChild(scoreTxt);
+// Lane markers (visual only)
+for (var i = 1; i < laneCount; i++) {
+ var marker = LK.getAsset('laneMarker', {
+ anchorX: 0.5,
+ anchorY: 0,
+ x: laneMargin + i * laneWidth,
+ y: 0,
+ scaleY: 1
+ });
+ game.addChild(marker);
+}
+// Create horse
+var horse = new Horse();
+horse.x = laneX(1);
+horse.y = groundY;
+horse.groundY = groundY;
+game.addChild(horse);
+// Touch/drag controls
+var dragStartX = null;
+var dragStartY = null;
+var dragStartLane = null;
+var dragStartTime = null;
+var dragActive = false;
+function getLaneFromX(x) {
+ for (var i = 0; i < laneCount; i++) {
+ var lx = laneX(i);
+ if (x < lx + laneWidth / 2) return i;
+ }
+ return laneCount - 1;
+}
+// Touch down: record start
+game.down = function (x, y, obj) {
+ dragStartX = x;
+ dragStartY = y;
+ dragStartLane = horse.lane;
+ dragStartTime = LK.ticks;
+ dragActive = true;
+};
+// Touch move: if horizontal drag, change lane
+game.move = function (x, y, obj) {
+ if (!dragActive) return;
+ var dx = x - dragStartX;
+ var dy = y - dragStartY;
+ if (Math.abs(dx) > 80 && Math.abs(dx) > Math.abs(dy)) {
+ // Lane change
+ if (dx > 0 && horse.lane < laneCount - 1) {
+ horse.moveToLane(horse.lane + 1);
+ dragStartX = x;
+ dragStartLane = horse.lane;
+ } else if (dx < 0 && horse.lane > 0) {
+ horse.moveToLane(horse.lane - 1);
+ dragStartX = x;
+ dragStartLane = horse.lane;
+ }
+ }
+};
+// Touch up: if short tap or upward swipe, jump
+game.up = function (x, y, obj) {
+ if (!dragActive) return;
+ var dt = LK.ticks - dragStartTime;
+ var dx = x - dragStartX;
+ var dy = y - dragStartY;
+ if (dt < 30 && Math.abs(dx) < 60 && Math.abs(dy) < 60) {
+ // Tap: jump
+ horse.jump();
+ } else if (dy < -100 && Math.abs(dy) > Math.abs(dx)) {
+ // Upward swipe: jump
+ horse.jump();
+ }
+ dragActive = false;
+};
+// Obstacle/Apple spawn logic
+var lastObstacleY = 0;
+var lastAppleY = 0;
+var minObstacleGap = 520;
+var minAppleGap = 340;
+var obstacleTypes = ['rock', 'fence', 'puddle'];
+// Helper: spawn obstacle at y, lane
+function spawnObstacle(type, lane, y) {
+ var obs;
+ if (type === 'rock') obs = new Rock();else if (type === 'fence') obs = new Fence();else obs = new Puddle();
+ obs.lane = lane;
+ obs.x = laneX(lane);
+ obs.y = y;
+ game.addChild(obs);
+ obstacles.push(obs);
+}
+// Helper: spawn apple at y, lane
+function spawnApple(lane, y) {
+ var apple = new Apple();
+ apple.lane = lane;
+ apple.x = laneX(lane);
+ apple.y = y;
+ game.addChild(apple);
+ apples.push(apple);
+}
+// Main game update
+game.update = function () {
+ // Speed up over time
+ if (speed < maxSpeed) speed += speedIncrease;
+ distance += speed;
+ // Move obstacles/apples down
+ for (var i = obstacles.length - 1; i >= 0; i--) {
+ var obs = obstacles[i];
+ obs.y += speed;
+ // Remove if off screen
+ if (obs.y > 2800) {
+ obs.destroy();
+ obstacles.splice(i, 1);
+ continue;
+ }
+ // Collision: only if in same lane and not already hit
+ if (!obs.hit && obs.lane === horse.lane) {
+ // Fence: must be jumped over
+ if (obs instanceof Fence) {
+ if (Math.abs(obs.y - horse.y) < 120 && horse.jumpY > -40) {
+ // Not high enough: hit
+ obs.hit = true;
+ LK.effects.flashScreen(0xff0000, 800);
+ LK.showGameOver();
+ return;
+ }
+ } else {
+ // Rock/Puddle: must be jumped or avoided
+ if (Math.abs(obs.y - horse.y) < 100 && horse.jumpY > -40) {
+ obs.hit = true;
+ LK.effects.flashScreen(0xff0000, 800);
+ LK.showGameOver();
+ return;
+ }
+ }
+ }
+ }
+ for (var i = apples.length - 1; i >= 0; i--) {
+ var apple = apples[i];
+ apple.y += speed;
+ // Remove if off screen
+ if (apple.y > 2800) {
+ apple.destroy();
+ apples.splice(i, 1);
+ continue;
+ }
+ // Collect: same lane, close, not already collected, and not jumping over
+ if (!apple.collected && apple.lane === horse.lane && Math.abs(apple.y - horse.y) < 120 && horse.jumpY > -120) {
+ apple.collected = true;
+ LK.setScore(LK.getScore() + 1);
+ scoreTxt.setText(LK.getScore());
+ // Animate apple
+ tween(apple, {
+ y: apple.y - 120,
+ alpha: 0
+ }, {
+ duration: 320,
+ easing: tween.cubicIn,
+ onFinish: function onFinish() {
+ apple.destroy();
+ }
+ });
+ apples.splice(i, 1);
+ }
+ }
+ // Spawn obstacles
+ if (distance - lastObstacleY > minObstacleGap + Math.random() * 320) {
+ var type = obstacleTypes[Math.floor(Math.random() * obstacleTypes.length)];
+ var lane = Math.floor(Math.random() * laneCount);
+ spawnObstacle(type, lane, -180);
+ lastObstacleY = distance;
+ }
+ // Spawn apples
+ if (distance - lastAppleY > minAppleGap + Math.random() * 220) {
+ var lane = Math.floor(Math.random() * laneCount);
+ spawnApple(lane, -120);
+ lastAppleY = distance;
+ }
+};
+// Reset score on game start
+LK.setScore(0);
+scoreTxt.setText('0');
\ No newline at end of file
horse with tongue sticking out with saddle . No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
horse dung with green whiff cloud trailing out. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
APPLE . No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
unlucky horse shoe. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat