/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Tween plugin import removed to fix plugin load error
var BananaClickEffect = Container.expand(function () {
var self = Container.call(this);
var effect = self.attachAsset('bananaClickEffect', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.5,
scaleY: 0.5,
alpha: 1
});
self.init = function (x, y) {
self.x = x;
self.y = y;
// Animate: scale up and fade out
tween(effect, {
scaleX: 1.2,
scaleY: 1.2,
alpha: 0
}, {
duration: 600,
easing: tween.easeOut,
onFinish: function onFinish() {
self.destroy();
}
});
};
return self;
});
var BananaEffect = Container.expand(function () {
var self = Container.call(this);
self.init = function (x, y) {
// Create multiple banana particles
for (var i = 0; i < 8; i++) {
var particle = self.attachAsset('banana', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.2,
scaleY: 0.2,
alpha: 0.8
});
// Calculate angle for particle direction
var angle = Math.PI * 2 * (i / 8);
// Position particle
particle.x = 0;
particle.y = 0;
// Calculate target position for the tween
var targetX = Math.cos(angle) * 100;
var targetY = Math.sin(angle) * 100;
// Animate particle
tween(particle, {
x: targetX,
y: targetY,
alpha: 0,
rotation: Math.random() * Math.PI * 2,
scaleX: 0.05,
scaleY: 0.05
}, {
duration: 800 + Math.random() * 400,
easing: tween.easeOut
});
}
// Set position of the effect
self.x = x;
self.y = y;
// Auto-destroy after all animations complete
LK.setTimeout(function () {
self.destroy();
}, 1500);
};
return self;
});
var FallingItem = Container.expand(function () {
var self = Container.call(this);
self.type = "banana"; // default type
self.speed = 2; // default speed
self.lastY = 0;
self.active = true;
self.graphics = null;
self.init = function (type, speed) {
self.type = type || "banana";
self.speed = speed || 2;
// Remove any existing graphics
if (self.graphics) {
self.removeChild(self.graphics);
}
// Create the appropriate graphics based on type
if (self.type === "banana") {
self.graphics = self.attachAsset('banana', {
anchorX: 0.5,
anchorY: 0.5
});
} else if (self.type === "bomb") {
self.graphics = self.attachAsset('bomb', {
anchorX: 0.5,
anchorY: 0.5
});
} else if (self.type === "heart") {
self.graphics = self.attachAsset('heartRestore', {
anchorX: 0.5,
anchorY: 0.5
});
} else if (self.type === "rottenBanana") {
self.graphics = self.attachAsset('rottenBanana', {
anchorX: 0.5,
anchorY: 0.5
});
}
// Set initial position
self.x = Math.random() * (2048 - 200) + 100;
self.y = -100;
self.lastY = self.y;
// Interactive for tapping
self.interactive = true;
};
self.update = function () {
if (!self.active) {
return;
}
self.lastY = self.y;
self.y += self.speed;
};
self.down = function (x, y, obj) {
if (!self.active) {
return;
}
if (self.type === "banana") {
// Score 1 point for each banana
LK.setScore(LK.getScore() + 1);
LK.getSound('pop').play();
// Create banana effect at tap position
createBananaEffect(self.x, self.y);
// Create banana click effect at tap position
createBananaClickEffect(self.x, self.y);
self.remove(false);
} else if (self.type === "bomb") {
// Lost a life by tapping bomb
LK.getSound('explosion').play();
decreaseLife();
self.remove();
} else if (self.type === "heart") {
// Gained a life by tapping heart
LK.getSound('heartRestoreSound').play();
increaseLife();
self.remove();
} else if (self.type === "rottenBanana") {
// Lost a life by tapping rotten banana
LK.getSound('rottenBananaSound').play();
decreaseLife();
self.remove();
}
};
self.remove = function (createSouls) {
self.active = false;
// Create soul effect based on item type, but only if createSouls is not false
if (createSouls !== false) {
if (self.type === "banana") {
createSoulEffect(self.x, self.y, 3);
} else if (self.type === "heart") {
createSoulEffect(self.x, self.y, 5);
} else if (self.type === "bomb" || self.type === "rottenBanana") {
// No souls for negative items
}
}
tween(self, {
alpha: 0,
scaleX: 0.3,
scaleY: 0.3
}, {
duration: 200,
onFinish: function onFinish() {
self.destroy();
}
});
};
return self;
});
var Menu = Container.expand(function () {
var self = Container.call(this);
// Menu background
var bg = self.attachAsset('menuBg', {
anchorX: 0.5,
anchorY: 0.5,
x: SCREEN_WIDTH / 2,
y: SCREEN_HEIGHT / 2
});
// Play button
var playBtn = self.attachAsset('playButton', {
anchorX: 0.5,
anchorY: 0.5,
x: SCREEN_WIDTH / 2,
y: SCREEN_HEIGHT / 2 - 100
});
// Settings button
var settingsBtn = self.attachAsset('settingsButton', {
anchorX: 0.5,
anchorY: 0.5,
x: SCREEN_WIDTH / 2,
y: SCREEN_HEIGHT / 2 + 120
});
// Title text
var titleText = new Text2('Banana Game', {
size: 140,
fill: 0xFFF200,
stroke: 0x000000,
strokeThickness: 10,
bold: true
});
titleText.anchor.set(0.5, 0.5);
titleText.x = SCREEN_WIDTH / 2;
titleText.y = SCREEN_HEIGHT / 2 - 350;
self.addChild(titleText);
// Play button text
var playText = new Text2('Play', {
size: 90,
fill: 0xFFFFFF,
stroke: 0x000000,
strokeThickness: 8,
bold: true
});
playText.anchor.set(0.5, 0.5);
playText.x = SCREEN_WIDTH / 2;
playText.y = SCREEN_HEIGHT / 2 - 100;
self.addChild(playText);
// Settings button text
var settingsText = new Text2('Settings', {
size: 70,
fill: 0xFFFFFF,
stroke: 0x000000,
strokeThickness: 6,
bold: true
});
settingsText.anchor.set(0.5, 0.5);
settingsText.x = SCREEN_WIDTH / 2;
settingsText.y = SCREEN_HEIGHT / 2 + 120;
self.addChild(settingsText);
// Assets button (top right)
var assetsBtn = self.attachAsset('pastScoresMenuButton', {
anchorX: 1,
anchorY: 0,
x: SCREEN_WIDTH - 50,
y: 23.05 // moved down by 0.3cm (11.55px)
});
var assetsText = new Text2('Past Scores', {
size: 60,
fill: 0xFFFFFF,
stroke: 0x000000,
strokeThickness: 5,
bold: true
});
assetsText.anchor.set(1, 0.5);
assetsText.x = SCREEN_WIDTH - 80;
assetsText.y = 50 + 60;
self.addChild(assetsText);
assetsBtn.interactive = true;
assetsBtn.down = function () {
showScoreHistoryPopup();
};
// Button interactivity
playBtn.interactive = true;
playBtn.down = function () {
if (self.parent) self.parent.removeChild(self);
showGame();
};
settingsBtn.interactive = true;
settingsBtn.down = function () {
if (self.parent) self.parent.removeChild(self);
showSettingsMenu();
};
return self;
});
var SettingsMenu = Container.expand(function () {
var self = Container.call(this);
// Settings background
var bg = self.attachAsset('menuBg', {
anchorX: 0.5,
anchorY: 0.5,
x: SCREEN_WIDTH / 2,
y: SCREEN_HEIGHT / 2
});
// Title
var settingsTitle = new Text2('Settings', {
size: 120,
fill: 0xFFF200,
stroke: 0x000000,
strokeThickness: 8,
bold: true
});
settingsTitle.anchor.set(0.5, 0.5);
settingsTitle.x = SCREEN_WIDTH / 2;
settingsTitle.y = SCREEN_HEIGHT / 2 - 300;
self.addChild(settingsTitle);
// Back button
var backBtn = self.attachAsset('menuButton', {
anchorX: 0.5,
anchorY: 0.5,
x: SCREEN_WIDTH / 2,
y: SCREEN_HEIGHT / 2 + 350
});
var backText = new Text2('Back', {
size: 80,
fill: 0xFFFFFF,
stroke: 0x000000,
strokeThickness: 7,
bold: true
});
backText.anchor.set(0.5, 0.5);
backText.x = SCREEN_WIDTH / 2;
backText.y = SCREEN_HEIGHT / 2 + 350;
self.addChild(backText);
// Example settings text
var infoText = new Text2('Sound: On\nMusic: On', {
size: 70,
fill: 0xFFFFFF,
stroke: 0x000000,
strokeThickness: 5,
bold: true
});
infoText.anchor.set(0.5, 0.5);
infoText.x = SCREEN_WIDTH / 2;
infoText.y = SCREEN_HEIGHT / 2;
self.addChild(infoText);
backBtn.interactive = true;
backBtn.down = function () {
if (self.parent) self.parent.removeChild(self);
showMenu();
};
return self;
});
var Soul = Container.expand(function () {
var self = Container.call(this);
self.init = function (x, y) {
// Create soul graphics
var soulGraphics = self.attachAsset('heart', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.5,
scaleY: 0.5,
alpha: 0.7
});
// Set initial position
self.x = x;
self.y = y;
// Randomize direction slightly
self.targetX = Math.random() * 300 - 150 + x;
self.targetY = y - 300 - Math.random() * 200; // Always float upward
// Start the float animation
tween(self, {
x: self.targetX,
y: self.targetY,
alpha: 0,
scaleX: 0.1,
scaleY: 0.1
}, {
duration: 1500 + Math.random() * 1000,
easing: tween.easeOut,
onFinish: function onFinish() {
self.destroy();
}
});
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000000
});
/****
* Game Code
****/
// New effect asset
// Menu and settings assets
;
// Game constants
var SCREEN_WIDTH = 2048;
var SCREEN_HEIGHT = 2732;
var MAX_LIVES = 3;
var BOMB_THRESHOLD_SCORE = 15;
var SPAWN_INTERVAL_INITIAL = 60; // frames
var MIN_SPAWN_INTERVAL = 20; // frames
var INTERVAL_DECREMENT = 1;
// Game variables
var fallingItems = [];
var lives = MAX_LIVES;
var spawnCounter = 0;
var currentSpawnInterval = SPAWN_INTERVAL_INITIAL;
var currentSpeed = 2;
var isGameOver = false;
var extraHeartSpawned = false;
var extraHeartCaught = false;
var gameStarted = false;
// Banana combo system variables (REMOVED)
// var bananaCombo = 0;
// var bananaComboTimer = null;
// var BANANA_COMBO_TIMEOUT = 1500; // ms
// var maxBananaCombo = 0;
// Combo text UI (REMOVED)
// var comboText = new Text2('', {
// size: 120,
// fill: 0xA259FF,
// // purple
// stroke: 0x000000,
// strokeThickness: 8,
// bold: true
// });
// comboText.anchor.set(0.5, 0);
// comboText.x = SCREEN_WIDTH / 2;
// comboText.y = 200;
// comboText.visible = false;
// game.addChild(comboText);
// Add background
var background = game.addChild(LK.getAsset('background', {
anchorX: 0,
anchorY: 0
}));
// Menu logic
var menuInstance = null;
var settingsMenuInstance = null;
// Global variable to store score history (in-memory, not persistent)
var scoreHistory = [];
// Show popup with past scores
function showScoreHistoryPopup() {
// Remove existing popup if present
if (game.scoreHistoryPopup && game.scoreHistoryPopup.parent) {
game.removeChild(game.scoreHistoryPopup);
game.scoreHistoryPopup = null;
}
var popup = new Container();
// Popup background
var bg = popup.attachAsset('menuBg', {
anchorX: 0.5,
anchorY: 0.5,
x: SCREEN_WIDTH / 2,
y: SCREEN_HEIGHT / 2,
scaleX: 0.7,
scaleY: 0.7
});
// Title
var title = new Text2('Past Scores', {
size: 90,
fill: 0xFFF200,
stroke: 0x000000,
strokeThickness: 7,
bold: true
});
title.anchor.set(0.5, 0.5);
title.x = SCREEN_WIDTH / 2;
title.y = SCREEN_HEIGHT / 2 - 350;
popup.addChild(title);
// Get score history from global variable (show up to 10 most recent)
var history = scoreHistory || [];
var displayScores = history.slice(-10).reverse();
var scoresText = displayScores.length > 0 ? displayScores.map(function (s, i) {
return i + 1 + '. ' + s;
}).join('\n') : 'No scores yet!';
var scoresList = new Text2(scoresText, {
size: 70,
fill: 0xFFFFFF,
stroke: 0x000000,
strokeThickness: 5,
bold: true
});
scoresList.anchor.set(0.5, 0);
scoresList.x = SCREEN_WIDTH / 2;
scoresList.y = SCREEN_HEIGHT / 2 - 220;
popup.addChild(scoresList);
// Close button
var closeBtn = popup.attachAsset('menuButton', {
anchorX: 0.5,
anchorY: 0.5,
x: SCREEN_WIDTH / 2,
y: SCREEN_HEIGHT / 2 + 350,
scaleX: 0.7,
scaleY: 0.7
});
var closeText = new Text2('Close', {
size: 70,
fill: 0xFFFFFF,
stroke: 0x000000,
strokeThickness: 6,
bold: true
});
closeText.anchor.set(0.5, 0.5);
closeText.x = SCREEN_WIDTH / 2;
closeText.y = SCREEN_HEIGHT / 2 + 350;
popup.addChild(closeText);
closeBtn.interactive = true;
closeBtn.down = function () {
if (popup.parent) game.removeChild(popup);
game.scoreHistoryPopup = null;
};
game.addChild(popup);
game.scoreHistoryPopup = popup;
}
// Show menu
function showMenu() {
if (menuInstance) {
if (!menuInstance.parent) game.addChild(menuInstance);
return;
}
menuInstance = new Menu();
game.addChild(menuInstance);
}
// Show settings menu
function showSettingsMenu() {
if (settingsMenuInstance) {
if (!settingsMenuInstance.parent) game.addChild(settingsMenuInstance);
return;
}
settingsMenuInstance = new SettingsMenu();
game.addChild(settingsMenuInstance);
}
// Hide menu and start game
function showGame() {
gameStarted = true;
clickToPlayText.visible = false;
initGame();
}
// Show menu on game start
LK.setTimeout(function () {
showMenu();
}, 10);
// Initialize score text
var scoreText = new Text2('Score: 0', {
size: 80,
fill: 0xFFFFFF,
stroke: 0x000000,
strokeThickness: 8,
bold: true
});
scoreText.anchor.set(0.5, 0);
scoreText.x = SCREEN_WIDTH / 2;
scoreText.y = 50;
game.addChild(scoreText);
// Create click to play text (hidden, menu will be used instead)
var clickToPlayText = new Text2('Click to Start', {
size: 120,
fill: 0xFFFFFF,
stroke: 0x000000,
strokeThickness: 8,
bold: true
});
clickToPlayText.anchor.set(0.5, 0.5);
clickToPlayText.x = SCREEN_WIDTH / 2;
clickToPlayText.y = SCREEN_HEIGHT / 2;
clickToPlayText.visible = false;
game.addChild(clickToPlayText);
// Create hearts container
var heartsContainer = new Container();
heartsContainer.x = 1410;
heartsContainer.y = 50;
game.addChild(heartsContainer);
// Initialize hearts display
function initLives() {
// Clear existing hearts
while (heartsContainer.children.length > 0) {
heartsContainer.removeChildAt(0);
}
// Add hearts based on current lives
for (var i = 0; i < lives; i++) {
var heart = LK.getAsset('heart', {
anchorX: 0,
anchorY: 0,
x: i * 190,
y: 0
});
heartsContainer.addChild(heart);
}
}
// Function to create floating soul effect
function createSoulEffect(x, y, count) {
count = count || 1;
for (var i = 0; i < count; i++) {
var soul = new Soul();
soul.init(x, y);
game.addChild(soul);
}
}
// Function to create banana effect when banana is clicked
function createBananaEffect(x, y) {
var effect = new BananaEffect();
effect.init(x, y);
game.addChild(effect);
}
// Function to create banana click effect animation
function createBananaClickEffect(x, y) {
var effect = new BananaClickEffect();
effect.init(x, y);
game.addChild(effect);
}
// Function to check if a heart is already falling
function isHeartAlreadyFalling() {
for (var i = 0; i < fallingItems.length; i++) {
if (fallingItems[i] && fallingItems[i].type === "heart" && fallingItems[i].active) {
return true;
}
}
return false;
}
// Function to increase life
function increaseLife() {
if (lives < MAX_LIVES) {
lives++;
initLives();
extraHeartCaught = true; // Mark that a heart was caught
}
}
// Function to decrease life
function decreaseLife() {
// Create soul effect at heart position that was lost
var heartIndex = lives - 1;
if (heartIndex >= 0 && heartsContainer.children[heartIndex]) {
var heartPos = heartsContainer.children[heartIndex];
var globalPos = heartsContainer.toGlobal({
x: heartPos.x + 50,
y: heartPos.y + 50
});
var gamePos = game.toLocal(globalPos);
createSoulEffect(gamePos.x, gamePos.y, 7);
}
lives--;
initLives();
// We only play the heart loss sound for actual life losses, not from bombs or rotten bananas
// This is handled in the game.update and FallingItem.down methods where decreaseLife is called.
// LK.getSound('heartLossSound').play(); // Removed sound here
// Shake the screen using the tween library
tween(game, {
x: game.x + 5
}, {
duration: 50,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(game, {
x: game.x - 10
}, {
duration: 100,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(game, {
x: game.x + 5
}, {
duration: 50,
easing: tween.easeIn,
onFinish: function onFinish() {
// Check for game over after shake is complete
if (lives <= 0) {
gameOver();
}
}
});
}
});
}
});
}
// Function to handle game over
function gameOver() {
if (isGameOver) {
return;
}
isGameOver = true;
gameStarted = false;
// Reset banana combo system (REMOVED)
// bananaCombo = 0;
// comboText.visible = false;
// if (bananaComboTimer) {
// LK.clearTimeout(bananaComboTimer);
// bananaComboTimer = null;
// }
LK.getSound('gameover').play();
LK.effects.flashScreen(0xff0000, 1000);
// [Bu kısım kaldırıldı] -> createSoulEffect ile kalp efektleri artık çıkmayacak
// Remove all falling items
for (var i = fallingItems.length - 1; i >= 0; i--) {
fallingItems[i].destroy();
}
fallingItems = [];
// Save score to global score history (not persistent)
var score = LK.getScore();
if (typeof score === "number" && score > 0) {
scoreHistory = scoreHistory || [];
scoreHistory.push(score);
// Keep only last 20 scores
if (scoreHistory.length > 20) {
scoreHistory = scoreHistory.slice(scoreHistory.length - 20);
}
}
// Show game over screen
LK.setTimeout(function () {
LK.showGameOver();
}, 1000);
// Show click to play text again
clickToPlayText.visible = true;
}
function spawnItem() {
var score = LK.getScore();
var isBomb = false;
var isRottenBanana = false;
var isHeart = false;
// Heart spawn logic
if (!isHeartAlreadyFalling()) {
if (score >= 50 && lives === 1 && !extraHeartSpawned) {
isHeart = true;
extraHeartSpawned = true;
} else if (score >= 70 && lives === 1 && extraHeartSpawned && !extraHeartCaught) {
isHeart = true;
}
}
// Rotten banana and bomb logic (independent, so both can spawn)
if (!isHeart) {
if (score >= 20 && Math.random() < 0.3) {
isRottenBanana = true;
} else if (score >= 10 && Math.random() < 0.3) {
isBomb = true;
}
}
var itemType = "banana";
if (isHeart) {
itemType = "heart";
} else if (isRottenBanana) {
itemType = "rottenBanana";
} else if (isBomb) {
itemType = "bomb";
}
var item = new FallingItem();
if (itemType === "heart" && score > 100 && lives === 1) {
item.init(itemType, 16);
} else if (itemType === "heart" && score >= 50 && lives === 1) {
item.init(itemType, 10);
} else {
item.init(itemType, currentSpeed);
}
fallingItems.push(item);
game.addChild(item);
return item;
}
// Update game state each frame
game.update = function () {
if (!gameStarted || isGameOver) {
return;
}
// Update all falling items
for (var i = fallingItems.length - 1; i >= 0; i--) {
var item = fallingItems[i];
// Check if item has fallen off screen
if (item && item.lastY !== undefined && item.active && item.lastY < SCREEN_HEIGHT && item.y >= SCREEN_HEIGHT) {
if (item.type === "banana" && item.active) {
// Missed a banana - lose a life
decreaseLife();
LK.getSound('heartLossSound').play(); // Play sound for missed banana
item.remove();
} else if (item.type === "bomb" && item.active || item.type === "rottenBanana" && item.active) {
// Bomb or rotten banana fell off screen - remove it with no penalty
item.destroy();
fallingItems.splice(i, 1);
}
}
// Remove destroyed items from array
if (!item || !item.active || item.alpha <= 0) {
fallingItems.splice(i, 1);
}
}
// Spawn new items at intervals
spawnCounter++;
// Get current score for difficulty calculations
var score = LK.getScore();
// Hearts will be spawned based on specific conditions in spawnItem function
if (spawnCounter >= currentSpawnInterval) {
spawnItem();
spawnCounter = 0;
// Set speed multiplier based on score thresholds
var speedMultiplier = 1;
// 0-150 arası sabit artışlar (orijinal hız tablosu)
if (score >= 150) {
speedMultiplier = 21;
} else if (score >= 140) {
speedMultiplier = 20.5;
} else if (score >= 130) {
speedMultiplier = 20;
} else if (score >= 120) {
speedMultiplier = 19.5;
} else if (score >= 110) {
speedMultiplier = 19;
} else if (score >= 100) {
speedMultiplier = 18;
} else if (score >= 90) {
speedMultiplier = 17;
} else if (score >= 80) {
speedMultiplier = 16;
} else if (score >= 70) {
speedMultiplier = 15;
} else if (score >= 60) {
speedMultiplier = 14;
} else if (score >= 50) {
speedMultiplier = 12.5;
} else if (score >= 40) {
speedMultiplier = 12;
} else if (score >= 30) {
speedMultiplier = 11.5;
} else if (score >= 20) {
speedMultiplier = 11;
} else if (score >= 10) {
speedMultiplier = 10;
} else if (score >= 0) {
speedMultiplier = 9;
} else {
speedMultiplier = 7;
}
// 150’den sonra 300000’e kadar dinamik artış: +0.25 her 1 skor artışı için
if (score > 150 && score <= 300000) {
speedMultiplier = 15 + (score - 150) * 0.5;
}
// Eğer istersen 300000’den sonrası için burada farklı artış mantığı eklenebilir.
// Örnek olarak, 300000’den sonra her 1000 puanda 0.1 artış veya başka bir şey gibi.
// Güncellenen hız, oyun içindeki hız değişkenine atanıyor
currentSpeed = 2 * speedMultiplier;
// Spawn interval (yeniden item çıkma aralığı) puana göre azalıyor ama minimum sınırı var
currentSpawnInterval = Math.max(MIN_SPAWN_INTERVAL, SPAWN_INTERVAL_INITIAL - score * INTERVAL_DECREMENT);
}
// Score text’i güncelle
scoreText.setText('Score: ' + score);
};
// Initialize the game
function initGame() {
// Reset game variables
lives = MAX_LIVES;
LK.setScore(0);
spawnCounter = 0;
currentSpawnInterval = SPAWN_INTERVAL_INITIAL;
currentSpeed = 2;
isGameOver = false;
extraHeartSpawned = false; // Reset heart spawn tracking
extraHeartCaught = false; // Reset heart catch tracking
fallingItems = [];
// Reset banana combo system (REMOVED)
// bananaCombo = 0;
// maxBananaCombo = 0;
// comboText.visible = false;
// if (bananaComboTimer) {
// LK.clearTimeout(bananaComboTimer);
// bananaComboTimer = null;
// }
// Initialize UI
initLives();
scoreText.setText('Score: 0');
// Play background music
LK.playMusic('gameMusic');
}
// Set up click handler to start game
// (Removed, menu handles game start)
// Initialize but don't start the game yet
lives = MAX_LIVES;
initLives(); /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Tween plugin import removed to fix plugin load error
var BananaClickEffect = Container.expand(function () {
var self = Container.call(this);
var effect = self.attachAsset('bananaClickEffect', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.5,
scaleY: 0.5,
alpha: 1
});
self.init = function (x, y) {
self.x = x;
self.y = y;
// Animate: scale up and fade out
tween(effect, {
scaleX: 1.2,
scaleY: 1.2,
alpha: 0
}, {
duration: 600,
easing: tween.easeOut,
onFinish: function onFinish() {
self.destroy();
}
});
};
return self;
});
var BananaEffect = Container.expand(function () {
var self = Container.call(this);
self.init = function (x, y) {
// Create multiple banana particles
for (var i = 0; i < 8; i++) {
var particle = self.attachAsset('banana', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.2,
scaleY: 0.2,
alpha: 0.8
});
// Calculate angle for particle direction
var angle = Math.PI * 2 * (i / 8);
// Position particle
particle.x = 0;
particle.y = 0;
// Calculate target position for the tween
var targetX = Math.cos(angle) * 100;
var targetY = Math.sin(angle) * 100;
// Animate particle
tween(particle, {
x: targetX,
y: targetY,
alpha: 0,
rotation: Math.random() * Math.PI * 2,
scaleX: 0.05,
scaleY: 0.05
}, {
duration: 800 + Math.random() * 400,
easing: tween.easeOut
});
}
// Set position of the effect
self.x = x;
self.y = y;
// Auto-destroy after all animations complete
LK.setTimeout(function () {
self.destroy();
}, 1500);
};
return self;
});
var FallingItem = Container.expand(function () {
var self = Container.call(this);
self.type = "banana"; // default type
self.speed = 2; // default speed
self.lastY = 0;
self.active = true;
self.graphics = null;
self.init = function (type, speed) {
self.type = type || "banana";
self.speed = speed || 2;
// Remove any existing graphics
if (self.graphics) {
self.removeChild(self.graphics);
}
// Create the appropriate graphics based on type
if (self.type === "banana") {
self.graphics = self.attachAsset('banana', {
anchorX: 0.5,
anchorY: 0.5
});
} else if (self.type === "bomb") {
self.graphics = self.attachAsset('bomb', {
anchorX: 0.5,
anchorY: 0.5
});
} else if (self.type === "heart") {
self.graphics = self.attachAsset('heartRestore', {
anchorX: 0.5,
anchorY: 0.5
});
} else if (self.type === "rottenBanana") {
self.graphics = self.attachAsset('rottenBanana', {
anchorX: 0.5,
anchorY: 0.5
});
}
// Set initial position
self.x = Math.random() * (2048 - 200) + 100;
self.y = -100;
self.lastY = self.y;
// Interactive for tapping
self.interactive = true;
};
self.update = function () {
if (!self.active) {
return;
}
self.lastY = self.y;
self.y += self.speed;
};
self.down = function (x, y, obj) {
if (!self.active) {
return;
}
if (self.type === "banana") {
// Score 1 point for each banana
LK.setScore(LK.getScore() + 1);
LK.getSound('pop').play();
// Create banana effect at tap position
createBananaEffect(self.x, self.y);
// Create banana click effect at tap position
createBananaClickEffect(self.x, self.y);
self.remove(false);
} else if (self.type === "bomb") {
// Lost a life by tapping bomb
LK.getSound('explosion').play();
decreaseLife();
self.remove();
} else if (self.type === "heart") {
// Gained a life by tapping heart
LK.getSound('heartRestoreSound').play();
increaseLife();
self.remove();
} else if (self.type === "rottenBanana") {
// Lost a life by tapping rotten banana
LK.getSound('rottenBananaSound').play();
decreaseLife();
self.remove();
}
};
self.remove = function (createSouls) {
self.active = false;
// Create soul effect based on item type, but only if createSouls is not false
if (createSouls !== false) {
if (self.type === "banana") {
createSoulEffect(self.x, self.y, 3);
} else if (self.type === "heart") {
createSoulEffect(self.x, self.y, 5);
} else if (self.type === "bomb" || self.type === "rottenBanana") {
// No souls for negative items
}
}
tween(self, {
alpha: 0,
scaleX: 0.3,
scaleY: 0.3
}, {
duration: 200,
onFinish: function onFinish() {
self.destroy();
}
});
};
return self;
});
var Menu = Container.expand(function () {
var self = Container.call(this);
// Menu background
var bg = self.attachAsset('menuBg', {
anchorX: 0.5,
anchorY: 0.5,
x: SCREEN_WIDTH / 2,
y: SCREEN_HEIGHT / 2
});
// Play button
var playBtn = self.attachAsset('playButton', {
anchorX: 0.5,
anchorY: 0.5,
x: SCREEN_WIDTH / 2,
y: SCREEN_HEIGHT / 2 - 100
});
// Settings button
var settingsBtn = self.attachAsset('settingsButton', {
anchorX: 0.5,
anchorY: 0.5,
x: SCREEN_WIDTH / 2,
y: SCREEN_HEIGHT / 2 + 120
});
// Title text
var titleText = new Text2('Banana Game', {
size: 140,
fill: 0xFFF200,
stroke: 0x000000,
strokeThickness: 10,
bold: true
});
titleText.anchor.set(0.5, 0.5);
titleText.x = SCREEN_WIDTH / 2;
titleText.y = SCREEN_HEIGHT / 2 - 350;
self.addChild(titleText);
// Play button text
var playText = new Text2('Play', {
size: 90,
fill: 0xFFFFFF,
stroke: 0x000000,
strokeThickness: 8,
bold: true
});
playText.anchor.set(0.5, 0.5);
playText.x = SCREEN_WIDTH / 2;
playText.y = SCREEN_HEIGHT / 2 - 100;
self.addChild(playText);
// Settings button text
var settingsText = new Text2('Settings', {
size: 70,
fill: 0xFFFFFF,
stroke: 0x000000,
strokeThickness: 6,
bold: true
});
settingsText.anchor.set(0.5, 0.5);
settingsText.x = SCREEN_WIDTH / 2;
settingsText.y = SCREEN_HEIGHT / 2 + 120;
self.addChild(settingsText);
// Assets button (top right)
var assetsBtn = self.attachAsset('pastScoresMenuButton', {
anchorX: 1,
anchorY: 0,
x: SCREEN_WIDTH - 50,
y: 23.05 // moved down by 0.3cm (11.55px)
});
var assetsText = new Text2('Past Scores', {
size: 60,
fill: 0xFFFFFF,
stroke: 0x000000,
strokeThickness: 5,
bold: true
});
assetsText.anchor.set(1, 0.5);
assetsText.x = SCREEN_WIDTH - 80;
assetsText.y = 50 + 60;
self.addChild(assetsText);
assetsBtn.interactive = true;
assetsBtn.down = function () {
showScoreHistoryPopup();
};
// Button interactivity
playBtn.interactive = true;
playBtn.down = function () {
if (self.parent) self.parent.removeChild(self);
showGame();
};
settingsBtn.interactive = true;
settingsBtn.down = function () {
if (self.parent) self.parent.removeChild(self);
showSettingsMenu();
};
return self;
});
var SettingsMenu = Container.expand(function () {
var self = Container.call(this);
// Settings background
var bg = self.attachAsset('menuBg', {
anchorX: 0.5,
anchorY: 0.5,
x: SCREEN_WIDTH / 2,
y: SCREEN_HEIGHT / 2
});
// Title
var settingsTitle = new Text2('Settings', {
size: 120,
fill: 0xFFF200,
stroke: 0x000000,
strokeThickness: 8,
bold: true
});
settingsTitle.anchor.set(0.5, 0.5);
settingsTitle.x = SCREEN_WIDTH / 2;
settingsTitle.y = SCREEN_HEIGHT / 2 - 300;
self.addChild(settingsTitle);
// Back button
var backBtn = self.attachAsset('menuButton', {
anchorX: 0.5,
anchorY: 0.5,
x: SCREEN_WIDTH / 2,
y: SCREEN_HEIGHT / 2 + 350
});
var backText = new Text2('Back', {
size: 80,
fill: 0xFFFFFF,
stroke: 0x000000,
strokeThickness: 7,
bold: true
});
backText.anchor.set(0.5, 0.5);
backText.x = SCREEN_WIDTH / 2;
backText.y = SCREEN_HEIGHT / 2 + 350;
self.addChild(backText);
// Example settings text
var infoText = new Text2('Sound: On\nMusic: On', {
size: 70,
fill: 0xFFFFFF,
stroke: 0x000000,
strokeThickness: 5,
bold: true
});
infoText.anchor.set(0.5, 0.5);
infoText.x = SCREEN_WIDTH / 2;
infoText.y = SCREEN_HEIGHT / 2;
self.addChild(infoText);
backBtn.interactive = true;
backBtn.down = function () {
if (self.parent) self.parent.removeChild(self);
showMenu();
};
return self;
});
var Soul = Container.expand(function () {
var self = Container.call(this);
self.init = function (x, y) {
// Create soul graphics
var soulGraphics = self.attachAsset('heart', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.5,
scaleY: 0.5,
alpha: 0.7
});
// Set initial position
self.x = x;
self.y = y;
// Randomize direction slightly
self.targetX = Math.random() * 300 - 150 + x;
self.targetY = y - 300 - Math.random() * 200; // Always float upward
// Start the float animation
tween(self, {
x: self.targetX,
y: self.targetY,
alpha: 0,
scaleX: 0.1,
scaleY: 0.1
}, {
duration: 1500 + Math.random() * 1000,
easing: tween.easeOut,
onFinish: function onFinish() {
self.destroy();
}
});
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000000
});
/****
* Game Code
****/
// New effect asset
// Menu and settings assets
;
// Game constants
var SCREEN_WIDTH = 2048;
var SCREEN_HEIGHT = 2732;
var MAX_LIVES = 3;
var BOMB_THRESHOLD_SCORE = 15;
var SPAWN_INTERVAL_INITIAL = 60; // frames
var MIN_SPAWN_INTERVAL = 20; // frames
var INTERVAL_DECREMENT = 1;
// Game variables
var fallingItems = [];
var lives = MAX_LIVES;
var spawnCounter = 0;
var currentSpawnInterval = SPAWN_INTERVAL_INITIAL;
var currentSpeed = 2;
var isGameOver = false;
var extraHeartSpawned = false;
var extraHeartCaught = false;
var gameStarted = false;
// Banana combo system variables (REMOVED)
// var bananaCombo = 0;
// var bananaComboTimer = null;
// var BANANA_COMBO_TIMEOUT = 1500; // ms
// var maxBananaCombo = 0;
// Combo text UI (REMOVED)
// var comboText = new Text2('', {
// size: 120,
// fill: 0xA259FF,
// // purple
// stroke: 0x000000,
// strokeThickness: 8,
// bold: true
// });
// comboText.anchor.set(0.5, 0);
// comboText.x = SCREEN_WIDTH / 2;
// comboText.y = 200;
// comboText.visible = false;
// game.addChild(comboText);
// Add background
var background = game.addChild(LK.getAsset('background', {
anchorX: 0,
anchorY: 0
}));
// Menu logic
var menuInstance = null;
var settingsMenuInstance = null;
// Global variable to store score history (in-memory, not persistent)
var scoreHistory = [];
// Show popup with past scores
function showScoreHistoryPopup() {
// Remove existing popup if present
if (game.scoreHistoryPopup && game.scoreHistoryPopup.parent) {
game.removeChild(game.scoreHistoryPopup);
game.scoreHistoryPopup = null;
}
var popup = new Container();
// Popup background
var bg = popup.attachAsset('menuBg', {
anchorX: 0.5,
anchorY: 0.5,
x: SCREEN_WIDTH / 2,
y: SCREEN_HEIGHT / 2,
scaleX: 0.7,
scaleY: 0.7
});
// Title
var title = new Text2('Past Scores', {
size: 90,
fill: 0xFFF200,
stroke: 0x000000,
strokeThickness: 7,
bold: true
});
title.anchor.set(0.5, 0.5);
title.x = SCREEN_WIDTH / 2;
title.y = SCREEN_HEIGHT / 2 - 350;
popup.addChild(title);
// Get score history from global variable (show up to 10 most recent)
var history = scoreHistory || [];
var displayScores = history.slice(-10).reverse();
var scoresText = displayScores.length > 0 ? displayScores.map(function (s, i) {
return i + 1 + '. ' + s;
}).join('\n') : 'No scores yet!';
var scoresList = new Text2(scoresText, {
size: 70,
fill: 0xFFFFFF,
stroke: 0x000000,
strokeThickness: 5,
bold: true
});
scoresList.anchor.set(0.5, 0);
scoresList.x = SCREEN_WIDTH / 2;
scoresList.y = SCREEN_HEIGHT / 2 - 220;
popup.addChild(scoresList);
// Close button
var closeBtn = popup.attachAsset('menuButton', {
anchorX: 0.5,
anchorY: 0.5,
x: SCREEN_WIDTH / 2,
y: SCREEN_HEIGHT / 2 + 350,
scaleX: 0.7,
scaleY: 0.7
});
var closeText = new Text2('Close', {
size: 70,
fill: 0xFFFFFF,
stroke: 0x000000,
strokeThickness: 6,
bold: true
});
closeText.anchor.set(0.5, 0.5);
closeText.x = SCREEN_WIDTH / 2;
closeText.y = SCREEN_HEIGHT / 2 + 350;
popup.addChild(closeText);
closeBtn.interactive = true;
closeBtn.down = function () {
if (popup.parent) game.removeChild(popup);
game.scoreHistoryPopup = null;
};
game.addChild(popup);
game.scoreHistoryPopup = popup;
}
// Show menu
function showMenu() {
if (menuInstance) {
if (!menuInstance.parent) game.addChild(menuInstance);
return;
}
menuInstance = new Menu();
game.addChild(menuInstance);
}
// Show settings menu
function showSettingsMenu() {
if (settingsMenuInstance) {
if (!settingsMenuInstance.parent) game.addChild(settingsMenuInstance);
return;
}
settingsMenuInstance = new SettingsMenu();
game.addChild(settingsMenuInstance);
}
// Hide menu and start game
function showGame() {
gameStarted = true;
clickToPlayText.visible = false;
initGame();
}
// Show menu on game start
LK.setTimeout(function () {
showMenu();
}, 10);
// Initialize score text
var scoreText = new Text2('Score: 0', {
size: 80,
fill: 0xFFFFFF,
stroke: 0x000000,
strokeThickness: 8,
bold: true
});
scoreText.anchor.set(0.5, 0);
scoreText.x = SCREEN_WIDTH / 2;
scoreText.y = 50;
game.addChild(scoreText);
// Create click to play text (hidden, menu will be used instead)
var clickToPlayText = new Text2('Click to Start', {
size: 120,
fill: 0xFFFFFF,
stroke: 0x000000,
strokeThickness: 8,
bold: true
});
clickToPlayText.anchor.set(0.5, 0.5);
clickToPlayText.x = SCREEN_WIDTH / 2;
clickToPlayText.y = SCREEN_HEIGHT / 2;
clickToPlayText.visible = false;
game.addChild(clickToPlayText);
// Create hearts container
var heartsContainer = new Container();
heartsContainer.x = 1410;
heartsContainer.y = 50;
game.addChild(heartsContainer);
// Initialize hearts display
function initLives() {
// Clear existing hearts
while (heartsContainer.children.length > 0) {
heartsContainer.removeChildAt(0);
}
// Add hearts based on current lives
for (var i = 0; i < lives; i++) {
var heart = LK.getAsset('heart', {
anchorX: 0,
anchorY: 0,
x: i * 190,
y: 0
});
heartsContainer.addChild(heart);
}
}
// Function to create floating soul effect
function createSoulEffect(x, y, count) {
count = count || 1;
for (var i = 0; i < count; i++) {
var soul = new Soul();
soul.init(x, y);
game.addChild(soul);
}
}
// Function to create banana effect when banana is clicked
function createBananaEffect(x, y) {
var effect = new BananaEffect();
effect.init(x, y);
game.addChild(effect);
}
// Function to create banana click effect animation
function createBananaClickEffect(x, y) {
var effect = new BananaClickEffect();
effect.init(x, y);
game.addChild(effect);
}
// Function to check if a heart is already falling
function isHeartAlreadyFalling() {
for (var i = 0; i < fallingItems.length; i++) {
if (fallingItems[i] && fallingItems[i].type === "heart" && fallingItems[i].active) {
return true;
}
}
return false;
}
// Function to increase life
function increaseLife() {
if (lives < MAX_LIVES) {
lives++;
initLives();
extraHeartCaught = true; // Mark that a heart was caught
}
}
// Function to decrease life
function decreaseLife() {
// Create soul effect at heart position that was lost
var heartIndex = lives - 1;
if (heartIndex >= 0 && heartsContainer.children[heartIndex]) {
var heartPos = heartsContainer.children[heartIndex];
var globalPos = heartsContainer.toGlobal({
x: heartPos.x + 50,
y: heartPos.y + 50
});
var gamePos = game.toLocal(globalPos);
createSoulEffect(gamePos.x, gamePos.y, 7);
}
lives--;
initLives();
// We only play the heart loss sound for actual life losses, not from bombs or rotten bananas
// This is handled in the game.update and FallingItem.down methods where decreaseLife is called.
// LK.getSound('heartLossSound').play(); // Removed sound here
// Shake the screen using the tween library
tween(game, {
x: game.x + 5
}, {
duration: 50,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(game, {
x: game.x - 10
}, {
duration: 100,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(game, {
x: game.x + 5
}, {
duration: 50,
easing: tween.easeIn,
onFinish: function onFinish() {
// Check for game over after shake is complete
if (lives <= 0) {
gameOver();
}
}
});
}
});
}
});
}
// Function to handle game over
function gameOver() {
if (isGameOver) {
return;
}
isGameOver = true;
gameStarted = false;
// Reset banana combo system (REMOVED)
// bananaCombo = 0;
// comboText.visible = false;
// if (bananaComboTimer) {
// LK.clearTimeout(bananaComboTimer);
// bananaComboTimer = null;
// }
LK.getSound('gameover').play();
LK.effects.flashScreen(0xff0000, 1000);
// [Bu kısım kaldırıldı] -> createSoulEffect ile kalp efektleri artık çıkmayacak
// Remove all falling items
for (var i = fallingItems.length - 1; i >= 0; i--) {
fallingItems[i].destroy();
}
fallingItems = [];
// Save score to global score history (not persistent)
var score = LK.getScore();
if (typeof score === "number" && score > 0) {
scoreHistory = scoreHistory || [];
scoreHistory.push(score);
// Keep only last 20 scores
if (scoreHistory.length > 20) {
scoreHistory = scoreHistory.slice(scoreHistory.length - 20);
}
}
// Show game over screen
LK.setTimeout(function () {
LK.showGameOver();
}, 1000);
// Show click to play text again
clickToPlayText.visible = true;
}
function spawnItem() {
var score = LK.getScore();
var isBomb = false;
var isRottenBanana = false;
var isHeart = false;
// Heart spawn logic
if (!isHeartAlreadyFalling()) {
if (score >= 50 && lives === 1 && !extraHeartSpawned) {
isHeart = true;
extraHeartSpawned = true;
} else if (score >= 70 && lives === 1 && extraHeartSpawned && !extraHeartCaught) {
isHeart = true;
}
}
// Rotten banana and bomb logic (independent, so both can spawn)
if (!isHeart) {
if (score >= 20 && Math.random() < 0.3) {
isRottenBanana = true;
} else if (score >= 10 && Math.random() < 0.3) {
isBomb = true;
}
}
var itemType = "banana";
if (isHeart) {
itemType = "heart";
} else if (isRottenBanana) {
itemType = "rottenBanana";
} else if (isBomb) {
itemType = "bomb";
}
var item = new FallingItem();
if (itemType === "heart" && score > 100 && lives === 1) {
item.init(itemType, 16);
} else if (itemType === "heart" && score >= 50 && lives === 1) {
item.init(itemType, 10);
} else {
item.init(itemType, currentSpeed);
}
fallingItems.push(item);
game.addChild(item);
return item;
}
// Update game state each frame
game.update = function () {
if (!gameStarted || isGameOver) {
return;
}
// Update all falling items
for (var i = fallingItems.length - 1; i >= 0; i--) {
var item = fallingItems[i];
// Check if item has fallen off screen
if (item && item.lastY !== undefined && item.active && item.lastY < SCREEN_HEIGHT && item.y >= SCREEN_HEIGHT) {
if (item.type === "banana" && item.active) {
// Missed a banana - lose a life
decreaseLife();
LK.getSound('heartLossSound').play(); // Play sound for missed banana
item.remove();
} else if (item.type === "bomb" && item.active || item.type === "rottenBanana" && item.active) {
// Bomb or rotten banana fell off screen - remove it with no penalty
item.destroy();
fallingItems.splice(i, 1);
}
}
// Remove destroyed items from array
if (!item || !item.active || item.alpha <= 0) {
fallingItems.splice(i, 1);
}
}
// Spawn new items at intervals
spawnCounter++;
// Get current score for difficulty calculations
var score = LK.getScore();
// Hearts will be spawned based on specific conditions in spawnItem function
if (spawnCounter >= currentSpawnInterval) {
spawnItem();
spawnCounter = 0;
// Set speed multiplier based on score thresholds
var speedMultiplier = 1;
// 0-150 arası sabit artışlar (orijinal hız tablosu)
if (score >= 150) {
speedMultiplier = 21;
} else if (score >= 140) {
speedMultiplier = 20.5;
} else if (score >= 130) {
speedMultiplier = 20;
} else if (score >= 120) {
speedMultiplier = 19.5;
} else if (score >= 110) {
speedMultiplier = 19;
} else if (score >= 100) {
speedMultiplier = 18;
} else if (score >= 90) {
speedMultiplier = 17;
} else if (score >= 80) {
speedMultiplier = 16;
} else if (score >= 70) {
speedMultiplier = 15;
} else if (score >= 60) {
speedMultiplier = 14;
} else if (score >= 50) {
speedMultiplier = 12.5;
} else if (score >= 40) {
speedMultiplier = 12;
} else if (score >= 30) {
speedMultiplier = 11.5;
} else if (score >= 20) {
speedMultiplier = 11;
} else if (score >= 10) {
speedMultiplier = 10;
} else if (score >= 0) {
speedMultiplier = 9;
} else {
speedMultiplier = 7;
}
// 150’den sonra 300000’e kadar dinamik artış: +0.25 her 1 skor artışı için
if (score > 150 && score <= 300000) {
speedMultiplier = 15 + (score - 150) * 0.5;
}
// Eğer istersen 300000’den sonrası için burada farklı artış mantığı eklenebilir.
// Örnek olarak, 300000’den sonra her 1000 puanda 0.1 artış veya başka bir şey gibi.
// Güncellenen hız, oyun içindeki hız değişkenine atanıyor
currentSpeed = 2 * speedMultiplier;
// Spawn interval (yeniden item çıkma aralığı) puana göre azalıyor ama minimum sınırı var
currentSpawnInterval = Math.max(MIN_SPAWN_INTERVAL, SPAWN_INTERVAL_INITIAL - score * INTERVAL_DECREMENT);
}
// Score text’i güncelle
scoreText.setText('Score: ' + score);
};
// Initialize the game
function initGame() {
// Reset game variables
lives = MAX_LIVES;
LK.setScore(0);
spawnCounter = 0;
currentSpawnInterval = SPAWN_INTERVAL_INITIAL;
currentSpeed = 2;
isGameOver = false;
extraHeartSpawned = false; // Reset heart spawn tracking
extraHeartCaught = false; // Reset heart catch tracking
fallingItems = [];
// Reset banana combo system (REMOVED)
// bananaCombo = 0;
// maxBananaCombo = 0;
// comboText.visible = false;
// if (bananaComboTimer) {
// LK.clearTimeout(bananaComboTimer);
// bananaComboTimer = null;
// }
// Initialize UI
initLives();
scoreText.setText('Score: 0');
// Play background music
LK.playMusic('gameMusic');
}
// Set up click handler to start game
// (Removed, menu handles game start)
// Initialize but don't start the game yet
lives = MAX_LIVES;
initLives();
Pixel banana. In-Game asset. High contrast. No shadows
Pixel art Bomb.. In-Game asset. High contrast. No shadows
Pixel art Heart. In-Game asset. High contrast. No shadows
Pixel art Forest background. In-Game asset. High contrast. No shadows
Purple color "+1" in pixels art style . No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
Simple empty clean pixel art background in brown. In-Game asset. 2d. High contrast. No shadows. Game menu background.
Menu button. Pixel art dark brown.. In-Game asset. 2d. High contrast. No shadows No writing inside