Code edit (4 edits merged)
Please save this source code
Code edit (3 edits merged)
Please save this source code
User prompt
Please fix the bug: 'Cannot read properties of null (reading 'addChild')' in or related to this line: 'menuGroup.addChild(menuScoreTxt);' Line Number: 267
User prompt
The score should also be displayed on the start screen, i.e., the main menu
Code edit (1 edits merged)
Please save this source code
User prompt
Add assets to your articles with glasses, beard and moustache
User prompt
Bearded, moustached and bespectacled assets add
Code edit (1 edits merged)
Please save this source code
User prompt
Compilation error[L21]:Plugins failed to load fix this error
Code edit (1 edits merged)
Please save this source code
User prompt
Compilation error[l21]:Plugins failed to load fix this error
User prompt
Please fix the bug: 'Cannot set properties of undefined (setting 'fill')' in or related to this line: 'birdSelectLabels[i].style.fill = i === selectedBirdIndex ? 0xFFF700 : birdChoices[i].color;' Line Number: 317
User prompt
Please fix the bug: 'Cannot read properties of undefined (reading 'undefined')' in or related to this line: 'bird = new Bird(birdChoices[selectedBirdIndex].id);' Line Number: 223
User prompt
Add a birds section to the menu screen and let's play with the 3 birds we choose there
User prompt
Compilation error[L19]:Plugins failed to load fix this error
Code edit (3 edits merged)
Please save this source code
User prompt
Compilation error[19]:Plugins failed to load fix this error
Code edit (1 edits merged)
Please save this source code
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
// Bird class
var Bird = Container.expand(function (birdType) {
var self = Container.call(this);
var birdAssetId = typeof birdType === "string" ? birdType : "bird";
var birdSprite = self.attachAsset(birdAssetId, {
anchorX: 0.5,
anchorY: 0.5
});
self.width = birdSprite.width;
self.height = birdSprite.height;
self.vy = 0;
self.gravity = 1.2;
self.flapStrength = -22;
self.alive = true;
self.rotation = 0;
self.flap = function () {
if (!self.alive) {
return;
}
self.vy = self.flapStrength;
LK.getSound('flap').play();
};
self.die = function () {
self.alive = false;
};
self.update = function () {
// Always track lastY and lastX for event/collision tracking
if (typeof self.lastY === "undefined") {
self.lastY = self.y;
}
if (typeof self.lastX === "undefined") {
self.lastX = self.x;
}
self.lastY = self.y;
self.lastX = self.x;
if (!self.alive) {
return;
}
self.vy += self.gravity;
self.y += self.vy;
// Clamp rotation between -0.5 and 1.0 radians
var targetRot = Math.max(-0.5, Math.min(1.0, self.vy / 30));
self.rotation += (targetRot - self.rotation) * 0.2;
};
return self;
});
// Cloud class
var Cloud = Container.expand(function () {
var self = Container.call(this);
var cloudSprite = self.attachAsset('cloud', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 2 + Math.random() * 2;
self.update = function () {
self.x -= self.speed;
};
self.isOffScreen = function () {
return self.x < -cloudSprite.width / 2;
};
return self;
});
// PipePair class
var PipePair = Container.expand(function () {
var self = Container.call(this);
self.passed = false;
self.speed = 10;
self.gap = 480; // vertical gap between pipes (increased for bigger pipes)
self.pipeWidth = 208;
self.pipeHeight = 1280;
// Randomize gap position
var minY = 400;
var maxY = 2732 - 112 - 200 - self.gap; // leave space for ground
var gapY = minY + Math.floor(Math.random() * (maxY - minY));
// Top pipe
var topPipe = self.attachAsset('pipe', {
anchorX: 0.5,
anchorY: 1.0,
x: 0,
y: gapY
});
// Bottom pipe (flipped)
var bottomPipe = self.attachAsset('pipe', {
anchorX: 0.5,
anchorY: 0.0,
x: 0,
y: gapY + self.gap,
flipY: 1
});
self.topPipe = topPipe;
self.bottomPipe = bottomPipe;
self.width = self.pipeWidth;
self.height = self.pipeHeight * 2 + self.gap;
self.update = function () {
self.x -= self.speed;
};
self.isOffScreen = function () {
return self.x < -self.pipeWidth / 2;
};
self.checkPass = function (bird) {
if (!self.passed && self.x + self.pipeWidth / 2 < bird.x) {
self.passed = true;
return true;
}
return false;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x70c5ce // Flappy Bird sky blue
});
/****
* Game Code
****/
// Music (not used, but placeholder for future)
// SFX
// Cloud (white, pixel-art, 128x64)
// Background (sky blue, pixel-art, 2048x2732)
// Ground (pixel-art, 2048x112)
// Pipe (green, pixel-art, 104x640, vertical, top and bottom use same asset, flipY for bottom)
// Bird (yellow, pixel-art style, 48x34)
// Game constants
var GAME_STATE = {
MENU: 0,
READY: 1,
PLAY: 2,
GAMEOVER: 3
};
var state = GAME_STATE.MENU;
var pipes = [];
var clouds = [];
var bird = null;
var ground = null;
var bg = null;
var score = 0;
var best = storage.best || 0;
var scoreTxt = null;
var bestTxt = null;
var groundY = 2732 - 112;
var pipeTimer = 0;
var cloudTimer = 0;
var menuGroup = null;
var gameOverGroup = null;
var tapToStartTxt = null;
var dragNode = null;
// --- Setup background ---
bg = LK.getAsset('bg', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0
});
game.addChild(bg);
// --- Setup clouds ---
function spawnCloud() {
var c = new Cloud();
c.x = 2048 + 100 + Math.random() * 400;
c.y = 200 + Math.random() * 800;
clouds.push(c);
game.addChild(c);
}
// --- Setup ground ---
// Use two ground sprites for seamless scrolling, scaled to cover the full width
var groundScale = 2048 / LK.getAsset('ground', {
anchorX: 0,
anchorY: 0
}).width;
ground = LK.getAsset('ground', {
anchorX: 0,
anchorY: 0,
x: 0,
y: groundY,
scaleX: groundScale,
scaleY: 112 / LK.getAsset('ground', {
anchorX: 0,
anchorY: 0
}).height
});
var ground2 = LK.getAsset('ground', {
anchorX: 0,
anchorY: 0,
x: 2048,
y: groundY,
scaleX: groundScale,
scaleY: 112 / LK.getAsset('ground', {
anchorX: 0,
anchorY: 0
}).height
});
game.addChild(ground);
game.addChild(ground2);
// --- Bird selection section ---
var birdChoices = [{
id: 'bird',
label: 'Klasik',
color: 0xffffff
}, {
id: 'bird2',
label: 'Mavi',
color: 0x4fc3f7
}, {
id: 'bird3',
label: 'Kırmızı',
color: 0xe53935
}];
var selectedBirdIndex = 0;
// --- Setup bird ---
bird = new Bird(birdChoices[selectedBirdIndex].id);
bird.x = 700;
bird.y = 1366;
game.addChild(bird);
// --- Setup score text ---
scoreTxt = new Text2('0', {
size: 180,
fill: 0xFFF700,
font: "Impact"
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// --- Setup best score text (for game over) ---
bestTxt = new Text2('', {
size: 90,
fill: 0xFFFFFF,
font: "Impact"
});
bestTxt.anchor.set(0.5, 0);
// --- Setup menu group ---
menuGroup = new Container();
var titleTxt = new Text2('Keko Bird', {
size: 200,
fill: 0xFFF700,
font: "Impact"
});
titleTxt.anchor.set(0.5, 0.5);
titleTxt.x = 2048 / 2;
titleTxt.y = 700;
menuGroup.addChild(titleTxt);
// --- Bird selection section ---
var birdChoices = [{
id: 'bird',
label: 'Klasik',
color: 0xffffff
}, {
id: 'bird2',
label: 'Mavi',
color: 0x4fc3f7
}, {
id: 'bird3',
label: 'Kırmızı',
color: 0xe53935
}];
// Register extra bird assets if not already present
var selectedBirdIndex = 0;
var birdSelectSprites = [];
var birdSelectLabels = [];
var birdSelectY = 950;
var birdSelectSpacing = 350;
var birdSelectXStart = 2048 / 2 - birdSelectSpacing;
for (var i = 0; i < birdChoices.length; i++) {
var bx = birdSelectXStart + i * birdSelectSpacing;
var birdSprite = LK.getAsset(birdChoices[i].id, {
anchorX: 0.5,
anchorY: 0.5,
x: bx,
y: birdSelectY,
scaleX: 1.5,
scaleY: 1.5
});
menuGroup.addChild(birdSprite);
birdSelectSprites.push(birdSprite);
var label = new Text2(birdChoices[i].label, {
size: 70,
fill: birdChoices[i].color,
font: "Impact"
});
label.anchor.set(0.5, 0);
label.x = bx;
label.y = birdSelectY + 100;
menuGroup.addChild(label);
birdSelectLabels.push(label);
}
// Helper to update selection highlight
function updateBirdSelection() {
for (var i = 0; i < birdSelectSprites.length; i++) {
birdSelectSprites[i].scale.x = i === selectedBirdIndex ? 2.0 : 1.5;
birdSelectSprites[i].scale.y = i === selectedBirdIndex ? 2.0 : 1.5;
birdSelectLabels[i].style.fill = i === selectedBirdIndex ? 0xFFF700 : birdChoices[i].color;
}
}
updateBirdSelection();
// Start button using Buton asset
var startBtnAsset = LK.getAsset('Buton', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 1400,
scaleX: 3.5,
scaleY: 1.5
});
menuGroup.addChild(startBtnAsset);
var startBtn = new Text2('START', {
size: 140,
fill: 0xFFFFFF,
font: "Impact"
});
startBtn.anchor.set(0.5, 0.5);
startBtn.x = 2048 / 2;
startBtn.y = 1400;
menuGroup.addChild(startBtn);
var copyrightTxt = new Text2('© keko bird', {
size: 60,
fill: 0xFFFFFF,
font: "Impact"
});
copyrightTxt.anchor.set(0.5, 0.5);
copyrightTxt.x = 2048 / 2;
copyrightTxt.y = 2732 - 60;
menuGroup.addChild(copyrightTxt);
game.addChild(menuGroup);
// --- Setup tap to start text ---
tapToStartTxt = new Text2('TAP TO START', {
size: 120,
fill: 0xFFFFFF,
font: "Impact"
});
tapToStartTxt.anchor.set(0.5, 0.5);
tapToStartTxt.x = 2048 / 2;
tapToStartTxt.y = 1000;
// --- Setup game over group ---
gameOverGroup = new Container();
var gameOverTxt = new Text2('Kaybettin', {
size: 180,
fill: 0xFF0000,
font: "Impact"
});
gameOverTxt.anchor.set(0.5, 0.5);
gameOverTxt.x = 2048 / 2;
gameOverTxt.y = 700;
gameOverGroup.addChild(gameOverTxt);
var scoreLabel = new Text2('SCORE', {
size: 90,
fill: 0xFFF700,
font: "Impact"
});
scoreLabel.anchor.set(0.5, 0.5);
scoreLabel.x = 2048 / 2;
scoreLabel.y = 1000;
gameOverGroup.addChild(scoreLabel);
var finalScoreTxt = new Text2('0', {
size: 140,
fill: 0xFFF700,
font: "Impact"
});
finalScoreTxt.anchor.set(0.5, 0.5);
finalScoreTxt.x = 2048 / 2;
finalScoreTxt.y = 1100;
gameOverGroup.addChild(finalScoreTxt);
var bestLabel = new Text2('BEST', {
size: 90,
fill: 0xFFFFFF,
font: "Impact"
});
bestLabel.anchor.set(0.5, 0.5);
bestLabel.x = 2048 / 2;
bestLabel.y = 1250;
gameOverGroup.addChild(bestLabel);
bestTxt.x = 2048 / 2;
bestTxt.y = 1340;
gameOverGroup.addChild(bestTxt);
// Retry button using Buton asset
var retryBtnAsset = LK.getAsset('Buton', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 1600,
scaleX: 2.5,
scaleY: 1.2
});
gameOverGroup.addChild(retryBtnAsset);
var retryBtn = new Text2('RETRY', {
size: 120,
fill: 0xFFFFFF,
font: "Impact"
});
retryBtn.anchor.set(0.5, 0.5);
retryBtn.x = 2048 / 2;
retryBtn.y = 1600;
gameOverGroup.addChild(retryBtn);
// Menu button using Buton asset
var menuBtnAsset = LK.getAsset('Buton', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 1750,
scaleX: 2.0,
scaleY: 1.0
});
gameOverGroup.addChild(menuBtnAsset);
var menuBtn = new Text2('MENU', {
size: 100,
fill: 0xFFFFFF,
font: "Impact"
});
menuBtn.anchor.set(0.5, 0.5);
menuBtn.x = 2048 / 2;
menuBtn.y = 1750;
gameOverGroup.addChild(menuBtn);
// --- Helper functions ---
function resetGame() {
// Remove pipes
for (var i = 0; i < pipes.length; i++) {
pipes[i].destroy();
}
pipes = [];
// Remove clouds
for (var i = 0; i < clouds.length; i++) {
clouds[i].destroy();
}
clouds = [];
// Reset bird
if (bird) {
bird.destroy();
}
bird = new Bird(birdChoices[selectedBirdIndex].id);
bird.x = 700;
bird.y = 1366;
game.addChild(bird);
bird.vy = 0;
bird.rotation = 0;
bird.alive = true;
// Reset score
score = 0;
scoreTxt.setText('0');
// Reset timers
pipeTimer = 0;
cloudTimer = 0;
}
function startGame() {
resetGame();
state = GAME_STATE.READY;
menuGroup.visible = false;
gameOverGroup.visible = false;
tapToStartTxt.visible = true;
LK.gui.top.addChild(tapToStartTxt);
}
function playGame() {
state = GAME_STATE.PLAY;
tapToStartTxt.visible = false;
}
function showGameOver() {
state = GAME_STATE.GAMEOVER;
finalScoreTxt.setText(score);
if (score > best) {
best = score;
storage.best = best;
}
bestTxt.setText(best);
gameOverGroup.visible = true;
game.addChild(gameOverGroup);
LK.getSound('die').play();
}
function showMenu() {
state = GAME_STATE.MENU;
menuGroup.visible = true;
gameOverGroup.visible = false;
tapToStartTxt.visible = false;
}
// --- Event handlers ---
game.down = function (x, y, obj) {
if (state === GAME_STATE.MENU) {
// Bird selection
for (var i = 0; i < birdSelectSprites.length; i++) {
var localBird = birdSelectSprites[i].toLocal({
x: x,
y: y
}, game);
if (Math.abs(localBird.x) < birdSelectSprites[i].width / 2 && Math.abs(localBird.y) < birdSelectSprites[i].height / 2) {
selectedBirdIndex = i;
updateBirdSelection();
return;
}
}
// Start button
var local = startBtn.toLocal({
x: x,
y: y
}, game);
if (Math.abs(local.x) < startBtn.width / 2 && Math.abs(local.y) < startBtn.height / 2) {
startGame();
return;
}
}
if (state === GAME_STATE.READY) {
playGame();
bird.flap();
return;
}
if (state === GAME_STATE.PLAY) {
bird.flap();
return;
}
if (state === GAME_STATE.GAMEOVER) {
// Retry button
var localRetry = retryBtn.toLocal({
x: x,
y: y
}, game);
if (Math.abs(localRetry.x) < retryBtn.width / 2 && Math.abs(localRetry.y) < retryBtn.height / 2) {
startGame();
return;
}
// Menu button
var localMenu = menuBtn.toLocal({
x: x,
y: y
}, game);
if (Math.abs(localMenu.x) < menuBtn.width / 2 && Math.abs(localMenu.y) < menuBtn.height / 2) {
showMenu();
return;
}
}
};
game.move = function (x, y, obj) {
// No drag in Flappy Bird
};
game.up = function (x, y, obj) {
// No drag in Flappy Bird
};
// --- Main update loop ---
game.update = function () {
// Animate clouds
for (var i = clouds.length - 1; i >= 0; i--) {
var c = clouds[i];
c.update();
if (c.isOffScreen()) {
c.destroy();
clouds.splice(i, 1);
}
}
if (state === GAME_STATE.MENU || state === GAME_STATE.READY) {
// Spawn clouds slowly
cloudTimer++;
if (cloudTimer > 90) {
spawnCloud();
cloudTimer = 0;
}
}
if (state === GAME_STATE.READY) {
// Bird idle bobbing
bird.y = 1366 + Math.sin(LK.ticks / 15) * 40;
bird.rotation = Math.sin(LK.ticks / 30) * 0.1;
}
if (state === GAME_STATE.PLAY) {
// Clouds
cloudTimer++;
if (cloudTimer > 60) {
spawnCloud();
cloudTimer = 0;
}
// Bird physics
bird.update();
// Pipes
pipeTimer++;
if (pipeTimer > 90) {
var p = new PipePair();
p.x = 2048 + 208;
game.addChild(p);
pipes.push(p);
pipeTimer = 0;
}
for (var i = pipes.length - 1; i >= 0; i--) {
var p = pipes[i];
p.update();
// Check for pass
if (p.checkPass(bird)) {
score++;
scoreTxt.setText(score);
LK.getSound('point').play();
}
// Remove offscreen
if (p.isOffScreen()) {
p.destroy();
pipes.splice(i, 1);
}
}
// Collision detection
for (var i = 0; i < pipes.length; i++) {
var p = pipes[i];
// Bird bounding box
var bx = bird.x;
var by = bird.y;
var bw = bird.width * 0.7;
var bh = bird.height * 0.7;
// Top pipe
var px = p.x;
var py = p.topPipe.y;
var pw = p.pipeWidth;
var ph = p.pipeHeight;
// Top pipe rect
if (bx + bw / 2 > px - pw / 2 && bx - bw / 2 < px + pw / 2 && by - bh / 2 < py && by + bh / 2 > py - ph) {
// Hit top pipe
bird.die();
LK.getSound('hit').play();
showGameOver();
return;
}
// Bottom pipe rect
var bpy = p.bottomPipe.y;
if (bx + bw / 2 > px - pw / 2 && bx - bw / 2 < px + pw / 2 && by + bh / 2 > bpy && by - bh / 2 < bpy + ph) {
// Hit bottom pipe
bird.die();
LK.getSound('hit').play();
showGameOver();
return;
}
}
// Ground collision
if (bird.y + bird.height / 2 > groundY) {
bird.y = groundY - bird.height / 2;
bird.die();
LK.getSound('hit').play();
showGameOver();
return;
}
// Ceiling
if (bird.y - bird.height / 2 < 0) {
bird.y = bird.height / 2;
bird.vy = 0;
}
}
// Animate ground (scrolling effect)
ground.x -= 10;
ground2.x -= 10;
// When a ground sprite moves off screen, move it to the right of the other
if (ground.x <= -2048) {
ground.x = ground2.x + 2048;
}
if (ground2.x <= -2048) {
ground2.x = ground.x + 2048;
}
// Show/hide UI
scoreTxt.visible = state === GAME_STATE.PLAY;
menuGroup.visible = state === GAME_STATE.MENU;
tapToStartTxt.visible = state === GAME_STATE.READY;
gameOverGroup.visible = state === GAME_STATE.GAMEOVER;
};
// --- Initial state ---
showMenu(); ===================================================================
--- original.js
+++ change.js
@@ -202,8 +202,23 @@
}).height
});
game.addChild(ground);
game.addChild(ground2);
+// --- Bird selection section ---
+var birdChoices = [{
+ id: 'bird',
+ label: 'Klasik',
+ color: 0xffffff
+}, {
+ id: 'bird2',
+ label: 'Mavi',
+ color: 0x4fc3f7
+}, {
+ id: 'bird3',
+ label: 'Kırmızı',
+ color: 0xe53935
+}];
+var selectedBirdIndex = 0;
// --- Setup bird ---
bird = new Bird(birdChoices[selectedBirdIndex].id);
bird.x = 700;
bird.y = 1366;
cloudy. In-Game asset. 2d. High contrast. No shadows
realistic mixed city. In-Game asset. 2d. High contrast. No shadows
Ground asphalt white striped road. In-Game asset. 2d. High contrast. No shadows
black block. In-Game asset. 2d. High contrast. No shadows
thin upward long muslim prayer beads. In-Game asset. 2d. High contrast. No shadows
Cartoon-style head of a “keko” character inspired by Turkish street culture. The sides of his hair are shaved short, and the top is longer with volume. A clear razor line is cut into the left side of his hair. He has a thin mustache, thick eyebrows, and half-closed, confident eyes. His expression is bold and slightly smug. Skin tone is tan or medium. Facial features are sharp and masculine. The style is cartoonish, not realistic. The background is simple to keep focus on the head. The head is slightly tilted forward, as if flying like in Flappy Bird. Add a playful but tough street vibe.. In-Game asset. 2d. High contrast. No shadows
Cartoon-style head of a “keko” character inspired by Turkish street style. The sides of his hair are shaved short, the top is longer and voluminous. A sharp razor line is cut into the left side of his hair. He has a thin mustache and a neatly trimmed beard along the jawline. Thick eyebrows and half-closed, confident eyes give him a bold, slightly smug expression. Skin tone is tan or medium. His face has sharp, masculine features. The style is cartoonish, not photorealistic. Background is minimal to keep focus on the character’s head. The head is slightly tilted forward, as if ready to fly like in Flappy Bird. Overall vibe is playful but with a tough, urban edge.. In-Game asset. 2d. High contrast. No shadows