User prompt
Atış hakkım 0 olduğunda kaybedeyim oyunu
User prompt
Kuşa çarpınca atış hakkım azalsın+ oyunda saat emojisi görüyorum ve dünya emojisini kaldır
User prompt
Oyuna kuş ekleyebilir miyiz? Havada uçan ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Arkaplan müzik ismi angrybirds add
User prompt
Müzik çalmıyor arka plan
User prompt
Angrybirds add sound
User prompt
Ekle
User prompt
Ekle
User prompt
Start menü ekranına bölümler yazısının Altına nasıl oynanır butonu ekle tıkladığında oyunu anlat
User prompt
Oyun game over olmuyor
User prompt
6 atış hakkım olsun ve de hakkım bitince game över olsun
User prompt
Bazen kutular ekran dışında oluyor onları düzelt
User prompt
Atış hakkım bitince start ekranına dön
User prompt
Fix
User prompt
5 kutu yaptık ama hala çok gözüküyor
User prompt
Kutu sayısını azalt 5 tane kalsın
User prompt
Oyunda kasmalar mevcut düzelt
User prompt
Atış yaparken zorlanıyorum topu tutarken
User prompt
Ekle
User prompt
Topu tutup atması zor oluyor düzelt arka doğru atmasın topu kutulara doğru sadece
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of undefined (reading 'toGlobal')' in or related to this line: 'var localPos = self.toLocal(obj.parent.toGlobal(obj.position));' Line Number: 234
User prompt
Hepsini ekle + oyuna giriş bölümü de ekle. ↪💡 Consider importing and using the following plugins: @upit/tween.v1, @upit/storage.v1
User prompt
Düzelt
User prompt
Tasarımları öner Türkçe
User prompt
Zemini çimen yap
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var AchievementSystem = Container.expand(function () {
var self = Container.call(this);
self.achievements = {
perfectShot: false,
oneShot: false,
destructionMaster: false,
sharpshooter: false
};
self.loadAchievements = function () {
var saved = storage.achievements;
if (saved) {
self.achievements = saved;
}
};
self.saveAchievements = function () {
storage.achievements = self.achievements;
};
self.checkAchievement = function (type, value) {
switch (type) {
case 'perfectShot':
if (value === 1 && !self.achievements.perfectShot) {
self.achievements.perfectShot = true;
self.showAchievement('Mükemmel Atış!', 'Tek atışta tüm hedefleri yok et');
}
break;
case 'oneShot':
if (value >= 5 && !self.achievements.oneShot) {
self.achievements.oneShot = true;
self.showAchievement('Tek Atış Ustası!', 'Tek atışta 5 blok yok et');
}
break;
case 'destructionMaster':
if (value >= 100 && !self.achievements.destructionMaster) {
self.achievements.destructionMaster = true;
self.showAchievement('Yıkım Ustası!', '100 blok yok et');
}
break;
case 'sharpshooter':
if (value >= 10 && !self.achievements.sharpshooter) {
self.achievements.sharpshooter = true;
self.showAchievement('Keskin Nişancı!', '10 seviye tamamla');
}
break;
}
self.saveAchievements();
};
self.showAchievement = function (title, description) {
var popup = game.addChild(LK.getAsset('targetBlock', {
anchorX: 0.5,
anchorY: 0.5
}));
popup.x = 1024;
popup.y = 400;
popup.scaleX = 4;
popup.scaleY = 2;
popup.tint = 0xFFD700;
popup.alpha = 0;
var titleText = new Text2(title, {
size: 60,
fill: 0x000000
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 1024;
titleText.y = 380;
game.addChild(titleText);
var descText = new Text2(description, {
size: 40,
fill: 0x333333
});
descText.anchor.set(0.5, 0.5);
descText.x = 1024;
descText.y = 420;
game.addChild(descText);
// Animate in
tween(popup, {
alpha: 1
}, {
duration: 300,
easing: tween.easeOut
});
tween(titleText, {
alpha: 1
}, {
duration: 300,
easing: tween.easeOut
});
tween(descText, {
alpha: 1
}, {
duration: 300,
easing: tween.easeOut
});
// Animate out after delay
LK.setTimeout(function () {
tween(popup, {
alpha: 0
}, {
duration: 300,
easing: tween.easeIn,
onFinish: function onFinish() {
popup.destroy();
}
});
tween(titleText, {
alpha: 0
}, {
duration: 300,
easing: tween.easeIn,
onFinish: function onFinish() {
titleText.destroy();
}
});
tween(descText, {
alpha: 0
}, {
duration: 300,
easing: tween.easeIn,
onFinish: function onFinish() {
descText.destroy();
}
});
}, 3000);
};
return self;
});
var IntroScreen = Container.expand(function () {
var self = Container.call(this);
// Create background overlay
var overlay = self.attachAsset('grass', {
anchorX: 0.5,
anchorY: 0.5,
color: 0x000000,
alpha: 0.8
});
overlay.width = 2048;
overlay.height = 2732;
overlay.x = 1024;
overlay.y = 1366;
// Title text
var titleText = new Text2('SAPAN USTASI', {
size: 120,
fill: 0xFFD700
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 1024;
titleText.y = 800;
self.addChild(titleText);
// Play button
var playButton = self.attachAsset('targetBlock', {
anchorX: 0.5,
anchorY: 0.5
});
playButton.x = 1024;
playButton.y = 1200;
playButton.scaleX = 2;
playButton.scaleY = 1.2;
playButton.tint = 0x4CAF50;
var playText = new Text2('OYNA', {
size: 80,
fill: 0xFFFFFF
});
playText.anchor.set(0.5, 0.5);
playText.x = 1024;
playText.y = 1200;
self.addChild(playText);
// Settings button
var settingsButton = self.attachAsset('targetBlock', {
anchorX: 0.5,
anchorY: 0.5
});
settingsButton.x = 1024;
settingsButton.y = 1400;
settingsButton.scaleX = 2;
settingsButton.scaleY = 1.2;
settingsButton.tint = 0x2196F3;
var settingsText = new Text2('AYARLAR', {
size: 80,
fill: 0xFFFFFF
});
settingsText.anchor.set(0.5, 0.5);
settingsText.x = 1024;
settingsText.y = 1400;
self.addChild(settingsText);
// Level selector button
var levelButton = self.attachAsset('targetBlock', {
anchorX: 0.5,
anchorY: 0.5
});
levelButton.x = 1024;
levelButton.y = 1600;
levelButton.scaleX = 2;
levelButton.scaleY = 1.2;
levelButton.tint = 0xFF9800;
var levelText = new Text2('BÖLÜMLER', {
size: 80,
fill: 0xFFFFFF
});
levelText.anchor.set(0.5, 0.5);
levelText.x = 1024;
levelText.y = 1600;
self.addChild(levelText);
// Click handlers
self.down = function (x, y, obj) {
// Use the x, y coordinates directly instead of trying to convert object position
// Play button
if (Math.abs(x - 1024) < 200 && Math.abs(y - 1200) < 60) {
startGame();
}
// Settings button
else if (Math.abs(x - 1024) < 200 && Math.abs(y - 1400) < 60) {
showSettings();
}
// Level button
else if (Math.abs(x - 1024) < 200 && Math.abs(y - 1600) < 60) {
showLevelSelector();
}
};
// Animation entrance
self.show = function () {
self.alpha = 0;
tween(self, {
alpha: 1
}, {
duration: 500,
easing: tween.easeOut
});
tween(titleText, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 1000,
easing: tween.elasticOut
});
};
self.hide = function (callback) {
tween(self, {
alpha: 0
}, {
duration: 300,
easing: tween.easeIn,
onFinish: callback
});
};
return self;
});
var ParticleSystem = Container.expand(function () {
var self = Container.call(this);
self.particles = [];
self.createExplosion = function (x, y, color, count) {
// Limit particle count to prevent performance issues
count = Math.min(count, 6);
for (var i = 0; i < count; i++) {
var particle = game.addChild(LK.getAsset('trajectoryDot', {
anchorX: 0.5,
anchorY: 0.5
}));
particle.x = x;
particle.y = y;
particle.tint = color;
particle.alpha = 1;
self.particles.push(particle);
var angle = i / count * Math.PI * 2;
var speed = 50 + Math.random() * 100;
var distance = speed * (1 + Math.random());
tween(particle, {
x: x + Math.cos(angle) * distance,
y: y + Math.sin(angle) * distance,
alpha: 0,
scaleX: 0,
scaleY: 0
}, {
duration: 600,
easing: tween.easeOut,
onFinish: function onFinish() {
particle.destroy();
var index = self.particles.indexOf(particle);
if (index > -1) self.particles.splice(index, 1);
}
});
}
};
self.createTrail = function (x, y, vx, vy) {
var trail = game.addChild(LK.getAsset('trajectoryDot', {
anchorX: 0.5,
anchorY: 0.5
}));
trail.x = x;
trail.y = y;
trail.alpha = 0.6;
trail.scaleX = 0.5;
trail.scaleY = 0.5;
self.particles.push(trail);
tween(trail, {
alpha: 0,
scaleX: 0,
scaleY: 0
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
trail.destroy();
var index = self.particles.indexOf(trail);
if (index > -1) self.particles.splice(index, 1);
}
});
};
self.cleanup = function () {
// Clean up any remaining particles
for (var i = self.particles.length - 1; i >= 0; i--) {
if (self.particles[i] && self.particles[i].destroyed) {
self.particles.splice(i, 1);
}
}
// Limit total particles
if (self.particles.length > 50) {
for (var i = 0; i < 10; i++) {
if (self.particles[i]) {
self.particles[i].destroy();
self.particles.splice(i, 1);
}
}
}
};
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 1
});
self.isReady = true;
self.celebrate = function () {
// More dramatic celebration animation
tween(self, {
scaleX: 1.3,
scaleY: 1.3,
rotation: 0.2
}, {
duration: 150,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(self, {
scaleX: 1.2,
scaleY: 1.2,
rotation: 0
}, {
duration: 200,
easing: tween.bounceOut
});
}
});
};
self.aim = function () {
// More pronounced aiming stance
tween(self, {
rotation: 0.15,
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 150,
easing: tween.easeOut
});
};
self.resetPose = function () {
// Return to normal stance with bounce
tween(self, {
rotation: 0,
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 300,
easing: tween.elasticOut
});
};
return self;
});
var Portal = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('trajectoryDot', {
anchorX: 0.5,
anchorY: 0.5
});
graphics.scaleX = 4;
graphics.scaleY = 4;
graphics.tint = 0x9400D3;
self.linkedPortal = null;
self.cooldown = 0;
self.isActive = true;
// Add swirling animation
tween(graphics, {
rotation: Math.PI * 2
}, {
duration: 2000,
easing: tween.linear,
repeat: -1
});
// Add pulsing effect
tween(graphics, {
scaleX: 5,
scaleY: 5
}, {
duration: 1000,
easing: tween.easeInOut,
yoyo: true,
repeat: -1
});
self.teleport = function (projectile) {
if (!self.isActive || self.cooldown > 0 || !self.linkedPortal || !self.linkedPortal.isActive) return false;
var distance = Math.sqrt((projectile.x - self.x) * (projectile.x - self.x) + (projectile.y - self.y) * (projectile.y - self.y));
if (distance < 50) {
// Teleport projectile
projectile.x = self.linkedPortal.x;
projectile.y = self.linkedPortal.y;
// Add teleport effects
LK.effects.flashScreen(0x9400D3, 200);
particleSystem.createExplosion(self.x, self.y, 0x9400D3, 8);
particleSystem.createExplosion(self.linkedPortal.x, self.linkedPortal.y, 0x9400D3, 8);
// Set cooldown for both portals
self.cooldown = 60;
self.linkedPortal.cooldown = 60;
return true;
}
return false;
};
self.update = function () {
if (self.cooldown > 0) {
self.cooldown--;
if (self.cooldown === 0) {
graphics.alpha = 1;
}
} else {
graphics.alpha = 0.8 + Math.sin(LK.ticks * 0.1) * 0.2;
}
};
return self;
});
var PowerUp = Container.expand(function () {
var self = Container.call(this);
self.type = 'normal';
self.icon = null;
self.init = function (type) {
self.type = type;
var color = 0xFFFFFF;
var text = 'N';
switch (type) {
case 'explosive':
color = 0xFF4444;
text = 'E';
break;
case 'bouncy':
color = 0x44FF44;
text = 'B';
break;
case 'heavy':
color = 0x444444;
text = 'H';
break;
}
self.icon = self.attachAsset('trajectoryDot', {
anchorX: 0.5,
anchorY: 0.5
});
self.icon.tint = color;
self.icon.scaleX = 3;
self.icon.scaleY = 3;
var powerText = new Text2(text, {
size: 40,
fill: 0xFFFFFF
});
powerText.anchor.set(0.5, 0.5);
self.addChild(powerText);
};
return self;
});
var Projectile = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('projectile', {
anchorX: 0.5,
anchorY: 0.5
});
self.velocityX = 0;
self.velocityY = 0;
self.gravity = GRAVITY;
self.launched = false;
self.destroyed = false;
self.spinSpeed = 0;
self.lastX = 0;
self.lastY = 0;
self.type = 'normal';
self.bounceCount = 0;
self.explosionRadius = 150;
self.launch = function (vx, vy, projectileType) {
self.type = projectileType || 'normal';
self.velocityX = vx;
self.velocityY = vy;
self.launched = true;
// Calculate spin speed based on velocity
self.spinSpeed = Math.sqrt(vx * vx + vy * vy) * 0.02;
// Apply type-specific modifications
switch (self.type) {
case 'explosive':
graphics.tint = 0xFF4444;
self.gravity = GRAVITY * 0.8;
break;
case 'bouncy':
graphics.tint = 0x44FF44;
self.gravity = GRAVITY * 0.9;
break;
case 'heavy':
graphics.tint = 0x444444;
self.gravity = GRAVITY * 1.5;
self.velocityX *= 1.2;
self.velocityY *= 1.2;
graphics.scaleX = 1.3;
graphics.scaleY = 1.3;
break;
default:
graphics.tint = 0xFFFFFF;
}
// Add launch scale animation
tween(self, {
scaleX: 1.3,
scaleY: 1.3
}, {
duration: 100,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(self, {
scaleX: 1,
scaleY: 1
}, {
duration: 150,
easing: tween.easeIn
});
}
});
LK.getSound('launch').play();
};
self.update = function () {
if (self.launched && !self.destroyed) {
// Apply time slow effect
var timeMultiplier = timeSlowActive ? 0.3 : 1.0;
self.x += self.velocityX * timeMultiplier;
self.y += self.velocityY * timeMultiplier;
// Apply gravity based on current gravity state
var currentGravity = gravityReversed ? -self.gravity : self.gravity;
self.velocityY += currentGravity * timeMultiplier;
// Add spinning animation during flight
graphics.rotation += self.spinSpeed;
// Add slight scale pulsing for trail effect
var speed = Math.sqrt(self.velocityX * self.velocityX + self.velocityY * self.velocityY);
var scaleEffect = 1 + Math.sin(LK.ticks * 0.3) * 0.1 * (speed / 20);
graphics.scaleX = scaleEffect;
graphics.scaleY = scaleEffect;
// Check ground collision with transition detection
if (self.lastY < groundY - 30 && self.y >= groundY - 30) {
self.y = groundY - 30;
self.velocityY = -self.velocityY * 0.3;
self.velocityX *= 0.8;
self.spinSpeed *= 0.8;
LK.getSound('impact').play();
// Add bounce animation
tween(self, {
scaleX: 1.5,
scaleY: 0.7
}, {
duration: 100,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(self, {
scaleX: 1,
scaleY: 1
}, {
duration: 200,
easing: tween.bounceOut
});
}
});
if (Math.abs(self.velocityY) < 2 && Math.abs(self.velocityX) < 1) {
self.launched = false;
self.spinSpeed = 0;
}
}
// Update last position for transition detection
self.lastX = self.x;
self.lastY = self.y;
// Check screen bounds
if (self.x > 2200 || self.x < -100 || self.y > 2800) {
self.destroyed = true;
}
}
};
self.explode = function () {
if (self.type === 'explosive') {
// Create explosion effect
LK.effects.flashScreen(0xFF4444, 300);
// Damage all blocks within radius
for (var i = 0; i < targetBlocks.length; i++) {
var block = targetBlocks[i];
if (!block.destroyed) {
var distance = Math.sqrt((block.x - self.x) * (block.x - self.x) + (block.y - self.y) * (block.y - self.y));
if (distance < self.explosionRadius) {
block.takeDamage();
// Add explosion knockback
tween(block, {
x: block.x + (block.x - self.x) * 0.3,
y: block.y + (block.y - self.y) * 0.3,
rotation: Math.random() * 0.5 - 0.25
}, {
duration: 200,
easing: tween.easeOut
});
}
}
}
// Create particle effect with reduced count
particleSystem.createExplosion(self.x, self.y, 0xFF4444, 6);
}
};
return self;
});
var Slingshot = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('slingshot', {
anchorX: 0.5,
anchorY: 1
});
self.stretched = false;
self.originalRotation = 0;
self.stretch = function (deltaX, deltaY, distance) {
// Calculate stretch angle based on pull direction
var stretchAngle = Math.atan2(deltaY, deltaX) * 0.1;
var stretchAmount = Math.min(distance / 150, 1) * 0.2;
// Animate slingshot stretch
tween(self, {
rotation: stretchAngle,
scaleX: 1 + stretchAmount,
scaleY: 1 - stretchAmount * 0.5
}, {
duration: 50,
easing: tween.easeOut
});
self.stretched = true;
};
self.release = function () {
// Dramatic release animation with bounce back
tween(self, {
rotation: self.originalRotation - 0.3,
scaleX: 0.8,
scaleY: 1.3
}, {
duration: 100,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(self, {
rotation: self.originalRotation,
scaleX: 1,
scaleY: 1
}, {
duration: 200,
easing: tween.elasticOut
});
}
});
self.stretched = false;
};
self.reset = function () {
// Return to normal state
tween(self, {
rotation: self.originalRotation,
scaleX: 1,
scaleY: 1
}, {
duration: 150,
easing: tween.easeOut
});
self.stretched = false;
};
return self;
});
var TargetBlock = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('targetBlock', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 1;
self.destroyed = false;
self.magneticType = 'none'; // none, attract, repel
self.magneticStrength = 200;
self.takeDamage = function () {
self.health--;
if (self.health <= 0) {
self.destroyed = true;
LK.getSound('destroy').play();
LK.setScore(LK.getScore() + 100);
LK.effects.flashObject(self, 0xFFFFFF, 200);
}
};
self.setMagnetic = function (type) {
self.magneticType = type;
if (type === 'attract') {
graphics.tint = 0x0066FF; // Blue for attraction
// Add pulsing effect
tween(graphics, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 1000,
easing: tween.easeInOut,
yoyo: true,
repeat: -1
});
} else if (type === 'repel') {
graphics.tint = 0xFF0000; // Red for repulsion
// Add pulsing effect
tween(graphics, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 1000,
easing: tween.easeInOut,
yoyo: true,
repeat: -1
});
}
};
self.applyMagneticForce = function (projectile) {
if (self.magneticType === 'none' || self.destroyed) return;
var dx = projectile.x - self.x;
var dy = projectile.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < self.magneticStrength && distance > 0) {
var force = (self.magneticStrength - distance) / self.magneticStrength * 0.5;
var normalizedX = dx / distance;
var normalizedY = dy / distance;
if (self.magneticType === 'attract') {
projectile.velocityX -= normalizedX * force;
projectile.velocityY -= normalizedY * force;
} else if (self.magneticType === 'repel') {
projectile.velocityX += normalizedX * force;
projectile.velocityY += normalizedY * force;
}
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87CEEB
});
/****
* Game Code
****/
// Game constants
var GRAVITY = 0.3;
var MAX_DRAG_DISTANCE = 150;
var VELOCITY_MULTIPLIER = 0.3;
var GROUND_Y = 2550;
var INITIAL_SHOTS = 5;
var BLOCK_POINTS = 100;
// Game state management
var gameState = 'intro'; // intro, playing, paused, gameOver
var introScreen = null;
var particleSystem = null;
var achievementSystem = null;
var currentProjectileType = 'normal';
var availablePowerUps = ['normal', 'explosive', 'bouncy', 'heavy'];
var powerUpIndex = 0;
var totalBlocksDestroyed = 0;
var levelsCompleted = 0;
var windSpeed = 0;
var windDirection = 1;
var gravityReversed = false;
var gravityTimer = 0;
var maxGravityTime = 300; // 5 seconds at 60fps
var portals = [];
var timeSlowActive = false;
var timeSlowTimer = 0;
var maxTimeSlowDuration = 180; // 3 seconds
var timeSlowCooldown = 0;
var maxTimeSlowCooldown = 600; // 10 seconds
// Game variables
var slingshot;
var slingshotBase;
var player;
var currentProjectile = null;
var isAiming = false;
var aimStartX = 0;
var aimStartY = 0;
var trajectoryDots = [];
var targetBlocks = [];
var projectiles = [];
var shotsRemaining = INITIAL_SHOTS;
var level = 1;
var groundY = GROUND_Y;
// UI elements
var shotsText = new Text2('Atış: 5', {
size: 80,
fill: 0x000000
});
shotsText.anchor.set(0, 0);
LK.gui.topRight.addChild(shotsText);
shotsText.x = -300;
shotsText.y = 100;
var scoreText = new Text2('Puan: 0', {
size: 80,
fill: 0x000000
});
scoreText.anchor.set(0, 0);
LK.gui.top.addChild(scoreText);
scoreText.y = 100;
// Create ability indicators
var gravityButton = new Text2('🌍', {
size: 60,
fill: 0x000000
});
gravityButton.anchor.set(1, 0);
gravityButton.x = -50;
gravityButton.y = 200;
LK.gui.topRight.addChild(gravityButton);
var timeButton = new Text2('⏱️', {
size: 60,
fill: 0x000000
});
timeButton.anchor.set(0.5, 1);
timeButton.x = 0;
timeButton.y = -100;
LK.gui.bottom.addChild(timeButton);
var typeButton = new Text2('💥', {
size: 60,
fill: 0x000000
});
typeButton.anchor.set(0, 0);
typeButton.x = 50;
typeButton.y = 200;
LK.gui.topLeft.addChild(typeButton);
// Create grass ground
var ground = game.addChild(LK.getAsset('grass', {
anchorX: 0.5,
anchorY: 0.5
}));
ground.x = 1024;
ground.y = GROUND_Y + 100; // Position grass lower for better visual effect
ground.scaleY = 1.5; // Make grass thicker
// Create slingshot
slingshotBase = game.addChild(LK.getAsset('slingshotBase', {
anchorX: 0.5,
anchorY: 1
}));
slingshotBase.x = 200;
slingshotBase.y = GROUND_Y;
slingshot = game.addChild(new Slingshot());
slingshot.x = 200;
slingshot.y = GROUND_Y;
// Create player character
player = game.addChild(new Player());
player.x = 80; // Position further behind slingshot
player.y = GROUND_Y;
player.scaleX = 1.2; // Make player more visible
player.scaleY = 1.2;
// Add slingshot asset to player's hand
var playerSlingshot = player.addChild(LK.getAsset('Sapan', {
anchorX: 0.5,
anchorY: 0.8
}));
playerSlingshot.x = 50; // Offset from player center to hand position
playerSlingshot.y = -100; // Offset upward to hand level
playerSlingshot.scaleX = 0.8; // Scale down for better proportion
playerSlingshot.scaleY = 0.8;
// Create trajectory dots
for (var i = 0; i < 15; i++) {
var dot = game.addChild(LK.getAsset('trajectoryDot', {
anchorX: 0.5,
anchorY: 0.5
}));
dot.visible = false;
trajectoryDots.push(dot);
}
// Create slingshot grab area indicator
var slingshotArea = game.addChild(LK.getAsset('trajectoryDot', {
anchorX: 0.5,
anchorY: 0.5
}));
slingshotArea.x = 200;
slingshotArea.y = GROUND_Y - 100;
slingshotArea.scaleX = 15; // Large enough to show grab area
slingshotArea.scaleY = 15;
slingshotArea.alpha = 0.2;
slingshotArea.tint = 0x00FF00; // Green to indicate interaction area
// Pulse animation for grab area
tween(slingshotArea, {
scaleX: 18,
scaleY: 18,
alpha: 0.1
}, {
duration: 1500,
easing: tween.easeInOut,
yoyo: true,
repeat: -1
});
// Create target structures
function createLevel() {
// Clear existing targets
for (var i = targetBlocks.length - 1; i >= 0; i--) {
if (targetBlocks[i].destroyed) {
targetBlocks[i].destroy();
targetBlocks.splice(i, 1);
}
}
targetBlocks = [];
// Progressive difficulty and varied level designs
var levelPattern = level % 8; // Increased variety
var startX = 1400;
var startY = GROUND_Y - 50;
// Procedural generation for levels beyond 20
if (level > 20) {
// Generate random but balanced structures
var blockCount = 8 + Math.floor(level / 5);
var maxHeight = 5 + Math.floor(level / 10);
for (var i = 0; i < blockCount; i++) {
var block = game.addChild(new TargetBlock());
block.x = startX + (Math.random() - 0.5) * 600;
block.y = startY - Math.random() * maxHeight * 110;
targetBlocks.push(block);
}
return; // Skip normal level patterns
}
// Add wind effect for higher levels
if (level > 10) {
windSpeed = (Math.random() - 0.5) * 2;
windDirection = windSpeed > 0 ? 1 : -1;
// Show wind indicator
var windText = new Text2('Rüzgar: ' + (windSpeed > 0 ? '→' : '←'), {
size: 60,
fill: 0x0066CC
});
windText.anchor.set(0.5, 0);
windText.x = 1024;
windText.y = 300;
LK.gui.top.addChild(windText);
LK.setTimeout(function () {
windText.destroy();
}, 3000);
} else {
windSpeed = 0;
}
switch (levelPattern) {
case 0:
// Classic pyramid
// Bottom row
for (var i = 0; i < 4; i++) {
var block = game.addChild(new TargetBlock());
block.x = startX + i * 110;
block.y = startY;
targetBlocks.push(block);
}
// Middle row
for (var i = 0; i < 3; i++) {
var block = game.addChild(new TargetBlock());
block.x = startX + 55 + i * 110;
block.y = startY - 110;
targetBlocks.push(block);
}
// Top row
for (var i = 0; i < 2; i++) {
var block = game.addChild(new TargetBlock());
block.x = startX + 110 + i * 110;
block.y = startY - 220;
targetBlocks.push(block);
}
// Top block
var block = game.addChild(new TargetBlock());
block.x = startX + 165;
block.y = startY - 330;
targetBlocks.push(block);
break;
case 1:
// Wall formation
for (var row = 0; row < 4; row++) {
for (var col = 0; col < 3; col++) {
var block = game.addChild(new TargetBlock());
block.x = startX + col * 110;
block.y = startY - row * 110;
targetBlocks.push(block);
}
}
break;
case 2:
// L-shape
// Horizontal part
for (var i = 0; i < 5; i++) {
var block = game.addChild(new TargetBlock());
block.x = startX + i * 110;
block.y = startY;
targetBlocks.push(block);
}
// Vertical part
for (var i = 1; i < 4; i++) {
var block = game.addChild(new TargetBlock());
block.x = startX;
block.y = startY - i * 110;
targetBlocks.push(block);
}
break;
case 3:
// Scattered formation
var positions = [{
x: 0,
y: 0
}, {
x: 220,
y: -50
}, {
x: 110,
y: -150
}, {
x: 330,
y: -100
}, {
x: 50,
y: -250
}, {
x: 280,
y: -200
}, {
x: 150,
y: -300
}, {
x: 400,
y: -150
}];
for (var i = 0; i < positions.length; i++) {
var block = game.addChild(new TargetBlock());
block.x = startX + positions[i].x;
block.y = startY + positions[i].y;
targetBlocks.push(block);
}
break;
case 4:
// Bridge formation
// Pillars
for (var pillar = 0; pillar < 2; pillar++) {
for (var i = 0; i < 3; i++) {
var block = game.addChild(new TargetBlock());
block.x = startX + pillar * 330;
block.y = startY - i * 110;
targetBlocks.push(block);
}
}
// Bridge
for (var i = 0; i < 3; i++) {
var block = game.addChild(new TargetBlock());
block.x = startX + 110 + i * 110;
block.y = startY - 330;
targetBlocks.push(block);
}
break;
case 5:
// Spiral formation
var centerX = startX + 150;
var centerY = startY - 150;
for (var i = 0; i < 12; i++) {
var angle = i * 0.8;
var radius = 30 + i * 15;
var block = game.addChild(new TargetBlock());
block.x = centerX + Math.cos(angle) * radius;
block.y = centerY + Math.sin(angle) * radius;
targetBlocks.push(block);
}
break;
case 6:
// Cross formation
// Horizontal line
for (var i = 0; i < 5; i++) {
var block = game.addChild(new TargetBlock());
block.x = startX + i * 110;
block.y = startY - 220;
targetBlocks.push(block);
}
// Vertical line
for (var i = 0; i < 5; i++) {
var block = game.addChild(new TargetBlock());
block.x = startX + 220;
block.y = startY - i * 110;
targetBlocks.push(block);
}
break;
case 7:
// Diamond formation
var positions = [{
x: 165,
y: -110
}, {
x: 110,
y: -220
}, {
x: 220,
y: -220
}, {
x: 55,
y: -330
}, {
x: 165,
y: -330
}, {
x: 275,
y: -330
}, {
x: 110,
y: -440
}, {
x: 220,
y: -440
}, {
x: 165,
y: -550
}];
for (var i = 0; i < positions.length; i++) {
var block = game.addChild(new TargetBlock());
block.x = startX + positions[i].x;
block.y = startY + positions[i].y;
targetBlocks.push(block);
}
break;
}
// Add special blocks for higher levels
if (level > 5) {
// Some blocks require multiple hits
var specialBlockCount = Math.min(Math.floor(level / 5), 3);
for (var i = 0; i < specialBlockCount && i < targetBlocks.length; i++) {
var specialBlock = targetBlocks[Math.floor(Math.random() * targetBlocks.length)];
specialBlock.health = 2;
// Visual indicator for special blocks
tween(specialBlock, {
tint: 0xFF6600
}, {
duration: 500,
easing: tween.easeInOut
});
specialBlock.scaleX = 1.1;
specialBlock.scaleY = 1.1;
}
}
// Add magnetic blocks for higher levels
if (level > 8) {
var magneticBlockCount = Math.min(Math.floor(level / 8), 2);
for (var i = 0; i < magneticBlockCount && i < targetBlocks.length; i++) {
var magneticBlock = targetBlocks[Math.floor(Math.random() * targetBlocks.length)];
var magneticType = Math.random() > 0.5 ? 'attract' : 'repel';
magneticBlock.setMagnetic(magneticType);
}
}
// Add portals for very high levels
if (level > 12) {
// Clear existing portals
for (var i = 0; i < portals.length; i++) {
portals[i].destroy();
}
portals = [];
// Create portal pairs
var portal1 = game.addChild(new Portal());
portal1.x = 600 + Math.random() * 200;
portal1.y = GROUND_Y - 200 - Math.random() * 300;
var portal2 = game.addChild(new Portal());
portal2.x = 1600 + Math.random() * 200;
portal2.y = GROUND_Y - 200 - Math.random() * 300;
// Link portals
portal1.linkedPortal = portal2;
portal2.linkedPortal = portal1;
portals.push(portal1, portal2);
}
}
// Initialize game systems
particleSystem = new ParticleSystem();
achievementSystem = new AchievementSystem();
achievementSystem.loadAchievements();
// Load saved progress
level = storage.currentLevel || 1;
totalBlocksDestroyed = storage.totalBlocksDestroyed || 0;
levelsCompleted = storage.levelsCompleted || 0;
// Show intro screen
introScreen = game.addChild(new IntroScreen());
introScreen.show();
// Game control functions
function startGame() {
gameState = 'playing';
introScreen.hide(function () {
introScreen.destroy();
introScreen = null;
createLevel();
LK.playMusic('Angrybirds');
});
}
function showSettings() {
// Settings implementation would go here
console.log("Settings clicked");
}
function showLevelSelector() {
// Level selector implementation would go here
console.log("Level selector clicked");
}
function switchProjectileType() {
powerUpIndex = (powerUpIndex + 1) % availablePowerUps.length;
currentProjectileType = availablePowerUps[powerUpIndex];
// Update UI to show current projectile type
var typeText = new Text2('Tip: ' + currentProjectileType.toUpperCase(), {
size: 60,
fill: 0x000000
});
typeText.anchor.set(0.5, 0);
typeText.x = 1024;
typeText.y = 200;
LK.gui.top.addChild(typeText);
// Remove after 2 seconds
LK.setTimeout(function () {
typeText.destroy();
}, 2000);
}
// Don't initialize level if we're showing intro
// createLevel();
// Helper functions
function calculateTrajectory(startX, startY, velocityX, velocityY) {
var points = [];
var x = startX;
var y = startY;
var vx = velocityX;
var vy = velocityY;
var timeStep = 2;
var gravity = GRAVITY * timeStep;
for (var i = 0; i < 15; i++) {
points.push({
x: x,
y: y
});
x += vx * timeStep;
y += vy * timeStep;
vy += gravity;
if (y >= GROUND_Y - 30) break;
}
return points;
}
function updateTrajectoryDisplay(points) {
for (var i = 0; i < trajectoryDots.length; i++) {
if (i < points.length) {
trajectoryDots[i].x = points[i].x;
trajectoryDots[i].y = points[i].y;
trajectoryDots[i].visible = true;
} else {
trajectoryDots[i].visible = false;
}
}
}
function hideTrajectoryDisplay() {
for (var i = 0; i < trajectoryDots.length; i++) {
trajectoryDots[i].visible = false;
}
}
function checkProjectileCollisions(projectile) {
var hitSomething = false;
var blocksDestroyed = 0;
// Apply magnetic forces from all blocks
for (var i = 0; i < targetBlocks.length; i++) {
var block = targetBlocks[i];
if (!block.destroyed && block.magneticType !== 'none') {
block.applyMagneticForce(projectile);
}
}
// Check portal teleportation
for (var i = 0; i < portals.length; i++) {
if (portals[i].teleport(projectile)) {
break; // Only one teleport per frame
}
}
for (var i = 0; i < targetBlocks.length; i++) {
var block = targetBlocks[i];
if (!block.destroyed && projectile.intersects(block)) {
var wasDestroyed = block.destroyed;
block.takeDamage();
if (!wasDestroyed && block.destroyed) {
blocksDestroyed++;
totalBlocksDestroyed++;
storage.totalBlocksDestroyed = totalBlocksDestroyed;
// Create destruction particles
particleSystem.createExplosion(block.x, block.y, 0xFFFFFF, 8);
}
LK.getSound('impact').play();
hitSomething = true;
// Type-specific collision effects
switch (projectile.type) {
case 'explosive':
projectile.explode();
projectile.destroyed = true;
return true;
case 'bouncy':
projectile.velocityX *= -0.8;
projectile.velocityY *= -0.8;
projectile.bounceCount++;
LK.getSound('bounce').play();
if (projectile.bounceCount < 3) {
// Add bounce particle effect
particleSystem.createExplosion(projectile.x, projectile.y, 0x44FF44, 5);
}
break;
case 'heavy':
// Heavy projectiles don't bounce much and continue through
projectile.velocityX *= -0.1;
projectile.velocityY *= -0.1;
break;
default:
// Normal projectile behavior
projectile.velocityX *= -0.2;
projectile.velocityY *= -0.2;
break;
}
// Add some randomness to bounce
projectile.velocityX += (Math.random() - 0.5) * 2;
projectile.velocityY += (Math.random() - 0.5) * 2;
if (block.destroyed) {
player.celebrate(); // Player celebrates when destroying a block
}
}
}
// Check achievements
if (blocksDestroyed >= 5) {
achievementSystem.checkAchievement('oneShot', blocksDestroyed);
}
achievementSystem.checkAchievement('destructionMaster', totalBlocksDestroyed);
return hitSomething;
}
function checkLevelComplete() {
var remainingBlocks = 0;
for (var i = 0; i < targetBlocks.length; i++) {
if (!targetBlocks[i].destroyed) {
remainingBlocks++;
}
}
if (remainingBlocks === 0) {
// Level complete - restart with new level
var shotsUsed = INITIAL_SHOTS - shotsRemaining;
level++;
levelsCompleted++;
storage.currentLevel = level;
storage.levelsCompleted = levelsCompleted;
// Check for perfect shot achievement
if (shotsUsed === 1) {
achievementSystem.checkAchievement('perfectShot', 1);
}
// Check level completion achievement
achievementSystem.checkAchievement('sharpshooter', levelsCompleted);
// Calculate star rating
var stars = 3;
if (shotsUsed > 2) stars = 2;
if (shotsUsed > 3) stars = 1;
// Show level complete message
var completeText = new Text2('Bölüm Tamamlandı!\n' + stars + ' Yıldız', {
size: 80,
fill: 0xFFD700
});
completeText.anchor.set(0.5, 0.5);
completeText.x = 1024;
completeText.y = 1000;
completeText.alpha = 0;
game.addChild(completeText);
tween(completeText, {
alpha: 1
}, {
duration: 500,
easing: tween.easeOut
});
shotsRemaining = INITIAL_SHOTS;
shotsText.setText('Atış: ' + shotsRemaining);
LK.setTimeout(function () {
tween(completeText, {
alpha: 0
}, {
duration: 300,
easing: tween.easeIn,
onFinish: function onFinish() {
completeText.destroy();
}
});
createLevel();
}, 2000);
return true;
}
if (shotsRemaining <= 0 && projectiles.length === 0) {
// Game over
LK.showGameOver();
return true;
}
return false;
}
// Event handlers
game.down = function (x, y, obj) {
if (gameState !== 'playing') return;
// Double tap to switch projectile type
if (!currentProjectile && shotsRemaining > 0) {
var distance = Math.sqrt((x - slingshot.x) * (x - slingshot.x) + (y - slingshot.y) * (y - slingshot.y));
// Check if clicking on projectile type indicator (top left area)
if (x < 300 && y < 300) {
switchProjectileType();
return;
}
// Check if clicking on gravity control (top right area)
if (x > 1748 && y < 300) {
if (level > 6) {
// Unlock gravity control after level 6
gravityReversed = !gravityReversed;
gravityTimer = maxGravityTime;
// Visual feedback
var gravityText = new Text2('Yerçekimi: ' + (gravityReversed ? 'TERS' : 'NORMAL'), {
size: 60,
fill: gravityReversed ? 0xFF0000 : 0x00FF00
});
gravityText.anchor.set(0.5, 0);
gravityText.x = 1024;
gravityText.y = 250;
LK.gui.top.addChild(gravityText);
LK.setTimeout(function () {
gravityText.destroy();
}, 2000);
LK.effects.flashScreen(gravityReversed ? 0xFF0000 : 0x0000FF, 300);
}
return;
}
// Check if clicking on time control (bottom center area)
if (x > 924 && x < 1124 && y > 2500) {
if (level > 10 && timeSlowCooldown === 0 && !timeSlowActive) {
// Unlock time control after level 10
timeSlowActive = true;
timeSlowTimer = maxTimeSlowDuration;
timeSlowCooldown = maxTimeSlowCooldown;
// Visual feedback
var timeText = new Text2('ZAMAN YAVAŞ!', {
size: 80,
fill: 0x00FFFF
});
timeText.anchor.set(0.5, 0);
timeText.x = 1024;
timeText.y = 350;
LK.gui.top.addChild(timeText);
LK.setTimeout(function () {
timeText.destroy();
}, 1000);
LK.effects.flashScreen(0x00FFFF, 400);
}
return;
}
if (distance < 250) {
// Increased from 150 to 250 for easier grabbing
isAiming = true;
aimStartX = x;
aimStartY = y;
currentProjectile = game.addChild(new Projectile());
currentProjectile.x = slingshot.x;
currentProjectile.y = slingshot.y - 100;
currentProjectile.type = currentProjectileType;
// Visual feedback for successful grab
LK.effects.flashObject(slingshot, 0x00FF00, 200);
// Scale animation to show projectile is grabbed
tween(currentProjectile, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 100,
easing: tween.easeOut
});
player.aim(); // Player leans forward when aiming
}
}
};
game.move = function (x, y, obj) {
if (isAiming && currentProjectile) {
var deltaX = aimStartX - x;
var deltaY = aimStartY - y;
// Restrict aiming to forward direction only (positive deltaX means forward)
if (deltaX < 0) {
deltaX = 0; // Don't allow backward aiming
}
// Limit drag distance
var distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
if (distance > MAX_DRAG_DISTANCE) {
deltaX = deltaX / distance * MAX_DRAG_DISTANCE;
deltaY = deltaY / distance * MAX_DRAG_DISTANCE;
distance = MAX_DRAG_DISTANCE;
}
// Smooth projectile following with magnetic snap to slingshot
var targetX = slingshot.x - deltaX * 0.5;
var targetY = slingshot.y - 100 - deltaY * 0.5;
// If very close to slingshot, snap to it for better control
if (distance < 30) {
targetX = slingshot.x;
targetY = slingshot.y - 100;
}
// Smooth interpolation for better feel
currentProjectile.x += (targetX - currentProjectile.x) * 0.8;
currentProjectile.y += (targetY - currentProjectile.y) * 0.8;
// Animate slingshot stretch
slingshot.stretch(deltaX, deltaY, distance);
// Calculate and show trajectory
var velocityX = deltaX * VELOCITY_MULTIPLIER;
var velocityY = deltaY * VELOCITY_MULTIPLIER;
var trajectoryPoints = calculateTrajectory(currentProjectile.x, currentProjectile.y, velocityX, velocityY);
updateTrajectoryDisplay(trajectoryPoints);
}
};
game.up = function (x, y, obj) {
if (gameState !== 'playing') return;
if (isAiming && currentProjectile) {
var deltaX = aimStartX - x;
var deltaY = aimStartY - y;
// Restrict aiming to forward direction only (positive deltaX means forward)
if (deltaX < 0) {
deltaX = 0; // Don't allow backward shooting
}
// Limit drag distance
var distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
if (distance > MAX_DRAG_DISTANCE) {
deltaX = deltaX / distance * MAX_DRAG_DISTANCE;
deltaY = deltaY / distance * MAX_DRAG_DISTANCE;
}
if (distance > 10 && deltaX > 0) {
// Reduced from 20 to 10 for easier shooting
// Only shoot if there's forward movement
var velocityX = deltaX * VELOCITY_MULTIPLIER;
var velocityY = deltaY * VELOCITY_MULTIPLIER;
// Apply wind effect
velocityX += windSpeed;
// Animate slingshot release
slingshot.release();
// Add screen flash effect for dramatic launch
LK.effects.flashScreen(0xFFFFFF, 200);
currentProjectile.launch(velocityX, velocityY, currentProjectileType);
currentProjectile.lastX = currentProjectile.x;
currentProjectile.lastY = currentProjectile.y;
projectiles.push(currentProjectile);
shotsRemaining--;
shotsText.setText('Atış: ' + shotsRemaining);
player.celebrate(); // Player celebrates the shot
// Play power-up sound for special projectiles
if (currentProjectileType !== 'normal') {
LK.getSound('powerup').play();
}
} else {
currentProjectile.destroy();
slingshot.reset(); // Reset slingshot if no shot
}
currentProjectile = null;
isAiming = false;
hideTrajectoryDisplay();
player.resetPose(); // Player returns to normal stance
}
};
game.update = function () {
if (gameState !== 'playing') return;
// Update score display
scoreText.setText('Puan: ' + LK.getScore());
// Update gravity timer
if (gravityTimer > 0) {
gravityTimer--;
if (gravityTimer === 0) {
gravityReversed = false;
var gravityText = new Text2('Yerçekimi Normal', {
size: 60,
fill: 0x00FF00
});
gravityText.anchor.set(0.5, 0);
gravityText.x = 1024;
gravityText.y = 250;
LK.gui.top.addChild(gravityText);
LK.setTimeout(function () {
gravityText.destroy();
}, 1500);
}
}
// Update time slow mechanics
if (timeSlowActive) {
timeSlowTimer--;
if (timeSlowTimer === 0) {
timeSlowActive = false;
var timeText = new Text2('Zaman Normal', {
size: 60,
fill: 0x00FF00
});
timeText.anchor.set(0.5, 0);
timeText.x = 1024;
timeText.y = 300;
LK.gui.top.addChild(timeText);
LK.setTimeout(function () {
timeText.destroy();
}, 1500);
}
}
if (timeSlowCooldown > 0) {
timeSlowCooldown--;
}
// Update portals
for (var i = 0; i < portals.length; i++) {
portals[i].update();
}
// Update projectiles
for (var i = projectiles.length - 1; i >= 0; i--) {
var projectile = projectiles[i];
if (projectile.destroyed) {
projectile.destroy();
projectiles.splice(i, 1);
continue;
}
if (projectile.launched) {
// Add wind effect to projectile
if (windSpeed !== 0) {
projectile.velocityX += windSpeed * 0.05;
}
// Create particle trail for special projectiles - reduced frequency
if (projectile.type !== 'normal' && LK.ticks % 8 === 0) {
particleSystem.createTrail(projectile.x - projectile.velocityX * 0.5, projectile.y - projectile.velocityY * 0.5, projectile.velocityX, projectile.velocityY);
}
checkProjectileCollisions(projectile);
}
}
// Remove destroyed blocks with particle effects
for (var i = targetBlocks.length - 1; i >= 0; i--) {
if (targetBlocks[i].destroyed) {
// Create destruction particles if not already done
if (!targetBlocks[i].particlesCreated) {
particleSystem.createExplosion(targetBlocks[i].x, targetBlocks[i].y, 0xFFFFFF, 6);
targetBlocks[i].particlesCreated = true;
}
targetBlocks[i].destroy();
targetBlocks.splice(i, 1);
}
}
// Color-changing world based on level progression
if (LK.ticks % 120 === 0) {
var colorPhase = (level - 1) % 6;
var skyColor, grassColor;
switch (colorPhase) {
case 0:
// Dawn
skyColor = 0x87CEEB;
grassColor = 0x4caf50;
break;
case 1:
// Morning
skyColor = 0xADD8E6;
grassColor = 0x228B22;
break;
case 2:
// Noon
skyColor = 0x00BFFF;
grassColor = 0x32CD32;
break;
case 3:
// Afternoon
skyColor = 0xFF7F50;
grassColor = 0x6B8E23;
break;
case 4:
// Sunset
skyColor = 0xFF6347;
grassColor = 0x556B2F;
break;
case 5:
// Night
skyColor = 0x191970;
grassColor = 0x2F4F2F;
break;
}
// Smooth color transition
tween(ground, {
tint: grassColor
}, {
duration: 2000,
easing: tween.easeInOut
});
game.setBackgroundColor(skyColor);
}
// Environmental effects - reduced frequency
if (level > 15 && LK.ticks % 300 === 0) {
// Add occasional falling leaves or snow
var leaf = game.addChild(LK.getAsset('trajectoryDot', {
anchorX: 0.5,
anchorY: 0.5
}));
leaf.x = Math.random() * 2048;
leaf.y = -50;
leaf.tint = 0x228B22;
leaf.scaleX = 0.5;
leaf.scaleY = 0.5;
tween(leaf, {
x: leaf.x + (Math.random() - 0.5) * 200,
y: 2800,
rotation: Math.PI * 2,
alpha: 0
}, {
duration: 2000,
easing: tween.linear,
onFinish: function onFinish() {
leaf.destroy();
}
});
}
// Periodic cleanup to prevent memory leaks
if (LK.ticks % 300 === 0) {
particleSystem.cleanup();
}
// Check level completion
checkLevelComplete();
}; ===================================================================
--- original.js
+++ change.js
@@ -255,8 +255,10 @@
var ParticleSystem = Container.expand(function () {
var self = Container.call(this);
self.particles = [];
self.createExplosion = function (x, y, color, count) {
+ // Limit particle count to prevent performance issues
+ count = Math.min(count, 6);
for (var i = 0; i < count; i++) {
var particle = game.addChild(LK.getAsset('trajectoryDot', {
anchorX: 0.5,
anchorY: 0.5
@@ -264,8 +266,9 @@
particle.x = x;
particle.y = y;
particle.tint = color;
particle.alpha = 1;
+ self.particles.push(particle);
var angle = i / count * Math.PI * 2;
var speed = 50 + Math.random() * 100;
var distance = speed * (1 + Math.random());
tween(particle, {
@@ -274,12 +277,14 @@
alpha: 0,
scaleX: 0,
scaleY: 0
}, {
- duration: 800 + Math.random() * 400,
+ duration: 600,
easing: tween.easeOut,
onFinish: function onFinish() {
particle.destroy();
+ var index = self.particles.indexOf(particle);
+ if (index > -1) self.particles.splice(index, 1);
}
});
}
};
@@ -292,20 +297,40 @@
trail.y = y;
trail.alpha = 0.6;
trail.scaleX = 0.5;
trail.scaleY = 0.5;
+ self.particles.push(trail);
tween(trail, {
alpha: 0,
scaleX: 0,
scaleY: 0
}, {
- duration: 300,
+ duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
trail.destroy();
+ var index = self.particles.indexOf(trail);
+ if (index > -1) self.particles.splice(index, 1);
}
});
};
+ self.cleanup = function () {
+ // Clean up any remaining particles
+ for (var i = self.particles.length - 1; i >= 0; i--) {
+ if (self.particles[i] && self.particles[i].destroyed) {
+ self.particles.splice(i, 1);
+ }
+ }
+ // Limit total particles
+ if (self.particles.length > 50) {
+ for (var i = 0; i < 10; i++) {
+ if (self.particles[i]) {
+ self.particles[i].destroy();
+ self.particles.splice(i, 1);
+ }
+ }
+ }
+ };
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
@@ -597,35 +622,10 @@
});
}
}
}
- // Create particle effect
- for (var j = 0; j < 10; j++) {
- var particle = game.addChild(LK.getAsset('trajectoryDot', {
- anchorX: 0.5,
- anchorY: 0.5
- }));
- particle.x = self.x;
- particle.y = self.y;
- particle.tint = 0xFF4444;
- particle.scaleX = 2;
- particle.scaleY = 2;
- var angle = j / 10 * Math.PI * 2;
- var distance = 100 + Math.random() * 100;
- tween(particle, {
- x: self.x + Math.cos(angle) * distance,
- y: self.y + Math.sin(angle) * distance,
- alpha: 0,
- scaleX: 0,
- scaleY: 0
- }, {
- duration: 500,
- easing: tween.easeOut,
- onFinish: function onFinish() {
- particle.destroy();
- }
- });
- }
+ // Create particle effect with reduced count
+ particleSystem.createExplosion(self.x, self.y, 0xFF4444, 6);
}
};
return self;
});
@@ -1625,10 +1625,10 @@
// Add wind effect to projectile
if (windSpeed !== 0) {
projectile.velocityX += windSpeed * 0.05;
}
- // Create particle trail for special projectiles
- if (projectile.type !== 'normal' && LK.ticks % 3 === 0) {
+ // Create particle trail for special projectiles - reduced frequency
+ if (projectile.type !== 'normal' && LK.ticks % 8 === 0) {
particleSystem.createTrail(projectile.x - projectile.velocityX * 0.5, projectile.y - projectile.velocityY * 0.5, projectile.velocityX, projectile.velocityY);
}
checkProjectileCollisions(projectile);
}
@@ -1689,10 +1689,10 @@
easing: tween.easeInOut
});
game.setBackgroundColor(skyColor);
}
- // Environmental effects
- if (level > 15 && LK.ticks % 60 === 0) {
+ // Environmental effects - reduced frequency
+ if (level > 15 && LK.ticks % 300 === 0) {
// Add occasional falling leaves or snow
var leaf = game.addChild(LK.getAsset('trajectoryDot', {
anchorX: 0.5,
anchorY: 0.5
@@ -1707,14 +1707,18 @@
y: 2800,
rotation: Math.PI * 2,
alpha: 0
}, {
- duration: 3000 + Math.random() * 2000,
+ duration: 2000,
easing: tween.linear,
onFinish: function onFinish() {
leaf.destroy();
}
});
}
+ // Periodic cleanup to prevent memory leaks
+ if (LK.ticks % 300 === 0) {
+ particleSystem.cleanup();
+ }
// Check level completion
checkLevelComplete();
};
\ No newline at end of file