User prompt
Oyunun herseyini optimize et ve eklediğim müziği oyun başladığı gibi başlasın bitincede tekrarlansın ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Puanin altindaki yay seviyesini aşağı taşı
User prompt
Yay seviyelerini biraz sağa taşı
User prompt
64 yap ve yazıları rank ve can barinin ortasına taşı
User prompt
Yay seviye yazılarını çok büyüt
User prompt
Can barinin yanına taşı ve boyutları çok büyük olsun
User prompt
Rank resminin üstüne yay 1 yay 2 yay 3 yay 4 yay 5 yazılarını ekle yanlarında parası 1 seviye 200 coin 2 seviye 500 coin 3 seviye 750 coin 4 seviye 950 coin 5 seviye 1500 coin olsun coin yeterse üstüne tıklayarak alınır ve yazının yani alındı yazsin. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Geri al yaptığını ve coin ve kill yazısını rank resminin üstüne taşı
User prompt
Coin ve kill yazısını rank resminin yukarisina tadı ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Adamlara vurunca coini 50 yerine 10 ver ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Yay seviyesi yazısını puanın altına ekle ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Yay seviyesi yazısını görünür yap
User prompt
Yay seviyesi tam olarak can barının üstünde olsun yay seviyesi için ilk önce 5 seviye teker teker 1 2 3 4 5 diye rütbe resminin yukarisina ekle ve bitir. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Oyuna para birimi ekle altın olsun her top vurduğunda 50 para kazanılsın rank resminin yanında coin para birimi gözüksün para alıncada yazı efectle coin saçsın, diğer bir seçenek ise yanlarda yay seviyeleri olsun toplam 5 seviye 1. Seviye 100 coin bunu alınca yay toplara vurunca 30 puan yerine 50 puan alsın, 2 seviyede 200 coin olsun bunu alinca yay toplara vurunca 50 puan yerine 70 puan alsın, 3 seviyede coini 300 olsun bu seviyede yay topa vurunca 70 puan yerine 100 alsın, 4 seviye coini 700 olsun yay toplara vurunca 70 puan yerine 90 puan alsın, 5 seviyede coini 1050 olsun yay topa vurunca 100 yerine 120 puan alsın, bu seviyeleri ilk seviyeden açmadan diğerlerini acamasin, yay seviyesi canın üstünde gözüksün seviye atlayınca yazı renk efekti alsın. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Vurulan her top için kill alınsın kill sayısı rank resminin yanında yazsin kill alınca sayı renkli efect alsın ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Değişikliği geri al ve toplar ve bombalar sadece efect yap çok az ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Toplar bombalar renk şansın
User prompt
Topları ve bombaları içlerinden ağaç kabuğu geçerek hepsiyle birleşerek olsun ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Geri sayım boyutu büyük olsun rengide siyah
User prompt
Oyun başlamadan önce 5 sn ekranda say ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Müziği oyun başlayınca başlat bitincede tekrarla
User prompt
Müziği oyunun 30dk direk baslat
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Arrow = Container.expand(function (targetX, targetY, startX, startY) {
var self = Container.call(this);
// Attach arrow asset
var arrowGraphics = self.attachAsset('arrow', {
anchorX: 0.5,
anchorY: 0.5
});
// Calculate direction and speed
var dx = targetX - startX;
var dy = targetY - startY;
var distance = Math.sqrt(dx * dx + dy * dy);
// Set base speed and apply power-up multiplier
var baseSpeed = 8;
var speed = baseSpeed;
if (extraPowerActive) speed *= 1.8;
if (speedBoostActive) speed *= 1.5;
// Cache velocity calculations
var velocityMultiplier = speed / distance;
self.velocityX = dx * velocityMultiplier;
self.velocityY = dy * velocityMultiplier;
// Set rotation to point toward target
arrowGraphics.rotation = Math.atan2(dy, dx);
self.update = function () {
// Don't update if countdown is active
if (countdownActive) return;
self.x += self.velocityX;
self.y += self.velocityY;
// Remove arrow if it goes off screen (check this first for early exit)
if (self.x < -100 || self.x > 2148 || self.y < -100 || self.y > 2832) {
self.destroy();
return;
}
// Only check collisions every 12 frames to optimize performance
if (LK.ticks % 12 === 0) {
// Check collision with balls (optimized)
for (var i = balls.length - 1; i >= 0; i--) {
var ball = balls[i];
// Quick distance check before expensive intersection test
var dx = self.x - ball.x;
var dy = self.y - ball.y;
var distanceSquared = dx * dx + dy * dy;
if (distanceSquared < ballCollisionRange) {
// 80px collision range - optimized
if (self.intersects(ball)) {
// Trigger ball hit
ball.hit();
self.destroy();
return;
}
}
}
// Check collision with bombs (optimized)
for (var j = bombs.length - 1; j >= 0; j--) {
var bomb = bombs[j];
// Quick distance check before expensive intersection test
var dx2 = self.x - bomb.x;
var dy2 = self.y - bomb.y;
var distanceSquared2 = dx2 * dx2 + dy2 * dy2;
if (distanceSquared2 < bombCollisionRange) {
// 80px collision range - optimized
if (self.intersects(bomb)) {
// Trigger bomb hit
bomb.hit();
self.destroy();
return;
}
}
}
}
};
return self;
});
var Ball = Container.expand(function (ballType) {
var self = Container.call(this);
// Store ball type and set properties based on type
self.ballType = ballType;
var assetId, points;
switch (ballType) {
case 'red':
assetId = 'redBall';
points = 30;
break;
case 'yellow':
assetId = 'yellowBall';
points = 30;
break;
case 'blue':
assetId = 'blueBall';
points = 30;
break;
}
self.points = points;
// Attach the appropriate ball asset
var ballGraphics = self.attachAsset(assetId, {
anchorX: 0.5,
anchorY: 0.5
});
// Apply subtle scale effect instead of color tinting
var randomScale = 0.9 + Math.random() * 0.2; // Scale between 0.9 and 1.1
ballGraphics.scaleX = randomScale;
ballGraphics.scaleY = randomScale;
// Add floating animation
self.floatDirection = Math.random() > 0.5 ? 1 : -1;
self.floatSpeed = 0.5 + Math.random() * 0.5;
self.floatOffset = 0;
// Add horizontal movement
self.horizontalDirection = Math.random() > 0.5 ? 1 : -1;
self.horizontalSpeed = 4 + Math.random() * 3;
// Add vertical movement
self.verticalDirection = Math.random() > 0.5 ? 1 : -1;
self.verticalSpeed = 1.5 + Math.random() * 2;
// Initialize falling properties
self.isHit = false;
self.isFalling = false;
self.fallSpeed = 0;
self.gravity = 0.5;
self.update = function () {
// Don't update if countdown is active
if (countdownActive) return;
// If ball is falling after being hit, apply gravity
if (self.isFalling) {
self.fallSpeed += self.gravity;
self.y += self.fallSpeed;
// Check if ball hits the ground (bottom of screen)
if (self.y >= 2600) {
// Simply destroy the ball without effects
self.destroy();
return;
}
} else {
// Normal ball movement when not hit
// Only update floating animation every 35 frames to reduce CPU load
if (LK.ticks % 35 === 0) {
self.floatOffset += self.floatSpeed;
self.y += Math.sin(self.floatOffset) * self.floatDirection * 0.2;
}
// Cache movement calculations for better performance
var horizontalMovement = self.horizontalSpeed * self.horizontalDirection;
var verticalMovement = self.verticalSpeed * self.verticalDirection;
// Add horizontal movement in both directions
self.x += horizontalMovement;
// Add vertical movement for diagonal motion
self.y += verticalMovement;
// Keep balls in upper area - restrict Y position for portrait screen
if (self.y > 1800) {
self.y = 1800;
self.verticalDirection = -1; // Bounce upward
}
if (self.y < 100) {
self.y = 100;
self.verticalDirection = 1; // Bounce downward
}
// Bounce off screen edges - keep balls in central area for portrait screen
if (self.x <= 200 || self.x >= 1848) {
self.horizontalDirection *= -1; // Reverse horizontal direction
if (self.x <= 200) self.x = 200;
if (self.x >= 1848) self.x = 1848;
}
}
};
self.hit = function () {
// Award points and remove ball
var basePoints = self.points;
var finalPoints = basePoints;
// Apply extra power bonus if active
if (extraPowerActive) {
finalPoints += 30;
}
var oldScore = LK.getScore();
LK.setScore(oldScore + finalPoints);
scoreTxt.setText(LK.getScore());
// Add colorful effect to score based on ball type
var effectColor;
switch (self.ballType) {
case 'red':
effectColor = 0xFF4444;
break;
case 'yellow':
effectColor = 0xFFFF44;
break;
case 'blue':
effectColor = 0x4444FF;
break;
}
// Stop any existing tween on score text
tween.stop(scoreTxt, {
tint: true,
scaleX: true,
scaleY: true
});
// Apply color tint effect
tween(scoreTxt, {
tint: effectColor
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
// Fade back to white
tween(scoreTxt, {
tint: 0xFFFFFF
}, {
duration: 500,
easing: tween.easeInOut
});
}
});
// Add scale pulse effect
scoreTxt.scaleX = 1.3;
scoreTxt.scaleY = 1.3;
tween(scoreTxt, {
scaleX: 1,
scaleY: 1
}, {
duration: 400,
easing: tween.bounceOut
});
updateRankDisplay();
try {
LK.getSound('ballHit').play();
} catch (e) {
console.log('Ball hit sound failed to play');
}
// Check for extra life every 5000 points
var newScore = LK.getScore();
var oldLifeBonuses = Math.floor(oldScore / 5000);
var newLifeBonuses = Math.floor(newScore / 5000);
if (newLifeBonuses > oldLifeBonuses) {
lives++;
updateHeartsDisplay();
LK.effects.flashScreen(0x00FF00, 800); // Green flash for extra life
}
// Check for arrow speed boost every 10000 points
var oldSpeedBonuses = Math.floor(oldScore / 10000);
var newSpeedBonuses = Math.floor(newScore / 10000);
if (newSpeedBonuses > oldSpeedBonuses) {
// Activate speed boost for 1 minute
speedBoostActive = true;
speedBoostEndTime = remainingTime - 60; // 1 minute duration
LK.effects.flashScreen(0x0080FF, 800); // Blue flash for speed boost
}
// 1% chance to gain extra life on ball hit
if (Math.random() < 0.01) {
lives++;
updateHeartsDisplay();
LK.effects.flashScreen(0x00FF00, 800); // Green flash for extra life
}
// 6% chance to activate power-up
if (Math.random() < 0.06) {
// 50% chance for each power-up type
if (Math.random() < 0.5) {
// Activate extra power (+30 points)
extraPowerActive = true;
extraPowerEndTime = remainingTime - powerUpDuration;
} else {
// Activate dual shot
dualShotActive = true;
dualShotEndTime = remainingTime - powerUpDuration;
}
}
// Create tree bark merging effect before falling
createMergingEffect(self.x, self.y, 'ball');
// Mark ball as hit and start falling
self.isHit = true;
self.isFalling = true;
self.fallSpeed = 0;
self.gravity = 0.5;
// Remove from balls array
for (var i = balls.length - 1; i >= 0; i--) {
if (balls[i] === self) {
balls.splice(i, 1);
break;
}
}
// Spawn a new random ball at a random position for portrait screen
var randomBallType = ballTypes[Math.floor(Math.random() * ballTypes.length)];
var newBall = new Ball(randomBallType);
// Random position in the game area (avoiding edges) for portrait screen
newBall.x = 300 + Math.random() * 1448;
newBall.y = 300 + Math.random() * 1200;
balls.push(newBall);
game.addChild(newBall);
};
return self;
});
var Bomb = Container.expand(function () {
var self = Container.call(this);
// Attach bomb asset
var bombGraphics = self.attachAsset('bomb', {
anchorX: 0.5,
anchorY: 0.5
});
// Apply subtle alpha effect instead of color tinting
var randomAlpha = 0.85 + Math.random() * 0.15; // Alpha between 0.85 and 1.0
bombGraphics.alpha = randomAlpha;
// Add pulsing animation to make it look dangerous
self.pulseOffset = Math.random() * Math.PI * 2;
// Add horizontal movement
self.horizontalDirection = Math.random() > 0.5 ? 1 : -1;
self.horizontalSpeed = 4 + Math.random() * 3;
// Add vertical movement
self.verticalDirection = Math.random() > 0.5 ? 1 : -1;
self.verticalSpeed = 1.5 + Math.random() * 2;
self.update = function () {
// Don't update if countdown is active
if (countdownActive) return;
// Only update pulsing animation every 28 frames to reduce CPU load
if (LK.ticks % 28 === 0) {
self.pulseOffset += 0.08;
var scale = 1 + Math.sin(self.pulseOffset) * 0.08;
bombGraphics.scaleX = scale;
bombGraphics.scaleY = scale;
}
// Cache movement calculations for better performance
var horizontalMovement = self.horizontalSpeed * self.horizontalDirection;
var verticalMovement = self.verticalSpeed * self.verticalDirection;
// Add horizontal movement in both directions
self.x += horizontalMovement;
// Add vertical movement for diagonal motion
self.y += verticalMovement;
// Keep bombs in upper area - restrict Y position for portrait screen
if (self.y > 1800) {
self.y = 1800;
self.verticalDirection = -1; // Bounce upward
}
if (self.y < 100) {
self.y = 100;
self.verticalDirection = 1; // Bounce downward
}
// Bounce off screen edges - keep bombs in central area for portrait screen
if (self.x <= 200 || self.x >= 1848) {
self.horizontalDirection *= -1; // Reverse horizontal direction
if (self.x <= 200) self.x = 200;
if (self.x >= 1848) self.x = 1848;
}
};
self.hit = function () {
// Play bomb sound effect with error handling
try {
LK.getSound('bombSound').play();
} catch (e) {
console.log('Bomb sound failed to play');
}
// Deduct points and lose a life for hitting bomb
LK.setScore(Math.max(0, LK.getScore() - 10));
scoreTxt.setText(LK.getScore());
updateRankDisplay();
lives--;
updateHeartsDisplay();
bombHitCount++;
// Create tree bark merging effect
createMergingEffect(self.x, self.y, 'bomb');
// Flash screen red to indicate penalty
LK.effects.flashScreen(0xff0000, 500);
// Check if 5 bombs hit - restart game
if (bombHitCount >= 5) {
LK.showGameOver();
return;
}
// Check game over
if (lives <= 0) {
LK.showGameOver();
return;
}
// Remove from bombs array
for (var i = bombs.length - 1; i >= 0; i--) {
if (bombs[i] === self) {
bombs.splice(i, 1);
break;
}
}
self.destroy();
};
return self;
});
var TreeBark = Container.expand(function (startX, startY, targetX, targetY) {
var self = Container.call(this);
// Attach tree bark asset
var barkGraphics = self.attachAsset('treeBark', {
anchorX: 0.5,
anchorY: 0.5
});
// Set initial position
self.x = startX;
self.y = startY;
// Calculate movement direction
var dx = targetX - startX;
var dy = targetY - startY;
var distance = Math.sqrt(dx * dx + dy * dy);
// Set speed and direction
self.speed = 6;
if (distance > 0) {
self.velocityX = dx / distance * self.speed;
self.velocityY = dy / distance * self.speed;
} else {
self.velocityX = 0;
self.velocityY = 0;
}
// Add spinning animation
barkGraphics.rotation = Math.random() * Math.PI * 2;
self.rotationSpeed = (Math.random() - 0.5) * 0.3;
// Set alpha and scale
barkGraphics.alpha = 0.8;
barkGraphics.scaleX = 0.8 + Math.random() * 0.4;
barkGraphics.scaleY = barkGraphics.scaleX;
self.update = function () {
// Don't update if countdown is active
if (countdownActive) return;
// Move towards target
self.x += self.velocityX;
self.y += self.velocityY;
// Rotate
barkGraphics.rotation += self.rotationSpeed;
// Fade out over time
barkGraphics.alpha -= 0.01;
// Remove when fully transparent or off screen
if (barkGraphics.alpha <= 0 || self.x < -100 || self.x > 2148 || self.y < -100 || self.y > 2832) {
self.destroy();
}
};
return self;
});
/****
* Initialize Game
****/
// Game arrays to track objects
var game = new LK.Game({
backgroundColor: 0x0080FF
});
/****
* Game Code
****/
// Game arrays to track objects
// Initialize ball assets with different colors
var balls = [];
var bombs = [];
var lives = 5;
var hearts = [];
var bombHitCount = 0;
// Timer variables (30 minutes = 1800 seconds)
var totalGameTime = 1800; // 30 minutes in seconds
var remainingTime = totalGameTime;
var lastSecondTick = 0;
// Power-up system variables
var extraPowerActive = false;
var dualShotActive = false;
var speedBoostActive = false;
var extraPowerEndTime = 0;
var dualShotEndTime = 0;
var speedBoostEndTime = 0;
var powerUpDuration = 180; // 3 minutes in seconds
// Performance optimization: cached calculations
var screenCenterX = 1024;
var screenCenterY = 1366;
var maxHandDistance = 90;
var ballCollisionRange = 6400;
var bombCollisionRange = 6400;
// CS2 Rank System - 3 Categories
var rankThresholds = [{
name: 'Gümüş Seviyeler',
min: 0,
max: 4910,
color: 0x808080,
asset: 'rankSilver'
}, {
name: 'Altın Nova Seviyeler',
min: 4911,
max: 9734,
color: 0xFFD700,
asset: 'rankGoldNova'
}, {
name: 'Supreme Seviyeler',
min: 9735,
max: 999999,
color: 0xFF0000,
asset: 'rankSupreme'
}];
var currentRank = rankThresholds[0];
var rankIcon = null;
var rankNameTxt = null;
// Score display
var scoreTxt = new Text2('0', {
size: 80,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(1, 0);
scoreTxt.x = -20;
scoreTxt.y = 20;
LK.gui.topRight.addChild(scoreTxt);
// Timer display
var timerTxt = new Text2('30:00', {
size: 80,
fill: 0xFFFFFF
});
timerTxt.anchor.set(0.5, 0);
timerTxt.x = 0;
timerTxt.y = 20;
LK.gui.top.addChild(timerTxt);
// Power-up display texts
var extraPowerTxt = new Text2('', {
size: 50,
fill: 0x00FF00
});
extraPowerTxt.anchor.set(1, 0);
extraPowerTxt.x = -20;
extraPowerTxt.y = 120;
LK.gui.topRight.addChild(extraPowerTxt);
var dualShotTxt = new Text2('', {
size: 50,
fill: 0x00FFFF
});
dualShotTxt.anchor.set(1, 0);
dualShotTxt.x = -20;
dualShotTxt.y = 180;
LK.gui.topRight.addChild(dualShotTxt);
var speedBoostTxt = new Text2('', {
size: 50,
fill: 0x0080FF
});
speedBoostTxt.anchor.set(1, 0);
speedBoostTxt.x = -20;
speedBoostTxt.y = 240;
LK.gui.topRight.addChild(speedBoostTxt);
// Initialize rank display in bottom left corner
rankNameTxt = new Text2('', {
size: 40,
fill: 0xFFFFFF
});
rankNameTxt.anchor.set(0, 1);
rankNameTxt.x = 540;
rankNameTxt.y = 2712;
game.addChild(rankNameTxt);
// Fire effects variables
var fireEffects = [];
// Merging system variables
var treeBarkParticles = [];
var mergingBalls = [];
var mergingBombs = [];
var mergeRange = 150;
// Function to add fire effects around rank icon
function addFireEffectsToRank() {
// Remove existing fire effects
if (fireEffects && fireEffects.length > 0) {
for (var i = 0; i < fireEffects.length; i++) {
if (fireEffects[i]) {
fireEffects[i].destroy();
}
}
}
fireEffects = [];
if (!rankIcon) return;
// Create fire particles around the rank icon
var numFireParticles = 1;
var iconCenterX = rankIcon.x + 250; // Center of rank icon
var iconCenterY = rankIcon.y - 250; // Center of rank icon
var radius = 280; // Distance from center
for (var i = 0; i < numFireParticles; i++) {
var angle = i / numFireParticles * Math.PI * 2;
var fireX = iconCenterX + Math.cos(angle) * radius;
var fireY = iconCenterY + Math.sin(angle) * radius;
// Create fire particle using a small red/orange shape
var fireParticle = LK.getAsset('redBall', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.3,
scaleY: 0.3
});
fireParticle.tint = 0xFF4400; // Orange-red color
fireParticle.x = fireX;
fireParticle.y = fireY;
fireParticle.alpha = 0.8;
fireParticle.baseX = fireX;
fireParticle.baseY = fireY;
fireParticle.animationOffset = i * 0.5; // Stagger animation
game.addChild(fireParticle);
fireEffects.push(fireParticle);
// Start flickering animation
animateFireParticle(fireParticle);
}
}
// Function to animate individual fire particle
function animateFireParticle(particle) {
if (!particle) return;
// Random flicker effect
var flickerDuration = 200 + Math.random() * 300;
var targetAlpha = 0.3 + Math.random() * 0.7;
var targetScale = 0.2 + Math.random() * 0.3;
var targetTint = Math.random() > 0.5 ? 0xFF4400 : 0xFF6600;
tween(particle, {
alpha: targetAlpha,
scaleX: targetScale,
scaleY: targetScale,
tint: targetTint
}, {
duration: flickerDuration,
easing: tween.easeInOut,
onFinish: function onFinish() {
// Continue animation loop
animateFireParticle(particle);
}
});
}
// Initialize rank display
updateRankDisplay();
// Function to get current rank based on score
function getCurrentRank(score) {
for (var i = rankThresholds.length - 1; i >= 0; i--) {
if (score >= rankThresholds[i].min) {
return rankThresholds[i];
}
}
return rankThresholds[0];
}
// Function to get rank level within current rank category
function getRankLevel(score, rank) {
var rangeSize = rank.max - rank.min + 1;
var relativeScore = score - rank.min;
var level = Math.floor(relativeScore / rangeSize * 10) + 1;
return Math.min(level, 10);
}
// Function to update rank display
function updateRankDisplay() {
var newRank = getCurrentRank(LK.getScore());
var rankLevel = getRankLevel(LK.getScore(), newRank);
// Always update rank display to ensure it's visible
currentRank = newRank;
// Remove old rank icon if exists
if (rankIcon) {
rankIcon.destroy();
}
// Create new rank icon in bottom left corner
rankIcon = LK.getAsset(currentRank.asset, {
anchorX: 0,
anchorY: 1
});
rankIcon.x = 20;
rankIcon.y = 2712;
game.addChild(rankIcon);
// Update rank name text
if (rankNameTxt) {
rankNameTxt.setText(currentRank.name + ' - Seviye ' + rankLevel);
rankNameTxt.tint = currentRank.color;
}
// Add fire effects around rank icon
addFireEffectsToRank();
// Flash screen with rank color when rank changes (except first time)
if (LK.getScore() > 0) {
LK.effects.flashScreen(currentRank.color, 1000);
}
}
// Initialize hearts display
function updateHeartsDisplay() {
// Clear existing hearts
for (var h = 0; h < hearts.length; h++) {
hearts[h].destroy();
}
hearts = [];
// Create new hearts based on current lives
for (var i = 0; i < lives; i++) {
var heart = LK.getAsset('heart', {
anchorX: 0.5,
anchorY: 0.5
});
heart.x = -120 - i * 70;
heart.y = -120;
LK.gui.bottomRight.addChild(heart);
hearts.push(heart);
}
}
// Function to create tree bark merging effect
function createMergingEffect(centerX, centerY, objectType) {
// Find nearby objects to merge with
var nearbyObjects = [];
var color = objectType === 'ball' ? 0x8B4513 : 0x654321; // Brown colors
// Check for nearby balls
for (var i = 0; i < balls.length; i++) {
var ball = balls[i];
var distance = Math.sqrt((ball.x - centerX) * (ball.x - centerX) + (ball.y - centerY) * (ball.y - centerY));
if (distance < mergeRange && !ball.isHit) {
nearbyObjects.push(ball);
}
}
// Check for nearby bombs
for (var j = 0; j < bombs.length; j++) {
var bomb = bombs[j];
var distance2 = Math.sqrt((bomb.x - centerX) * (bomb.x - centerX) + (bomb.y - centerY) * (bomb.y - centerY));
if (distance2 < mergeRange) {
nearbyObjects.push(bomb);
}
}
// Create tree bark particles flowing between objects
for (var k = 0; k < nearbyObjects.length; k++) {
var target = nearbyObjects[k];
// Create multiple bark particles flowing from center to target
for (var p = 0; p < 3; p++) {
var bark = new TreeBark(centerX, centerY, target.x, target.y);
bark.tint = color;
treeBarkParticles.push(bark);
game.addChild(bark);
// Add slight delay for each particle
tween(bark, {
alpha: 0.9
}, {
duration: 100 + p * 50,
onFinish: function onFinish() {
// Create merging glow effect on target
if (target && !target.destroyed) {
tween(target, {
tint: color
}, {
duration: 300,
onFinish: function onFinish() {
tween(target, {
tint: 0xFFFFFF
}, {
duration: 500,
easing: tween.easeOut
});
}
});
}
}
});
}
// Create reverse flow particles from target to center
for (var r = 0; r < 2; r++) {
var reverseBark = new TreeBark(target.x, target.y, centerX, centerY);
reverseBark.tint = color;
reverseBark.alpha = 0.6;
treeBarkParticles.push(reverseBark);
game.addChild(reverseBark);
}
}
// Create explosion of bark particles around the center
for (var e = 0; e < 8; e++) {
var angle = e / 8 * Math.PI * 2;
var explosionX = centerX + Math.cos(angle) * 100;
var explosionY = centerY + Math.sin(angle) * 100;
var explosionBark = new TreeBark(centerX, centerY, explosionX, explosionY);
explosionBark.tint = color;
explosionBark.alpha = 0.7;
treeBarkParticles.push(explosionBark);
game.addChild(explosionBark);
}
}
// Initialize hearts display
updateHeartsDisplay();
// Ball types for spawning
var ballTypes = ['red', 'yellow', 'blue'];
// Create initial grid of balls and bombs arranged for portrait layout
var currentX = 200;
var currentY = 150;
var itemsPerRow = 10;
var spacing = 150;
var itemCount = 0;
// Create equal amounts of balls and bombs in a grid
for (var row = 0; row < 10; row++) {
for (var col = 0; col < itemsPerRow; col++) {
var x = currentX + col * spacing;
var y = currentY + row * spacing;
if (itemCount % 6 === 5) {
// Every 6th item is a bomb
var bomb = new Bomb();
bomb.x = x;
bomb.y = y;
bombs.push(bomb);
game.addChild(bomb);
} else {
// Create balls in sequence: red, yellow, blue
var ballType = ballTypes[itemCount % 3];
var ball = new Ball(ballType);
ball.x = x;
ball.y = y;
balls.push(ball);
game.addChild(ball);
}
itemCount++;
}
}
// Create hand launcher at bottom center
var hand = game.addChild(LK.getAsset('hand', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 1.5
}));
hand.x = 1024;
hand.y = 2400;
var isDragging = false;
var dragStartX = 0;
var dragStartY = 0;
game.down = function (x, y, obj) {
// Don't allow shooting during countdown
if (countdownActive) return;
// Check if touch is near the hand
var distance = Math.sqrt((x - hand.x) * (x - hand.x) + (y - hand.y) * (y - hand.y));
if (distance < 100) {
isDragging = true;
dragStartX = x;
dragStartY = y;
}
};
game.move = function (x, y, obj) {
if (isDragging) {
// Move hand slightly toward drag direction
var dx = x - dragStartX;
var dy = y - dragStartY;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 10) {
// Limit movement using cached values for better performance
var targetX = screenCenterX + dx * 0.3;
var targetY = 2400 + dy * 0.3;
var distanceFromCenter = Math.sqrt((targetX - screenCenterX) * (targetX - screenCenterX) + (targetY - 2400) * (targetY - 2400));
if (distanceFromCenter > maxHandDistance) {
var ratio = maxHandDistance / distanceFromCenter;
targetX = screenCenterX + (targetX - screenCenterX) * ratio;
targetY = 2400 + (targetY - 2400) * ratio;
}
hand.x = targetX;
hand.y = targetY;
// Calculate rotation angle based on drag direction
var targetRotation = Math.atan2(dy, dx);
// Smooth rotation using tween
tween.stop(hand, {
rotation: true
});
tween(hand, {
rotation: targetRotation
}, {
duration: 200,
easing: tween.easeOut
});
}
}
};
game.up = function (x, y, obj) {
if (isDragging) {
// Calculate launch direction (upward from hand position)
var dx = x - hand.x;
var dy = y - hand.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 20) {
// Create and launch arrow toward touch point
var arrow = new Arrow(x, y, hand.x, hand.y);
arrow.x = hand.x;
arrow.y = hand.y;
game.addChild(arrow);
// If dual shot is active, create a second arrow with slight offset
if (dualShotActive) {
var arrow2 = new Arrow(x + 50, y, hand.x, hand.y);
arrow2.x = hand.x;
arrow2.y = hand.y;
game.addChild(arrow2);
}
}
// Reset hand position and rotation
hand.x = 1024;
hand.y = 2400;
// Smooth rotation back to neutral position
tween.stop(hand, {
rotation: true
});
tween(hand, {
rotation: 0
}, {
duration: 300,
easing: tween.easeOut
});
isDragging = false;
}
};
game.update = function () {
// Timer logic - update every second (60 ticks = 1 second at 60 FPS)
if (LK.ticks - lastSecondTick >= 60) {
remainingTime--;
lastSecondTick = LK.ticks;
// Format and display time as MM:SS with optimized string creation
var minutes = Math.floor(remainingTime / 60);
var seconds = remainingTime % 60;
var timeString = minutes + ':' + (seconds < 10 ? '0' : '') + seconds;
timerTxt.setText(timeString);
// Check if time is up
if (remainingTime <= 0) {
LK.showYouWin(); // Player survives 30 minutes = win condition
return;
}
// Change timer color when less than 5 minutes remain (warning)
if (remainingTime <= 300) {
// 5 minutes = 300 seconds
timerTxt.tint = 0xFF0000; // Red color for urgency
} else if (remainingTime <= 600) {
// 10 minutes = 600 seconds
timerTxt.tint = 0xFFFF00; // Yellow color for caution
}
}
// Check and update power-up timers
if (extraPowerActive && remainingTime <= extraPowerEndTime) {
extraPowerActive = false;
extraPowerTxt.setText('');
}
if (dualShotActive && remainingTime <= dualShotEndTime) {
dualShotActive = false;
dualShotTxt.setText('');
}
if (speedBoostActive && remainingTime <= speedBoostEndTime) {
speedBoostActive = false;
speedBoostTxt.setText('');
}
// Update power-up display texts only when needed
if (extraPowerActive) {
var extraTimeLeft = extraPowerEndTime - remainingTime;
var extraMinutes = Math.floor(Math.abs(extraTimeLeft) / 60);
var extraSeconds = Math.abs(extraTimeLeft) % 60;
var extraTimeString = extraMinutes + ':' + (extraSeconds < 10 ? '0' : '') + extraSeconds;
extraPowerTxt.setText('Güç +30: ' + extraTimeString);
}
if (dualShotActive) {
var dualTimeLeft = dualShotEndTime - remainingTime;
var dualMinutes = Math.floor(Math.abs(dualTimeLeft) / 60);
var dualSeconds = Math.abs(dualTimeLeft) % 60;
var dualTimeString = dualMinutes + ':' + (dualSeconds < 10 ? '0' : '') + dualSeconds;
dualShotTxt.setText('Çift Ok: ' + dualTimeString);
}
if (speedBoostActive) {
var speedTimeLeft = speedBoostEndTime - remainingTime;
var speedMinutes = Math.floor(Math.abs(speedTimeLeft) / 60);
var speedSeconds = Math.abs(speedTimeLeft) % 60;
var speedTimeString = speedMinutes + ':' + (speedSeconds < 10 ? '0' : '') + speedSeconds;
speedBoostTxt.setText('Hız Artışı: ' + speedTimeString);
}
// Clean up destroyed tree bark particles
for (var b = treeBarkParticles.length - 1; b >= 0; b--) {
var bark = treeBarkParticles[b];
if (!bark || bark.destroyed) {
treeBarkParticles.splice(b, 1);
}
}
// Update fire effects animation every 55 frames for better performance
if (LK.ticks % 55 === 0) {
for (var i = 0; i < fireEffects.length; i++) {
var fire = fireEffects[i];
if (fire && fire.baseX !== undefined && fire.baseY !== undefined) {
// Add slight floating movement
fire.x = fire.baseX + Math.sin((LK.ticks + fire.animationOffset) * 0.04) * 8;
fire.y = fire.baseY + Math.cos((LK.ticks + fire.animationOffset) * 0.025) * 6;
}
}
}
// Score is updated only when it changes in Ball.hit() and Bomb.hit()
// No need for redundant updates here
};
// Game state variables
var gameStarted = false;
var countdownActive = true;
var countdownValue = 5;
var countdownTxt = new Text2('5', {
size: 400,
fill: 0x000000
});
countdownTxt.anchor.set(0.5, 0.5);
countdownTxt.x = 1024;
countdownTxt.y = 1366;
game.addChild(countdownTxt);
// Countdown logic
var countdownTimer = LK.setInterval(function () {
countdownValue--;
if (countdownValue > 0) {
countdownTxt.setText(countdownValue.toString());
// Scale animation for countdown
countdownTxt.scaleX = 1.5;
countdownTxt.scaleY = 1.5;
tween(countdownTxt, {
scaleX: 1,
scaleY: 1
}, {
duration: 800,
easing: tween.bounceOut
});
} else {
countdownTxt.setText('BAŞLA!');
// Final animation
tween(countdownTxt, {
scaleX: 2,
scaleY: 2,
alpha: 0
}, {
duration: 1000,
easing: tween.easeOut,
onFinish: function onFinish() {
countdownTxt.destroy();
gameStarted = true;
countdownActive = false;
// Start background music when countdown finishes
try {
LK.playMusic('backgroundMusic', {
loop: true,
fade: {
start: 0,
end: 0.15,
duration: 1500
}
});
} catch (e) {
console.log('Background music failed to play:', e);
}
}
});
LK.clearInterval(countdownTimer);
}
}, 1000); ===================================================================
--- original.js
+++ change.js
@@ -102,12 +102,12 @@
var ballGraphics = self.attachAsset(assetId, {
anchorX: 0.5,
anchorY: 0.5
});
- // Apply random color tint to ball
- var randomColors = [0xFF0000, 0x00FF00, 0x0000FF, 0xFFFF00, 0xFF00FF, 0x00FFFF, 0xFFA500, 0x800080, 0xFFC0CB, 0x90EE90];
- var randomColor = randomColors[Math.floor(Math.random() * randomColors.length)];
- ballGraphics.tint = randomColor;
+ // Apply subtle scale effect instead of color tinting
+ var randomScale = 0.9 + Math.random() * 0.2; // Scale between 0.9 and 1.1
+ ballGraphics.scaleX = randomScale;
+ ballGraphics.scaleY = randomScale;
// Add floating animation
self.floatDirection = Math.random() > 0.5 ? 1 : -1;
self.floatSpeed = 0.5 + Math.random() * 0.5;
self.floatOffset = 0;
@@ -296,12 +296,11 @@
var bombGraphics = self.attachAsset('bomb', {
anchorX: 0.5,
anchorY: 0.5
});
- // Apply random color tint to bomb
- var randomColors = [0xFF0000, 0x00FF00, 0x0000FF, 0xFFFF00, 0xFF00FF, 0x00FFFF, 0xFFA500, 0x800080, 0xFFC0CB, 0x90EE90];
- var randomColor = randomColors[Math.floor(Math.random() * randomColors.length)];
- bombGraphics.tint = randomColor;
+ // Apply subtle alpha effect instead of color tinting
+ var randomAlpha = 0.85 + Math.random() * 0.15; // Alpha between 0.85 and 1.0
+ bombGraphics.alpha = randomAlpha;
// Add pulsing animation to make it look dangerous
self.pulseOffset = Math.random() * Math.PI * 2;
// Add horizontal movement
self.horizontalDirection = Math.random() > 0.5 ? 1 : -1;
@@ -439,10 +438,10 @@
/****
* Game Code
****/
-// Initialize ball assets with different colors
// Game arrays to track objects
+// Initialize ball assets with different colors
var balls = [];
var bombs = [];
var lives = 5;
var hearts = [];