/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Coin class
var Coin = Container.expand(function () {
var self = Container.call(this);
// Attach asset (ellipse for now)
var coinAsset = self.attachAsset('coin', {
anchorX: 0.5,
anchorY: 0.5
});
coinAsset.width = 90;
coinAsset.height = 90;
// Animation: simple up-down bob
self.bobPhase = Math.random() * Math.PI * 2;
self.update = function () {
self.x -= gameSpeed;
coinAsset.y = Math.sin(LK.ticks * 0.15 + self.bobPhase) * 12;
};
return self;
});
// Obstacle class
var Obstacle = Container.expand(function () {
var self = Container.call(this);
// Randomly choose obstacle type: "low" (jump over) or "high" (slide under)
self.type = Math.random() < 0.5 ? 'low' : 'high';
// Attach asset
if (self.type === 'low') {
// Low obstacle: box, short and wide
self.asset = self.attachAsset('obstacleLow', {
anchorX: 0.5,
anchorY: 1
});
} else {
// High obstacle: box, tall and narrow
self.asset = self.attachAsset('obstacleHigh', {
anchorX: 0.5,
anchorY: 1
});
}
// Set size
if (self.type === 'low') {
self.asset.width = 180;
self.asset.height = 120;
} else {
self.asset.width = 120;
self.asset.height = 260;
}
// Update per frame
self.update = function () {
self.x -= gameSpeed;
};
return self;
});
// Player character class
var Runner = Container.expand(function () {
var self = Container.call(this);
// Attach runner asset (box for now)
var runnerAsset = self.attachAsset('runner', {
anchorX: 0.5,
anchorY: 1
});
// Physics
self.vy = 0;
self.isJumping = false;
self.isSliding = false;
self.slideTimer = 0;
// Constants
var GRAVITY = 2.2;
var JUMP_VELOCITY = -48;
var SLIDE_DURATION = 36; // ~0.6s at 60fps
// Runner size for collision
self.normalHeight = runnerAsset.height;
self.slideHeight = runnerAsset.height * 0.5;
// Methods
self.jump = function () {
if (!self.isJumping && !self.isSliding) {
self.vy = JUMP_VELOCITY;
self.isJumping = true;
}
};
self.slide = function () {
if (!self.isSliding && !self.isJumping) {
self.isSliding = true;
self.slideTimer = SLIDE_DURATION;
// Animate to slide
tween(runnerAsset, {
height: self.slideHeight
}, {
duration: 120,
easing: tween.cubicOut
});
}
};
self.standUp = function () {
if (self.isSliding) {
self.isSliding = false;
// Animate back to normal
tween(runnerAsset, {
height: self.normalHeight
}, {
duration: 120,
easing: tween.cubicOut
});
}
};
// Update per frame
self.update = function () {
// Jumping physics
if (self.isJumping) {
self.y += self.vy;
self.vy += GRAVITY;
if (self.y >= groundY) {
self.y = groundY;
self.vy = 0;
self.isJumping = false;
}
}
// Sliding timer
if (self.isSliding) {
self.slideTimer--;
if (self.slideTimer <= 0) {
self.standUp();
}
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x222a36
});
/****
* Game Code
****/
// Game constants
var groundY = 2200; // Y position of the ground
var runnerStartX = 420;
var gameSpeed = 14.4; // Initial speed (pixels per frame) - reduced by 40%
var speedIncreaseEvery = 840; // Increase speed every N ticks - slowed by 40%
var speedIncreaseAmount = 0.72; // Speed increase per step - reduced by 40%
var maxGameSpeed = 28.8; // Max speed - reduced by 40%
// Arrays for obstacles and coins
var obstacles = [];
var coins = [];
// Score and distance
var score = 0;
var distance = 0;
// Coin system
var coinsCollected = 0;
var coinTxt = new Text2('0', {
size: 90,
fill: 0xFFE066
});
coinTxt.anchor.set(0, 0);
LK.gui.top.addChild(coinTxt);
coinTxt.x = 120; // Avoid top left menu
coinTxt.y = 10;
// GUI
var scoreTxt = new Text2('0', {
size: 110,
fill: "#fff"
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
var distanceTxt = new Text2('0m', {
size: 70,
fill: "#fff"
});
distanceTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(distanceTxt);
distanceTxt.y = 120;
// Create runner
var runner = new Runner();
game.addChild(runner);
runner.x = runnerStartX;
runner.y = groundY;
// Ground visual (simple box)
var ground = LK.getAsset('ground', {
anchorX: 0,
anchorY: 0,
width: 2048,
height: 40,
y: groundY + 1,
x: 0
});
game.addChild(ground);
// Spawn timers
var obstacleTimer = 0;
var coinTimer = 0;
// Touch/gesture handling
var dragStartY = null;
var dragStartX = null;
var dragStartTime = null;
var gestureActive = false;
// Helper: check collision between two containers (AABB)
function isColliding(a, b) {
var ab = a.getBounds();
var bb = b.getBounds();
return ab.x + ab.width > bb.x && ab.x < bb.x + bb.width && ab.y + ab.height > bb.y && ab.y < bb.y + bb.height;
}
// Handle tap/swipe for jump/slide
game.down = function (x, y, obj) {
dragStartY = y;
dragStartX = x;
dragStartTime = LK.ticks;
gestureActive = true;
};
game.up = function (x, y, obj) {
if (!gestureActive) return;
var dy = y - dragStartY;
var dx = x - dragStartX;
var dt = LK.ticks - dragStartTime;
gestureActive = false;
// Simple swipe detection
if (dt < 30) {
// Quick gesture
if (Math.abs(dy) > Math.abs(dx)) {
if (dy < -80) {
// Swipe up: jump
runner.jump();
} else if (dy > 80) {
// Swipe down: slide
runner.slide();
}
} else {
// Could add left/right actions here
}
} else {
// Tap (short press): jump
if (Math.abs(dy) < 40 && Math.abs(dx) < 40) {
runner.jump();
}
}
};
// Prevent runner from being dragged
game.move = function (x, y, obj) {
// No drag for runner
};
// Main update loop
game.update = function () {
// Increase speed over time
if (LK.ticks % speedIncreaseEvery === 0 && gameSpeed < maxGameSpeed) {
gameSpeed += speedIncreaseAmount;
if (gameSpeed > maxGameSpeed) gameSpeed = maxGameSpeed;
}
// Update runner
runner.update();
// Spawn obstacles
obstacleTimer--;
if (obstacleTimer <= 0) {
var obs = new Obstacle();
obs.x = 2048 + 120;
if (obs.type === 'low') {
obs.y = groundY;
} else {
// High obstacle: place so runner must slide under
obs.y = groundY - 100;
}
game.addChild(obs);
obstacles.push(obs);
// Next obstacle in 1.1-1.7s (randomized)
obstacleTimer = 66 + Math.floor(Math.random() * 36);
}
// Spawn coins
coinTimer--;
if (coinTimer <= 0) {
var coin = new Coin();
coin.x = 2048 + 90;
// Place coin at random height: above, at, or below runner
var coinYType = Math.floor(Math.random() * 3);
if (coinYType === 0) {
coin.y = groundY - 320; // high
} else if (coinYType === 1) {
coin.y = groundY - 120; // mid
} else {
coin.y = groundY - 40; // low
}
game.addChild(coin);
coins.push(coin);
// Next coin in 0.7-1.2s
coinTimer = 42 + Math.floor(Math.random() * 30);
}
// Update obstacles
for (var i = obstacles.length - 1; i >= 0; i--) {
var obs = obstacles[i];
obs.update();
// Remove if off screen
if (obs.x < -200) {
obs.destroy();
obstacles.splice(i, 1);
continue;
}
// Collision with runner
if (isColliding(runner, obs)) {
// If obstacle is low, must jump; if high, must slide
if (obs.type === 'low') {
if (!runner.isJumping) {
LK.effects.flashScreen(0xff0000, 800);
LK.showGameOver();
return;
}
} else {
// High obstacle
var runnerAsset = runner.children[0];
if (!runner.isSliding || runnerAsset.height > runner.slideHeight + 2) {
LK.effects.flashScreen(0xff0000, 800);
LK.showGameOver();
return;
}
}
}
}
// Update coins
for (var j = coins.length - 1; j >= 0; j--) {
var coin = coins[j];
coin.update();
// Remove if off screen
if (coin.x < -100) {
coin.destroy();
coins.splice(j, 1);
continue;
}
// Collect coin
if (isColliding(runner, coin)) {
score += 1;
LK.setScore(score);
scoreTxt.setText(score);
// Coin system: increment and update coin count
coinsCollected += 1;
coinTxt.setText(coinsCollected);
coin.destroy();
coins.splice(j, 1);
// Flash coin
LK.effects.flashObject(runner, 0xffe066, 200);
}
}
// Update distance
distance += gameSpeed * 0.18; // scale to meters
distanceTxt.setText(Math.floor(distance) + "m");
};
// Asset initialization (shapes) ===================================================================
--- original.js
+++ change.js
@@ -154,8 +154,18 @@
var coins = [];
// Score and distance
var score = 0;
var distance = 0;
+// Coin system
+var coinsCollected = 0;
+var coinTxt = new Text2('0', {
+ size: 90,
+ fill: 0xFFE066
+});
+coinTxt.anchor.set(0, 0);
+LK.gui.top.addChild(coinTxt);
+coinTxt.x = 120; // Avoid top left menu
+coinTxt.y = 10;
// GUI
var scoreTxt = new Text2('0', {
size: 110,
fill: "#fff"
@@ -324,8 +334,11 @@
if (isColliding(runner, coin)) {
score += 1;
LK.setScore(score);
scoreTxt.setText(score);
+ // Coin system: increment and update coin count
+ coinsCollected += 1;
+ coinTxt.setText(coinsCollected);
coin.destroy();
coins.splice(j, 1);
// Flash coin
LK.effects.flashObject(runner, 0xffe066, 200);
Street. In-Game asset. 2d. High contrast. No shadows
Sprey. In-Game asset. 2d. High contrast. No shadows
Street wall. In-Game asset. 2d. High contrast. No shadows
Duvar. In-Game asset. 2d. High contrast. No shadows
Gercekci duvar. In-Game asset. 2d. High contrast. No shadows
Kosucu. In-Game asset. 2d. High contrast. No shadows