User prompt
Toplara vurduktan sonra toplar yok olmak yerine aşağı doğru düşsün ve yerde patlama efekti olsun ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Şimdi puan skorunu toplardan puan aldıkça renklenip efect olsun ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Sol alt köşeye koy
User prompt
500x500 pixels olsun
User prompt
300x300 pixels yap
User prompt
Dahada çok büyüt
User prompt
Rank fotoğraflarını dahada büyüt
User prompt
Bütün rank sistemini sil ve sadece 3 adet kategori fotoğraf ekle gümüş seviyeler altın nova seviyeler supreme seviyeler ve puanları şunlara göre oyun içinde değişecek gümüş seviyeler 4.910 puana kadar altın nova seviyeler 9734 puana kadar, supreme seviyeler 30.000 puan ve fazlasina kadar sürsün
User prompt
Rank fotograflarini büyüt
User prompt
Şimdi 0 puandan 4999 kadar gümüş rütbeler, 5000 puandan 9999 kadar Altın Nova seviyesi , 10.000 puandan 14.999 puana kadar Usta Muhafız Seviyesi , 15.000 puandan 19.000 puana kadar efsane kartal seviyesi, 20.000 puandan 24.999 puana kadar Birinci Sınıf Usta Muhafız sınıfı, 25.000 puandan 29.999 kadar Dünyaca Seçkin seviyesi , 30.000 puan üstü En yüksek seviyedeki seckin oyuncuları, bu ranklari fotogrsf olarak oluştur ve oyuna isimleriyle beraber aşağı sol alt köşeye yerleştir puanlara göre gözüküp değişsin.
User prompt
Oyun arka planını mavi yap ve ranklari bildiğine göre şu puanlara göre aşağıdaki sol köşede resmini ve ismini göster puanları: Gri: 0 – 4.999 MMR (Gümüş rütbeler)Açık Mavi: 5.000 – 9.999 MMR (Altın Nova seviyesi)Mavi: 10.000 – 14.999 MMR (Usta Muhafız seviyesi)Mor: 15.000 – 19.999 MMR (Efsanevi Kartal seviyesi)Pembe: 20.000 – 24.999 MMR (Birinci Sınıf Üstün Usta seviyesi)Kırmızı: 25.000 – 29.999 MMR (Dünyaca Seçkin seviyesi)Altın: 30.000+ MMR (En yüksek seviyedeki oyuncuları temsil eder)
User prompt
Oyun arka planını beyaz yap
User prompt
Oyun içinde goster
User prompt
Şimdi bu ranklari puanına göre canın sol köşesinde göster
User prompt
Cs 2 deki ranklar olsun puana göre yanda fotoğraflı göster hepsini ranklar şunlar ve puana göre: Gri: 0 – 4.999 MMR (Gümüş rütbeler)Açık Mavi: 5.000 – 9.999 MMR (Altın Nova seviyesi)Mavi: 10.000 – 14.999 MMR (Usta Muhafız seviyesi)Mor: 15.000 – 19.999 MMR (Efsanevi Kartal seviyesi)Pembe: 20.000 – 24.999 MMR (Birinci Sınıf Üstün Usta seviyesi)Kırmızı: 25.000 – 29.999 MMR (Dünyaca Seçkin seviyesi)Altın: 30.000+ MMR (En yüksek seviyedeki oyuncuları temsil eder)
User prompt
Oyun arka plan dosyası oluştur assets bölümüne
User prompt
Oyun arka planını mavi yap ve optimize et
User prompt
Oyunu diğer haline geri getir
User prompt
Oyunu diktorgen olarak büyüt
User prompt
Oyun arkaplan rengini cs2 deki dust 2 map resmini ekle
User prompt
Ok rengini beyaz yap
User prompt
El resmini biraz büyüt ve sıktığı yöne doğru dönsün ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Her 5k puan artınca ekstra 1 can ver bide Her 10k puan artinca 1 dk lik okları hizlandir ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Her 5 k can olunca ekstra 1 can al ve yeni özellik ekle %1 sansla top vurarak ekstra can kazanma ekle
User prompt
Güç +30 özelliği geldiğinde oklarin hızı daha hızlı gitsin bittiğinde normal hıza dönsün ↪💡 Consider importing and using the following plugins: @upit/tween.v1
/****
* 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 = extraPowerActive ? baseSpeed * 1.8 : baseSpeed;
self.velocityX = dx / distance * speed;
self.velocityY = dy / distance * speed;
// Set rotation to point toward target
arrowGraphics.rotation = Math.atan2(dy, dx);
self.update = function () {
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;
}
// 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 < 10000) {
// 100px collision range
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 < 10000) {
// 100px collision range
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 = 40;
break;
case 'yellow':
assetId = 'yellowBall';
points = 60;
break;
case 'blue':
assetId = 'blueBall';
points = 70;
break;
}
self.points = points;
// Attach the appropriate ball asset
var ballGraphics = self.attachAsset(assetId, {
anchorX: 0.5,
anchorY: 0.5
});
// 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;
self.update = function () {
// Only update floating animation every few frames to reduce CPU load
if (LK.ticks % 3 === 0) {
self.floatOffset += self.floatSpeed;
self.y += Math.sin(self.floatOffset) * self.floatDirection * 0.3;
}
// Add horizontal movement in both directions
self.x += self.horizontalSpeed * self.horizontalDirection;
// Add vertical movement for diagonal motion
self.y += self.verticalSpeed * self.verticalDirection;
// Keep balls in upper area - restrict Y position
if (self.y > 1500) {
self.y = 1500;
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
if (self.x <= 300 || self.x >= 1748) {
self.horizontalDirection *= -1; // Reverse horizontal direction
if (self.x <= 300) self.x = 300;
if (self.x >= 1748) self.x = 1748;
}
};
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;
}
LK.setScore(LK.getScore() + finalPoints);
scoreTxt.setText(LK.getScore());
LK.getSound('pop').play();
// 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;
}
}
// 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
var randomBallType = ballTypes[Math.floor(Math.random() * ballTypes.length)];
var newBall = new Ball(randomBallType);
// Random position in the game area (avoiding edges)
newBall.x = 400 + Math.random() * 1248;
newBall.y = 1800 + Math.random() * 400;
balls.push(newBall);
game.addChild(newBall);
self.destroy();
};
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
});
// 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 () {
// Only update pulsing animation every few frames to reduce CPU load
if (LK.ticks % 2 === 0) {
self.pulseOffset += 0.1;
var scale = 1 + Math.sin(self.pulseOffset) * 0.1;
bombGraphics.scaleX = scale;
bombGraphics.scaleY = scale;
}
// Add horizontal movement in both directions
self.x += self.horizontalSpeed * self.horizontalDirection;
// Add vertical movement for diagonal motion
self.y += self.verticalSpeed * self.verticalDirection;
// Keep bombs in upper area - restrict Y position
if (self.y > 1500) {
self.y = 1500;
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
if (self.x <= 300 || self.x >= 1748) {
self.horizontalDirection *= -1; // Reverse horizontal direction
if (self.x <= 300) self.x = 300;
if (self.x >= 1748) self.x = 1748;
}
};
self.hit = function () {
// Play bomb sound effect
LK.getSound('bombSound').play();
// Deduct points and lose a life for hitting bomb
LK.setScore(Math.max(0, LK.getScore() - 30));
scoreTxt.setText(LK.getScore());
lives--;
updateHeartsDisplay();
bombHitCount++;
// 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;
});
/****
* Initialize Game
****/
// Game arrays to track objects
var game = new LK.Game({
backgroundColor: 0x001122
});
/****
* Game Code
****/
// Initialize ball assets with different colors
// Game arrays to track objects
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 extraPowerEndTime = 0;
var dualShotEndTime = 0;
var powerUpDuration = 180; // 3 minutes in seconds
// 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);
// 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);
}
}
// Initialize hearts display
updateHeartsDisplay();
// Ball types for spawning
var ballTypes = ['red', 'yellow', 'blue'];
// Create initial grid of balls and bombs arranged side by side
var currentX = 120;
var currentY = 200;
var itemsPerRow = 10;
var spacing = 150;
var itemCount = 0;
// Create equal amounts of balls and bombs in a grid
for (var row = 0; row < 8; 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
}));
hand.x = 1024;
hand.y = 2500;
var isDragging = false;
var dragStartX = 0;
var dragStartY = 0;
game.down = function (x, y, obj) {
// 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 to 3 steps (90 pixels) from center
var maxDistance = 90;
var targetX = 1024 + dx * 0.3;
var targetY = 2500 + dy * 0.3;
var distanceFromCenter = Math.sqrt((targetX - 1024) * (targetX - 1024) + (targetY - 2500) * (targetY - 2500));
if (distanceFromCenter > maxDistance) {
var ratio = maxDistance / distanceFromCenter;
targetX = 1024 + (targetX - 1024) * ratio;
targetY = 2500 + (targetY - 2500) * ratio;
}
hand.x = targetX;
hand.y = targetY;
}
}
};
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
hand.x = 1024;
hand.y = 2500;
isDragging = false;
}
};
// Play background music
LK.playMusic('J');
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
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('');
}
// Update power-up display texts
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);
} else {
extraPowerTxt.setText('');
}
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);
} else {
dualShotTxt.setText('');
}
// Score is updated only when it changes in Ball.hit() and Bomb.hit()
// No need for redundant updates here
}; /****
* 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 = extraPowerActive ? baseSpeed * 1.8 : baseSpeed;
self.velocityX = dx / distance * speed;
self.velocityY = dy / distance * speed;
// Set rotation to point toward target
arrowGraphics.rotation = Math.atan2(dy, dx);
self.update = function () {
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;
}
// 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 < 10000) {
// 100px collision range
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 < 10000) {
// 100px collision range
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 = 40;
break;
case 'yellow':
assetId = 'yellowBall';
points = 60;
break;
case 'blue':
assetId = 'blueBall';
points = 70;
break;
}
self.points = points;
// Attach the appropriate ball asset
var ballGraphics = self.attachAsset(assetId, {
anchorX: 0.5,
anchorY: 0.5
});
// 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;
self.update = function () {
// Only update floating animation every few frames to reduce CPU load
if (LK.ticks % 3 === 0) {
self.floatOffset += self.floatSpeed;
self.y += Math.sin(self.floatOffset) * self.floatDirection * 0.3;
}
// Add horizontal movement in both directions
self.x += self.horizontalSpeed * self.horizontalDirection;
// Add vertical movement for diagonal motion
self.y += self.verticalSpeed * self.verticalDirection;
// Keep balls in upper area - restrict Y position
if (self.y > 1500) {
self.y = 1500;
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
if (self.x <= 300 || self.x >= 1748) {
self.horizontalDirection *= -1; // Reverse horizontal direction
if (self.x <= 300) self.x = 300;
if (self.x >= 1748) self.x = 1748;
}
};
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;
}
LK.setScore(LK.getScore() + finalPoints);
scoreTxt.setText(LK.getScore());
LK.getSound('pop').play();
// 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;
}
}
// 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
var randomBallType = ballTypes[Math.floor(Math.random() * ballTypes.length)];
var newBall = new Ball(randomBallType);
// Random position in the game area (avoiding edges)
newBall.x = 400 + Math.random() * 1248;
newBall.y = 1800 + Math.random() * 400;
balls.push(newBall);
game.addChild(newBall);
self.destroy();
};
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
});
// 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 () {
// Only update pulsing animation every few frames to reduce CPU load
if (LK.ticks % 2 === 0) {
self.pulseOffset += 0.1;
var scale = 1 + Math.sin(self.pulseOffset) * 0.1;
bombGraphics.scaleX = scale;
bombGraphics.scaleY = scale;
}
// Add horizontal movement in both directions
self.x += self.horizontalSpeed * self.horizontalDirection;
// Add vertical movement for diagonal motion
self.y += self.verticalSpeed * self.verticalDirection;
// Keep bombs in upper area - restrict Y position
if (self.y > 1500) {
self.y = 1500;
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
if (self.x <= 300 || self.x >= 1748) {
self.horizontalDirection *= -1; // Reverse horizontal direction
if (self.x <= 300) self.x = 300;
if (self.x >= 1748) self.x = 1748;
}
};
self.hit = function () {
// Play bomb sound effect
LK.getSound('bombSound').play();
// Deduct points and lose a life for hitting bomb
LK.setScore(Math.max(0, LK.getScore() - 30));
scoreTxt.setText(LK.getScore());
lives--;
updateHeartsDisplay();
bombHitCount++;
// 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;
});
/****
* Initialize Game
****/
// Game arrays to track objects
var game = new LK.Game({
backgroundColor: 0x001122
});
/****
* Game Code
****/
// Initialize ball assets with different colors
// Game arrays to track objects
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 extraPowerEndTime = 0;
var dualShotEndTime = 0;
var powerUpDuration = 180; // 3 minutes in seconds
// 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);
// 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);
}
}
// Initialize hearts display
updateHeartsDisplay();
// Ball types for spawning
var ballTypes = ['red', 'yellow', 'blue'];
// Create initial grid of balls and bombs arranged side by side
var currentX = 120;
var currentY = 200;
var itemsPerRow = 10;
var spacing = 150;
var itemCount = 0;
// Create equal amounts of balls and bombs in a grid
for (var row = 0; row < 8; 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
}));
hand.x = 1024;
hand.y = 2500;
var isDragging = false;
var dragStartX = 0;
var dragStartY = 0;
game.down = function (x, y, obj) {
// 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 to 3 steps (90 pixels) from center
var maxDistance = 90;
var targetX = 1024 + dx * 0.3;
var targetY = 2500 + dy * 0.3;
var distanceFromCenter = Math.sqrt((targetX - 1024) * (targetX - 1024) + (targetY - 2500) * (targetY - 2500));
if (distanceFromCenter > maxDistance) {
var ratio = maxDistance / distanceFromCenter;
targetX = 1024 + (targetX - 1024) * ratio;
targetY = 2500 + (targetY - 2500) * ratio;
}
hand.x = targetX;
hand.y = targetY;
}
}
};
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
hand.x = 1024;
hand.y = 2500;
isDragging = false;
}
};
// Play background music
LK.playMusic('J');
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
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('');
}
// Update power-up display texts
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);
} else {
extraPowerTxt.setText('');
}
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);
} else {
dualShotTxt.setText('');
}
// Score is updated only when it changes in Ball.hit() and Bomb.hit()
// No need for redundant updates here
};