/**** * Plugins ****/ var storage = LK.import("@upit/storage.v1"); var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ var Bird = Container.expand(function () { var self = Container.call(this); // Attach a simple ellipse as the bird var birdAsset = self.attachAsset('bird', { anchorX: 0.5, anchorY: 0.5 }); // Bird physics self.y = 1200; self.x = 600; self.velocityY = 0; self.gravity = 2.5; self.flapStrength = -38; // Track lastY for possible future use self.lastY = self.y; // Update method: apply gravity and move bird self.update = function () { self.lastY = self.y; // Only apply gravity and movement if the game has started if (typeof gameStarted === "undefined" || !gameStarted) { return; } self.velocityY += self.gravity; self.y += self.velocityY; // Bird looks up when going up, down when falling // Clamp rotation between -0.5 (up) and 0.5 (down) radians for a nice diagonal look if (self.velocityY < -5) { self.rotation = -0.5; } else if (self.velocityY > 5) { self.rotation = 0.5; } else { self.rotation = self.velocityY / 10; // smooth transition between -0.5 and 0.5 if (self.rotation < -0.5) self.rotation = -0.5; if (self.rotation > 0.5) self.rotation = 0.5; } // Prevent bird from going above the screen if (self.y < birdAsset.height / 2) { self.y = birdAsset.height / 2; self.velocityY = 0; } // Prevent bird from falling below the screen if (self.y > 2732 - birdAsset.height / 2) { self.y = 2732 - birdAsset.height / 2; self.velocityY = 0; } }; // Flap method: called on tap self.flap = function () { self.velocityY = self.flapStrength; }; return self; }); // Cloud class for moving clouds across the screen var Cloud = Container.expand(function () { var self = Container.call(this); // Attach cloud asset var cloudAsset = self.attachAsset('cloud', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.6, scaleY: 0.6 }); // Set initial position and speed self.x = 2048 + 200; // Start just off the right edge // Allow clouds to spawn anywhere vertically, including near the top and bottom self.y = Math.random() * (2732 - cloudAsset.height) + cloudAsset.height / 2; // 40% chance to be a fast cloud if (Math.random() < 0.4) { self.speed = 10 + Math.random() * 3; // Faster cloud } else { self.speed = 5 + Math.random() * 3; // Faster normal cloud } self.lastX = self.x; self.update = function () { self.lastX = self.x; // Only move if gameStarted is true if (typeof gameStarted !== "undefined" && gameStarted) { self.x -= self.speed; } // If cloud moves off left edge, reset to right if (self.x < -cloudAsset.width / 2) { self.x = 2048 + cloudAsset.width / 2; // Allow clouds to respawn anywhere vertically, including near the top and bottom self.y = Math.random() * (2732 - cloudAsset.height) + cloudAsset.height / 2; // 40% chance to be a fast cloud if (Math.random() < 0.4) { self.speed = 10 + Math.random() * 3; // Faster cloud } else { self.speed = 5 + Math.random() * 3; // Faster normal cloud } } }; return self; }); // Hat class for moving hats across the screen var Hat = Container.expand(function () { var self = Container.call(this); // Attach a hat asset (use a box as a placeholder, or replace with a hat image asset if available) var hatAsset = self.attachAsset('box', { width: 120, height: 80, color: 0x222222, anchorX: 0.5, anchorY: 0.5 }); // Start just off the right edge self.x = 2048 + 100; // Random vertical position, but not too close to the top/bottom self.y = 400 + Math.random() * (2732 - 800); self.speed = 12; self.lastX = self.x; self.update = function () { self.lastX = self.x; self.x -= self.speed; // If hat moves off left edge, reset to right and randomize y if (self.x < -100) { self.x = 2048 + 100; self.y = 400 + Math.random() * (2732 - 800); } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x000000 }); /**** * Game Code ****/ // Add background image behind the bird var background = LK.getAsset('background', { anchorX: 0, anchorY: 0, x: 0, y: 0 }); game.addChild(background); // Score variables var survivalTime = 0; // in seconds // Import storage plugin for persistent best score // Best score persistent storage var bestScore = storage.bestScore || 0; // Best score text at top center var bestScoreText = new Text2('BEST: ' + bestScore, { size: 100, fill: "#fff" }); bestScoreText.anchor.set(0.5, 0); // center-top LK.gui.top.addChild(bestScoreText); // Current score at top right var scoreText = new Text2('0', { size: 100, fill: "#fff" }); scoreText.anchor.set(1, 0); // right-top LK.gui.topRight.addChild(scoreText); // Add clouds behind the bird, but only after 3 seconds from first tap var clouds = []; var cloudsSpawned = false; function spawnClouds(numClouds) { if (cloudsSpawned && typeof numClouds === "undefined") return; if (typeof numClouds === "undefined") numClouds = 3; // If clouds already spawned, only add new clouds if needed if (clouds.length < numClouds) { for (var i = clouds.length; i < numClouds; i++) { var cloud = new Cloud(); cloud.x = 2048 + 200; clouds.push(cloud); game.addChild(cloud); } } cloudsSpawned = true; } // Create the bird and add to the game var bird = new Bird(); game.addChild(bird); // Create hats array, but do not spawn hats until game starts var hats = []; var hatsSpawned = false; function spawnHats() { if (hatsSpawned) return; hatsSpawned = true; // Spawn multiple hats for increased challenge, all at the right edge after 3 seconds for (var i = 0; i < 1; i++) { var hat = new Hat(); // All hats spawn at the right edge (2048 + 100) hat.x = 2048 + 100; // Randomize y position for each hat hat.y = 400 + Math.random() * (2732 - 800); hats.push(hat); game.addChild(hat); } } // Game state: wait for first tap to start var gameStarted = false; var scoreTimer = null; // Show "Tap to Start" text at the center of the screen until the game starts var tapToStartText = new Text2('Tap to Start', { size: 160, fill: "#fff" }); tapToStartText.anchor.set(0.5, 0.5); LK.gui.center.addChild(tapToStartText); // Tap anywhere to start the game and make the bird flap game.down = function (x, y, obj) { if (!gameStarted) { gameStarted = true; // Remove "Tap to Start" text if (tapToStartText && tapToStartText.parent) { tapToStartText.parent.removeChild(tapToStartText); } // Start score timer scoreTimer = LK.setInterval(function () { survivalTime += 1; LK.setScore(survivalTime); scoreText.setText(survivalTime); }, 1000); // Spawn clouds and hats immediately var initialClouds = 3 + Math.floor(survivalTime / 5); spawnClouds(initialClouds); spawnHats(); } if (gameStarted) { bird.flap(); LK.getSound('flap').play(); } }; // Update clouds every frame game.update = function () { if (!gameStarted) { return; } if (cloudsSpawned) { for (var i = 0; i < clouds.length; i++) { clouds[i].update(); // Check for collision between bird and cloud if (clouds[i].lastWasIntersecting === undefined) clouds[i].lastWasIntersecting = false; var nowIntersecting = bird.intersects(clouds[i]); if (!clouds[i].lastWasIntersecting && nowIntersecting) { // Stop score timer if (scoreTimer) LK.clearInterval(scoreTimer); // Update best score if needed if (survivalTime > bestScore) { bestScore = survivalTime; storage.bestScore = bestScore; bestScoreText.setText('BEST: ' + bestScore); } // Set score to survival time for game over screen LK.setScore(survivalTime); // Show game over screen // Bird dies: rotate and fall bird.velocityY = 30; bird.gravity = 6; // Change bird visual to bird2 if (bird.children && bird.children.length > 0) { var oldBirdAsset = bird.children[0]; var idx = bird.getChildIndex(oldBirdAsset); bird.removeChild(oldBirdAsset); var bird2Asset = bird.attachAsset('bird2', { anchorX: 0.5, anchorY: 0.5 }); bird2Asset.x = 0; bird2Asset.y = 0; bird.addChildAt(bird2Asset, idx); } if (bird.rotationTween) tween.stop(bird, { rotation: true }); bird.rotationTween = tween(bird, { rotation: Math.PI / 2 }, { duration: 500 }); LK.showGameOver(); return; } clouds[i].lastWasIntersecting = nowIntersecting; } } // Update hats and check for collision with bird, only if hats have spawned if (hatsSpawned) { for (var h = 0; h < hats.length; h++) { hats[h].update(); if (hats[h].lastWasIntersecting === undefined) hats[h].lastWasIntersecting = false; var hatNowIntersecting = bird.intersects(hats[h]); if (!hats[h].lastWasIntersecting && hatNowIntersecting) { // Increase score by 1 for each hat collected survivalTime += 1; LK.setScore(survivalTime); scoreText.setText(survivalTime); // Flash hat red for 400ms LK.effects.flashObject(hats[h], 0xff0000, 400); // Increase clouds every 5 points if (survivalTime % 5 === 0) { spawnClouds(3 + Math.floor(survivalTime / 5)); } } hats[h].lastWasIntersecting = hatNowIntersecting; } } // Check for collision with top or bottom of the screen var birdAssetHeight = 200; // matches bird asset height if (bird.lastY > birdAssetHeight / 2 && bird.y <= birdAssetHeight / 2 || bird.lastY < 2732 - birdAssetHeight / 2 && bird.y >= 2732 - birdAssetHeight / 2) { if (scoreTimer) LK.clearInterval(scoreTimer); // Update best score if needed if (survivalTime > bestScore) { bestScore = survivalTime; storage.bestScore = bestScore; bestScoreText.setText('BEST: ' + bestScore); } LK.setScore(survivalTime); // Bird dies: rotate and fall bird.velocityY = 30; bird.gravity = 6; // Change bird visual to bird2 if (bird.children && bird.children.length > 0) { var oldBirdAsset = bird.children[0]; var idx = bird.getChildIndex(oldBirdAsset); bird.removeChild(oldBirdAsset); var bird2Asset = bird.attachAsset('bird2', { anchorX: 0.5, anchorY: 0.5 }); bird2Asset.x = 0; bird2Asset.y = 0; bird.addChildAt(bird2Asset, idx); } if (bird.rotationTween) tween.stop(bird, { rotation: true }); bird.rotationTween = tween(bird, { rotation: Math.PI / 2 }, { duration: 500 }); LK.showGameOver(); return; } };
/****
* Plugins
****/
var storage = LK.import("@upit/storage.v1");
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Bird = Container.expand(function () {
var self = Container.call(this);
// Attach a simple ellipse as the bird
var birdAsset = self.attachAsset('bird', {
anchorX: 0.5,
anchorY: 0.5
});
// Bird physics
self.y = 1200;
self.x = 600;
self.velocityY = 0;
self.gravity = 2.5;
self.flapStrength = -38;
// Track lastY for possible future use
self.lastY = self.y;
// Update method: apply gravity and move bird
self.update = function () {
self.lastY = self.y;
// Only apply gravity and movement if the game has started
if (typeof gameStarted === "undefined" || !gameStarted) {
return;
}
self.velocityY += self.gravity;
self.y += self.velocityY;
// Bird looks up when going up, down when falling
// Clamp rotation between -0.5 (up) and 0.5 (down) radians for a nice diagonal look
if (self.velocityY < -5) {
self.rotation = -0.5;
} else if (self.velocityY > 5) {
self.rotation = 0.5;
} else {
self.rotation = self.velocityY / 10; // smooth transition between -0.5 and 0.5
if (self.rotation < -0.5) self.rotation = -0.5;
if (self.rotation > 0.5) self.rotation = 0.5;
}
// Prevent bird from going above the screen
if (self.y < birdAsset.height / 2) {
self.y = birdAsset.height / 2;
self.velocityY = 0;
}
// Prevent bird from falling below the screen
if (self.y > 2732 - birdAsset.height / 2) {
self.y = 2732 - birdAsset.height / 2;
self.velocityY = 0;
}
};
// Flap method: called on tap
self.flap = function () {
self.velocityY = self.flapStrength;
};
return self;
});
// Cloud class for moving clouds across the screen
var Cloud = Container.expand(function () {
var self = Container.call(this);
// Attach cloud asset
var cloudAsset = self.attachAsset('cloud', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.6,
scaleY: 0.6
});
// Set initial position and speed
self.x = 2048 + 200; // Start just off the right edge
// Allow clouds to spawn anywhere vertically, including near the top and bottom
self.y = Math.random() * (2732 - cloudAsset.height) + cloudAsset.height / 2;
// 40% chance to be a fast cloud
if (Math.random() < 0.4) {
self.speed = 10 + Math.random() * 3; // Faster cloud
} else {
self.speed = 5 + Math.random() * 3; // Faster normal cloud
}
self.lastX = self.x;
self.update = function () {
self.lastX = self.x;
// Only move if gameStarted is true
if (typeof gameStarted !== "undefined" && gameStarted) {
self.x -= self.speed;
}
// If cloud moves off left edge, reset to right
if (self.x < -cloudAsset.width / 2) {
self.x = 2048 + cloudAsset.width / 2;
// Allow clouds to respawn anywhere vertically, including near the top and bottom
self.y = Math.random() * (2732 - cloudAsset.height) + cloudAsset.height / 2;
// 40% chance to be a fast cloud
if (Math.random() < 0.4) {
self.speed = 10 + Math.random() * 3; // Faster cloud
} else {
self.speed = 5 + Math.random() * 3; // Faster normal cloud
}
}
};
return self;
});
// Hat class for moving hats across the screen
var Hat = Container.expand(function () {
var self = Container.call(this);
// Attach a hat asset (use a box as a placeholder, or replace with a hat image asset if available)
var hatAsset = self.attachAsset('box', {
width: 120,
height: 80,
color: 0x222222,
anchorX: 0.5,
anchorY: 0.5
});
// Start just off the right edge
self.x = 2048 + 100;
// Random vertical position, but not too close to the top/bottom
self.y = 400 + Math.random() * (2732 - 800);
self.speed = 12;
self.lastX = self.x;
self.update = function () {
self.lastX = self.x;
self.x -= self.speed;
// If hat moves off left edge, reset to right and randomize y
if (self.x < -100) {
self.x = 2048 + 100;
self.y = 400 + Math.random() * (2732 - 800);
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000000
});
/****
* Game Code
****/
// Add background image behind the bird
var background = LK.getAsset('background', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0
});
game.addChild(background);
// Score variables
var survivalTime = 0; // in seconds
// Import storage plugin for persistent best score
// Best score persistent storage
var bestScore = storage.bestScore || 0;
// Best score text at top center
var bestScoreText = new Text2('BEST: ' + bestScore, {
size: 100,
fill: "#fff"
});
bestScoreText.anchor.set(0.5, 0); // center-top
LK.gui.top.addChild(bestScoreText);
// Current score at top right
var scoreText = new Text2('0', {
size: 100,
fill: "#fff"
});
scoreText.anchor.set(1, 0); // right-top
LK.gui.topRight.addChild(scoreText);
// Add clouds behind the bird, but only after 3 seconds from first tap
var clouds = [];
var cloudsSpawned = false;
function spawnClouds(numClouds) {
if (cloudsSpawned && typeof numClouds === "undefined") return;
if (typeof numClouds === "undefined") numClouds = 3;
// If clouds already spawned, only add new clouds if needed
if (clouds.length < numClouds) {
for (var i = clouds.length; i < numClouds; i++) {
var cloud = new Cloud();
cloud.x = 2048 + 200;
clouds.push(cloud);
game.addChild(cloud);
}
}
cloudsSpawned = true;
}
// Create the bird and add to the game
var bird = new Bird();
game.addChild(bird);
// Create hats array, but do not spawn hats until game starts
var hats = [];
var hatsSpawned = false;
function spawnHats() {
if (hatsSpawned) return;
hatsSpawned = true;
// Spawn multiple hats for increased challenge, all at the right edge after 3 seconds
for (var i = 0; i < 1; i++) {
var hat = new Hat();
// All hats spawn at the right edge (2048 + 100)
hat.x = 2048 + 100;
// Randomize y position for each hat
hat.y = 400 + Math.random() * (2732 - 800);
hats.push(hat);
game.addChild(hat);
}
}
// Game state: wait for first tap to start
var gameStarted = false;
var scoreTimer = null;
// Show "Tap to Start" text at the center of the screen until the game starts
var tapToStartText = new Text2('Tap to Start', {
size: 160,
fill: "#fff"
});
tapToStartText.anchor.set(0.5, 0.5);
LK.gui.center.addChild(tapToStartText);
// Tap anywhere to start the game and make the bird flap
game.down = function (x, y, obj) {
if (!gameStarted) {
gameStarted = true;
// Remove "Tap to Start" text
if (tapToStartText && tapToStartText.parent) {
tapToStartText.parent.removeChild(tapToStartText);
}
// Start score timer
scoreTimer = LK.setInterval(function () {
survivalTime += 1;
LK.setScore(survivalTime);
scoreText.setText(survivalTime);
}, 1000);
// Spawn clouds and hats immediately
var initialClouds = 3 + Math.floor(survivalTime / 5);
spawnClouds(initialClouds);
spawnHats();
}
if (gameStarted) {
bird.flap();
LK.getSound('flap').play();
}
};
// Update clouds every frame
game.update = function () {
if (!gameStarted) {
return;
}
if (cloudsSpawned) {
for (var i = 0; i < clouds.length; i++) {
clouds[i].update();
// Check for collision between bird and cloud
if (clouds[i].lastWasIntersecting === undefined) clouds[i].lastWasIntersecting = false;
var nowIntersecting = bird.intersects(clouds[i]);
if (!clouds[i].lastWasIntersecting && nowIntersecting) {
// Stop score timer
if (scoreTimer) LK.clearInterval(scoreTimer);
// Update best score if needed
if (survivalTime > bestScore) {
bestScore = survivalTime;
storage.bestScore = bestScore;
bestScoreText.setText('BEST: ' + bestScore);
}
// Set score to survival time for game over screen
LK.setScore(survivalTime);
// Show game over screen
// Bird dies: rotate and fall
bird.velocityY = 30;
bird.gravity = 6;
// Change bird visual to bird2
if (bird.children && bird.children.length > 0) {
var oldBirdAsset = bird.children[0];
var idx = bird.getChildIndex(oldBirdAsset);
bird.removeChild(oldBirdAsset);
var bird2Asset = bird.attachAsset('bird2', {
anchorX: 0.5,
anchorY: 0.5
});
bird2Asset.x = 0;
bird2Asset.y = 0;
bird.addChildAt(bird2Asset, idx);
}
if (bird.rotationTween) tween.stop(bird, {
rotation: true
});
bird.rotationTween = tween(bird, {
rotation: Math.PI / 2
}, {
duration: 500
});
LK.showGameOver();
return;
}
clouds[i].lastWasIntersecting = nowIntersecting;
}
}
// Update hats and check for collision with bird, only if hats have spawned
if (hatsSpawned) {
for (var h = 0; h < hats.length; h++) {
hats[h].update();
if (hats[h].lastWasIntersecting === undefined) hats[h].lastWasIntersecting = false;
var hatNowIntersecting = bird.intersects(hats[h]);
if (!hats[h].lastWasIntersecting && hatNowIntersecting) {
// Increase score by 1 for each hat collected
survivalTime += 1;
LK.setScore(survivalTime);
scoreText.setText(survivalTime);
// Flash hat red for 400ms
LK.effects.flashObject(hats[h], 0xff0000, 400);
// Increase clouds every 5 points
if (survivalTime % 5 === 0) {
spawnClouds(3 + Math.floor(survivalTime / 5));
}
}
hats[h].lastWasIntersecting = hatNowIntersecting;
}
}
// Check for collision with top or bottom of the screen
var birdAssetHeight = 200; // matches bird asset height
if (bird.lastY > birdAssetHeight / 2 && bird.y <= birdAssetHeight / 2 || bird.lastY < 2732 - birdAssetHeight / 2 && bird.y >= 2732 - birdAssetHeight / 2) {
if (scoreTimer) LK.clearInterval(scoreTimer);
// Update best score if needed
if (survivalTime > bestScore) {
bestScore = survivalTime;
storage.bestScore = bestScore;
bestScoreText.setText('BEST: ' + bestScore);
}
LK.setScore(survivalTime);
// Bird dies: rotate and fall
bird.velocityY = 30;
bird.gravity = 6;
// Change bird visual to bird2
if (bird.children && bird.children.length > 0) {
var oldBirdAsset = bird.children[0];
var idx = bird.getChildIndex(oldBirdAsset);
bird.removeChild(oldBirdAsset);
var bird2Asset = bird.attachAsset('bird2', {
anchorX: 0.5,
anchorY: 0.5
});
bird2Asset.x = 0;
bird2Asset.y = 0;
bird.addChildAt(bird2Asset, idx);
}
if (bird.rotationTween) tween.stop(bird, {
rotation: true
});
bird.rotationTween = tween(bird, {
rotation: Math.PI / 2
}, {
duration: 500
});
LK.showGameOver();
return;
}
};
Fullscreen modern App Store landscape banner, 16:9, high definition, for a game titled "Flappy Yap" and with the description "Guide a bird through endless pipes by tapping to flap and avoid obstacles. Survive as long as possible and beat your high score!". No text on banner!
cloudless sky. In-Game asset. 2d. High contrast. No shadows
cloudy. In-Game asset. 2d. High contrast. No shadows
şapka. In-Game asset. 2d. High contrast. No shadows
dead yellow bird. In-Game asset. 2d. High contrast. No shadows