User prompt
cat 2 karakterini lütfen büyütelim
User prompt
cat2 karakterini şütfen büyütelim
User prompt
cat2 düşmanı sağ alt zeminin üzerine eklermisin rica etsem
User prompt
güneş1 karakteirni biraz büyütürmüsün
User prompt
güneş1 karakterini sağ üste eklermsin rica etsem
User prompt
zemin sola doğru akmaya devam etsin lütfen
User prompt
zemin yollunu tek şerit gibi uzatırmısın rica etsem
User prompt
zemindeki boşlukları kapatırmısın lütfen
User prompt
zemin resminde boşluklar onları doldurmusun rica etsem
User prompt
arkaplandaki zemin resmini birbileriyle birleştitrimisn rica etsem aralarında boşluk var tam yolmuş gibi
User prompt
kedi hareket ettikçe zemin desola doğru harekt etsin lütfen
User prompt
kedinin ve kaktüslerin altına background olarak ayaklarının dibinden başlamak kahidesiyle zemin resmini eklermisn rica etsem
User prompt
ana karakterimin altına bacaklarının altına toprak zemin eklermsin katüs kedinin altına
User prompt
kedicik yürüken zemin resminin üzerinde yürsün lütfen
User prompt
kedi boşlukta koşmasın zemin resmini kedinin koşması için düzenlermsin rica etsem
User prompt
arka plandaki resmi uzatıp sadce kedinin alt kısmı için dağıtmak bastgından sonra zemin olara
User prompt
katüsle kedinin ayaklarının altına zemin resmini koyarmısın rica etsem
User prompt
layer kum zemin olarak ayarla lütfen
User prompt
arka plandaki resmi uzatıp sadce kedinin alt kısmı için dağıtmak bastgından sonra zemin olara
User prompt
kum resmini background olacak sekilde kedi ve katüsün altına getirsmiisn lütfen
User prompt
yukardaki kum resmini kedinin aykların altına getirmsin lütfen
User prompt
o uzzatgın kum resmi kedinin altında toprak olarak kullanman gerkiyor
User prompt
resimlerdeki kum resmini zemin olarak kullan lütfen uzatarak kedi gittignde oda sola dogru gelsin
User prompt
kum resmini zemin olarak kullan lütfen
User prompt
kum fayansını lütfen kedinin ayağından sonrasından başlatalım
/**** * Classes ****/ // Bird class: flies from right to left, above ground, destroys itself off screen var Bird = Container.expand(function () { var self = Container.call(this); // Use 'gunes' asset for bird (placeholder, should be replaced with a bird asset if available) var birdSprite = self.attachAsset('gunes', { anchorX: 0.5, anchorY: 0.5 }); birdSprite.width = 120; birdSprite.height = 90; birdSprite.tint = 0x888888; birdSprite.alpha = 0.92; self.speed = 10 + Math.random() * 4; self.update = function () { self.x -= self.speed; // Destroy if off screen if (self.lastX >= -200 && self.x < -200) { self.destroy(); } self.lastX = self.x; }; return self; }); // Cactus class: moves left, destroys itself off screen var Cactus = Container.expand(function () { var self = Container.call(this); // Attach cactus asset, anchor bottom left var cactusSprite = self.attachAsset('cactus', { anchorX: 0.5, anchorY: 1 }); self.speed = 7 + Math.random() * 2; // even slower speed for easier gameplay self.update = function () { self.x -= self.speed; // Destroy if off screen if (self.lastX >= -200 && self.x < -200) { self.destroy(); } self.lastX = self.x; }; return self; }); // Cat class: handles jump, gravity, and collision var Cat = Container.expand(function () { var self = Container.call(this); // Attach cat asset, anchor bottom left for ground logic var catSprite = self.attachAsset('cat', { anchorX: 0.5, anchorY: 1 }); // Cat physics self.y = 0; self.x = 0; self.vy = 0; self.isJumping = false; self.groundY = 0; // will be set after creation // Double jump state self.jumpCount = 0; self.maxJumps = 2; // Jump parameters self.jumpVelocity = -65; self.gravity = 4; // Update method for physics self.update = function () { // Handle 3-second glide if long press is active, but only once per jump and only if stamina is full if (typeof isPressing !== "undefined" && isPressing && self.isJumping && !glideActive && !self.hasGlided && self.vy > 0 && typeof stamina !== "undefined" && stamina >= maxStamina) { // Only start glide if falling, not already gliding, haven't glided yet this jump, and stamina is full if (LK.ticks - pressStartTick >= 18) { // ~300ms threshold to avoid accidental short taps glideActive = true; self.isHovering = false; self.hasHovered = true; self.glideStartTick = LK.ticks; self.vy = 0; self.hasGlided = true; // Mark that we've glided this jump // Consume all stamina stamina = 0; staminaBar.width = Math.max(1, stamina / maxStamina * staminaBarFullWidth); // Activate bird damage immunity for 5 seconds birdImmunityActive = true; birdImmunityStartTick = LK.ticks; } } // If gliding, keep cat in air for up to 3 seconds (180 ticks) if (typeof glideActive !== "undefined" && glideActive) { if (LK.ticks - self.glideStartTick < 180) { // Stay in air, do not apply gravity, regardless of isPressing return; } else { // End glide glideActive = false; } } if (self.isJumping) { // If we are hovering, do not apply gravity or move if (self.isHovering) { // Determine hover duration: 12 ticks (195ms) for first jump, 6 ticks (100ms) for others var hoverDuration = self.jumpCount === 1 ? 12 : 6; if (LK.ticks - self.hoverStartTick >= hoverDuration) { self.isHovering = false; // Resume falling, keep vy as 0 so gravity starts pulling down self.vy = 0; } // While hovering, do nothing else return; } // Normal jump/fall self.vy += self.gravity; self.y += self.vy; // At apex: vy just turned positive (was going up, now going down) if (!self.isHovering && self.vy > 0 && !self.hasHovered) { self.isHovering = true; self.hasHovered = true; self.hoverStartTick = LK.ticks; self.vy = 0; // Stop vertical movement during hover return; } // Land on ground if (self.y >= self.groundY) { self.y = self.groundY; self.vy = 0; self.isJumping = false; self.isHovering = false; self.hasHovered = false; // If we just finished a glide (hasGlided true, glideActive false), start counting cacti for stamina refill if (typeof self.hasGlided !== "undefined" && self.hasGlided && typeof glideActive !== "undefined" && !glideActive) { // Start post-glide cactus counting if (typeof postGlideCactusCounter === "undefined") postGlideCactusCounter = 0; postGlideCactusCounter = 0; postGlideCountingActive = true; } self.hasGlided = false; // Reset glide on landing self.jumpCount = 0; // Reset jump count on landing } } }; // Jump method self.jump = function () { if (self.jumpCount < self.maxJumps) { self.isJumping = true; self.vy = self.jumpVelocity; self.isHovering = false; self.hasHovered = false; self.hasGlided = false; // Allow one glide per jump self.hoverStartTick = 0; self.jumpCount++; // Play cat sound on jump LK.getSound('kedi').play(); } }; return self; }); // Cloud class: moves left, destroys itself off screen var Cloud = Container.expand(function () { var self = Container.call(this); // Use a white ellipse for the cloud var cloudSprite = self.attachAsset('centerCircle', { anchorX: 0.5, anchorY: 0.5 }); // Randomize cloud size var scale = 1.2 + Math.random() * 1.2; cloudSprite.width = 320 * scale; cloudSprite.height = 120 * scale; cloudSprite.tint = 0xFFFFFF; cloudSprite.alpha = 0.7 + Math.random() * 0.2; self.speed = 1.5 + Math.random() * 1.2; self.update = function () { self.x -= self.speed; if (self.lastX >= -400 && self.x < -400) { self.destroy(); } self.lastX = self.x; }; return self; }); // Gold class: moves left, destroys itself off screen, collectible by cat var Gold = Container.expand(function () { var self = Container.call(this); // Attach gold asset, anchor center var goldSprite = self.attachAsset('ghost', { anchorX: 0.5, anchorY: 0.5 }); goldSprite.width = 80; goldSprite.height = 80; self.speed = 7 + Math.random() * 2; self.collected = false; self.update = function () { self.x -= self.speed; // Destroy if off screen if (self.lastX >= -200 && self.x < -200) { self.destroy(); } self.lastX = self.x; }; return self; }); // Sun class: static, top right var Sun = Container.expand(function () { var self = Container.call(this); // Use a yellow ellipse for the sun var sunSprite = self.attachAsset('centerCircle', { anchorX: 0.5, anchorY: 0.5 }); sunSprite.width = 260; sunSprite.height = 260; sunSprite.tint = 0xFFF700; sunSprite.alpha = 0.95; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0xF7E9A0 // light sand yellow, desert-like }); /**** * Game Code ****/ ; // --- GAME CODE --- // --- Scrolling sand ground (kum) --- // We'll tile enough kum images to cover the screen width, and scroll them leftward. // When a kum tile moves off the left, move it to the right to loop seamlessly. var KUM_TILE_WIDTH = 200; // Use 200px for a bit of overlap and to reduce number of tiles var KUM_TILE_HEIGHT = 120; // Height of the sand ground var KUM_Y = GROUND_Y + 60; // Place under cat/cacti (centered at ground + half height) var kumTiles = []; var kumTileCount = Math.ceil(2048 / KUM_TILE_WIDTH) + 2; // +2 for seamless looping // Start kum tiles after the cat's feet (right after cat's right edge) var kumStartX = CAT_START_X + 100; // 100 is half cat width (cat is 200px wide) for (var i = 0; i < kumTileCount; i++) { var kumTile = LK.getAsset('kum', { anchorX: 0, anchorY: 0.5 }); kumTile.width = KUM_TILE_WIDTH; kumTile.height = KUM_TILE_HEIGHT; kumTile.x = kumStartX + i * KUM_TILE_WIDTH; kumTile.y = GROUND_Y + KUM_TILE_HEIGHT / 2; game.addChild(kumTile); kumTiles.push(kumTile); } // Remove old groundPath and pebbles/stripes code (they will be replaced by kum tiles) // (groundPath, pebbles, and stripes removed - replaced by kum tiles) // Sun and clouds var sun; var clouds = []; var nextCloudTick = 0; // Birds var birds = []; var nextBirdTick = 0; // Game constants var GROUND_Y = 2200; // y position of ground (bottom of screen minus margin) var CAT_START_X = 400; var CAT_START_Y = GROUND_Y; var CACTUS_SPAWN_MIN = 70; // min frames between cacti (slower, more time to jump) var CACTUS_SPAWN_MAX = 130; // max frames between cacti (slower, more time to jump) // Game state var cat; var cacti = []; var golds = []; var score = 0; var goldScore = 0; var scoreTxt; var goldScoreTxt; var nextCactusTick = 0; var nextGoldTick = 0; var gameOver = false; // On game start, stamina is full stamina = maxStamina; if (typeof staminaBar !== "undefined") { staminaBar.width = Math.max(1, stamina / maxStamina * staminaBarFullWidth); } // Track how many cacti have been jumped over for stamina refill var cactiJumpedOver = 0; // Track post-glide cactus counting for stamina refill var postGlideCactusCounter = 0; var postGlideCountingActive = false; // Speed multiplier for game progression var speedMultiplier = 1; var SPEED_MULTIPLIER_INCREMENT = 0.08; // how much to increase per score var SPEED_MULTIPLIER_MAX = 3; // cap the speed increase // HP bar variables var maxHp = 100; var hp = maxHp; var hpBarFullWidth = 420; var hpBarHeight = 38; // Add HP bar background (grey) var hpBarBg = LK.getAsset('centerCircle', { anchorX: 0, anchorY: 0 }); hpBarBg.width = hpBarFullWidth; hpBarBg.height = hpBarHeight; hpBarBg.x = 110; hpBarBg.y = 30; hpBarBg.tint = 0x444444; hpBarBg.alpha = 0.45; LK.gui.top.addChild(hpBarBg); // Add HP bar (red) var hpBar = LK.getAsset('centerCircle', { anchorX: 0, anchorY: 0 }); hpBar.width = hpBarFullWidth; hpBar.height = hpBarHeight; hpBar.x = 110; hpBar.y = 30; hpBar.tint = 0xff4444; hpBar.alpha = 0.95; LK.gui.top.addChild(hpBar); // --- Stamina bar variables and GUI --- var maxStamina = 100; var stamina = maxStamina; var staminaBarFullWidth = 420; var staminaBarHeight = 28; // Stamina bar background (grey, below HP bar) var staminaBarBg = LK.getAsset('centerCircle', { anchorX: 0, anchorY: 0 }); staminaBarBg.width = staminaBarFullWidth; staminaBarBg.height = staminaBarHeight; staminaBarBg.x = 110; staminaBarBg.y = 80; staminaBarBg.tint = 0x444444; staminaBarBg.alpha = 0.35; LK.gui.top.addChild(staminaBarBg); // Stamina bar (blue) var staminaBar = LK.getAsset('centerCircle', { anchorX: 0, anchorY: 0 }); staminaBar.width = staminaBarFullWidth; staminaBar.height = staminaBarHeight; staminaBar.x = 110; staminaBar.y = 80; staminaBar.tint = 0x44aaff; staminaBar.alpha = 0.95; LK.gui.top.addChild(staminaBar); // Add score text to GUI scoreTxt = new Text2('0', { size: 120, fill: 0xFFFFFF }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); // Gold score text (smaller, right of score) goldScoreTxt = new Text2('0', { size: 90, fill: 0xFFD700 // gold color }); goldScoreTxt.anchor.set(0, 0); goldScoreTxt.x = 120; // right of main score goldScoreTxt.y = 20; LK.gui.top.addChild(goldScoreTxt); // Add sun (top right, margin from edge) sun = new Sun(); sun.x = 2048 - 220; sun.y = 220; game.addChild(sun); // Add static 'gunes1' (sun) image to the top right var gunes1Sprite = LK.getAsset('gunes1', { anchorX: 1, anchorY: 0 }); gunes1Sprite.width = 180; gunes1Sprite.height = 180; gunes1Sprite.x = 2048 - 40; // 40px margin from right gunes1Sprite.y = 40; // 40px margin from top game.addChild(gunes1Sprite); // Add 'evet' button to the top right corner of the GUI var evetBtn = new Text2('evet', { size: 90, fill: 0xFFFFFF, font: "Arial" }); evetBtn.anchor.set(1, 0); // right-top anchor evetBtn.x = LK.gui.top.width - 40; // 40px margin from right evetBtn.y = 30; // 30px margin from top LK.gui.topRight.addChild(evetBtn); // Spawn a few initial clouds for (var i = 0; i < 3; i++) { var cloud = new Cloud(); cloud.x = 400 + Math.random() * 1400; cloud.y = 200 + Math.random() * 400; cloud.lastX = cloud.x; game.addChild(cloud); clouds.push(cloud); } nextCloudTick = 60 + Math.floor(Math.random() * 120); // Create cat cat = new Cat(); cat.x = CAT_START_X; cat.y = CAT_START_Y; cat.groundY = CAT_START_Y; game.addChild(cat); // Track long press for gliding var isPressing = false; var pressStartTick = 0; var glideActive = false; // --- Bird damage immunity after stamina glide --- var birdImmunityActive = false; var birdImmunityStartTick = 0; var BIRD_IMMUNITY_DURATION = 300; // 5 seconds at 60fps // Touch/click to jump or start glide game.down = function (x, y, obj) { if (!gameOver) { cat.jump(); isPressing = true; pressStartTick = LK.ticks; glideActive = false; } // Update golds, check for collection for (var j = golds.length - 1; j >= 0; j--) { var gold = golds[j]; gold.update(); // Remove if off screen if (gold.x < -200) { gold.destroy(); golds.splice(j, 1); continue; } // Collect gold: only trigger on first intersect and not already collected if (!gold.collected && cat.intersects(gold)) { gold.collected = true; goldScore++; goldScoreTxt.setText(goldScore); gold.destroy(); golds.splice(j, 1); continue; } } }; // On release, stop pressing and gliding game.up = function (x, y, obj) { isPressing = false; // Do not forcibly end glide here; glide ends after 3s or on landing }; // Main update loop game.update = function () { if (gameOver) return; // --- Scroll kum tiles leftward and loop --- var kumScrollSpeed = 7 * speedMultiplier; // Match cactus base speed for realism for (var i = 0; i < kumTiles.length; i++) { var tile = kumTiles[i]; tile.x -= kumScrollSpeed; // If tile is fully off the left, move it to the right end if (tile.x <= -KUM_TILE_WIDTH) { // Find current rightmost tile var maxX = -Infinity; for (var j = 0; j < kumTiles.length; j++) { if (kumTiles[j].x > maxX) maxX = kumTiles[j].x; } tile.x = maxX + KUM_TILE_WIDTH; } } // Update clouds and spawn new ones for (var i = clouds.length - 1; i >= 0; i--) { var cloud = clouds[i]; cloud.update(); if (cloud.x < -400) { cloud.destroy(); clouds.splice(i, 1); } } if (nextCloudTick <= 0) { var cloud = new Cloud(); cloud.x = 2048 + 200; cloud.y = 120 + Math.random() * 600; cloud.lastX = cloud.x; game.addChild(cloud); clouds.push(cloud); nextCloudTick = 60 + Math.floor(Math.random() * 120); } else { nextCloudTick--; } // Deactivate bird immunity after 5 seconds if (birdImmunityActive && LK.ticks - birdImmunityStartTick >= BIRD_IMMUNITY_DURATION) { birdImmunityActive = false; } // Update birds and spawn new ones for (var i = birds.length - 1; i >= 0; i--) { var bird = birds[i]; bird.update(); if (bird.x < -200) { bird.destroy(); birds.splice(i, 1); continue; } // Bird collision detection (only trigger on first intersect) if (!bird.lastWasIntersecting && cat.intersects(bird)) { // If immunity is active, skip damage if (!birdImmunityActive) { // Decrease HP by 10 hp -= 10; if (hp < 0) hp = 0; // Play cat sound on HP loss LK.getSound('kedi1').play(); // Update HP bar hpBar.width = Math.max(1, hp / maxHp * hpBarFullWidth); // Flash red for hit LK.effects.flashObject(cat, 0xff0000, 400); // If HP is 0, game over if (hp <= 0) { LK.effects.flashScreen(0xff0000, 800); LK.showGameOver(); LK.getSound('kedi3').play(); gameOver = true; return; } } } bird.lastWasIntersecting = cat.intersects(bird); } if (nextBirdTick <= 0) { // Spawn 2-3 birds at once, with more scattered (random) vertical and horizontal spacing var birdCount = 2 + Math.floor(Math.random() * 2); // 2 or 3 birds var minBirdY = GROUND_Y - 950; // Lowered: birds fly closer to ground var maxBirdY = GROUND_Y - 650; // Lowered: birds fly closer to ground if (minBirdY < 0) minBirdY = 0; if (maxBirdY < 0) maxBirdY = 0; var yRange = maxBirdY - minBirdY; var usedYs = []; for (var b = 0; b < birdCount; b++) { var bird = new Bird(); // Scatter birds horizontally more bird.x = 2048 + 100 + Math.random() * 200 + b * 60 + Math.random() * 60; // Scatter birds vertically, allow overlap and more randomness var baseY = minBirdY + Math.random() * yRange; // Add more jitter, and avoid birds being too close vertically var jitterY = (Math.random() - 0.5) * 180; var finalY = baseY + jitterY; // Optionally, keep birds at least 120px apart vertically var minDist = 120; var attempts = 0; while (usedYs.some(function (y) { return Math.abs(y - finalY) < minDist; }) && attempts < 10) { finalY = minBirdY + Math.random() * yRange + (Math.random() - 0.5) * 180; attempts++; } usedYs.push(finalY); bird.y = finalY; bird.lastX = bird.x; // Apply speed multiplier to bird bird.speed = bird.speed * (0.8 + 0.4 * Math.random()) * speedMultiplier; game.addChild(bird); birds.push(bird); } // Bird group appears every 220-340 ticks (increased interval for more jump time) nextBirdTick = 220 + Math.floor(Math.random() * 120); } else { nextBirdTick--; } // Update cat cat.update(); // Spawn cactus if (nextCactusTick <= 0) { var cactus = new Cactus(); cactus.x = 2048 + 100; // spawn just off right edge cactus.y = GROUND_Y; cactus.lastX = cactus.x; // Apply speed multiplier to cactus cactus.speed = cactus.speed * speedMultiplier; game.addChild(cactus); cacti.push(cactus); // Use new CACTUS_SPAWN_MIN/MAX for more consistent jump windows var spawnInterval = CACTUS_SPAWN_MIN + Math.floor(Math.random() * (CACTUS_SPAWN_MAX - CACTUS_SPAWN_MIN + 1)); nextCactusTick = Math.floor(spawnInterval); } else { nextCactusTick--; } // Spawn gold if (nextGoldTick <= 0) { var gold = new Gold(); gold.x = 2048 + 100; // Random Y: between ground and a bit above cat's jump apex var jumpApex = GROUND_Y + cat.jumpVelocity * (Math.abs(cat.jumpVelocity) / (2 * cat.gravity)); var minY = GROUND_Y - 400; var maxY = GROUND_Y - 1000; if (maxY < 0) maxY = 0; gold.y = minY - Math.random() * (minY - maxY); gold.lastX = gold.x; gold.collected = false; gold.speed = gold.speed * speedMultiplier; game.addChild(gold); golds.push(gold); // Gold appears less frequently than cacti nextGoldTick = 80 + Math.floor(Math.random() * 120); } else { nextGoldTick--; } // Update golds, check for collection for (var j = golds.length - 1; j >= 0; j--) { var gold = golds[j]; gold.update(); // Remove if off screen if (gold.x < -200) { gold.destroy(); golds.splice(j, 1); continue; } // Collect gold: only trigger on first intersect and not already collected if (!gold.collected && cat.intersects(gold)) { gold.collected = true; goldScore++; goldScoreTxt.setText(goldScore); // Increase HP by 10, up to maxHp hp += 10; if (hp > maxHp) hp = maxHp; hpBar.width = Math.max(1, hp / maxHp * hpBarFullWidth); gold.destroy(); golds.splice(j, 1); continue; } } // Update cacti, check for collision and scoring for (var i = cacti.length - 1; i >= 0; i--) { var cactus = cacti[i]; cactus.update(); // Remove if off screen if (cactus.x < -200) { cactus.destroy(); cacti.splice(i, 1); continue; } // Collision detection (only trigger on first intersect) if (!cactus.lastWasIntersecting && cat.intersects(cactus)) { // Decrease HP by 20 hp -= 20; if (hp < 0) hp = 0; // Play cat sound on HP loss LK.getSound('kedi1').play(); // Update HP bar hpBar.width = Math.max(1, hp / maxHp * hpBarFullWidth); // Flash red for hit LK.effects.flashObject(cat, 0xff0000, 400); // If HP is 0, game over if (hp <= 0) { LK.effects.flashScreen(0xff0000, 800); LK.showGameOver(); LK.getSound('kedi3').play(); gameOver = true; return; } } // Scoring: passed cactus (cat.x > cactus.x + cactus.width/2) and not already scored if (!cactus.scored && cat.x > cactus.x + cactus.width / 2) { score++; scoreTxt.setText(score); cactus.scored = true; // Increase speed multiplier, capped at max speedMultiplier += SPEED_MULTIPLIER_INCREMENT; if (speedMultiplier > SPEED_MULTIPLIER_MAX) speedMultiplier = SPEED_MULTIPLIER_MAX; // After level 30, allow 3 jumps if (score >= 30) { cat.maxJumps = 3; } // Track cacti jumped over for stamina refill after glide if (typeof cactiJumpedOver === "undefined") { cactiJumpedOver = 0; } cactiJumpedOver++; // Handle post-glide cactus counting for stamina refill if (typeof postGlideCountingActive === "undefined") postGlideCountingActive = false; if (typeof postGlideCactusCounter === "undefined") postGlideCactusCounter = 0; if (postGlideCountingActive) { postGlideCactusCounter++; if (postGlideCactusCounter >= 10) { stamina = maxStamina; staminaBar.width = Math.max(1, stamina / maxStamina * staminaBarFullWidth); postGlideCactusCounter = 0; // Continue counting for next refill } } // (Stamina refill now handled in Cat landing after glide.) } cactus.lastWasIntersecting = cat.intersects(cactus); } };
/****
* Classes
****/
// Bird class: flies from right to left, above ground, destroys itself off screen
var Bird = Container.expand(function () {
var self = Container.call(this);
// Use 'gunes' asset for bird (placeholder, should be replaced with a bird asset if available)
var birdSprite = self.attachAsset('gunes', {
anchorX: 0.5,
anchorY: 0.5
});
birdSprite.width = 120;
birdSprite.height = 90;
birdSprite.tint = 0x888888;
birdSprite.alpha = 0.92;
self.speed = 10 + Math.random() * 4;
self.update = function () {
self.x -= self.speed;
// Destroy if off screen
if (self.lastX >= -200 && self.x < -200) {
self.destroy();
}
self.lastX = self.x;
};
return self;
});
// Cactus class: moves left, destroys itself off screen
var Cactus = Container.expand(function () {
var self = Container.call(this);
// Attach cactus asset, anchor bottom left
var cactusSprite = self.attachAsset('cactus', {
anchorX: 0.5,
anchorY: 1
});
self.speed = 7 + Math.random() * 2; // even slower speed for easier gameplay
self.update = function () {
self.x -= self.speed;
// Destroy if off screen
if (self.lastX >= -200 && self.x < -200) {
self.destroy();
}
self.lastX = self.x;
};
return self;
});
// Cat class: handles jump, gravity, and collision
var Cat = Container.expand(function () {
var self = Container.call(this);
// Attach cat asset, anchor bottom left for ground logic
var catSprite = self.attachAsset('cat', {
anchorX: 0.5,
anchorY: 1
});
// Cat physics
self.y = 0;
self.x = 0;
self.vy = 0;
self.isJumping = false;
self.groundY = 0; // will be set after creation
// Double jump state
self.jumpCount = 0;
self.maxJumps = 2;
// Jump parameters
self.jumpVelocity = -65;
self.gravity = 4;
// Update method for physics
self.update = function () {
// Handle 3-second glide if long press is active, but only once per jump and only if stamina is full
if (typeof isPressing !== "undefined" && isPressing && self.isJumping && !glideActive && !self.hasGlided && self.vy > 0 && typeof stamina !== "undefined" && stamina >= maxStamina) {
// Only start glide if falling, not already gliding, haven't glided yet this jump, and stamina is full
if (LK.ticks - pressStartTick >= 18) {
// ~300ms threshold to avoid accidental short taps
glideActive = true;
self.isHovering = false;
self.hasHovered = true;
self.glideStartTick = LK.ticks;
self.vy = 0;
self.hasGlided = true; // Mark that we've glided this jump
// Consume all stamina
stamina = 0;
staminaBar.width = Math.max(1, stamina / maxStamina * staminaBarFullWidth);
// Activate bird damage immunity for 5 seconds
birdImmunityActive = true;
birdImmunityStartTick = LK.ticks;
}
}
// If gliding, keep cat in air for up to 3 seconds (180 ticks)
if (typeof glideActive !== "undefined" && glideActive) {
if (LK.ticks - self.glideStartTick < 180) {
// Stay in air, do not apply gravity, regardless of isPressing
return;
} else {
// End glide
glideActive = false;
}
}
if (self.isJumping) {
// If we are hovering, do not apply gravity or move
if (self.isHovering) {
// Determine hover duration: 12 ticks (195ms) for first jump, 6 ticks (100ms) for others
var hoverDuration = self.jumpCount === 1 ? 12 : 6;
if (LK.ticks - self.hoverStartTick >= hoverDuration) {
self.isHovering = false;
// Resume falling, keep vy as 0 so gravity starts pulling down
self.vy = 0;
}
// While hovering, do nothing else
return;
}
// Normal jump/fall
self.vy += self.gravity;
self.y += self.vy;
// At apex: vy just turned positive (was going up, now going down)
if (!self.isHovering && self.vy > 0 && !self.hasHovered) {
self.isHovering = true;
self.hasHovered = true;
self.hoverStartTick = LK.ticks;
self.vy = 0; // Stop vertical movement during hover
return;
}
// Land on ground
if (self.y >= self.groundY) {
self.y = self.groundY;
self.vy = 0;
self.isJumping = false;
self.isHovering = false;
self.hasHovered = false;
// If we just finished a glide (hasGlided true, glideActive false), start counting cacti for stamina refill
if (typeof self.hasGlided !== "undefined" && self.hasGlided && typeof glideActive !== "undefined" && !glideActive) {
// Start post-glide cactus counting
if (typeof postGlideCactusCounter === "undefined") postGlideCactusCounter = 0;
postGlideCactusCounter = 0;
postGlideCountingActive = true;
}
self.hasGlided = false; // Reset glide on landing
self.jumpCount = 0; // Reset jump count on landing
}
}
};
// Jump method
self.jump = function () {
if (self.jumpCount < self.maxJumps) {
self.isJumping = true;
self.vy = self.jumpVelocity;
self.isHovering = false;
self.hasHovered = false;
self.hasGlided = false; // Allow one glide per jump
self.hoverStartTick = 0;
self.jumpCount++;
// Play cat sound on jump
LK.getSound('kedi').play();
}
};
return self;
});
// Cloud class: moves left, destroys itself off screen
var Cloud = Container.expand(function () {
var self = Container.call(this);
// Use a white ellipse for the cloud
var cloudSprite = self.attachAsset('centerCircle', {
anchorX: 0.5,
anchorY: 0.5
});
// Randomize cloud size
var scale = 1.2 + Math.random() * 1.2;
cloudSprite.width = 320 * scale;
cloudSprite.height = 120 * scale;
cloudSprite.tint = 0xFFFFFF;
cloudSprite.alpha = 0.7 + Math.random() * 0.2;
self.speed = 1.5 + Math.random() * 1.2;
self.update = function () {
self.x -= self.speed;
if (self.lastX >= -400 && self.x < -400) {
self.destroy();
}
self.lastX = self.x;
};
return self;
});
// Gold class: moves left, destroys itself off screen, collectible by cat
var Gold = Container.expand(function () {
var self = Container.call(this);
// Attach gold asset, anchor center
var goldSprite = self.attachAsset('ghost', {
anchorX: 0.5,
anchorY: 0.5
});
goldSprite.width = 80;
goldSprite.height = 80;
self.speed = 7 + Math.random() * 2;
self.collected = false;
self.update = function () {
self.x -= self.speed;
// Destroy if off screen
if (self.lastX >= -200 && self.x < -200) {
self.destroy();
}
self.lastX = self.x;
};
return self;
});
// Sun class: static, top right
var Sun = Container.expand(function () {
var self = Container.call(this);
// Use a yellow ellipse for the sun
var sunSprite = self.attachAsset('centerCircle', {
anchorX: 0.5,
anchorY: 0.5
});
sunSprite.width = 260;
sunSprite.height = 260;
sunSprite.tint = 0xFFF700;
sunSprite.alpha = 0.95;
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0xF7E9A0 // light sand yellow, desert-like
});
/****
* Game Code
****/
;
// --- GAME CODE ---
// --- Scrolling sand ground (kum) ---
// We'll tile enough kum images to cover the screen width, and scroll them leftward.
// When a kum tile moves off the left, move it to the right to loop seamlessly.
var KUM_TILE_WIDTH = 200; // Use 200px for a bit of overlap and to reduce number of tiles
var KUM_TILE_HEIGHT = 120; // Height of the sand ground
var KUM_Y = GROUND_Y + 60; // Place under cat/cacti (centered at ground + half height)
var kumTiles = [];
var kumTileCount = Math.ceil(2048 / KUM_TILE_WIDTH) + 2; // +2 for seamless looping
// Start kum tiles after the cat's feet (right after cat's right edge)
var kumStartX = CAT_START_X + 100; // 100 is half cat width (cat is 200px wide)
for (var i = 0; i < kumTileCount; i++) {
var kumTile = LK.getAsset('kum', {
anchorX: 0,
anchorY: 0.5
});
kumTile.width = KUM_TILE_WIDTH;
kumTile.height = KUM_TILE_HEIGHT;
kumTile.x = kumStartX + i * KUM_TILE_WIDTH;
kumTile.y = GROUND_Y + KUM_TILE_HEIGHT / 2;
game.addChild(kumTile);
kumTiles.push(kumTile);
}
// Remove old groundPath and pebbles/stripes code (they will be replaced by kum tiles)
// (groundPath, pebbles, and stripes removed - replaced by kum tiles)
// Sun and clouds
var sun;
var clouds = [];
var nextCloudTick = 0;
// Birds
var birds = [];
var nextBirdTick = 0;
// Game constants
var GROUND_Y = 2200; // y position of ground (bottom of screen minus margin)
var CAT_START_X = 400;
var CAT_START_Y = GROUND_Y;
var CACTUS_SPAWN_MIN = 70; // min frames between cacti (slower, more time to jump)
var CACTUS_SPAWN_MAX = 130; // max frames between cacti (slower, more time to jump)
// Game state
var cat;
var cacti = [];
var golds = [];
var score = 0;
var goldScore = 0;
var scoreTxt;
var goldScoreTxt;
var nextCactusTick = 0;
var nextGoldTick = 0;
var gameOver = false;
// On game start, stamina is full
stamina = maxStamina;
if (typeof staminaBar !== "undefined") {
staminaBar.width = Math.max(1, stamina / maxStamina * staminaBarFullWidth);
}
// Track how many cacti have been jumped over for stamina refill
var cactiJumpedOver = 0;
// Track post-glide cactus counting for stamina refill
var postGlideCactusCounter = 0;
var postGlideCountingActive = false;
// Speed multiplier for game progression
var speedMultiplier = 1;
var SPEED_MULTIPLIER_INCREMENT = 0.08; // how much to increase per score
var SPEED_MULTIPLIER_MAX = 3; // cap the speed increase
// HP bar variables
var maxHp = 100;
var hp = maxHp;
var hpBarFullWidth = 420;
var hpBarHeight = 38;
// Add HP bar background (grey)
var hpBarBg = LK.getAsset('centerCircle', {
anchorX: 0,
anchorY: 0
});
hpBarBg.width = hpBarFullWidth;
hpBarBg.height = hpBarHeight;
hpBarBg.x = 110;
hpBarBg.y = 30;
hpBarBg.tint = 0x444444;
hpBarBg.alpha = 0.45;
LK.gui.top.addChild(hpBarBg);
// Add HP bar (red)
var hpBar = LK.getAsset('centerCircle', {
anchorX: 0,
anchorY: 0
});
hpBar.width = hpBarFullWidth;
hpBar.height = hpBarHeight;
hpBar.x = 110;
hpBar.y = 30;
hpBar.tint = 0xff4444;
hpBar.alpha = 0.95;
LK.gui.top.addChild(hpBar);
// --- Stamina bar variables and GUI ---
var maxStamina = 100;
var stamina = maxStamina;
var staminaBarFullWidth = 420;
var staminaBarHeight = 28;
// Stamina bar background (grey, below HP bar)
var staminaBarBg = LK.getAsset('centerCircle', {
anchorX: 0,
anchorY: 0
});
staminaBarBg.width = staminaBarFullWidth;
staminaBarBg.height = staminaBarHeight;
staminaBarBg.x = 110;
staminaBarBg.y = 80;
staminaBarBg.tint = 0x444444;
staminaBarBg.alpha = 0.35;
LK.gui.top.addChild(staminaBarBg);
// Stamina bar (blue)
var staminaBar = LK.getAsset('centerCircle', {
anchorX: 0,
anchorY: 0
});
staminaBar.width = staminaBarFullWidth;
staminaBar.height = staminaBarHeight;
staminaBar.x = 110;
staminaBar.y = 80;
staminaBar.tint = 0x44aaff;
staminaBar.alpha = 0.95;
LK.gui.top.addChild(staminaBar);
// Add score text to GUI
scoreTxt = new Text2('0', {
size: 120,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Gold score text (smaller, right of score)
goldScoreTxt = new Text2('0', {
size: 90,
fill: 0xFFD700 // gold color
});
goldScoreTxt.anchor.set(0, 0);
goldScoreTxt.x = 120; // right of main score
goldScoreTxt.y = 20;
LK.gui.top.addChild(goldScoreTxt);
// Add sun (top right, margin from edge)
sun = new Sun();
sun.x = 2048 - 220;
sun.y = 220;
game.addChild(sun);
// Add static 'gunes1' (sun) image to the top right
var gunes1Sprite = LK.getAsset('gunes1', {
anchorX: 1,
anchorY: 0
});
gunes1Sprite.width = 180;
gunes1Sprite.height = 180;
gunes1Sprite.x = 2048 - 40; // 40px margin from right
gunes1Sprite.y = 40; // 40px margin from top
game.addChild(gunes1Sprite);
// Add 'evet' button to the top right corner of the GUI
var evetBtn = new Text2('evet', {
size: 90,
fill: 0xFFFFFF,
font: "Arial"
});
evetBtn.anchor.set(1, 0); // right-top anchor
evetBtn.x = LK.gui.top.width - 40; // 40px margin from right
evetBtn.y = 30; // 30px margin from top
LK.gui.topRight.addChild(evetBtn);
// Spawn a few initial clouds
for (var i = 0; i < 3; i++) {
var cloud = new Cloud();
cloud.x = 400 + Math.random() * 1400;
cloud.y = 200 + Math.random() * 400;
cloud.lastX = cloud.x;
game.addChild(cloud);
clouds.push(cloud);
}
nextCloudTick = 60 + Math.floor(Math.random() * 120);
// Create cat
cat = new Cat();
cat.x = CAT_START_X;
cat.y = CAT_START_Y;
cat.groundY = CAT_START_Y;
game.addChild(cat);
// Track long press for gliding
var isPressing = false;
var pressStartTick = 0;
var glideActive = false;
// --- Bird damage immunity after stamina glide ---
var birdImmunityActive = false;
var birdImmunityStartTick = 0;
var BIRD_IMMUNITY_DURATION = 300; // 5 seconds at 60fps
// Touch/click to jump or start glide
game.down = function (x, y, obj) {
if (!gameOver) {
cat.jump();
isPressing = true;
pressStartTick = LK.ticks;
glideActive = false;
}
// Update golds, check for collection
for (var j = golds.length - 1; j >= 0; j--) {
var gold = golds[j];
gold.update();
// Remove if off screen
if (gold.x < -200) {
gold.destroy();
golds.splice(j, 1);
continue;
}
// Collect gold: only trigger on first intersect and not already collected
if (!gold.collected && cat.intersects(gold)) {
gold.collected = true;
goldScore++;
goldScoreTxt.setText(goldScore);
gold.destroy();
golds.splice(j, 1);
continue;
}
}
};
// On release, stop pressing and gliding
game.up = function (x, y, obj) {
isPressing = false;
// Do not forcibly end glide here; glide ends after 3s or on landing
};
// Main update loop
game.update = function () {
if (gameOver) return;
// --- Scroll kum tiles leftward and loop ---
var kumScrollSpeed = 7 * speedMultiplier; // Match cactus base speed for realism
for (var i = 0; i < kumTiles.length; i++) {
var tile = kumTiles[i];
tile.x -= kumScrollSpeed;
// If tile is fully off the left, move it to the right end
if (tile.x <= -KUM_TILE_WIDTH) {
// Find current rightmost tile
var maxX = -Infinity;
for (var j = 0; j < kumTiles.length; j++) {
if (kumTiles[j].x > maxX) maxX = kumTiles[j].x;
}
tile.x = maxX + KUM_TILE_WIDTH;
}
}
// Update clouds and spawn new ones
for (var i = clouds.length - 1; i >= 0; i--) {
var cloud = clouds[i];
cloud.update();
if (cloud.x < -400) {
cloud.destroy();
clouds.splice(i, 1);
}
}
if (nextCloudTick <= 0) {
var cloud = new Cloud();
cloud.x = 2048 + 200;
cloud.y = 120 + Math.random() * 600;
cloud.lastX = cloud.x;
game.addChild(cloud);
clouds.push(cloud);
nextCloudTick = 60 + Math.floor(Math.random() * 120);
} else {
nextCloudTick--;
}
// Deactivate bird immunity after 5 seconds
if (birdImmunityActive && LK.ticks - birdImmunityStartTick >= BIRD_IMMUNITY_DURATION) {
birdImmunityActive = false;
}
// Update birds and spawn new ones
for (var i = birds.length - 1; i >= 0; i--) {
var bird = birds[i];
bird.update();
if (bird.x < -200) {
bird.destroy();
birds.splice(i, 1);
continue;
}
// Bird collision detection (only trigger on first intersect)
if (!bird.lastWasIntersecting && cat.intersects(bird)) {
// If immunity is active, skip damage
if (!birdImmunityActive) {
// Decrease HP by 10
hp -= 10;
if (hp < 0) hp = 0;
// Play cat sound on HP loss
LK.getSound('kedi1').play();
// Update HP bar
hpBar.width = Math.max(1, hp / maxHp * hpBarFullWidth);
// Flash red for hit
LK.effects.flashObject(cat, 0xff0000, 400);
// If HP is 0, game over
if (hp <= 0) {
LK.effects.flashScreen(0xff0000, 800);
LK.showGameOver();
LK.getSound('kedi3').play();
gameOver = true;
return;
}
}
}
bird.lastWasIntersecting = cat.intersects(bird);
}
if (nextBirdTick <= 0) {
// Spawn 2-3 birds at once, with more scattered (random) vertical and horizontal spacing
var birdCount = 2 + Math.floor(Math.random() * 2); // 2 or 3 birds
var minBirdY = GROUND_Y - 950; // Lowered: birds fly closer to ground
var maxBirdY = GROUND_Y - 650; // Lowered: birds fly closer to ground
if (minBirdY < 0) minBirdY = 0;
if (maxBirdY < 0) maxBirdY = 0;
var yRange = maxBirdY - minBirdY;
var usedYs = [];
for (var b = 0; b < birdCount; b++) {
var bird = new Bird();
// Scatter birds horizontally more
bird.x = 2048 + 100 + Math.random() * 200 + b * 60 + Math.random() * 60;
// Scatter birds vertically, allow overlap and more randomness
var baseY = minBirdY + Math.random() * yRange;
// Add more jitter, and avoid birds being too close vertically
var jitterY = (Math.random() - 0.5) * 180;
var finalY = baseY + jitterY;
// Optionally, keep birds at least 120px apart vertically
var minDist = 120;
var attempts = 0;
while (usedYs.some(function (y) {
return Math.abs(y - finalY) < minDist;
}) && attempts < 10) {
finalY = minBirdY + Math.random() * yRange + (Math.random() - 0.5) * 180;
attempts++;
}
usedYs.push(finalY);
bird.y = finalY;
bird.lastX = bird.x;
// Apply speed multiplier to bird
bird.speed = bird.speed * (0.8 + 0.4 * Math.random()) * speedMultiplier;
game.addChild(bird);
birds.push(bird);
}
// Bird group appears every 220-340 ticks (increased interval for more jump time)
nextBirdTick = 220 + Math.floor(Math.random() * 120);
} else {
nextBirdTick--;
}
// Update cat
cat.update();
// Spawn cactus
if (nextCactusTick <= 0) {
var cactus = new Cactus();
cactus.x = 2048 + 100; // spawn just off right edge
cactus.y = GROUND_Y;
cactus.lastX = cactus.x;
// Apply speed multiplier to cactus
cactus.speed = cactus.speed * speedMultiplier;
game.addChild(cactus);
cacti.push(cactus);
// Use new CACTUS_SPAWN_MIN/MAX for more consistent jump windows
var spawnInterval = CACTUS_SPAWN_MIN + Math.floor(Math.random() * (CACTUS_SPAWN_MAX - CACTUS_SPAWN_MIN + 1));
nextCactusTick = Math.floor(spawnInterval);
} else {
nextCactusTick--;
}
// Spawn gold
if (nextGoldTick <= 0) {
var gold = new Gold();
gold.x = 2048 + 100;
// Random Y: between ground and a bit above cat's jump apex
var jumpApex = GROUND_Y + cat.jumpVelocity * (Math.abs(cat.jumpVelocity) / (2 * cat.gravity));
var minY = GROUND_Y - 400;
var maxY = GROUND_Y - 1000;
if (maxY < 0) maxY = 0;
gold.y = minY - Math.random() * (minY - maxY);
gold.lastX = gold.x;
gold.collected = false;
gold.speed = gold.speed * speedMultiplier;
game.addChild(gold);
golds.push(gold);
// Gold appears less frequently than cacti
nextGoldTick = 80 + Math.floor(Math.random() * 120);
} else {
nextGoldTick--;
}
// Update golds, check for collection
for (var j = golds.length - 1; j >= 0; j--) {
var gold = golds[j];
gold.update();
// Remove if off screen
if (gold.x < -200) {
gold.destroy();
golds.splice(j, 1);
continue;
}
// Collect gold: only trigger on first intersect and not already collected
if (!gold.collected && cat.intersects(gold)) {
gold.collected = true;
goldScore++;
goldScoreTxt.setText(goldScore);
// Increase HP by 10, up to maxHp
hp += 10;
if (hp > maxHp) hp = maxHp;
hpBar.width = Math.max(1, hp / maxHp * hpBarFullWidth);
gold.destroy();
golds.splice(j, 1);
continue;
}
}
// Update cacti, check for collision and scoring
for (var i = cacti.length - 1; i >= 0; i--) {
var cactus = cacti[i];
cactus.update();
// Remove if off screen
if (cactus.x < -200) {
cactus.destroy();
cacti.splice(i, 1);
continue;
}
// Collision detection (only trigger on first intersect)
if (!cactus.lastWasIntersecting && cat.intersects(cactus)) {
// Decrease HP by 20
hp -= 20;
if (hp < 0) hp = 0;
// Play cat sound on HP loss
LK.getSound('kedi1').play();
// Update HP bar
hpBar.width = Math.max(1, hp / maxHp * hpBarFullWidth);
// Flash red for hit
LK.effects.flashObject(cat, 0xff0000, 400);
// If HP is 0, game over
if (hp <= 0) {
LK.effects.flashScreen(0xff0000, 800);
LK.showGameOver();
LK.getSound('kedi3').play();
gameOver = true;
return;
}
}
// Scoring: passed cactus (cat.x > cactus.x + cactus.width/2) and not already scored
if (!cactus.scored && cat.x > cactus.x + cactus.width / 2) {
score++;
scoreTxt.setText(score);
cactus.scored = true;
// Increase speed multiplier, capped at max
speedMultiplier += SPEED_MULTIPLIER_INCREMENT;
if (speedMultiplier > SPEED_MULTIPLIER_MAX) speedMultiplier = SPEED_MULTIPLIER_MAX;
// After level 30, allow 3 jumps
if (score >= 30) {
cat.maxJumps = 3;
}
// Track cacti jumped over for stamina refill after glide
if (typeof cactiJumpedOver === "undefined") {
cactiJumpedOver = 0;
}
cactiJumpedOver++;
// Handle post-glide cactus counting for stamina refill
if (typeof postGlideCountingActive === "undefined") postGlideCountingActive = false;
if (typeof postGlideCactusCounter === "undefined") postGlideCactusCounter = 0;
if (postGlideCountingActive) {
postGlideCactusCounter++;
if (postGlideCactusCounter >= 10) {
stamina = maxStamina;
staminaBar.width = Math.max(1, stamina / maxStamina * staminaBarFullWidth);
postGlideCactusCounter = 0;
// Continue counting for next refill
}
}
// (Stamina refill now handled in Cat landing after glide.)
}
cactus.lastWasIntersecting = cat.intersects(cactus);
}
};