Code edit (2 edits merged)
Please save this source code
User prompt
use differents shades of green for popup background and option backgrounds
User prompt
make options backgrounds darker green than pop up background
User prompt
now make a brighter green
User prompt
its not green its red make it green
User prompt
change popup backgrounds colour to green
User prompt
change popup backgrounds assets colour to dark green
User prompt
Please fix the bug: 'LK.effects.outline is not a function' in or related to this line: 'LK.effects.outline(bg, 0x000000, 8);' Line Number: 410
User prompt
Please fix the bug: 'LK.effects.outline is not a function' in or related to this line: 'LK.effects.outline(bg, 0x000000, 8);' Line Number: 410
User prompt
give the rectangles black outlines
User prompt
make the big popup backgrounds widths 1100
User prompt
Please fix the bug: 'LK.effects.roundedCorners is not a function' in or related to this line: 'LK.effects.roundedCorners(bg, 60);' Line Number: 410
User prompt
round the edges of the pop up backgrounds and option backgrounds rectangles
User prompt
move hero asset to the behind the pop up screens
User prompt
make all options background width 800
User prompt
make all explanation text size 40
User prompt
can u change all texts to monsterrat
User prompt
move them 30pixels down
User prompt
move it 60 more and make it same ingame popups
User prompt
move "choose your power" text up little and tell me how many pixel u move it
User prompt
make pop up options text sizes 54 (not the explanations)
Code edit (1 edits merged)
Please save this source code
User prompt
Make the ingame pop up screens same as starting pop up screen
Code edit (1 edits merged)
Please save this source code
Code edit (1 edits merged)
Please save this source code
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// BossEnemy class (big zombie boss)
var BossEnemy = Container.expand(function () {
var self = Container.call(this);
// Preload both right and left sprites, only one visible at a time
var bossSpriteRight = self.attachAsset('boss_enemy', {
anchorX: 0.5,
anchorY: 0.5
});
bossSpriteRight.assetId = 'boss_enemy';
var bossSpriteLeft = self.attachAsset('boss_enemy_left', {
anchorX: 0.5,
anchorY: 0.5
});
bossSpriteLeft.assetId = 'boss_enemy_left';
bossSpriteLeft.visible = false;
self.radius = 120;
self.speed = 0.7;
self.hp = 30;
self._lastFacingRight = true; // Track last facing direction
self.update = function () {
if (typeof game !== "undefined" && game._levelUpFrozen) {
return;
}
var dx = hero.x - self.x;
var dy = hero.y - self.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist > 0) {
self.x += dx / dist * self.speed;
self.y += dy / dist * self.speed;
}
// Face boss left/right depending on hero position, by toggling visibility
var shouldFaceRight = hero.x > self.x;
if (shouldFaceRight !== self._lastFacingRight) {
bossSpriteRight.visible = shouldFaceRight;
bossSpriteLeft.visible = !shouldFaceRight;
self._lastFacingRight = shouldFaceRight;
}
};
return self;
});
// Bullet class
var Bullet = Container.expand(function () {
var self = Container.call(this);
var bulletSprite = self.attachAsset('bullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.radius = 18;
self.speed = 9.5;
self.dirX = 1;
self.dirY = 0;
self.pierce = 1;
// Track enemies already hit by this bullet
self._hitEnemies = [];
self.update = function () {
if (typeof game !== "undefined" && game._levelUpFrozen) {
return;
}
// Homing logic: if enabled, adjust direction toward nearest enemy
if (Bullet.prototype.homing && typeof enemies !== "undefined" && enemies.length > 0) {
// Spread phase: if more than 1 bullet, spread out for a short time before homing
if (typeof bullets !== "undefined" && bullets.length > 1) {
if (typeof self._spreadTimer === "undefined") {
// Each bullet gets a unique spread angle based on its index in bullets array
var idx = 0;
for (var bidx = 0; bidx < bullets.length; bidx++) {
if (bullets[bidx] === self) {
idx = bidx;
break;
}
}
var spreadTotal = bullets.length;
var spreadAngle = Math.PI / 6; // 30 degrees total spread
var baseAngle = Math.atan2(self.dirY, self.dirX);
var angleOffset = -spreadAngle / 2 + (spreadTotal === 1 ? 0 : spreadAngle * idx / (spreadTotal - 1));
self._spreadTargetAngle = baseAngle + angleOffset;
self._spreadTimer = 12; // frames to spread before homing
}
if (self._spreadTimer > 0) {
// Lerp direction toward spread angle
var currentAngle = Math.atan2(self.dirY, self.dirX);
var targetAngle = self._spreadTargetAngle;
// Shortest angle difference
var da = targetAngle - currentAngle;
while (da > Math.PI) {
da -= Math.PI * 2;
}
while (da < -Math.PI) {
da += Math.PI * 2;
}
var lerp = 0.25;
var newAngle = currentAngle + da * lerp;
self.dirX = Math.cos(newAngle);
self.dirY = Math.sin(newAngle);
self.rotation = newAngle;
self._spreadTimer--;
} else {
// After spread, start homing
var minDist = 99999;
var nearest = null;
for (var i = 0; i < enemies.length; i++) {
var e = enemies[i];
// Exclude enemies already hit by this bullet
if (self._hitEnemies.indexOf(e) !== -1) {
continue;
}
var dx = e.x - self.x;
var dy = e.y - self.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist < minDist) {
minDist = dist;
nearest = e;
}
}
if (nearest) {
var dx = nearest.x - self.x;
var dy = nearest.y - self.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist > 0) {
var homingStrength = 0.18;
var targetDirX = dx / dist;
var targetDirY = dy / dist;
self.dirX = self.dirX * (1 - homingStrength) + targetDirX * homingStrength;
self.dirY = self.dirY * (1 - homingStrength) + targetDirY * homingStrength;
var norm = Math.sqrt(self.dirX * self.dirX + self.dirY * self.dirY);
if (norm > 0) {
self.dirX /= norm;
self.dirY /= norm;
}
self.rotation = Math.atan2(self.dirY, self.dirX);
}
}
}
} else {
// Only one bullet, home immediately
var minDist = 99999;
var nearest = null;
for (var i = 0; i < enemies.length; i++) {
var e = enemies[i];
// Exclude enemies already hit by this bullet
if (self._hitEnemies.indexOf(e) !== -1) {
continue;
}
var dx = e.x - self.x;
var dy = e.y - self.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist < minDist) {
minDist = dist;
nearest = e;
}
}
if (nearest) {
var dx = nearest.x - self.x;
var dy = nearest.y - self.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist > 0) {
var homingStrength = 0.18;
var targetDirX = dx / dist;
var targetDirY = dy / dist;
self.dirX = self.dirX * (1 - homingStrength) + targetDirX * homingStrength;
self.dirY = self.dirY * (1 - homingStrength) + targetDirY * homingStrength;
var norm = Math.sqrt(self.dirX * self.dirX + self.dirY * self.dirY);
if (norm > 0) {
self.dirX /= norm;
self.dirY /= norm;
}
self.rotation = Math.atan2(self.dirY, self.dirX);
}
}
}
}
self.x += self.dirX * self.speed;
self.y += self.dirY * self.speed;
// Ricochet logic: if enabled, on hit, bounce to nearest enemy up to N times
if (typeof self.ricochetLeft === "undefined" && Bullet.prototype.ricochet) {
self.ricochetLeft = Bullet.prototype.ricochet;
}
if (typeof self.ricochetLeft !== "undefined" && self.ricochetLeft > 0 && typeof enemies !== "undefined") {
// Ricochet handled in collision, see main game.update
}
};
return self;
});
// Enemy class
var Enemy = Container.expand(function () {
var self = Container.call(this);
// Preload both right and left sprites, only one visible at a time
var enemySpriteRight = self.attachAsset('enemy_right', {
anchorX: 0.5,
anchorY: 0.5
});
enemySpriteRight.assetId = 'enemy_right';
var enemySpriteLeft = self.attachAsset('enemy_left', {
anchorX: 0.5,
anchorY: 0.5
});
enemySpriteLeft.assetId = 'enemy_left';
enemySpriteLeft.visible = false;
self.radius = 50;
self.speed = 1.5 + Math.random();
self._lastFacingRight = true; // Track last facing direction
self.update = function () {
if (typeof game !== "undefined" && game._levelUpFrozen) {
return;
}
var dx = hero.x - self.x;
var dy = hero.y - self.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist > 0) {
self.x += dx / dist * self.speed;
self.y += dy / dist * self.speed;
}
// Face enemy left/right depending on hero position, by toggling visibility
var shouldFaceRight = hero.x > self.x;
if (shouldFaceRight !== self._lastFacingRight) {
enemySpriteRight.visible = shouldFaceRight;
enemySpriteLeft.visible = !shouldFaceRight;
self._lastFacingRight = shouldFaceRight;
}
};
return self;
});
// Experience Gem class (handles both normal and big XP gems)
var Gem = Container.expand(function (opts) {
var self = Container.call(this);
// Default to normal gem
self.type = opts && opts.type || 'xp';
if (self.type === 'big') {
var gemSprite = self.attachAsset('big_xp_gem', {
anchorX: 0.5,
anchorY: 0.5
});
self.radius = 30;
} else {
var gemSprite = self.attachAsset('xp_gem', {
anchorX: 0.5,
anchorY: 0.5
});
self.radius = 20;
}
self.update = function () {};
return self;
});
// HeartPowerup class (can artıran kalp)
var HeartPowerup = Container.expand(function () {
var self = Container.call(this);
self.attachAsset('heart_powerup', {
anchorX: 0.5,
anchorY: 0.5
});
self.radius = 30;
self.update = function () {};
return self;
});
// Hero class
var Hero = Container.expand(function () {
var self = Container.call(this);
// Preload both right and left hero sprites, only one visible at a time
var heroSpriteRight = self.attachAsset('hero_right', {
anchorX: 0.5,
anchorY: 0.5
});
heroSpriteRight.assetId = 'hero_right';
var heroSpriteLeft = self.attachAsset('hero_left', {
anchorX: 0.5,
anchorY: 0.5
});
heroSpriteLeft.assetId = 'hero_left';
heroSpriteLeft.visible = false;
self.radius = 60;
self.speed = 100;
self.targetX = 1024;
self.targetY = 1366;
self.magnetActive = false;
self.magnetDuration = 0;
self.magnetRange = 300;
self.magnetRangeBoosted = 800;
self._lastFacingRight = true; // Track last facing direction
self.update = function () {
var dx = self.targetX - self.x;
var dy = self.targetY - self.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist > 10) {
var move = Math.min(self.speed, dist);
var prevX = self.x;
self.x += dx / dist * move;
self.y += dy / dist * move;
// Face hero left/right depending on movement direction, by toggling visibility
var shouldFaceRight = self.x > prevX;
if (shouldFaceRight !== self._lastFacingRight) {
heroSpriteRight.visible = shouldFaceRight;
heroSpriteLeft.visible = !shouldFaceRight;
self._lastFacingRight = shouldFaceRight;
}
}
if (self.magnetActive) {
// Make hero glow blue while magnet is active
if (!self._magnetGlowActive) {
LK.effects.flashObject(self, 0x00ffff, 60000); // long duration, will be reset when deactivated
self._magnetGlowActive = true;
}
// Magnet duration is now synchronized with game time (ticksSurvived)
if (typeof self.magnetEndTick === "number") {
if (typeof ticksSurvived === "number" && ticksSurvived >= self.magnetEndTick) {
self.magnetActive = false;
self.magnetDuration = 0;
self.magnetEndTick = undefined;
} else {
// Update magnetDuration for UI display
if (typeof ticksSurvived === "number") {
self.magnetDuration = self.magnetEndTick - ticksSurvived;
}
}
}
} else {
self._magnetGlowActive = false;
}
};
return self;
});
// Powerup class (now only for magnet)
var Powerup = Container.expand(function (opts) {
var self = Container.call(this);
self.isMagnet = opts && opts.isMagnet || false;
if (self.isMagnet) {
self.attachAsset('magnet_powerup', {
anchorX: 0.5,
anchorY: 0.5
});
}
self.radius = 30;
self.update = function () {};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x444444
});
/****
* Game Code
****/
// <-- Kırmızı kalp powerup shape
var hero;
var heroLives = 5;
var enemies = [];
var bullets = [];
var gems = [];
var powerups = [];
var spawnTimer = 0;
var spawnInterval = 90;
var wave = 1;
var xp = 0;
var xpToLevel = 10;
var level = 1;
var dragging = false;
var lastGameOver = false;
var scoreTxt, xpTxt, levelTxt;
var centerX = 2048 / 2;
var centerY = 2732 / 2;
// --- Option popup at game start ---
var startOptionPopup;
function showStartOptionPopup() {
// Freeze all game logic and input
game._levelUpFrozen = true;
// Remove any previous popup if present
if (typeof startOptionPopup !== "undefined" && startOptionPopup && startOptionPopup.parent) {
startOptionPopup.parent.removeChild(startOptionPopup);
startOptionPopup = null;
}
startOptionPopup = new Container();
// Dim background
var bg = LK.getAsset('centerCircle', {
anchorX: 0.5,
anchorY: 0.5,
color: 0x39FF14 // brighter green (popup background)
});
bg.width = 1100;
bg.height = 1500;
bg.alpha = 0.92;
bg.x = centerX;
bg.y = centerY;
// Removed outline (LK.effects.outline not supported)
startOptionPopup.addChild(bg);
// Title
var titleTxt = new Text2('Choose Your Power!', {
size: 90,
fill: "#fff",
font: "Montserrat" // Set font to Montserrat
});
titleTxt.anchor.set(0.5, 0);
titleTxt.x = centerX;
titleTxt.y = centerY - 610;
startOptionPopup.addChild(titleTxt);
// Option vertical layout
var optionStartY = centerY - 320;
var optionSpacing = 220;
// Option 1: Attack Speed Up
var opt1 = new Container();
var opt1Bg = LK.getAsset('centerCircle', {
anchorX: 0.5,
anchorY: 0.5,
color: 0x006400 // even darker green (option background)
});
opt1Bg.width = 800;
opt1Bg.height = 160;
opt1Bg.alpha = 0.98;
opt1Bg.x = centerX;
opt1Bg.y = optionStartY;
// Removed outline (LK.effects.outline not supported)
opt1.addChild(opt1Bg);
var opt1Txt = new Text2('Attack Speed', {
size: 54,
fill: 0xF7E967,
font: "Montserrat"
});
opt1Txt.anchor.set(0.5, 0.5);
opt1Txt.x = centerX;
opt1Txt.y = optionStartY - 25;
opt1.addChild(opt1Txt);
var opt1Desc = new Text2('Fire faster from the start!', {
size: 40,
fill: "#fff",
font: "Montserrat"
});
opt1Desc.anchor.set(0.5, 0.5);
opt1Desc.x = centerX;
opt1Desc.y = optionStartY + 35;
opt1.addChild(opt1Desc);
opt1.interactive = true;
opt1.down = function (x, y, obj) {
// Apply attack speed boost
autoAttackInterval = Math.max(6, autoAttackInterval - 18);
// Resume game and remove popup
if (startOptionPopup && startOptionPopup.parent) {
startOptionPopup.parent.removeChild(startOptionPopup);
startOptionPopup = null;
}
game._levelUpFrozen = false;
};
startOptionPopup.addChild(opt1);
// Option 2: Ricochet Bullet
var opt2 = new Container();
var opt2Bg = LK.getAsset('centerCircle', {
anchorX: 0.5,
anchorY: 0.5,
color: 0x006400 // even darker green (option background)
});
opt2Bg.width = 800;
opt2Bg.height = 160;
opt2Bg.alpha = 0.98;
opt2Bg.x = centerX;
opt2Bg.y = optionStartY + optionSpacing;
// Removed outline (LK.effects.outline not supported)
opt2.addChild(opt2Bg);
var opt2Txt = new Text2('Ricochet', {
size: 54,
fill: 0x7BE495,
font: "Montserrat"
});
opt2Txt.anchor.set(0.5, 0.5);
opt2Txt.x = centerX;
opt2Txt.y = optionStartY + optionSpacing - 25;
opt2.addChild(opt2Txt);
var opt2Desc = new Text2('Bullets bounce to another enemy', {
size: 40,
fill: "#fff",
font: "Montserrat"
});
opt2Desc.anchor.set(0.5, 0.5);
opt2Desc.x = centerX;
opt2Desc.y = optionStartY + optionSpacing + 35;
opt2.addChild(opt2Desc);
opt2.interactive = true;
opt2.down = function (x, y, obj) {
Bullet.prototype.ricochet = 1;
if (startOptionPopup && startOptionPopup.parent) {
startOptionPopup.parent.removeChild(startOptionPopup);
startOptionPopup = null;
}
game._levelUpFrozen = false;
};
startOptionPopup.addChild(opt2);
// Option 3: +1 Bullet (spread shot)
var opt3 = new Container();
var opt3Bg = LK.getAsset('centerCircle', {
anchorX: 0.5,
anchorY: 0.5,
color: 0x006400 // even darker green (option background)
});
opt3Bg.width = 800;
opt3Bg.height = 160;
opt3Bg.alpha = 0.98;
opt3Bg.x = centerX;
opt3Bg.y = optionStartY + optionSpacing * 2;
// Removed outline (LK.effects.outline not supported)
opt3.addChild(opt3Bg);
var opt3Txt = new Text2('Bullet +1', {
size: 54,
fill: 0xFFB347,
font: "Montserrat"
});
opt3Txt.anchor.set(0.5, 0.5);
opt3Txt.x = centerX;
opt3Txt.y = optionStartY + optionSpacing * 2 - 25;
opt3.addChild(opt3Txt);
var opt3Desc = new Text2('Shoot more bullets at once', {
size: 40,
fill: "#fff",
font: "Montserrat"
});
opt3Desc.anchor.set(0.5, 0.5);
opt3Desc.x = centerX;
opt3Desc.y = optionStartY + optionSpacing * 2 + 35;
opt3.addChild(opt3Desc);
opt3.interactive = true;
opt3.down = function (x, y, obj) {
Bullet.prototype.extraBullets = 1;
if (startOptionPopup && startOptionPopup.parent) {
startOptionPopup.parent.removeChild(startOptionPopup);
startOptionPopup = null;
}
game._levelUpFrozen = false;
};
startOptionPopup.addChild(opt3);
// Option 4: Pierce +1
var opt4 = new Container();
var opt4Bg = LK.getAsset('centerCircle', {
anchorX: 0.5,
anchorY: 0.5,
color: 0x006400 // even darker green (option background)
});
opt4Bg.width = 800;
opt4Bg.height = 160;
opt4Bg.alpha = 0.98;
opt4Bg.x = centerX;
opt4Bg.y = optionStartY + optionSpacing * 3;
// Removed outline (LK.effects.outline not supported)
opt4.addChild(opt4Bg);
var opt4Txt = new Text2('Pierce +1', {
size: 54,
fill: 0x7BE4FF,
font: "Montserrat"
});
opt4Txt.anchor.set(0.5, 0.5);
opt4Txt.x = centerX;
opt4Txt.y = optionStartY + optionSpacing * 3 - 25;
opt4.addChild(opt4Txt);
var opt4Desc = new Text2('Bullets pass through more enemies', {
size: 40,
fill: "#fff",
font: "Montserrat"
});
opt4Desc.anchor.set(0.5, 0.5);
opt4Desc.x = centerX;
opt4Desc.y = optionStartY + optionSpacing * 3 + 35;
opt4.addChild(opt4Desc);
opt4.interactive = true;
opt4.down = function (x, y, obj) {
Bullet.prototype.pierce = 2;
if (startOptionPopup && startOptionPopup.parent) {
startOptionPopup.parent.removeChild(startOptionPopup);
startOptionPopup = null;
}
game._levelUpFrozen = false;
};
startOptionPopup.addChild(opt4);
// Option 5: Bullets can follow up enemies
var opt5 = new Container();
var opt5Bg = LK.getAsset('centerCircle', {
anchorX: 0.5,
anchorY: 0.5,
color: 0x006400 // even darker green (option background)
});
opt5Bg.width = 800;
opt5Bg.height = 160;
opt5Bg.alpha = 0.98;
opt5Bg.x = centerX;
opt5Bg.y = optionStartY + optionSpacing * 4;
// Removed outline (LK.effects.outline not supported)
opt5.addChild(opt5Bg);
var opt5Txt = new Text2('Missile', {
size: 54,
fill: 0xFF77FF,
font: "Montserrat"
});
opt5Txt.anchor.set(0.5, 0.5);
opt5Txt.x = centerX;
opt5Txt.y = optionStartY + optionSpacing * 4 - 25;
opt5.addChild(opt5Txt);
var opt5Desc = new Text2('Bullets home in on enemies', {
size: 40,
fill: "#fff",
font: "Montserrat"
});
opt5Desc.anchor.set(0.5, 0.5);
opt5Desc.x = centerX;
opt5Desc.y = optionStartY + optionSpacing * 4 + 35;
opt5.addChild(opt5Desc);
opt5.interactive = true;
opt5.down = function (x, y, obj) {
Bullet.prototype.homing = true;
if (startOptionPopup && startOptionPopup.parent) {
startOptionPopup.parent.removeChild(startOptionPopup);
startOptionPopup = null;
}
game._levelUpFrozen = false;
};
startOptionPopup.addChild(opt5);
// Add popup to game
game.addChild(startOptionPopup);
}
// Show the popup at game start
hero = new Hero();
hero.x = centerX;
hero.y = centerY;
game.addChild(hero);
showStartOptionPopup();
scoreTxt = new Text2('Score: 0', {
size: 54,
fill: "#fff",
font: "Montserrat"
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
var livesTxt = new Text2('Lives: ' + heroLives, {
size: 36,
fill: 0xFF5555,
font: "Montserrat"
});
livesTxt.anchor.set(0.5, 0);
livesTxt.y = 60;
LK.gui.top.addChild(livesTxt);
var timerTxt = new Text2('00:00', {
size: 54,
fill: "#fff",
font: "Montserrat"
});
timerTxt.anchor.set(1, 0);
LK.gui.topRight.addChild(timerTxt);
var magnetTimerTxt = new Text2('', {
size: 44,
fill: 0x00FFFF,
font: "Montserrat"
});
magnetTimerTxt.anchor.set(1, 0);
magnetTimerTxt.y = 60;
LK.gui.topRight.addChild(magnetTimerTxt);
xpTxt = new Text2('XP: 0/10', {
size: 36,
fill: 0x7BE495,
font: "Montserrat"
});
xpTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(xpTxt);
xpTxt.y = 110;
levelTxt = new Text2('Level: 1', {
size: 36,
fill: 0xF7E967,
font: "Montserrat"
});
levelTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(levelTxt);
levelTxt.y = 180;
function spawnEnemy() {
var edge = Math.floor(Math.random() * 4);
var x, y;
var useRight = false;
if (edge === 0) {
x = Math.random() * 2048;
y = -100;
if (x > 1024) {
useRight = true;
}
} else if (edge === 1) {
x = 2048 + 100;
y = Math.random() * 2732;
useRight = true;
} else if (edge === 2) {
x = Math.random() * 2048;
y = 2732 + 100;
if (x > 1024) {
useRight = true;
}
} else {
x = -100;
y = Math.random() * 2732;
}
var enemy = new Enemy();
// Set initial facing direction based on spawn side
if (useRight) {
// Face right: right sprite visible, left sprite hidden
if (enemy.children && enemy.children.length > 0) {
for (var i = 0; i < enemy.children.length; i++) {
var child = enemy.children[i];
if (child.assetId === 'enemy_right') {
child.visible = true;
}
if (child.assetId === 'enemy_left') {
child.visible = false;
}
}
}
enemy._lastFacingRight = true;
} else {
// Face left: left sprite visible, right sprite hidden
if (enemy.children && enemy.children.length > 0) {
for (var i = 0; i < enemy.children.length; i++) {
var child = enemy.children[i];
if (child.assetId === 'enemy_right') {
child.visible = false;
}
if (child.assetId === 'enemy_left') {
child.visible = true;
}
}
}
enemy._lastFacingRight = false;
}
enemy.x = x;
enemy.y = y;
enemies.push(enemy);
game.addChild(enemy);
}
function spawnGem(x, y, opts) {
var gem = new Gem(opts);
gem.x = x;
gem.y = y;
gems.push(gem);
game.addChild(gem);
}
function spawnMagnetPowerup(x, y) {
var powerup = new Powerup({
isMagnet: true
}); // isMagnet parametresiyle oluştur
powerup.x = x;
powerup.y = y;
powerups.push(powerup);
game.addChild(powerup);
}
function spawnPowerup(x, y) {
var powerup = new Powerup({
isMagnet: false
}); // Diğer poweruplar
powerup.x = x;
powerup.y = y;
powerups.push(powerup);
// Remove and re-add to ensure it's above any background (if present)
if (game.children && game.children.length > 0) {
game.removeChild(powerup);
game.addChild(powerup);
} else {
game.addChild(powerup);
}
}
// Yeni: kalp powerup spawn fonksiyonu
function spawnHeartPowerup(x, y) {
var heart = new HeartPowerup();
heart.x = x;
heart.y = y;
powerups.push(heart);
game.addChild(heart);
}
function fireBullet(dx, dy) {
var bullet = new Bullet();
bullet.x = hero.x;
bullet.y = hero.y;
if (typeof Bullet.prototype.pierce === "undefined") {
Bullet.prototype.pierce = 1;
}
bullet.pierce = Bullet.prototype.pierce;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist === 0) {
bullet.dirX = 1;
bullet.dirY = 0;
} else {
bullet.dirX = dx / dist;
bullet.dirY = dy / dist;
}
bullet.rotation = Math.atan2(bullet.dirY, bullet.dirX);
bullets.push(bullet);
game.addChild(bullet);
}
function randomDir() {
var angle = Math.random() * Math.PI * 2;
return {
x: Math.cos(angle),
y: Math.sin(angle)
};
}
function dist2(a, b) {
var dx = a.x - b.x;
var dy = a.y - b.y;
return Math.sqrt(dx * dx + dy * dy);
}
game.down = function (x, y, obj) {
if (game._levelUpFrozen) {
return;
}
if (x < 100 && y < 100) {
return;
}
hero.targetX = x;
hero.targetY = y;
dragging = true;
};
game.move = function (x, y, obj) {
if (game._levelUpFrozen) {
return;
}
hero.targetX = x;
hero.targetY = y;
};
game.up = function (x, y, obj) {
if (game._levelUpFrozen) {
return;
}
dragging = false;
};
var ticksSurvived = 0;
var autoAttackTimer = 0;
var autoAttackInterval = 96;
game.update = function () {
if (game._levelUpFrozen) {
// Freeze all game logic and input while level up popup is active
return;
}
hero.update();
for (var i = enemies.length - 1; i >= 0; i--) {
var e = enemies[i];
e.update();
// Track lastWasTouchingHero for exact frame detection
if (typeof e.lastWasTouchingHero === "undefined") {
e.lastWasTouchingHero = false;
}
var isTouchingHero = dist2(e, hero) < e.radius + hero.radius;
if (!e.lastWasTouchingHero && isTouchingHero) {
LK.effects.flashScreen(0xff0000, 1000);
heroLives--;
livesTxt.setText('Lives: ' + heroLives);
if (heroLives <= 0) {
LK.showGameOver();
lastGameOver = true;
}
}
e.lastWasTouchingHero = isTouchingHero;
}
for (var i = bullets.length - 1; i >= 0; i--) {
var b = bullets[i];
b.update();
if (b.x < -100 || b.x > 2148 || b.y < -100 || b.y > 2832) {
b.destroy();
bullets.splice(i, 1);
continue;
}
for (var j = enemies.length - 1; j >= 0; j--) {
var e = enemies[j];
if (dist2(b, e) < b.radius + e.radius) {
// Mark this enemy as hit by this bullet
if (b._hitEnemies && b._hitEnemies.indexOf(e) === -1) {
b._hitEnemies.push(e);
}
// Boss enemy logic
if (typeof e.hp === "number" && e.hp > 0) {
e.hp -= 1;
LK.effects.flashObject(e, 0xffffff, 120);
if (e.hp <= 0) {
// Boss defeated: drop multiple big gems and normal gems
for (var drop = 0; drop < 3; drop++) {
var angle = Math.random() * Math.PI * 2;
var dist = 60 + Math.random() * 40;
var gemX = e.x + Math.cos(angle) * dist;
var gemY = e.y + Math.sin(angle) * dist;
spawnGem(gemX, gemY, {
type: 'big'
});
}
for (var drop = 0; drop < 5; drop++) {
var angle = Math.random() * Math.PI * 2;
var dist = 80 + Math.random() * 60;
var gemX = e.x + Math.cos(angle) * dist;
var gemY = e.y + Math.sin(angle) * dist;
spawnGem(gemX, gemY);
}
// Always drop a magnet powerup
spawnMagnetPowerup(e.x, e.y);
// Yeni: boss öldüğünde kalp powerup düşürme (10% şans)
if (Math.random() < 0.1) {
spawnHeartPowerup(e.x, e.y);
}
e.destroy();
enemies.splice(j, 1);
}
} else {
var bigGemSpawned = false;
if (Math.random() < 0.10) {
// Drop big xp gem at 10% rate
spawnGem(e.x, e.y, {
type: 'big'
});
bigGemSpawned = true;
}
// Offset the normal gem if big gem was spawned to avoid overlap
if (bigGemSpawned) {
var offsetAngle = Math.random() * Math.PI * 2;
var offsetDist = 40;
var gemX = e.x + Math.cos(offsetAngle) * offsetDist;
var gemY = e.y + Math.sin(offsetAngle) * offsetDist;
spawnGem(gemX, gemY);
} else {
spawnGem(e.x, e.y);
}
// Set magnet drop rate to 5% (1 in 20 chance)
if (Math.random() < 0.05) {
spawnMagnetPowerup(e.x, e.y);
}
// Yeni: normal düşman öldüğünde kalp powerup düşürme (10% şans)
if (Math.random() < 0.1) {
spawnHeartPowerup(e.x, e.y);
}
e.destroy();
enemies.splice(j, 1);
}
b.pierce -= 1;
// Ricochet logic: if bullet has ricochetLeft, bounce to nearest enemy
if (typeof b.ricochetLeft !== "undefined" && b.ricochetLeft > 0 && enemies.length > 1) {
// Find nearest enemy that is not the one just hit
var minDist = 99999;
var nearest = null;
for (var ricI = 0; ricI < enemies.length; ricI++) {
var ricE = enemies[ricI];
// Exclude the just-hit enemy and any already-hit enemies
if (ricE === e) {
continue;
}
if (b._hitEnemies && b._hitEnemies.indexOf(ricE) !== -1) {
continue;
}
var d = dist2(b, ricE);
if (d < minDist) {
minDist = d;
nearest = ricE;
}
}
if (nearest) {
// Ricochet: set bullet position to current, aim at nearest enemy
var dx = nearest.x - b.x;
var dy = nearest.y - b.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist > 0) {
b.dirX = dx / dist;
b.dirY = dy / dist;
b.rotation = Math.atan2(b.dirY, b.dirX);
b.ricochetLeft--;
// Don't destroy or remove bullet, let it continue
// Restore pierce for next hit
b.pierce = Math.max(1, Bullet.prototype.pierce || 1);
// Move bullet slightly toward new direction to avoid instant re-collision
b.x += b.dirX * 10;
b.y += b.dirY * 10;
continue;
}
}
}
// If no ricochet, destroy as normal
if (b.pierce <= 0) {
b.destroy();
bullets.splice(i, 1);
}
break;
}
}
}
for (var i = gems.length - 1; i >= 0; i--) {
var g = gems[i];
// Set XP gem attraction area to 800 pixels when magnet is active, otherwise 150
var xpAttractRange = hero.magnetActive ? 800 : 150;
var d = dist2(g, hero);
if (d < xpAttractRange) {
var dx = hero.x - g.x;
var dy = hero.y - g.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist > 0) {
g.x += dx / dist * 18;
g.y += dy / dist * 18;
}
}
if (dist2(g, hero) < g.radius + hero.radius) {
// Big XP gem gives 5 XP, normal gives 1
if (g.type === 'big') {
xp += 5;
} else {
xp += 1;
}
g.destroy();
gems.splice(i, 1);
if (xp >= xpToLevel) {
level += 1;
xp = 0;
// Easier XP curve: gentler growth for faster level up
xpToLevel = 8 + level * 5 + Math.floor(level * level * 0.7);
LK.effects.flashObject(hero, 0xf7e967, 600);
// On level up, spawn a big XP gem near hero
spawnGem(hero.x + (Math.random() - 0.5) * 200, hero.y + (Math.random() - 0.5) * 200, {
type: 'big'
});
// Pause game and show level up popup with two options
// Remove any previous popup if present
if (typeof levelUpPopup !== "undefined" && levelUpPopup && levelUpPopup.parent) {
levelUpPopup.parent.removeChild(levelUpPopup);
levelUpPopup = null;
}
// Freeze all game logic and input
game._levelUpFrozen = true;
// Create popup container
var levelUpPopup = new Container();
// Dim background (match start popup)
var bg = LK.getAsset('centerCircle', {
anchorX: 0.5,
anchorY: 0.5,
color: 0x39FF14 // brighter green (popup background)
});
bg.width = 1100;
bg.height = 1500;
bg.alpha = 0.92;
bg.x = centerX;
bg.y = centerY;
// Removed outline (LK.effects.outline not supported)
levelUpPopup.addChild(bg);
// Title (match start popup style)
var titleTxt = new Text2('Level Up!', {
size: 90,
fill: "#fff",
font: "Montserrat"
});
titleTxt.anchor.set(0.5, 0);
titleTxt.x = centerX;
titleTxt.y = centerY - 550;
levelUpPopup.addChild(titleTxt);
// Option vertical layout (match start popup)
var optionStartY = centerY - 320;
var optionSpacing = 220;
// Option 1: Permanent Attack Speed Boost
var opt1 = new Container();
var opt1Bg = LK.getAsset('centerCircle', {
anchorX: 0.5,
anchorY: 0.5,
color: 0x006400 // even darker green (option background)
});
opt1Bg.width = 800;
opt1Bg.height = 160;
opt1Bg.alpha = 0.98;
opt1Bg.x = centerX;
opt1Bg.y = optionStartY;
// Removed outline (LK.effects.outline not supported)
opt1.addChild(opt1Bg);
var opt1Txt = new Text2('Attack Speed', {
size: 54,
fill: 0xF7E967,
font: "Montserrat"
});
opt1Txt.anchor.set(0.5, 0.5);
opt1Txt.x = centerX;
opt1Txt.y = optionStartY - 25;
opt1.addChild(opt1Txt);
var opt1Desc = new Text2('Fire faster every level!', {
size: 40,
fill: "#fff",
font: "Montserrat"
});
opt1Desc.anchor.set(0.5, 0.5);
opt1Desc.x = centerX;
opt1Desc.y = optionStartY + 35;
opt1.addChild(opt1Desc);
opt1.interactive = true;
opt1.down = function (x, y, obj) {
autoAttackInterval = Math.max(6, autoAttackInterval - 12);
if (levelUpPopup && levelUpPopup.parent) {
levelUpPopup.parent.removeChild(levelUpPopup);
levelUpPopup = null;
}
game._levelUpFrozen = false;
};
levelUpPopup.addChild(opt1);
// Option 2: Ricochet bullet
var opt2 = new Container();
var opt2Bg = LK.getAsset('centerCircle', {
anchorX: 0.5,
anchorY: 0.5,
color: 0x006400 // even darker green (option background)
});
opt2Bg.width = 800;
opt2Bg.height = 160;
opt2Bg.alpha = 0.98;
opt2Bg.x = centerX;
opt2Bg.y = optionStartY + optionSpacing;
// Removed outline (LK.effects.outline not supported)
opt2.addChild(opt2Bg);
var ricochetText = 'Ricochet';
if (typeof Bullet.prototype.ricochet !== "undefined" && Bullet.prototype.ricochet >= 1) {
ricochetText = 'Ricochet +1 bounce';
}
var opt2Txt = new Text2(ricochetText, {
size: 54,
fill: 0x7BE495,
font: "Montserrat"
});
opt2Txt.anchor.set(0.5, 0.5);
opt2Txt.x = centerX;
opt2Txt.y = optionStartY + optionSpacing - 25;
opt2.addChild(opt2Txt);
var opt2Desc = new Text2('Bullets bounce to another enemy', {
size: 40,
fill: "#fff",
font: "Montserrat"
});
opt2Desc.anchor.set(0.5, 0.5);
opt2Desc.x = centerX;
opt2Desc.y = optionStartY + optionSpacing + 35;
opt2.addChild(opt2Desc);
opt2.interactive = true;
opt2.down = function (x, y, obj) {
if (typeof Bullet.prototype.ricochet === "undefined" || Bullet.prototype.ricochet < 1) {
Bullet.prototype.ricochet = 1;
} else {
Bullet.prototype.ricochet += 1;
}
if (levelUpPopup && levelUpPopup.parent) {
levelUpPopup.parent.removeChild(levelUpPopup);
levelUpPopup = null;
}
game._levelUpFrozen = false;
};
levelUpPopup.addChild(opt2);
// Option 3: +1 Bullet (spread shot)
var opt3 = new Container();
var opt3Bg = LK.getAsset('centerCircle', {
anchorX: 0.5,
anchorY: 0.5,
color: 0x006400 // even darker green (option background)
});
opt3Bg.width = 800;
opt3Bg.height = 160;
opt3Bg.alpha = 0.98;
opt3Bg.x = centerX;
opt3Bg.y = optionStartY + optionSpacing * 2;
// Removed outline (LK.effects.outline not supported)
opt3.addChild(opt3Bg);
var opt3Txt = new Text2('Bullet +1', {
size: 54,
fill: 0xFFB347,
font: "Montserrat"
});
opt3Txt.anchor.set(0.5, 0.5);
opt3Txt.x = centerX;
opt3Txt.y = optionStartY + optionSpacing * 2 - 25;
opt3.addChild(opt3Txt);
var opt3Desc = new Text2('Shoot more bullets at once', {
size: 40,
fill: "#fff",
font: "Montserrat"
});
opt3Desc.anchor.set(0.5, 0.5);
opt3Desc.x = centerX;
opt3Desc.y = optionStartY + optionSpacing * 2 + 35;
opt3.addChild(opt3Desc);
opt3.interactive = true;
opt3.down = function (x, y, obj) {
if (typeof Bullet.prototype.extraBullets === "undefined") {
Bullet.prototype.extraBullets = 1;
} else {
Bullet.prototype.extraBullets += 1;
}
if (levelUpPopup && levelUpPopup.parent) {
levelUpPopup.parent.removeChild(levelUpPopup);
levelUpPopup = null;
}
game._levelUpFrozen = false;
};
levelUpPopup.addChild(opt3);
// Option 4: Pierce +1
var opt4 = new Container();
var opt4Bg = LK.getAsset('centerCircle', {
anchorX: 0.5,
anchorY: 0.5,
color: 0x006400 // even darker green (option background)
});
opt4Bg.width = 800;
opt4Bg.height = 160;
opt4Bg.alpha = 0.98;
opt4Bg.x = centerX;
opt4Bg.y = optionStartY + optionSpacing * 3;
// Removed outline (LK.effects.outline not supported)
opt4.addChild(opt4Bg);
var opt4Txt = new Text2('Pierce +1', {
size: 54,
fill: 0x7BE4FF,
font: "Montserrat"
});
opt4Txt.anchor.set(0.5, 0.5);
opt4Txt.x = centerX;
opt4Txt.y = optionStartY + optionSpacing * 3 - 25;
opt4.addChild(opt4Txt);
var opt4Desc = new Text2('Bullets pass through more enemies', {
size: 40,
fill: "#fff",
font: "Montserrat"
});
opt4Desc.anchor.set(0.5, 0.5);
opt4Desc.x = centerX;
opt4Desc.y = optionStartY + optionSpacing * 3 + 35;
opt4.addChild(opt4Desc);
opt4.interactive = true;
opt4.down = function (x, y, obj) {
if (typeof Bullet.prototype.pierce === "undefined") {
Bullet.prototype.pierce = 2;
} else {
Bullet.prototype.pierce += 1;
}
if (levelUpPopup && levelUpPopup.parent) {
levelUpPopup.parent.removeChild(levelUpPopup);
levelUpPopup = null;
}
game._levelUpFrozen = false;
};
levelUpPopup.addChild(opt4);
// Option 5: Bullets can follow up enemies
var opt5 = new Container();
var opt5Bg = LK.getAsset('centerCircle', {
anchorX: 0.5,
anchorY: 0.5,
color: 0x006400 // even darker green (option background)
});
opt5Bg.width = 800;
opt5Bg.height = 160;
opt5Bg.alpha = 0.98;
opt5Bg.x = centerX;
opt5Bg.y = optionStartY + optionSpacing * 4;
// Removed outline (LK.effects.outline not supported)
opt5.addChild(opt5Bg);
var opt5Txt = new Text2('Missile', {
size: 54,
fill: 0xFF77FF,
font: "Montserrat"
});
opt5Txt.anchor.set(0.5, 0.5);
opt5Txt.x = centerX;
opt5Txt.y = optionStartY + optionSpacing * 4 - 25;
opt5.addChild(opt5Txt);
var opt5Desc = new Text2('Bullets home in on enemies', {
size: 40,
fill: "#fff",
font: "Montserrat"
});
opt5Desc.anchor.set(0.5, 0.5);
opt5Desc.x = centerX;
opt5Desc.y = optionStartY + optionSpacing * 4 + 35;
opt5.addChild(opt5Desc);
opt5.interactive = true;
opt5.down = function (x, y, obj) {
Bullet.prototype.homing = true;
if (levelUpPopup && levelUpPopup.parent) {
levelUpPopup.parent.removeChild(levelUpPopup);
levelUpPopup = null;
}
game._levelUpFrozen = false;
};
levelUpPopup.addChild(opt5);
// Add popup to game
game.addChild(levelUpPopup);
}
}
}
for (var i = powerups.length - 1; i >= 0; i--) {
var p = powerups[i];
// Powerup collection area: always 150px (not affected by magnet)
var powerupAttractRange = 150;
var d = dist2(p, hero);
// Attract powerups (magnet, heart, and others) if within hero's collection area (150px), but NOT by magnet effect
if (d < powerupAttractRange && d > p.radius + hero.radius) {
// Move powerup toward hero (gentle attraction)
var dx = hero.x - p.x;
var dy = hero.y - p.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist > 0) {
p.x += dx / dist * 10;
p.y += dy / dist * 10;
}
}
// Magnet powerup pickup radius (same as attract range)
if (p.isMagnet && d < p.radius + hero.radius) {
hero.magnetActive = true;
// Set magnetEndTick to 10 seconds (600 frames) from now, synchronized with game time
if (typeof ticksSurvived === "number") {
hero.magnetEndTick = ticksSurvived + 600;
hero.magnetDuration = 600;
} else {
hero.magnetEndTick = undefined;
hero.magnetDuration = 600;
}
hero._magnetGlowActive = false; // force re-apply blue glow in Hero.update
LK.effects.flashObject(hero, 0x00ffff, 800);
p.destroy();
powerups.splice(i, 1);
}
// Yeni: Kalp powerup toplama
else if (p.constructor === HeartPowerup && d < p.radius + hero.radius) {
heroLives++;
if (heroLives > 5) {
heroLives = 5;
}
livesTxt.setText('Lives: ' + heroLives);
p.destroy();
powerups.splice(i, 1);
}
// Diğer poweruplar için (şu an sadece magnet ve heart var)
else if (!p.isMagnet && !(p.constructor === HeartPowerup) && d < p.radius + hero.radius) {
// Pick up other powerups if needed (future-proof)
p.destroy();
powerups.splice(i, 1);
}
}
autoAttackTimer++;
if (autoAttackTimer >= autoAttackInterval) {
autoAttackTimer = 0;
var nearest = null,
minDist = 99999;
for (var i = 0; i < enemies.length; i++) {
var e = enemies[i];
var d = dist2(hero, e);
if (d < minDist) {
minDist = d;
nearest = e;
}
}
if (nearest) {
var dx = nearest.x - hero.x;
var dy = nearest.y - hero.y;
// Remove automatic extra bullets from level; now controlled by upgrade
if (typeof Bullet.prototype.extraBullets === "undefined") {
Bullet.prototype.extraBullets = 0;
}
var extraBullets = Bullet.prototype.extraBullets;
var totalBullets = 1 + extraBullets;
var spread;
var baseAngle = Math.atan2(dy, dx);
if (totalBullets % 2 === 0 && totalBullets > 1) {
// Even number of bullets: 2 center bullets go straight and parallel, others scatter
var centerIdx1 = totalBullets / 2 - 1;
var centerIdx2 = totalBullets / 2;
var offsetDist = 30;
var perpAngle = baseAngle + Math.PI / 2;
// Fire center two bullets parallel
for (var b = 0; b < totalBullets; b++) {
if (b === centerIdx1 || b === centerIdx2) {
// Parallel bullets
var offset = (b === centerIdx1 ? -1 : 1) * offsetDist / 2;
var bulletX = hero.x + Math.cos(perpAngle) * offset;
var bulletY = hero.y + Math.sin(perpAngle) * offset;
var dirX = Math.cos(baseAngle);
var dirY = Math.sin(baseAngle);
var bullet = new Bullet();
bullet.x = bulletX;
bullet.y = bulletY;
bullet.pierce = Bullet.prototype.pierce || 1;
bullet.dirX = dirX;
bullet.dirY = dirY;
bullet.rotation = baseAngle;
bullets.push(bullet);
game.addChild(bullet);
} else {
// Scattered bullets
// Calculate scatter index for non-center bullets
var scatterCount = totalBullets - 2;
var scatterIdx = b < centerIdx1 ? b : b - 2;
var scatterSpread = Math.PI / 32 + (level - 2) * Math.PI / 48;
if (scatterSpread > Math.PI / 4) {
scatterSpread = Math.PI / 4;
}
var angle = baseAngle;
if (scatterCount > 1) {
angle = baseAngle - scatterSpread / 2 + scatterSpread * scatterIdx / (scatterCount - 1);
}
var dirX = Math.cos(angle);
var dirY = Math.sin(angle);
fireBullet(dirX, dirY);
}
}
} else if (level > 2) {
spread = Math.PI / 32 + (level - 2) * Math.PI / 48;
if (spread > Math.PI / 4) {
spread = Math.PI / 4;
}
for (var b = 0; b < totalBullets; b++) {
var angle = baseAngle;
if (totalBullets > 1) {
angle = baseAngle - spread / 2 + spread * b / (totalBullets - 1);
}
var dirX = Math.cos(angle);
var dirY = Math.sin(angle);
fireBullet(dirX, dirY);
}
} else {
spread = Math.PI / 16;
for (var b = 0; b < totalBullets; b++) {
var angle = baseAngle;
if (totalBullets > 1) {
angle = baseAngle - spread / 2 + spread * b / (totalBullets - 1);
}
var dirX = Math.cos(angle);
var dirY = Math.sin(angle);
fireBullet(dirX, dirY);
}
}
} else {
var extraBullets = Math.max(0, level - 1);
var totalBullets = 1 + extraBullets;
var spread;
if (level === 2) {
spread = Math.PI / 32;
} else if (level > 2) {
spread = Math.PI / 32 + (level - 2) * Math.PI / 48;
if (spread > Math.PI / 4) {
spread = Math.PI / 4;
}
} else {
spread = Math.PI / 16;
}
var baseAngle = Math.random() * Math.PI * 2;
for (var b = 0; b < totalBullets; b++) {
var angle = baseAngle;
if (totalBullets > 1) {
angle = baseAngle - spread / 2 + spread * b / (totalBullets - 1);
}
var dirX = Math.cos(angle);
var dirY = Math.sin(angle);
fireBullet(dirX, dirY);
}
}
}
spawnTimer++;
if (spawnTimer >= spawnInterval) {
spawnTimer = 0;
var toSpawn = Math.max(1, Math.floor((1 + Math.floor(wave / 3)) / 4));
for (var i = 0; i < toSpawn; i++) {
spawnEnemy();
}
// Boss spawn logic: spawn boss every 30 waves
if (typeof bossSpawnedWaves === "undefined") {
bossSpawnedWaves = {};
}
if (wave % 30 === 0 && !bossSpawnedWaves[wave]) {
var boss = new BossEnemy();
// Spawn boss at a random edge
var edge = Math.floor(Math.random() * 4);
if (edge === 0) {
boss.x = Math.random() * 2048;
boss.y = -200;
} else if (edge === 1) {
boss.x = 2048 + 200;
boss.y = Math.random() * 2732;
} else if (edge === 2) {
boss.x = Math.random() * 2048;
boss.y = 2732 + 200;
} else {
boss.x = -200;
boss.y = Math.random() * 2732;
}
enemies.push(boss);
game.addChild(boss);
bossSpawnedWaves[wave] = true;
}
wave++;
spawnInterval = Math.max(24, 90 - Math.floor(wave / 2));
}
ticksSurvived++;
scoreTxt.setText('Score: ' + Math.floor(ticksSurvived / 60));
xpTxt.setText('XP: ' + xp + '/' + xpToLevel);
levelTxt.setText('Level: ' + level);
var totalSeconds = Math.floor(ticksSurvived / 60);
var minutes = Math.floor(totalSeconds / 60);
var seconds = totalSeconds % 60;
var minStr = minutes < 10 ? '0' + minutes : '' + minutes;
var secStr = seconds < 10 ? '0' + seconds : '' + seconds;
timerTxt.setText(minStr + ':' + secStr);
// Only reset heroLives and livesTxt on game restart, not every frame
if (lastGameOver && hero && hero.parent) {
lastGameOver = false;
heroLives = 5;
if (heroLives > 5) {
heroLives = 5;
}
if (livesTxt) {
livesTxt.setText('Lives: ' + heroLives);
}
}
// Magnet timer display
if (hero.magnetActive && hero.magnetDuration > 0) {
var magnetSeconds = Math.ceil(hero.magnetDuration / 60);
magnetTimerTxt.setText('Magnet: ' + magnetSeconds + 's');
} else {
magnetTimerTxt.setText('');
}
}; ===================================================================
--- original.js
+++ change.js
@@ -410,9 +410,9 @@
var opt1 = new Container();
var opt1Bg = LK.getAsset('centerCircle', {
anchorX: 0.5,
anchorY: 0.5,
- color: 0x008000 // darker green (option background)
+ color: 0x006400 // even darker green (option background)
});
opt1Bg.width = 800;
opt1Bg.height = 160;
opt1Bg.alpha = 0.98;
@@ -454,9 +454,9 @@
var opt2 = new Container();
var opt2Bg = LK.getAsset('centerCircle', {
anchorX: 0.5,
anchorY: 0.5,
- color: 0x008000 // darker green (option background)
+ color: 0x006400 // even darker green (option background)
});
opt2Bg.width = 800;
opt2Bg.height = 160;
opt2Bg.alpha = 0.98;
@@ -496,9 +496,9 @@
var opt3 = new Container();
var opt3Bg = LK.getAsset('centerCircle', {
anchorX: 0.5,
anchorY: 0.5,
- color: 0x008000 // darker green (option background)
+ color: 0x006400 // even darker green (option background)
});
opt3Bg.width = 800;
opt3Bg.height = 160;
opt3Bg.alpha = 0.98;
@@ -538,9 +538,9 @@
var opt4 = new Container();
var opt4Bg = LK.getAsset('centerCircle', {
anchorX: 0.5,
anchorY: 0.5,
- color: 0x008000 // darker green (option background)
+ color: 0x006400 // even darker green (option background)
});
opt4Bg.width = 800;
opt4Bg.height = 160;
opt4Bg.alpha = 0.98;
@@ -580,9 +580,9 @@
var opt5 = new Container();
var opt5Bg = LK.getAsset('centerCircle', {
anchorX: 0.5,
anchorY: 0.5,
- color: 0x008000 // darker green (option background)
+ color: 0x006400 // even darker green (option background)
});
opt5Bg.width = 800;
opt5Bg.height = 160;
opt5Bg.alpha = 0.98;
@@ -1055,9 +1055,9 @@
var opt1 = new Container();
var opt1Bg = LK.getAsset('centerCircle', {
anchorX: 0.5,
anchorY: 0.5,
- color: 0x008000 // darker green (option background)
+ color: 0x006400 // even darker green (option background)
});
opt1Bg.width = 800;
opt1Bg.height = 160;
opt1Bg.alpha = 0.98;
@@ -1097,9 +1097,9 @@
var opt2 = new Container();
var opt2Bg = LK.getAsset('centerCircle', {
anchorX: 0.5,
anchorY: 0.5,
- color: 0x008000 // darker green (option background)
+ color: 0x006400 // even darker green (option background)
});
opt2Bg.width = 800;
opt2Bg.height = 160;
opt2Bg.alpha = 0.98;
@@ -1147,9 +1147,9 @@
var opt3 = new Container();
var opt3Bg = LK.getAsset('centerCircle', {
anchorX: 0.5,
anchorY: 0.5,
- color: 0x008000 // darker green (option background)
+ color: 0x006400 // even darker green (option background)
});
opt3Bg.width = 800;
opt3Bg.height = 160;
opt3Bg.alpha = 0.98;
@@ -1193,9 +1193,9 @@
var opt4 = new Container();
var opt4Bg = LK.getAsset('centerCircle', {
anchorX: 0.5,
anchorY: 0.5,
- color: 0x008000 // darker green (option background)
+ color: 0x006400 // even darker green (option background)
});
opt4Bg.width = 800;
opt4Bg.height = 160;
opt4Bg.alpha = 0.98;
@@ -1239,9 +1239,9 @@
var opt5 = new Container();
var opt5Bg = LK.getAsset('centerCircle', {
anchorX: 0.5,
anchorY: 0.5,
- color: 0x008000 // darker green (option background)
+ color: 0x006400 // even darker green (option background)
});
opt5Bg.width = 800;
opt5Bg.height = 160;
opt5Bg.alpha = 0.98;
16x16 pixel wounded guy holding pistol. In-Game asset. 2d. High contrast. No shadows. pixel art. retro arcade game
3x3 pixel green coin. In-Game asset. 2d. High contrast. No shadows. retro arcade. Pixel art
3x3 pixel blue coin. In-Game asset. 2d. High contrast. No shadows. Pixel art. retro arcade
4x4 pixel art heart. In-Game asset. 2d. High contrast. No shadows. retro arcade. Pixel art. 8 bit
fill the circle with yellow colour
remove cars and buildings
Create an 8-bit style effect representing a magnetic power-up area. The effect should be a circular, glowing field with a soft, pulsing light. The colors should be green and blue, with a slight gradient effect to indicate the area where objects (such as coins or experience points) are attracted towards the character. The circle should have a subtle flicker to show the magnetic pull, and it should be designed to fit within the retro, pixel-art aesthetic of an 8-bit game. In-Game asset. 2d. High contrast. No shadows
Vertical windowed filled rectangle HUD for the 2d zombie theme game. Use green colours. Do not make it too much pixelated. In-Game asset. 2d. High contrast. No shadows. No text. No icon. No background Transparent.Retro arcade theme.
windowed filled rectangle HUD button for the 2d pixel art zombie theme game. Use dark green colours. In-Game asset. 2d. High contrast. No shadows. No text. No icon. No background Transparent.Retro arcade theme.
pixelart magnet In-Game asset. 2d. High contrast. No shadows. Pixel art
pixelart red circular enemy projectile to dodge In-Game asset. 2d. High contrast. No shadows. Pixel art
pixelart yellow circular bullet to shoot enemies In-Game asset. 2d. High contrast. No shadows. Pixel art
pixelart blue circular enemy projectile to dodge In-Game asset. 2d. High contrast. No shadows. Pixel art
4x4pixel bow and arrow. In-Game asset. 2d. High contrast. No shadows. Black outline
8x8 pixel movement speed powerup icon. boot with wings. In-Game asset. 2d. High contrast. No shadows. Black outline