User prompt
Eğer canın fullse ekstra can bari koy
User prompt
Engeller her 1500 adımda kosunun üzerine gelsin
User prompt
Her 1800 metrede bir otomatik can yenile
User prompt
Her 1000 metrede bir otomatik can yenile
User prompt
Her 1000 metrede bir can koy
User prompt
Her 1000 metrede bir %3 hiz artsın
User prompt
Her 1000 metrede bir oyun hızı %5 artsın
User prompt
Her 1000 metrede engeller arasındaki mesafe %10 artsın
User prompt
Engeller arasındaki mesafe %15 artır
User prompt
Engeller arasındaki mesafeyi %15 azalsın
User prompt
Canın azalınca 5 saniyeliğine hasar alma
User prompt
Bana arka plan aseti olsutur
User prompt
Engeller arasındaki mesafeyi %10 daha azalt
User prompt
Engeller arasındaki mesafeyi kısalt
User prompt
Yeni engel ekle
User prompt
Devam et
User prompt
Obstaclelow ararindaki mesafeyi %15 azalt
User prompt
Runner canı 5 olsun
User prompt
Obscatle hight %8 aşağı indir
User prompt
Obstacle hight %2 aşağı indir
User prompt
Obsacahight %2 indir
User prompt
Obsaca hight %2 indir
User prompt
Obsace hight %2 aşağı indir
User prompt
Obasaca hight %20 aşağı indir
User prompt
Obsatcilhigh %30daha yukarda olsun
/****
* 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), "high" (slide under), or "spike" (new)
var r = Math.random();
if (r < 0.45) {
self.type = 'low';
} else if (r < 0.9) {
self.type = 'high';
} else {
self.type = 'spike';
}
// Attach asset
if (self.type === 'low') {
// Low obstacle: box, short and wide
self.asset = self.attachAsset('obstacleLow', {
anchorX: 0.5,
anchorY: 1
});
} else if (self.type === 'high') {
// High obstacle: box, tall and narrow
self.asset = self.attachAsset('obstacleHigh', {
anchorX: 0.5,
anchorY: 1
});
} else {
// Spike obstacle: ellipse, short and narrow, dangerous
self.asset = self.attachAsset('obstacleSpike', {
anchorX: 0.5,
anchorY: 1
});
}
// Set size
if (self.type === 'low') {
self.asset.width = 180;
self.asset.height = 120;
} else if (self.type === 'high') {
self.asset.width = 120;
self.asset.height = 260;
} else {
self.asset.width = 120;
self.asset.height = 120;
}
// 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
// Background asset: a tall, wide box with a soft blue color for sky
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;
// Obstacle spacing multiplier, increases by 10% every 1000m
var obstacleSpacingMultiplier = 1;
var lastDistanceMilestone = 0;
// Runner lives (can) system
var runnerLives = 5;
var maxRunnerLives = 5;
var heartIcons = [];
// Invulnerability state and timer
var isInvulnerable = false;
var invulnerableTimer = 0;
var INVULNERABLE_DURATION = 300; // 5 seconds at 60fps
for (var h = 0; h < maxRunnerLives; h++) {
var heart = new Text2("❤", {
size: 90,
fill: 0xFF4D4D
});
heart.anchor.set(0, 0);
LK.gui.top.addChild(heart);
heart.x = 240 + h * 80;
heart.y = 10;
heartIcons.push(heart);
}
function updateHearts() {
for (var h = 0; h < maxRunnerLives; h++) {
heartIcons[h].alpha = h < runnerLives ? 1 : 0.25;
}
}
updateHearts();
// 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;
// Add background asset (sky) behind all gameplay elements
var background = LK.getAsset('background', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0,
width: 2048,
height: 2732
});
game.addChild(background);
// 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 invulnerability timer and visual feedback
if (isInvulnerable) {
invulnerableTimer--;
// Flicker runner for feedback
var runnerAsset = runner.children[0];
runnerAsset.alpha = LK.ticks % 12 < 6 ? 0.4 : 1;
if (invulnerableTimer <= 0) {
isInvulnerable = false;
runnerAsset.alpha = 1;
}
}
// Update runner
runner.update();
// Spawn obstacles
obstacleTimer--;
if (obstacleTimer <= 0) {
var obs = new Obstacle();
obs.x = 2048 + 120;
// Every 1500 steps, drop obstacle from above runner
if (Math.floor(distance) > 0 && Math.floor(distance) % 1500 < gameSpeed * 0.18) {
// Place above runner, falling down
obs.x = runner.x + 40; // slightly ahead of runner
obs.y = groundY - 900; // start high above
obs.fallingOnRunner = true;
obs.fallVy = 0;
obs.fallGravity = 3.2 + Math.random() * 1.5;
} else {
if (obs.type === 'low') {
obs.y = groundY;
} else if (obs.type === 'high') {
// High obstacle: place so runner must slide under, 2% higher (10% - 8% = 2%)
obs.y = groundY - 100 - 0.02 * 2200; // 2200 is groundY, so 2% higher
} else {
// Spike obstacle: always at ground level
obs.y = groundY;
}
}
game.addChild(obs);
obstacles.push(obs);
// Next obstacle in 1.5-2.2s (randomized) - obstacles are a bit rarer
if (obs.type === 'low') {
// Increase low obstacle spacing by 15% and by 10% every 1000m
obstacleTimer = Math.floor((90 + Math.floor(Math.random() * 42)) * 0.85 * 0.8 * 0.9 * 0.85 * 1.15 * obstacleSpacingMultiplier);
} else if (obs.type === 'high') {
obstacleTimer = Math.floor((90 + Math.floor(Math.random() * 42)) * 0.8 * 0.9 * 0.85 * 1.15 * obstacleSpacingMultiplier);
} else {
// Spikes: slightly rarer, also increase by 15% more and by 10% every 1000m
obstacleTimer = Math.floor((120 + Math.floor(Math.random() * 60)) * 0.8 * 0.9 * 0.85 * 1.15 * obstacleSpacingMultiplier);
}
}
// 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];
// Update falling obstacles
if (obs.fallingOnRunner) {
if (obs.lastY === undefined) obs.lastY = obs.y;
obs.fallVy += obs.fallGravity;
obs.y += obs.fallVy;
// When it lands on ground, stop falling
if (obs.lastY < groundY && obs.y >= groundY) {
obs.y = groundY;
obs.fallingOnRunner = false;
obs.fallVy = 0;
}
obs.lastY = obs.y;
} else {
obs.update();
}
// Remove if off screen
if (obs.x < -200 || obs.y > 3000) {
obs.destroy();
obstacles.splice(i, 1);
continue;
}
// Collision with runner
if (isColliding(runner, obs)) {
// If invulnerable, ignore obstacle and do not remove it
if (isInvulnerable) {
continue;
}
// If obstacle is low, must jump; if high, must slide; if spike, must jump
if (obs.type === 'low') {
if (!runner.isJumping) {
LK.effects.flashScreen(0xff0000, 800);
runnerLives--;
updateHearts();
if (runnerLives <= 0) {
LK.showGameOver();
return;
}
// Set invulnerability
isInvulnerable = true;
invulnerableTimer = INVULNERABLE_DURATION;
// Remove obstacle and continue
obs.destroy();
obstacles.splice(i, 1);
continue;
}
} else if (obs.type === 'high') {
// High obstacle
var runnerAsset = runner.children[0];
if (!runner.isSliding || runnerAsset.height > runner.slideHeight + 2) {
LK.effects.flashScreen(0xff0000, 800);
runnerLives--;
updateHearts();
if (runnerLives <= 0) {
LK.showGameOver();
return;
}
// Set invulnerability
isInvulnerable = true;
invulnerableTimer = INVULNERABLE_DURATION;
// Remove obstacle and continue
obs.destroy();
obstacles.splice(i, 1);
continue;
}
} else if (obs.type === 'spike') {
// Spike: always hurts unless jumping
if (!runner.isJumping) {
LK.effects.flashScreen(0xff0000, 800);
runnerLives--;
updateHearts();
if (runnerLives <= 0) {
LK.showGameOver();
return;
}
// Set invulnerability
isInvulnerable = true;
invulnerableTimer = INVULNERABLE_DURATION;
// Remove obstacle and continue
obs.destroy();
obstacles.splice(i, 1);
continue;
}
}
}
}
// 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 or heart
if (isColliding(runner, coin)) {
if (coin.isHeart) {
// Heart collectible: increase life if not max
if (runnerLives < maxRunnerLives) {
runnerLives++;
updateHearts();
LK.effects.flashObject(runner, 0xFF4D4D, 400);
}
} else {
score += 1;
LK.setScore(score);
scoreTxt.setText(score);
// Coin system: increment and update coin count
coinsCollected += 1;
coinTxt.setText(coinsCollected);
LK.effects.flashObject(runner, 0xffe066, 200);
}
coin.destroy();
coins.splice(j, 1);
}
}
// Update distance
distance += gameSpeed * 0.18; // scale to meters
distanceTxt.setText(Math.floor(distance) + "m");
// Every 1800 meters, increase obstacle spacing multiplier by 10% and game speed by 3%
if (Math.floor(distance / 1800) > lastDistanceMilestone) {
lastDistanceMilestone = Math.floor(distance / 1800);
obstacleSpacingMultiplier *= 1.1;
// Increase game speed by 3% every 1800 meters, but do not exceed maxGameSpeed
gameSpeed *= 1.03;
if (gameSpeed > maxGameSpeed) gameSpeed = maxGameSpeed;
// Add a heart collectible (life) every 1800 meters
if (runnerLives < maxRunnerLives) {
// Automatically restore one life
runnerLives++;
updateHearts();
LK.effects.flashObject(runner, 0xFF4D4D, 400);
// Still spawn a heart collectible for extra chance if not at max
var heartCollectible = new Coin(); // Use Coin class for heart collectible for now
heartCollectible.x = 2048 + 90;
heartCollectible.y = groundY - 320; // Place high to reward skill
// Change appearance to heart
if (heartCollectible.children.length > 0) {
var asset = heartCollectible.children[0];
asset.width = 90;
asset.height = 90;
asset.setText && asset.setText("❤");
asset.fill = 0xFF4D4D;
}
heartCollectible.isHeart = true;
game.addChild(heartCollectible);
coins.push(heartCollectible);
} else {
// If lives are full, spawn an extra heart collectible for bonus
var extraHeart = new Coin();
extraHeart.x = 2048 + 90;
extraHeart.y = groundY - 320;
if (extraHeart.children.length > 0) {
var asset = extraHeart.children[0];
asset.width = 90;
asset.height = 90;
asset.setText && asset.setText("❤");
asset.fill = 0xFF4D4D;
}
extraHeart.isHeart = true;
extraHeart.isBonusHeart = true; // Mark as bonus for possible future logic
game.addChild(extraHeart);
coins.push(extraHeart);
}
}
};
// Asset initialization (shapes) ===================================================================
--- original.js
+++ change.js
@@ -527,8 +527,24 @@
}
heartCollectible.isHeart = true;
game.addChild(heartCollectible);
coins.push(heartCollectible);
+ } else {
+ // If lives are full, spawn an extra heart collectible for bonus
+ var extraHeart = new Coin();
+ extraHeart.x = 2048 + 90;
+ extraHeart.y = groundY - 320;
+ if (extraHeart.children.length > 0) {
+ var asset = extraHeart.children[0];
+ asset.width = 90;
+ asset.height = 90;
+ asset.setText && asset.setText("❤");
+ asset.fill = 0xFF4D4D;
+ }
+ extraHeart.isHeart = true;
+ extraHeart.isBonusHeart = true; // Mark as bonus for possible future logic
+ game.addChild(extraHeart);
+ coins.push(extraHeart);
}
}
};
// Asset initialization (shapes)
\ No newline at end of file
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