/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var Anime = Container.expand(function () {
var self = Container.call(this);
var animeGraphics = self.attachAsset('Enemy', {
anchorX: 0.5,
anchorY: 0.5,
tint: 0xffccff
});
self.health = 150;
self.speed = 6;
self.specialAttackCooldown = 0;
self.specialAttackInterval = 180; // 3 seconds
self.powerLevel = 0;
self.glowActive = false;
self.auraSize = 1.0;
self.update = function () {
// Special movement pattern - more dynamic than regular enemies
self.x += Math.sin(LK.ticks * 0.05) * self.speed * 0.5;
self.y += Math.cos(LK.ticks * 0.03) * self.speed * 0.3;
// Boundary checking
if (self.x < 50) self.x = 50;
if (self.x > GAME_WIDTH - 50) self.x = GAME_WIDTH - 50;
if (self.y < 50) self.y = 50;
if (self.y > GAME_HEIGHT - 50) self.y = GAME_HEIGHT - 50;
// Special attack cooldown
self.specialAttackCooldown++;
if (self.specialAttackCooldown >= self.specialAttackInterval) {
self.useSpecialAttack();
self.specialAttackCooldown = 0;
}
if (self.glowActive) {
self.auraSize = 1.0 + 0.2 * Math.sin(LK.ticks * 0.1);
animeGraphics.scale.set(self.auraSize, self.auraSize);
animeGraphics.rotation += 0.02;
animeGraphics.tint = 0xffccff + (Math.floor(Math.sin(LK.ticks * 0.05) * 127) << 16);
}
};
self.useSpecialAttack = function () {
self.glowActive = true;
LK.effects.flashObject(self, 0xffffff, 500);
// Create energy burst effect
for (var i = 0; i < 8; i++) {
var angle = Math.PI * 2 * (i / 8);
var ghost = LK.getAsset('Enemy', {
anchorX: 0.5,
anchorY: 0.5,
tint: 0xffccff,
alpha: 0.7,
scale: 0.5
});
ghost.x = self.x + Math.cos(angle) * 50;
ghost.y = self.y + Math.sin(angle) * 50;
game.addChild(ghost);
// Animate the energy burst
tween(ghost, {
alpha: 0,
scale: 2,
x: ghost.x + Math.cos(angle) * 200,
y: ghost.y + Math.sin(angle) * 200
}, {
duration: 1000,
easing: tween.easeOut,
onComplete: function onComplete() {
ghost.destroy();
}
});
}
// Disable glow after a while
LK.setTimeout(function () {
self.glowActive = false;
animeGraphics.scale.set(1.0, 1.0);
animeGraphics.tint = 0xffccff;
}, 2000);
};
self.powerUp = function () {
self.powerLevel++;
self.speed += 0.5;
animeGraphics.tint = 0xff00ff;
LK.effects.flashObject(self, 0xffffff, 1000);
// Make the anime character larger with each power up
animeGraphics.scale.set(1.0 + self.powerLevel * 0.1, 1.0 + self.powerLevel * 0.1);
};
return self;
});
var DebugPower = Container.expand(function () {
var self = Container.call(this);
var powerGraphics = self.attachAsset('debugPowerShape', {
anchorX: 0.5,
anchorY: 0.5
});
self.rotateSpeed = 0.03;
self.update = function () {
// Rotate continuously
powerGraphics.rotation += self.rotateSpeed;
};
return self;
});
var Dummy1 = Container.expand(function () {
var self = Container.call(this);
var dummyGraphics = self.attachAsset('Dummy1', {
anchorX: 0.5,
anchorY: 0.5
});
// Dummy1 properties and methods
self.speed = 5;
self.targetEnemy = null;
self.attackDamage = 20;
self.attackRange = 150;
self.update = function () {
// Find the nearest enemy
self.targetEnemy = findNearestEnemy(self.x, self.y);
if (self.targetEnemy) {
// Move towards the target enemy
var dx = self.targetEnemy.x - self.x;
var dy = self.targetEnemy.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > self.speed) {
var ratio = self.speed / distance;
self.x += dx * ratio;
self.y += dy * ratio;
} else {
self.x = self.targetEnemy.x;
self.y = self.targetEnemy.y;
}
// Check if within attack range
if (distance < self.attackRange) {
attackEnemy(self.targetEnemy, self.attackDamage);
}
}
};
return self;
});
var Enemy = Container.expand(function () {
var self = Container.call(this);
var enemyGraphics = self.attachAsset('enemyShape', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 3 + Math.random() * 2;
self.moveAngle = Math.random() * Math.PI * 2;
self.changeDirectionTimer = 0;
self.changeDirectionInterval = 60 + Math.floor(Math.random() * 60);
self.damage = 10;
self.update = function () {
// Change direction occasionally
self.changeDirectionTimer++;
if (self.changeDirectionTimer >= self.changeDirectionInterval) {
self.moveAngle = Math.random() * Math.PI * 2;
self.changeDirectionTimer = 0;
self.changeDirectionInterval = 60 + Math.floor(Math.random() * 60);
}
// Move in current direction
self.x += Math.cos(self.moveAngle) * self.speed;
self.y += Math.sin(self.moveAngle) * self.speed;
// Bounce off walls
if (self.x < 50) {
self.x = 50;
self.moveAngle = Math.PI - self.moveAngle;
} else if (self.x > 2048 - 50) {
self.x = 2048 - 50;
self.moveAngle = Math.PI - self.moveAngle;
}
if (self.y < 50) {
self.y = 50;
self.moveAngle = -self.moveAngle;
} else if (self.y > 2732 - 50) {
self.y = 2732 - 50;
self.moveAngle = -self.moveAngle;
}
// Add a glitchy rotation
enemyGraphics.rotation += 0.05;
};
return self;
});
var Enemy2 = Container.expand(function () {
var self = Container.call(this);
var enemyGraphics = self.attachAsset('Enemy2', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 75; // More health than regular enemy
self.speed = 2; // Slower than regular enemy
self.moveAngle = Math.random() * Math.PI * 2;
self.changeDirectionTimer = 0;
self.changeDirectionInterval = 120 + Math.floor(Math.random() * 60); // Changes direction less frequently
self.damage = 20; // Does more damage than regular enemy
self.update = function () {
// Change direction occasionally
self.changeDirectionTimer++;
if (self.changeDirectionTimer >= self.changeDirectionInterval) {
self.moveAngle = Math.random() * Math.PI * 2;
self.changeDirectionTimer = 0;
self.changeDirectionInterval = 120 + Math.floor(Math.random() * 60);
}
// Move in current direction
self.x += Math.cos(self.moveAngle) * self.speed;
self.y += Math.sin(self.moveAngle) * self.speed;
// Bounce off walls
if (self.x < 50) {
self.x = 50;
self.moveAngle = Math.PI - self.moveAngle;
} else if (self.x > 2048 - 50) {
self.x = 2048 - 50;
self.moveAngle = Math.PI - self.moveAngle;
}
if (self.y < 50) {
self.y = 50;
self.moveAngle = -self.moveAngle;
} else if (self.y > 2732 - 50) {
self.y = 2732 - 50;
self.moveAngle = -self.moveAngle;
}
// Special rotation effect
enemyGraphics.rotation += 0.01;
// Pulse effect
if (LK.ticks % 60 < 30) {
enemyGraphics.scale.set(1.1, 1.1);
} else {
enemyGraphics.scale.set(1, 1);
}
};
return self;
});
var Enemy3 = Container.expand(function () {
var self = Container.call(this);
var enemyGraphics = self.attachAsset('Enemy', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 100; // Highest health of all enemies
self.speed = 1.5; // Slowest but most dangerous
self.moveAngle = Math.random() * Math.PI * 2;
self.changeDirectionTimer = 0;
self.changeDirectionInterval = 150 + Math.floor(Math.random() * 60); // Changes direction rarely
self.damage = 25; // Highest damage
self.update = function () {
// Change direction occasionally
self.changeDirectionTimer++;
if (self.changeDirectionTimer >= self.changeDirectionInterval) {
self.moveAngle = Math.random() * Math.PI * 2;
self.changeDirectionTimer = 0;
self.changeDirectionInterval = 150 + Math.floor(Math.random() * 60);
}
// Move in current direction
self.x += Math.cos(self.moveAngle) * self.speed;
self.y += Math.sin(self.moveAngle) * self.speed;
// Bounce off walls
if (self.x < 50) {
self.x = 50;
self.moveAngle = Math.PI - self.moveAngle;
} else if (self.x > 2048 - 50) {
self.x = 2048 - 50;
self.moveAngle = Math.PI - self.moveAngle;
}
if (self.y < 50) {
self.y = 50;
self.moveAngle = -self.moveAngle;
} else if (self.y > 2732 - 50) {
self.y = 2732 - 50;
self.moveAngle = -self.moveAngle;
}
// Special effect - slowly rotate and pulse with a red glow
enemyGraphics.rotation += 0.015;
if (LK.ticks % 90 < 45) {
enemyGraphics.tint = 0xff3333;
} else {
enemyGraphics.tint = 0xffffff;
}
};
return self;
});
var Enemy4 = Container.expand(function () {
var self = Container.call(this);
var enemyGraphics = self.attachAsset('Enemy', {
anchorX: 0.5,
anchorY: 0.5,
tint: 0x66ffcc
});
self.health = 60;
self.speed = 4; // Faster than most enemies
self.moveAngle = Math.random() * Math.PI * 2;
self.changeDirectionTimer = 0;
self.changeDirectionInterval = 40 + Math.floor(Math.random() * 30); // Changes direction frequently
self.damage = 15;
self.teleportTimer = 0;
self.teleportInterval = 180; // Teleport every ~3 seconds
self.update = function () {
// Teleportation ability
self.teleportTimer++;
if (self.teleportTimer >= self.teleportInterval) {
// Teleport to a random location near the edge
var edgeChoice = Math.floor(Math.random() * 4);
switch (edgeChoice) {
case 0:
// Top edge
self.x = 100 + Math.random() * (GAME_WIDTH - 200);
self.y = 100;
break;
case 1:
// Right edge
self.x = GAME_WIDTH - 100;
self.y = 100 + Math.random() * (GAME_HEIGHT - 200);
break;
case 2:
// Bottom edge
self.x = 100 + Math.random() * (GAME_WIDTH - 200);
self.y = GAME_HEIGHT - 100;
break;
case 3:
// Left edge
self.x = 100;
self.y = 100 + Math.random() * (GAME_HEIGHT - 200);
break;
}
// Visual effect for teleportation
LK.effects.flashObject(self, 0x66ffcc, 300);
self.teleportTimer = 0;
return; // Skip regular movement this frame
}
// Normal movement behavior
self.changeDirectionTimer++;
if (self.changeDirectionTimer >= self.changeDirectionInterval) {
self.moveAngle = Math.random() * Math.PI * 2;
self.changeDirectionTimer = 0;
self.changeDirectionInterval = 40 + Math.floor(Math.random() * 30);
}
// Move in current direction
self.x += Math.cos(self.moveAngle) * self.speed;
self.y += Math.sin(self.moveAngle) * self.speed;
// Bounce off walls
if (self.x < 50) {
self.x = 50;
self.moveAngle = Math.PI - self.moveAngle;
} else if (self.x > 2048 - 50) {
self.x = 2048 - 50;
self.moveAngle = Math.PI - self.moveAngle;
}
if (self.y < 50) {
self.y = 50;
self.moveAngle = -self.moveAngle;
} else if (self.y > 2732 - 50) {
self.y = 2732 - 50;
self.moveAngle = -self.moveAngle;
}
// Special visual effect - trail effect with alpha pulsing
if (LK.ticks % 3 === 0) {
var ghost = LK.getAsset('Enemy', {
anchorX: 0.5,
anchorY: 0.5,
tint: 0x66ffcc,
alpha: 0.3
});
ghost.x = self.x;
ghost.y = self.y;
game.addChild(ghost);
// Fade out and remove the ghost
tween(ghost, {
alpha: 0,
scale: 0.5
}, {
duration: 500,
easing: tween.easeOut,
onComplete: function onComplete() {
ghost.destroy();
}
});
}
};
return self;
});
var Enemyshape2 = Container.expand(function () {
var self = Container.call(this);
var enemyGraphics = self.attachAsset('Enemyshape2', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 50; // Example health
self.speed = 2 + Math.random() * 1;
self.moveAngle = Math.random() * Math.PI * 2;
self.changeDirectionTimer = 0;
self.changeDirectionInterval = 90 + Math.floor(Math.random() * 90);
self.damage = 15;
self.update = function () {
// Change direction occasionally
self.changeDirectionTimer++;
if (self.changeDirectionTimer >= self.changeDirectionInterval) {
self.moveAngle = Math.random() * Math.PI * 2;
self.changeDirectionTimer = 0;
self.changeDirectionInterval = 90 + Math.floor(Math.random() * 90);
}
// Move in current direction
self.x += Math.cos(self.moveAngle) * self.speed;
self.y += Math.sin(self.moveAngle) * self.speed;
// Bounce off walls
if (self.x < 50) {
self.x = 50;
self.moveAngle = Math.PI - self.moveAngle;
} else if (self.x > 2048 - 50) {
self.x = 2048 - 50;
self.moveAngle = Math.PI - self.moveAngle;
}
if (self.y < 50) {
self.y = 50;
self.moveAngle = -self.moveAngle;
} else if (self.y > 2732 - 50) {
self.y = 2732 - 50;
self.moveAngle = -self.moveAngle;
}
// Rotate slowly
enemyGraphics.rotation += 0.02;
};
return self;
});
var GlitchWall = Container.expand(function () {
var self = Container.call(this);
var wallGraphics = self.attachAsset('glitchWall', {
anchorX: 0.5,
anchorY: 0.5
});
self.glitchTimer = 0;
self.glitchInterval = 10;
self.update = function () {
// Visual glitch effect
self.glitchTimer++;
if (self.glitchTimer % self.glitchInterval === 0) {
// Random color shifts
wallGraphics.tint = Math.random() > 0.5 ? 0xff00ff : 0x00ffff;
// Random position shifts
wallGraphics.x = Math.random() * 10 - 5;
wallGraphics.y = Math.random() * 10 - 5;
}
if (self.glitchTimer >= 60) {
self.glitchTimer = 0;
wallGraphics.x = 0;
wallGraphics.y = 0;
}
};
return self;
});
var PibbyGlitch = Container.expand(function () {
var self = Container.call(this);
// Create the glitch visual effect container
var glitchGraphics = self.attachAsset('pixelShape', {
anchorX: 0.5,
anchorY: 0.5,
tint: 0xff00ff
});
// Properties for glitch effect
self.glitchIntensity = 0;
self.maxIntensity = 100;
self.affectedArea = 150;
self.glitchTimer = 0;
self.updateInterval = 2;
self.isActive = true;
self.growthRate = 0.5;
// The pibby glitch update function
self.update = function () {
self.glitchTimer++;
// Only update visuals on certain frames for performance
if (self.glitchTimer % self.updateInterval === 0) {
// Random visual glitching
glitchGraphics.x = (Math.random() * 20 - 10) * (self.glitchIntensity / 50);
glitchGraphics.y = (Math.random() * 20 - 10) * (self.glitchIntensity / 50);
// Randomly change tint color for glitch effect
if (Math.random() > 0.6) {
glitchGraphics.tint = Math.random() > 0.5 ? 0xff00ff : 0x00ffff;
}
// Scale based on intensity
var scale = 0.5 + self.glitchIntensity / self.maxIntensity * 2;
glitchGraphics.scaleX = scale;
glitchGraphics.scaleY = scale;
// Slowly grow the glitch if active
if (self.isActive && self.glitchIntensity < self.maxIntensity) {
self.glitchIntensity += self.growthRate;
}
}
};
// Function to increase glitch intensity
self.intensify = function (amount) {
self.glitchIntensity = Math.min(self.maxIntensity, self.glitchIntensity + amount);
// Visual feedback with tween
tween(glitchGraphics, {
alpha: 0.8,
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 300,
easing: tween.easeOut,
onComplete: function onComplete() {
var newScale = 0.5 + self.glitchIntensity / self.maxIntensity * 2;
tween(glitchGraphics, {
alpha: 0.6,
scaleX: newScale,
scaleY: newScale
}, {
duration: 300,
easing: tween.easeIn
});
}
});
};
return self;
});
var Pixel = Container.expand(function () {
var self = Container.call(this);
var pixelGraphics = self.attachAsset('pixelShape', {
anchorX: 0.5,
anchorY: 0.5
});
// Add a pulsing animation
self.pulseDirection = 1;
self.pulseSpeed = 0.02;
self.baseScale = 1;
self.update = function () {
// Pulse effect
var scale = pixelGraphics.scale.x;
scale += self.pulseSpeed * self.pulseDirection;
if (scale > 1.2) {
scale = 1.2;
self.pulseDirection = -1;
} else if (scale < 0.8) {
scale = 0.8;
self.pulseDirection = 1;
}
pixelGraphics.scale.set(scale, scale);
};
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
var playerGraphics = self.attachAsset('playerShape', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 100;
self.speed = 8;
self.isMoving = false;
self.targetX = 0;
self.targetY = 0;
self.debugPower = 0;
self.isInvulnerable = false;
self.moveTowards = function (targetX, targetY) {
self.isMoving = true;
self.targetX = targetX;
self.targetY = targetY;
};
self.stopMoving = function () {
self.isMoving = false;
};
self.takeDamage = function (amount) {
if (!self.isInvulnerable) {
self.health -= amount;
LK.getSound('hurt').play();
self.isInvulnerable = true;
playerGraphics.alpha = 0.5;
// Flash effect
LK.effects.flashObject(self, 0xff0000, 300);
LK.setTimeout(function () {
self.isInvulnerable = false;
playerGraphics.alpha = 1.0;
}, 1500);
if (self.health <= 0) {
self.health = 0;
gameOver();
}
}
};
self.collectPixel = function () {
self.health = Math.min(100, self.health + 10);
LK.getSound('collect').play();
};
self.collectDebugPower = function () {
self.debugPower++;
LK.getSound('powerup').play();
};
self.useDebugPower = function () {
if (self.debugPower > 0) {
self.debugPower--;
return true;
}
return false;
};
self.update = function () {
if (self.isMoving) {
var dx = self.targetX - self.x;
var dy = self.targetY - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > self.speed) {
var ratio = self.speed / distance;
self.x += dx * ratio;
self.y += dy * ratio;
} else {
self.x = self.targetX;
self.y = self.targetY;
self.isMoving = false;
}
}
};
return self;
});
var Villager = Container.expand(function () {
var self = Container.call(this);
var villagerGraphics = self.attachAsset('Villager', {
anchorX: 0.5,
anchorY: 0.5
});
// Villager properties and methods
self.health = 50;
self.speed = 4;
self.isGlitching = false;
self.glitchTimer = 0;
self.fearRadius = 300; // Distance at which villager senses enemies
self.transformationTimer = 0;
self.update = function () {
if (self.isGlitching) {
// Handle glitching animation
self.glitchTimer++;
// Visual glitch effect
if (self.glitchTimer % 5 === 0) {
// Random color shifts
villagerGraphics.tint = Math.random() > 0.5 ? 0xff00ff : 0x00ffff;
// Random position shifts
villagerGraphics.x = Math.random() * 10 - 5;
villagerGraphics.y = Math.random() * 10 - 5;
// Increase transformation timer
self.transformationTimer++;
// After enough glitching, transform into enemy
if (self.transformationTimer >= 30) {
self.transformIntoEnemy();
return;
}
}
} else {
// Check for nearby Pibby glitches - these have priority over enemies
var nearestGlitch = null;
var shortestGlitchDistance = Infinity;
// Find the nearest pibby glitch
for (var i = 0; i < pibbyGlitches.length; i++) {
var glitch = pibbyGlitches[i];
var dx = glitch.x - self.x;
var dy = glitch.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
// If within affected area, start glitching immediately
if (distance < glitch.affectedArea * (glitch.glitchIntensity / 50)) {
// Start glitching process when in range of pibby glitch
self.startGlitching();
// Intensify the glitch
glitch.intensify(2);
break;
}
if (distance < shortestGlitchDistance) {
shortestGlitchDistance = distance;
nearestGlitch = glitch;
}
}
// If near a glitch but not yet glitching, run away from it
if (nearestGlitch && shortestGlitchDistance < self.fearRadius * 1.5 && !self.isGlitching) {
// Run away from glitch (higher priority than running from enemies)
var dx = self.x - nearestGlitch.x;
var dy = self.y - nearestGlitch.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
// Normalize and apply speed (run faster from glitches)
dx = dx / distance * (self.speed * 1.5);
dy = dy / distance * (self.speed * 1.5);
// Move away from glitch
self.x += dx;
self.y += dy;
// Keep within game boundaries
if (self.x < 50) self.x = 50;
if (self.x > GAME_WIDTH - 50) self.x = GAME_WIDTH - 50;
if (self.y < 50) self.y = 50;
if (self.y > GAME_HEIGHT - 50) self.y = GAME_HEIGHT - 50;
}
} else {
// Run away from nearby enemies
var nearestEnemy = null;
var shortestDistance = Infinity;
// Find the nearest enemy
for (var i = 0; i < enemies.length; i++) {
var enemy = enemies[i];
var dx = enemy.x - self.x;
var dy = enemy.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
// Check for enemy collision
if (self.intersects(enemy)) {
// Start glitching process when touched by enemy
self.startGlitching();
break;
}
if (distance < shortestDistance) {
shortestDistance = distance;
nearestEnemy = enemy;
}
}
// Run away if enemy is within fear radius
if (nearestEnemy && shortestDistance < self.fearRadius) {
// Calculate direction away from enemy
var dx = self.x - nearestEnemy.x;
var dy = self.y - nearestEnemy.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
// Normalize and apply speed
dx = dx / distance * self.speed;
dy = dy / distance * self.speed;
// Move away from enemy
self.x += dx;
self.y += dy;
// Keep within game boundaries
if (self.x < 50) self.x = 50;
if (self.x > GAME_WIDTH - 50) self.x = GAME_WIDTH - 50;
if (self.y < 50) self.y = 50;
if (self.y > GAME_HEIGHT - 50) self.y = GAME_HEIGHT - 50;
}
}
}
}
};
self.startGlitching = function () {
if (!self.isGlitching) {
self.isGlitching = true;
self.glitchTimer = 0;
self.transformationTimer = 0;
// Visual feedback with tween
tween(villagerGraphics, {
alpha: 0.5
}, {
duration: 300,
easing: tween.easeInOut
});
// Play sound effect
LK.getSound('hurt').play();
}
};
self.transformIntoEnemy = function () {
// Check if any nearby Pibby glitches to determine what enemy type to spawn
var nearbyGlitch = false;
var strongestGlitch = null;
for (var i = 0; i < pibbyGlitches.length; i++) {
var glitch = pibbyGlitches[i];
var dx = glitch.x - self.x;
var dy = glitch.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < glitch.affectedArea) {
nearbyGlitch = true;
if (!strongestGlitch || glitch.glitchIntensity > strongestGlitch.glitchIntensity) {
strongestGlitch = glitch;
}
}
}
// Create a new enemy at the villager's position - stronger enemy if near glitch
var newEnemy;
if (nearbyGlitch) {
// Higher chance of stronger enemies when near a glitch
var enemyRoll = Math.random();
if (enemyRoll < 0.4) {
newEnemy = new Enemy3(); // Stronger enemy
} else if (enemyRoll < 0.7) {
newEnemy = new Enemy2();
} else if (enemyRoll < 0.9) {
newEnemy = new Enemy4(); // Teleporting enemy
} else {
newEnemy = new Anime(); // Rare chance for anime character
}
// Intensify the nearby glitch
if (strongestGlitch) {
strongestGlitch.intensify(10);
}
} else {
// Normal enemy spawn probability
newEnemy = Math.random() < 0.5 ? new Enemy() : new Enemyshape2();
}
newEnemy.x = self.x;
newEnemy.y = self.y;
game.addChild(newEnemy);
enemies.push(newEnemy);
// Visual effect
LK.effects.flashObject(newEnemy, 0xff00ff, 500);
// Remove villager
var index = villagers.indexOf(self);
if (index !== -1) {
villagers.splice(index, 1);
}
self.destroy();
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000033
});
/****
* Game Code
****/
// Game constants
var GAME_WIDTH = 2048;
var GAME_HEIGHT = 2732;
var MAX_ENEMIES = 15;
var MAX_PIXELS = 10;
var MAX_WALLS = 8;
var MAX_DEBUG_POWERS = 3;
var CORRUPTION_INTERVAL = 10000; // 10 seconds
var LEVEL_UP_SCORE = 10;
// Game variables
var villagers = []; // Array to hold villagers
var player;
var pixels = [];
var enemies = [];
var walls = [];
var debugPowers = [];
var pibbyGlitches = []; // Array to hold pibby glitch instances
var score = 0;
var level = 1;
var corruptionLevel = 0;
var gameActive = true;
var lastCorruptionTime = 0;
var lastGlitchSpawn = 0;
var pibbyGlitchChance = 0.1; // Base chance of spawning a glitch
var pibbySpawnInterval = 5000; // 5 seconds
var dummy1; // Add dummy1 variable
// UI elements
var scoreText;
var healthBar;
var healthBarBg;
var levelText;
var debugPowerText;
var corruptionText;
// Initialize game elements
function initializeGame() {
// Clear existing elements if needed
clearGameElements();
// Create player
player = new Player();
player.x = GAME_WIDTH / 2;
player.y = GAME_HEIGHT - 200;
game.addChild(player);
// Create Dummy1
dummy1 = new Dummy1();
dummy1.x = GAME_WIDTH / 2 - 150; // Position Dummy1 near the player
dummy1.y = GAME_HEIGHT - 200;
game.addChild(dummy1);
// Initialize UI
createUI();
// Generate initial game objects
spawnPixels(MAX_PIXELS);
spawnWalls(level);
spawnDebugPowers(1);
spawnVillagers(5); // Spawn 5 villagers initially
// Start corruption process
lastCorruptionTime = Date.now();
// Reset game state
score = 0;
corruptionLevel = 0;
level = 1;
gameActive = true;
// Update UI
updateUI();
// Play background music
LK.playMusic('gameTheme');
}
function clearGameElements() {
// Remove all existing game elements
if (player) {
player.destroy();
player = null;
}
if (dummy1) {
// Clear Dummy1
dummy1.destroy();
dummy1 = null;
}
for (var i = 0; i < pixels.length; i++) {
pixels[i].destroy();
}
pixels = [];
for (var i = 0; i < enemies.length; i++) {
enemies[i].destroy();
}
enemies = [];
for (var i = 0; i < walls.length; i++) {
walls[i].destroy();
}
walls = [];
for (var i = 0; i < debugPowers.length; i++) {
debugPowers[i].destroy();
}
debugPowers = [];
// Clear pibby glitches
for (var i = 0; i < pibbyGlitches.length; i++) {
pibbyGlitches[i].destroy();
}
pibbyGlitches = [];
lastGlitchSpawn = 0;
pibbySpawnInterval = 5000;
}
for (var i = 0; i < villagers.length; i++) {
villagers[i].destroy();
}
villagers = [];
function createUI() {
// Score text
scoreText = new Text2('Score: 0', {
size: 60,
fill: 0xFFFFFF
});
scoreText.anchor.set(0, 0);
scoreText.x = 120;
scoreText.y = 50;
LK.gui.addChild(scoreText);
// Level text
levelText = new Text2('Level: 1', {
size: 60,
fill: 0xFFFFFF
});
levelText.anchor.set(0.5, 0);
levelText.x = GAME_WIDTH / 2;
levelText.y = 50;
LK.gui.addChild(levelText);
// Debug power counter
debugPowerText = new Text2('Debug Powers: 0', {
size: 60,
fill: 0xFFFF00
});
debugPowerText.anchor.set(1, 0);
debugPowerText.x = GAME_WIDTH - 120;
debugPowerText.y = 50;
LK.gui.addChild(debugPowerText);
// Health bar background
healthBarBg = LK.getAsset('playerShape', {
anchorX: 0,
anchorY: 0,
width: 400,
height: 30,
tint: 0x666666
});
healthBarBg.x = GAME_WIDTH / 2 - 200;
healthBarBg.y = 120;
LK.gui.addChild(healthBarBg);
// Health bar
healthBar = LK.getAsset('playerShape', {
anchorX: 0,
anchorY: 0,
width: 400,
height: 30,
tint: 0x00ff00
});
healthBar.x = GAME_WIDTH / 2 - 200;
healthBar.y = 120;
LK.gui.addChild(healthBar);
// Corruption text
corruptionText = new Text2('Corruption: 0%', {
size: 50,
fill: 0xFF00FF
});
corruptionText.anchor.set(0.5, 0);
corruptionText.x = GAME_WIDTH / 2;
corruptionText.y = 160;
LK.gui.addChild(corruptionText);
}
function updateUI() {
// Update score display
scoreText.setText('Score: ' + score);
// Update health bar
healthBar.width = player.health / 100 * 400;
healthBar.tint = player.health > 50 ? 0x00ff00 : player.health > 25 ? 0xffff00 : 0xff0000;
// Update level display
levelText.setText('Level: ' + level);
// Update debug power counter
debugPowerText.setText('Debug Powers: ' + player.debugPower);
// Update corruption display
corruptionText.setText('Corruption: ' + corruptionLevel + '%');
// Use setStyle instead of directly accessing style which is undefined
corruptionText.setStyle({
fill: corruptionLevel > 75 ? "#FF0000" : "#FF00FF"
});
}
function findNearestEnemy(x, y) {
var nearestEnemy = null;
var shortestDistance = Infinity;
for (var i = 0; i < enemies.length; i++) {
var enemy = enemies[i];
var dx = enemy.x - x;
var dy = enemy.y - y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < shortestDistance) {
shortestDistance = distance;
nearestEnemy = enemy;
}
}
return nearestEnemy;
}
function attackEnemy(enemy, damage) {
enemy.health -= damage; // Assuming enemies have a health property
if (enemy.health <= 0) {
enemy.destroy();
enemies.splice(enemies.indexOf(enemy), 1);
// Optionally, increase score or spawn something on enemy defeat
}
}
function spawnPixels(count) {
for (var i = 0; i < count; i++) {
var pixel = new Pixel();
pixel.x = 100 + Math.random() * (GAME_WIDTH - 200);
pixel.y = 100 + Math.random() * (GAME_HEIGHT - 200);
game.addChild(pixel);
pixels.push(pixel);
}
}
function spawnEnemies(count) {
for (var i = 0; i < count; i++) {
var enemy;
var enemyType = Math.random();
// Add a small chance to spawn anime character
if (enemyType < 0.1) {
// 10% chance to spawn anime character
enemy = new Anime();
// Make anime characters appear with special effect
LK.effects.flashObject(enemy, 0xffccff, 500);
} else if (enemyType < 0.3) {
// 20% chance to spawn original enemy
enemy = new Enemy();
} else if (enemyType < 0.5) {
// 20% chance to spawn Enemyshape2
enemy = new Enemyshape2();
} else if (enemyType < 0.7) {
// 20% chance to spawn Enemy2
enemy = new Enemy2();
} else if (enemyType < 0.9) {
// 20% chance to spawn Enemy3
enemy = new Enemy3();
} else {
// 10% chance to spawn Enemy4
enemy = new Enemy4();
}
// Spawn from edges
if (Math.random() < 0.5) {
enemy.x = Math.random() < 0.5 ? 50 : GAME_WIDTH - 50;
enemy.y = 50 + Math.random() * (GAME_HEIGHT - 100);
} else {
enemy.x = 50 + Math.random() * (GAME_WIDTH - 100);
enemy.y = Math.random() < 0.5 ? 50 : GAME_HEIGHT - 50;
}
// Special entrance for Anime characters
if (enemy instanceof Anime && Math.random() < 0.5) {
// Teleport anime to center with special effect
enemy.x = GAME_WIDTH / 2 + (Math.random() * 200 - 100);
enemy.y = GAME_HEIGHT / 2 + (Math.random() * 200 - 100);
}
game.addChild(enemy);
enemies.push(enemy);
}
}
function spawnWalls(count) {
for (var i = 0; i < count; i++) {
var wall = new GlitchWall();
wall.x = 200 + Math.random() * (GAME_WIDTH - 400);
wall.y = 200 + Math.random() * (GAME_HEIGHT - 400);
// Randomize rotation
wall.rotation = Math.random() * Math.PI * 2;
game.addChild(wall);
walls.push(wall);
}
}
function spawnDebugPowers(count) {
for (var i = 0; i < count; i++) {
var power = new DebugPower();
power.x = 100 + Math.random() * (GAME_WIDTH - 200);
power.y = 100 + Math.random() * (GAME_HEIGHT - 200);
game.addChild(power);
debugPowers.push(power);
}
}
function spawnPibbyGlitch() {
// Create a new pibby glitch at a random position
var glitch = new PibbyGlitch();
// Position it near an edge for more dramatic entry
if (Math.random() < 0.5) {
glitch.x = Math.random() < 0.5 ? 100 : GAME_WIDTH - 100;
glitch.y = 100 + Math.random() * (GAME_HEIGHT - 200);
} else {
glitch.x = 100 + Math.random() * (GAME_WIDTH - 200);
glitch.y = Math.random() < 0.5 ? 100 : GAME_HEIGHT - 100;
}
// Add glitch visual effect
game.addChild(glitch);
// Visual feedback
LK.effects.flashObject(glitch, 0xff00ff, 500);
// Add to tracking array
pibbyGlitches.push(glitch);
// Play sound effect
LK.getSound('hurt').play();
return glitch;
}
function increaseCorruption() {
corruptionLevel += 5;
if (corruptionLevel >= 100) {
gameOver();
return;
}
// Visual feedback for corruption increase
LK.effects.flashScreen(0xff00ff, 300);
// Spawn more enemies as corruption increases
var enemiesToSpawn = Math.min(3, MAX_ENEMIES - enemies.length);
if (enemiesToSpawn > 0) {
spawnEnemies(enemiesToSpawn);
}
// Higher chance to spawn Pibby glitches as corruption increases
if (corruptionLevel > 30 && Math.random() < corruptionLevel / 100) {
// Spawn a pibby glitch if we don't have too many already
if (pibbyGlitches.length < 3) {
var newGlitch = spawnPibbyGlitch();
// Make the glitch more intense based on corruption
newGlitch.glitchIntensity = Math.min(80, corruptionLevel);
} else {
// If we already have maximum glitches, intensify an existing one
var randomGlitch = pibbyGlitches[Math.floor(Math.random() * pibbyGlitches.length)];
randomGlitch.intensify(10);
LK.effects.flashObject(randomGlitch, 0xff00ff, 300);
}
}
// Update UI
updateUI();
}
function spawnVillagers(count) {
for (var i = 0; i < count; i++) {
var villager = new Villager();
villager.x = 100 + Math.random() * (GAME_WIDTH - 200);
villager.y = 100 + Math.random() * (GAME_HEIGHT - 200);
// Small chance to spawn a pre-glitched villager based on corruption level
if (Math.random() < pibbyGlitchChance * (corruptionLevel / 50)) {
// Start the villager in glitched state
villager.startGlitching();
// Progress the glitch transformation timer
villager.transformationTimer = Math.floor(Math.random() * 20); // Random progress in transformation
}
game.addChild(villager);
villagers.push(villager);
}
}
function levelUp() {
level++;
// Spawn new walls
spawnWalls(1);
// Spawn debug power
if (level % 2 === 0 && debugPowers.length < MAX_DEBUG_POWERS) {
spawnDebugPowers(1);
}
// Visual feedback for level up
LK.effects.flashScreen(0x00ffff, 500);
// Update UI
updateUI();
}
function useDebugPower() {
if (player.useDebugPower()) {
// Clear nearby enemies
var powerRadius = 300;
for (var i = enemies.length - 1; i >= 0; i--) {
var enemy = enemies[i];
var dx = enemy.x - player.x;
var dy = enemy.y - player.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < powerRadius) {
enemy.destroy();
enemies.splice(i, 1);
}
}
// Visual effect
LK.effects.flashScreen(0xffff00, 300);
// Update UI
updateUI();
return true;
}
return false;
}
function gameOver() {
gameActive = false;
LK.showGameOver();
}
function checkCollisions() {
// Check player collision with pixels
for (var i = pixels.length - 1; i >= 0; i--) {
if (player.intersects(pixels[i])) {
player.collectPixel();
pixels[i].destroy();
pixels.splice(i, 1);
// Increment score
score++;
LK.setScore(score);
// Check for level up
if (score % LEVEL_UP_SCORE === 0) {
levelUp();
}
// Spawn new pixel if below max
if (pixels.length < MAX_PIXELS) {
spawnPixels(1);
}
updateUI();
}
}
// Check player collision with pibby glitches
for (var i = pibbyGlitches.length - 1; i >= 0; i--) {
if (player.intersects(pibbyGlitches[i])) {
// Touching a glitch hurts the player
player.takeDamage(5 + Math.floor(pibbyGlitches[i].glitchIntensity / 10));
// Visual glitch effect
LK.effects.flashObject(player, 0xff00ff, 300);
// Using debug power on a glitch removes it
if (player.debugPower > 0) {
if (player.useDebugPower()) {
pibbyGlitches[i].destroy();
pibbyGlitches.splice(i, 1);
// Visual feedback
LK.effects.flashScreen(0xffff00, 500);
continue;
}
}
// Otherwise the glitch grows stronger
pibbyGlitches[i].intensify(5);
// Push player away from glitch
var dx = player.x - pibbyGlitches[i].x;
var dy = player.y - pibbyGlitches[i].y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
var pushX = dx / distance * 30;
var pushY = dy / distance * 30;
player.x += pushX;
player.y += pushY;
}
}
}
// Check player collision with enemies
for (var i = 0; i < enemies.length; i++) {
if (player.intersects(enemies[i])) {
// Special handling for anime characters
if (enemies[i] instanceof Anime) {
// Anime characters deal more damage but have chance to power up player temporarily
player.takeDamage(enemies[i].damage * 1.5);
if (Math.random() < 0.3) {
// 30% chance to gain temporary invulnerability
player.isInvulnerable = true;
// Use direct player reference instead of undefined playerGraphics
player.alpha = 0.5;
LK.setTimeout(function () {
player.isInvulnerable = false;
player.alpha = 1.0;
}, 3000);
LK.effects.flashObject(player, 0xffccff, 500);
}
} else {
// Regular damage for normal enemies
player.takeDamage(enemies[i].damage);
}
updateUI();
}
}
// Check Dummy1 collision with enemies (Optional, Dummy1's attack is handled in its update)
// Check player collision with walls
for (var i = 0; i < walls.length; i++) {
if (player.intersects(walls[i])) {
player.takeDamage(5);
// Push player away from wall
var dx = player.x - walls[i].x;
var dy = player.y - walls[i].y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
var pushX = dx / distance * 30;
var pushY = dy / distance * 30;
player.x += pushX;
player.y += pushY;
}
updateUI();
}
}
// Check player collision with debug powers
for (var i = debugPowers.length - 1; i >= 0; i--) {
if (player.intersects(debugPowers[i])) {
player.collectDebugPower();
debugPowers[i].destroy();
debugPowers.splice(i, 1);
updateUI();
}
}
// Check villager collisions with enemies
// Note: This is now handled directly in the Villager.update method for better control
}
// Handle player movement
function handlePlayerMovement(x, y) {
if (gameActive) {
player.moveTowards(x, y);
}
}
// Game input handlers
game.down = function (x, y, obj) {
handlePlayerMovement(x, y);
// Use debug power on double tap
if (Date.now() - lastTapTime < 300) {
useDebugPower();
}
lastTapTime = Date.now();
};
game.move = function (x, y, obj) {
if (player.isMoving) {
handlePlayerMovement(x, y);
}
};
game.up = function (x, y, obj) {
player.stopMoving();
};
var lastTapTime = 0;
// Main game update loop
game.update = function () {
if (!gameActive) return;
// Update player
player.update();
// Update Dummy1
if (dummy1) {
dummy1.update();
}
// Update game objects
for (var i = 0; i < pixels.length; i++) {
pixels[i].update();
}
for (var i = 0; i < enemies.length; i++) {
enemies[i].update();
}
for (var i = 0; i < walls.length; i++) {
walls[i].update();
}
for (var i = 0; i < debugPowers.length; i++) {
debugPowers[i].update();
}
// Update pibby glitches
for (var i = 0; i < pibbyGlitches.length; i++) {
pibbyGlitches[i].update();
}
// Update villagers
for (var i = 0; i < villagers.length; i++) {
villagers[i].update();
}
// Check collisions
checkCollisions();
// Boundary check for player
if (player.x < 50) player.x = 50;
if (player.x > GAME_WIDTH - 50) player.x = GAME_WIDTH - 50;
if (player.y < 50) player.y = 50;
if (player.y > GAME_HEIGHT - 50) player.y = GAME_HEIGHT - 50;
// Check if we need to increase corruption
var currentTime = Date.now();
if (currentTime - lastCorruptionTime > CORRUPTION_INTERVAL) {
increaseCorruption();
lastCorruptionTime = currentTime;
}
// Check if we should spawn a new pibby glitch
if (currentTime - lastGlitchSpawn > pibbySpawnInterval) {
// Probability increases with corruption level
var spawnChance = pibbyGlitchChance + corruptionLevel / 100;
if (Math.random() < spawnChance && pibbyGlitches.length < 3) {
spawnPibbyGlitch();
lastGlitchSpawn = currentTime;
// Increase spawn interval if we already have multiple glitches
if (pibbyGlitches.length > 1) {
pibbySpawnInterval = 8000; // 8 seconds if we have multiple glitches
} else {
pibbySpawnInterval = 5000; // Reset to 5 seconds
}
}
}
// Spawn enemies over time based on corruption level
if (LK.ticks % 180 === 0 && enemies.length < MAX_ENEMIES) {
var spawnChance = 0.2 + corruptionLevel / 100 * 0.5;
if (Math.random() < spawnChance) {
spawnEnemies(1);
}
}
// Special anime-style attack when enemies reach a threshold
if (LK.ticks % 300 === 0 && enemies.length >= 8) {
// Find any anime characters
var animeCharacters = [];
for (var i = 0; i < enemies.length; i++) {
if (enemies[i] instanceof Anime) {
animeCharacters.push(enemies[i]);
}
}
// If we have anime characters, do special attack
if (animeCharacters.length > 0) {
var anime = animeCharacters[Math.floor(Math.random() * animeCharacters.length)];
anime.powerUp();
anime.useSpecialAttack();
// Add dramatic effect
LK.effects.flashScreen(0xff88ff, 500);
}
}
// Occasionally spawn pixels if below max
if (LK.ticks % 300 === 0 && pixels.length < MAX_PIXELS) {
spawnPixels(1);
}
};
// Initialize the game
initializeGame(); /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var Anime = Container.expand(function () {
var self = Container.call(this);
var animeGraphics = self.attachAsset('Enemy', {
anchorX: 0.5,
anchorY: 0.5,
tint: 0xffccff
});
self.health = 150;
self.speed = 6;
self.specialAttackCooldown = 0;
self.specialAttackInterval = 180; // 3 seconds
self.powerLevel = 0;
self.glowActive = false;
self.auraSize = 1.0;
self.update = function () {
// Special movement pattern - more dynamic than regular enemies
self.x += Math.sin(LK.ticks * 0.05) * self.speed * 0.5;
self.y += Math.cos(LK.ticks * 0.03) * self.speed * 0.3;
// Boundary checking
if (self.x < 50) self.x = 50;
if (self.x > GAME_WIDTH - 50) self.x = GAME_WIDTH - 50;
if (self.y < 50) self.y = 50;
if (self.y > GAME_HEIGHT - 50) self.y = GAME_HEIGHT - 50;
// Special attack cooldown
self.specialAttackCooldown++;
if (self.specialAttackCooldown >= self.specialAttackInterval) {
self.useSpecialAttack();
self.specialAttackCooldown = 0;
}
if (self.glowActive) {
self.auraSize = 1.0 + 0.2 * Math.sin(LK.ticks * 0.1);
animeGraphics.scale.set(self.auraSize, self.auraSize);
animeGraphics.rotation += 0.02;
animeGraphics.tint = 0xffccff + (Math.floor(Math.sin(LK.ticks * 0.05) * 127) << 16);
}
};
self.useSpecialAttack = function () {
self.glowActive = true;
LK.effects.flashObject(self, 0xffffff, 500);
// Create energy burst effect
for (var i = 0; i < 8; i++) {
var angle = Math.PI * 2 * (i / 8);
var ghost = LK.getAsset('Enemy', {
anchorX: 0.5,
anchorY: 0.5,
tint: 0xffccff,
alpha: 0.7,
scale: 0.5
});
ghost.x = self.x + Math.cos(angle) * 50;
ghost.y = self.y + Math.sin(angle) * 50;
game.addChild(ghost);
// Animate the energy burst
tween(ghost, {
alpha: 0,
scale: 2,
x: ghost.x + Math.cos(angle) * 200,
y: ghost.y + Math.sin(angle) * 200
}, {
duration: 1000,
easing: tween.easeOut,
onComplete: function onComplete() {
ghost.destroy();
}
});
}
// Disable glow after a while
LK.setTimeout(function () {
self.glowActive = false;
animeGraphics.scale.set(1.0, 1.0);
animeGraphics.tint = 0xffccff;
}, 2000);
};
self.powerUp = function () {
self.powerLevel++;
self.speed += 0.5;
animeGraphics.tint = 0xff00ff;
LK.effects.flashObject(self, 0xffffff, 1000);
// Make the anime character larger with each power up
animeGraphics.scale.set(1.0 + self.powerLevel * 0.1, 1.0 + self.powerLevel * 0.1);
};
return self;
});
var DebugPower = Container.expand(function () {
var self = Container.call(this);
var powerGraphics = self.attachAsset('debugPowerShape', {
anchorX: 0.5,
anchorY: 0.5
});
self.rotateSpeed = 0.03;
self.update = function () {
// Rotate continuously
powerGraphics.rotation += self.rotateSpeed;
};
return self;
});
var Dummy1 = Container.expand(function () {
var self = Container.call(this);
var dummyGraphics = self.attachAsset('Dummy1', {
anchorX: 0.5,
anchorY: 0.5
});
// Dummy1 properties and methods
self.speed = 5;
self.targetEnemy = null;
self.attackDamage = 20;
self.attackRange = 150;
self.update = function () {
// Find the nearest enemy
self.targetEnemy = findNearestEnemy(self.x, self.y);
if (self.targetEnemy) {
// Move towards the target enemy
var dx = self.targetEnemy.x - self.x;
var dy = self.targetEnemy.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > self.speed) {
var ratio = self.speed / distance;
self.x += dx * ratio;
self.y += dy * ratio;
} else {
self.x = self.targetEnemy.x;
self.y = self.targetEnemy.y;
}
// Check if within attack range
if (distance < self.attackRange) {
attackEnemy(self.targetEnemy, self.attackDamage);
}
}
};
return self;
});
var Enemy = Container.expand(function () {
var self = Container.call(this);
var enemyGraphics = self.attachAsset('enemyShape', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 3 + Math.random() * 2;
self.moveAngle = Math.random() * Math.PI * 2;
self.changeDirectionTimer = 0;
self.changeDirectionInterval = 60 + Math.floor(Math.random() * 60);
self.damage = 10;
self.update = function () {
// Change direction occasionally
self.changeDirectionTimer++;
if (self.changeDirectionTimer >= self.changeDirectionInterval) {
self.moveAngle = Math.random() * Math.PI * 2;
self.changeDirectionTimer = 0;
self.changeDirectionInterval = 60 + Math.floor(Math.random() * 60);
}
// Move in current direction
self.x += Math.cos(self.moveAngle) * self.speed;
self.y += Math.sin(self.moveAngle) * self.speed;
// Bounce off walls
if (self.x < 50) {
self.x = 50;
self.moveAngle = Math.PI - self.moveAngle;
} else if (self.x > 2048 - 50) {
self.x = 2048 - 50;
self.moveAngle = Math.PI - self.moveAngle;
}
if (self.y < 50) {
self.y = 50;
self.moveAngle = -self.moveAngle;
} else if (self.y > 2732 - 50) {
self.y = 2732 - 50;
self.moveAngle = -self.moveAngle;
}
// Add a glitchy rotation
enemyGraphics.rotation += 0.05;
};
return self;
});
var Enemy2 = Container.expand(function () {
var self = Container.call(this);
var enemyGraphics = self.attachAsset('Enemy2', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 75; // More health than regular enemy
self.speed = 2; // Slower than regular enemy
self.moveAngle = Math.random() * Math.PI * 2;
self.changeDirectionTimer = 0;
self.changeDirectionInterval = 120 + Math.floor(Math.random() * 60); // Changes direction less frequently
self.damage = 20; // Does more damage than regular enemy
self.update = function () {
// Change direction occasionally
self.changeDirectionTimer++;
if (self.changeDirectionTimer >= self.changeDirectionInterval) {
self.moveAngle = Math.random() * Math.PI * 2;
self.changeDirectionTimer = 0;
self.changeDirectionInterval = 120 + Math.floor(Math.random() * 60);
}
// Move in current direction
self.x += Math.cos(self.moveAngle) * self.speed;
self.y += Math.sin(self.moveAngle) * self.speed;
// Bounce off walls
if (self.x < 50) {
self.x = 50;
self.moveAngle = Math.PI - self.moveAngle;
} else if (self.x > 2048 - 50) {
self.x = 2048 - 50;
self.moveAngle = Math.PI - self.moveAngle;
}
if (self.y < 50) {
self.y = 50;
self.moveAngle = -self.moveAngle;
} else if (self.y > 2732 - 50) {
self.y = 2732 - 50;
self.moveAngle = -self.moveAngle;
}
// Special rotation effect
enemyGraphics.rotation += 0.01;
// Pulse effect
if (LK.ticks % 60 < 30) {
enemyGraphics.scale.set(1.1, 1.1);
} else {
enemyGraphics.scale.set(1, 1);
}
};
return self;
});
var Enemy3 = Container.expand(function () {
var self = Container.call(this);
var enemyGraphics = self.attachAsset('Enemy', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 100; // Highest health of all enemies
self.speed = 1.5; // Slowest but most dangerous
self.moveAngle = Math.random() * Math.PI * 2;
self.changeDirectionTimer = 0;
self.changeDirectionInterval = 150 + Math.floor(Math.random() * 60); // Changes direction rarely
self.damage = 25; // Highest damage
self.update = function () {
// Change direction occasionally
self.changeDirectionTimer++;
if (self.changeDirectionTimer >= self.changeDirectionInterval) {
self.moveAngle = Math.random() * Math.PI * 2;
self.changeDirectionTimer = 0;
self.changeDirectionInterval = 150 + Math.floor(Math.random() * 60);
}
// Move in current direction
self.x += Math.cos(self.moveAngle) * self.speed;
self.y += Math.sin(self.moveAngle) * self.speed;
// Bounce off walls
if (self.x < 50) {
self.x = 50;
self.moveAngle = Math.PI - self.moveAngle;
} else if (self.x > 2048 - 50) {
self.x = 2048 - 50;
self.moveAngle = Math.PI - self.moveAngle;
}
if (self.y < 50) {
self.y = 50;
self.moveAngle = -self.moveAngle;
} else if (self.y > 2732 - 50) {
self.y = 2732 - 50;
self.moveAngle = -self.moveAngle;
}
// Special effect - slowly rotate and pulse with a red glow
enemyGraphics.rotation += 0.015;
if (LK.ticks % 90 < 45) {
enemyGraphics.tint = 0xff3333;
} else {
enemyGraphics.tint = 0xffffff;
}
};
return self;
});
var Enemy4 = Container.expand(function () {
var self = Container.call(this);
var enemyGraphics = self.attachAsset('Enemy', {
anchorX: 0.5,
anchorY: 0.5,
tint: 0x66ffcc
});
self.health = 60;
self.speed = 4; // Faster than most enemies
self.moveAngle = Math.random() * Math.PI * 2;
self.changeDirectionTimer = 0;
self.changeDirectionInterval = 40 + Math.floor(Math.random() * 30); // Changes direction frequently
self.damage = 15;
self.teleportTimer = 0;
self.teleportInterval = 180; // Teleport every ~3 seconds
self.update = function () {
// Teleportation ability
self.teleportTimer++;
if (self.teleportTimer >= self.teleportInterval) {
// Teleport to a random location near the edge
var edgeChoice = Math.floor(Math.random() * 4);
switch (edgeChoice) {
case 0:
// Top edge
self.x = 100 + Math.random() * (GAME_WIDTH - 200);
self.y = 100;
break;
case 1:
// Right edge
self.x = GAME_WIDTH - 100;
self.y = 100 + Math.random() * (GAME_HEIGHT - 200);
break;
case 2:
// Bottom edge
self.x = 100 + Math.random() * (GAME_WIDTH - 200);
self.y = GAME_HEIGHT - 100;
break;
case 3:
// Left edge
self.x = 100;
self.y = 100 + Math.random() * (GAME_HEIGHT - 200);
break;
}
// Visual effect for teleportation
LK.effects.flashObject(self, 0x66ffcc, 300);
self.teleportTimer = 0;
return; // Skip regular movement this frame
}
// Normal movement behavior
self.changeDirectionTimer++;
if (self.changeDirectionTimer >= self.changeDirectionInterval) {
self.moveAngle = Math.random() * Math.PI * 2;
self.changeDirectionTimer = 0;
self.changeDirectionInterval = 40 + Math.floor(Math.random() * 30);
}
// Move in current direction
self.x += Math.cos(self.moveAngle) * self.speed;
self.y += Math.sin(self.moveAngle) * self.speed;
// Bounce off walls
if (self.x < 50) {
self.x = 50;
self.moveAngle = Math.PI - self.moveAngle;
} else if (self.x > 2048 - 50) {
self.x = 2048 - 50;
self.moveAngle = Math.PI - self.moveAngle;
}
if (self.y < 50) {
self.y = 50;
self.moveAngle = -self.moveAngle;
} else if (self.y > 2732 - 50) {
self.y = 2732 - 50;
self.moveAngle = -self.moveAngle;
}
// Special visual effect - trail effect with alpha pulsing
if (LK.ticks % 3 === 0) {
var ghost = LK.getAsset('Enemy', {
anchorX: 0.5,
anchorY: 0.5,
tint: 0x66ffcc,
alpha: 0.3
});
ghost.x = self.x;
ghost.y = self.y;
game.addChild(ghost);
// Fade out and remove the ghost
tween(ghost, {
alpha: 0,
scale: 0.5
}, {
duration: 500,
easing: tween.easeOut,
onComplete: function onComplete() {
ghost.destroy();
}
});
}
};
return self;
});
var Enemyshape2 = Container.expand(function () {
var self = Container.call(this);
var enemyGraphics = self.attachAsset('Enemyshape2', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 50; // Example health
self.speed = 2 + Math.random() * 1;
self.moveAngle = Math.random() * Math.PI * 2;
self.changeDirectionTimer = 0;
self.changeDirectionInterval = 90 + Math.floor(Math.random() * 90);
self.damage = 15;
self.update = function () {
// Change direction occasionally
self.changeDirectionTimer++;
if (self.changeDirectionTimer >= self.changeDirectionInterval) {
self.moveAngle = Math.random() * Math.PI * 2;
self.changeDirectionTimer = 0;
self.changeDirectionInterval = 90 + Math.floor(Math.random() * 90);
}
// Move in current direction
self.x += Math.cos(self.moveAngle) * self.speed;
self.y += Math.sin(self.moveAngle) * self.speed;
// Bounce off walls
if (self.x < 50) {
self.x = 50;
self.moveAngle = Math.PI - self.moveAngle;
} else if (self.x > 2048 - 50) {
self.x = 2048 - 50;
self.moveAngle = Math.PI - self.moveAngle;
}
if (self.y < 50) {
self.y = 50;
self.moveAngle = -self.moveAngle;
} else if (self.y > 2732 - 50) {
self.y = 2732 - 50;
self.moveAngle = -self.moveAngle;
}
// Rotate slowly
enemyGraphics.rotation += 0.02;
};
return self;
});
var GlitchWall = Container.expand(function () {
var self = Container.call(this);
var wallGraphics = self.attachAsset('glitchWall', {
anchorX: 0.5,
anchorY: 0.5
});
self.glitchTimer = 0;
self.glitchInterval = 10;
self.update = function () {
// Visual glitch effect
self.glitchTimer++;
if (self.glitchTimer % self.glitchInterval === 0) {
// Random color shifts
wallGraphics.tint = Math.random() > 0.5 ? 0xff00ff : 0x00ffff;
// Random position shifts
wallGraphics.x = Math.random() * 10 - 5;
wallGraphics.y = Math.random() * 10 - 5;
}
if (self.glitchTimer >= 60) {
self.glitchTimer = 0;
wallGraphics.x = 0;
wallGraphics.y = 0;
}
};
return self;
});
var PibbyGlitch = Container.expand(function () {
var self = Container.call(this);
// Create the glitch visual effect container
var glitchGraphics = self.attachAsset('pixelShape', {
anchorX: 0.5,
anchorY: 0.5,
tint: 0xff00ff
});
// Properties for glitch effect
self.glitchIntensity = 0;
self.maxIntensity = 100;
self.affectedArea = 150;
self.glitchTimer = 0;
self.updateInterval = 2;
self.isActive = true;
self.growthRate = 0.5;
// The pibby glitch update function
self.update = function () {
self.glitchTimer++;
// Only update visuals on certain frames for performance
if (self.glitchTimer % self.updateInterval === 0) {
// Random visual glitching
glitchGraphics.x = (Math.random() * 20 - 10) * (self.glitchIntensity / 50);
glitchGraphics.y = (Math.random() * 20 - 10) * (self.glitchIntensity / 50);
// Randomly change tint color for glitch effect
if (Math.random() > 0.6) {
glitchGraphics.tint = Math.random() > 0.5 ? 0xff00ff : 0x00ffff;
}
// Scale based on intensity
var scale = 0.5 + self.glitchIntensity / self.maxIntensity * 2;
glitchGraphics.scaleX = scale;
glitchGraphics.scaleY = scale;
// Slowly grow the glitch if active
if (self.isActive && self.glitchIntensity < self.maxIntensity) {
self.glitchIntensity += self.growthRate;
}
}
};
// Function to increase glitch intensity
self.intensify = function (amount) {
self.glitchIntensity = Math.min(self.maxIntensity, self.glitchIntensity + amount);
// Visual feedback with tween
tween(glitchGraphics, {
alpha: 0.8,
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 300,
easing: tween.easeOut,
onComplete: function onComplete() {
var newScale = 0.5 + self.glitchIntensity / self.maxIntensity * 2;
tween(glitchGraphics, {
alpha: 0.6,
scaleX: newScale,
scaleY: newScale
}, {
duration: 300,
easing: tween.easeIn
});
}
});
};
return self;
});
var Pixel = Container.expand(function () {
var self = Container.call(this);
var pixelGraphics = self.attachAsset('pixelShape', {
anchorX: 0.5,
anchorY: 0.5
});
// Add a pulsing animation
self.pulseDirection = 1;
self.pulseSpeed = 0.02;
self.baseScale = 1;
self.update = function () {
// Pulse effect
var scale = pixelGraphics.scale.x;
scale += self.pulseSpeed * self.pulseDirection;
if (scale > 1.2) {
scale = 1.2;
self.pulseDirection = -1;
} else if (scale < 0.8) {
scale = 0.8;
self.pulseDirection = 1;
}
pixelGraphics.scale.set(scale, scale);
};
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
var playerGraphics = self.attachAsset('playerShape', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 100;
self.speed = 8;
self.isMoving = false;
self.targetX = 0;
self.targetY = 0;
self.debugPower = 0;
self.isInvulnerable = false;
self.moveTowards = function (targetX, targetY) {
self.isMoving = true;
self.targetX = targetX;
self.targetY = targetY;
};
self.stopMoving = function () {
self.isMoving = false;
};
self.takeDamage = function (amount) {
if (!self.isInvulnerable) {
self.health -= amount;
LK.getSound('hurt').play();
self.isInvulnerable = true;
playerGraphics.alpha = 0.5;
// Flash effect
LK.effects.flashObject(self, 0xff0000, 300);
LK.setTimeout(function () {
self.isInvulnerable = false;
playerGraphics.alpha = 1.0;
}, 1500);
if (self.health <= 0) {
self.health = 0;
gameOver();
}
}
};
self.collectPixel = function () {
self.health = Math.min(100, self.health + 10);
LK.getSound('collect').play();
};
self.collectDebugPower = function () {
self.debugPower++;
LK.getSound('powerup').play();
};
self.useDebugPower = function () {
if (self.debugPower > 0) {
self.debugPower--;
return true;
}
return false;
};
self.update = function () {
if (self.isMoving) {
var dx = self.targetX - self.x;
var dy = self.targetY - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > self.speed) {
var ratio = self.speed / distance;
self.x += dx * ratio;
self.y += dy * ratio;
} else {
self.x = self.targetX;
self.y = self.targetY;
self.isMoving = false;
}
}
};
return self;
});
var Villager = Container.expand(function () {
var self = Container.call(this);
var villagerGraphics = self.attachAsset('Villager', {
anchorX: 0.5,
anchorY: 0.5
});
// Villager properties and methods
self.health = 50;
self.speed = 4;
self.isGlitching = false;
self.glitchTimer = 0;
self.fearRadius = 300; // Distance at which villager senses enemies
self.transformationTimer = 0;
self.update = function () {
if (self.isGlitching) {
// Handle glitching animation
self.glitchTimer++;
// Visual glitch effect
if (self.glitchTimer % 5 === 0) {
// Random color shifts
villagerGraphics.tint = Math.random() > 0.5 ? 0xff00ff : 0x00ffff;
// Random position shifts
villagerGraphics.x = Math.random() * 10 - 5;
villagerGraphics.y = Math.random() * 10 - 5;
// Increase transformation timer
self.transformationTimer++;
// After enough glitching, transform into enemy
if (self.transformationTimer >= 30) {
self.transformIntoEnemy();
return;
}
}
} else {
// Check for nearby Pibby glitches - these have priority over enemies
var nearestGlitch = null;
var shortestGlitchDistance = Infinity;
// Find the nearest pibby glitch
for (var i = 0; i < pibbyGlitches.length; i++) {
var glitch = pibbyGlitches[i];
var dx = glitch.x - self.x;
var dy = glitch.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
// If within affected area, start glitching immediately
if (distance < glitch.affectedArea * (glitch.glitchIntensity / 50)) {
// Start glitching process when in range of pibby glitch
self.startGlitching();
// Intensify the glitch
glitch.intensify(2);
break;
}
if (distance < shortestGlitchDistance) {
shortestGlitchDistance = distance;
nearestGlitch = glitch;
}
}
// If near a glitch but not yet glitching, run away from it
if (nearestGlitch && shortestGlitchDistance < self.fearRadius * 1.5 && !self.isGlitching) {
// Run away from glitch (higher priority than running from enemies)
var dx = self.x - nearestGlitch.x;
var dy = self.y - nearestGlitch.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
// Normalize and apply speed (run faster from glitches)
dx = dx / distance * (self.speed * 1.5);
dy = dy / distance * (self.speed * 1.5);
// Move away from glitch
self.x += dx;
self.y += dy;
// Keep within game boundaries
if (self.x < 50) self.x = 50;
if (self.x > GAME_WIDTH - 50) self.x = GAME_WIDTH - 50;
if (self.y < 50) self.y = 50;
if (self.y > GAME_HEIGHT - 50) self.y = GAME_HEIGHT - 50;
}
} else {
// Run away from nearby enemies
var nearestEnemy = null;
var shortestDistance = Infinity;
// Find the nearest enemy
for (var i = 0; i < enemies.length; i++) {
var enemy = enemies[i];
var dx = enemy.x - self.x;
var dy = enemy.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
// Check for enemy collision
if (self.intersects(enemy)) {
// Start glitching process when touched by enemy
self.startGlitching();
break;
}
if (distance < shortestDistance) {
shortestDistance = distance;
nearestEnemy = enemy;
}
}
// Run away if enemy is within fear radius
if (nearestEnemy && shortestDistance < self.fearRadius) {
// Calculate direction away from enemy
var dx = self.x - nearestEnemy.x;
var dy = self.y - nearestEnemy.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
// Normalize and apply speed
dx = dx / distance * self.speed;
dy = dy / distance * self.speed;
// Move away from enemy
self.x += dx;
self.y += dy;
// Keep within game boundaries
if (self.x < 50) self.x = 50;
if (self.x > GAME_WIDTH - 50) self.x = GAME_WIDTH - 50;
if (self.y < 50) self.y = 50;
if (self.y > GAME_HEIGHT - 50) self.y = GAME_HEIGHT - 50;
}
}
}
}
};
self.startGlitching = function () {
if (!self.isGlitching) {
self.isGlitching = true;
self.glitchTimer = 0;
self.transformationTimer = 0;
// Visual feedback with tween
tween(villagerGraphics, {
alpha: 0.5
}, {
duration: 300,
easing: tween.easeInOut
});
// Play sound effect
LK.getSound('hurt').play();
}
};
self.transformIntoEnemy = function () {
// Check if any nearby Pibby glitches to determine what enemy type to spawn
var nearbyGlitch = false;
var strongestGlitch = null;
for (var i = 0; i < pibbyGlitches.length; i++) {
var glitch = pibbyGlitches[i];
var dx = glitch.x - self.x;
var dy = glitch.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < glitch.affectedArea) {
nearbyGlitch = true;
if (!strongestGlitch || glitch.glitchIntensity > strongestGlitch.glitchIntensity) {
strongestGlitch = glitch;
}
}
}
// Create a new enemy at the villager's position - stronger enemy if near glitch
var newEnemy;
if (nearbyGlitch) {
// Higher chance of stronger enemies when near a glitch
var enemyRoll = Math.random();
if (enemyRoll < 0.4) {
newEnemy = new Enemy3(); // Stronger enemy
} else if (enemyRoll < 0.7) {
newEnemy = new Enemy2();
} else if (enemyRoll < 0.9) {
newEnemy = new Enemy4(); // Teleporting enemy
} else {
newEnemy = new Anime(); // Rare chance for anime character
}
// Intensify the nearby glitch
if (strongestGlitch) {
strongestGlitch.intensify(10);
}
} else {
// Normal enemy spawn probability
newEnemy = Math.random() < 0.5 ? new Enemy() : new Enemyshape2();
}
newEnemy.x = self.x;
newEnemy.y = self.y;
game.addChild(newEnemy);
enemies.push(newEnemy);
// Visual effect
LK.effects.flashObject(newEnemy, 0xff00ff, 500);
// Remove villager
var index = villagers.indexOf(self);
if (index !== -1) {
villagers.splice(index, 1);
}
self.destroy();
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000033
});
/****
* Game Code
****/
// Game constants
var GAME_WIDTH = 2048;
var GAME_HEIGHT = 2732;
var MAX_ENEMIES = 15;
var MAX_PIXELS = 10;
var MAX_WALLS = 8;
var MAX_DEBUG_POWERS = 3;
var CORRUPTION_INTERVAL = 10000; // 10 seconds
var LEVEL_UP_SCORE = 10;
// Game variables
var villagers = []; // Array to hold villagers
var player;
var pixels = [];
var enemies = [];
var walls = [];
var debugPowers = [];
var pibbyGlitches = []; // Array to hold pibby glitch instances
var score = 0;
var level = 1;
var corruptionLevel = 0;
var gameActive = true;
var lastCorruptionTime = 0;
var lastGlitchSpawn = 0;
var pibbyGlitchChance = 0.1; // Base chance of spawning a glitch
var pibbySpawnInterval = 5000; // 5 seconds
var dummy1; // Add dummy1 variable
// UI elements
var scoreText;
var healthBar;
var healthBarBg;
var levelText;
var debugPowerText;
var corruptionText;
// Initialize game elements
function initializeGame() {
// Clear existing elements if needed
clearGameElements();
// Create player
player = new Player();
player.x = GAME_WIDTH / 2;
player.y = GAME_HEIGHT - 200;
game.addChild(player);
// Create Dummy1
dummy1 = new Dummy1();
dummy1.x = GAME_WIDTH / 2 - 150; // Position Dummy1 near the player
dummy1.y = GAME_HEIGHT - 200;
game.addChild(dummy1);
// Initialize UI
createUI();
// Generate initial game objects
spawnPixels(MAX_PIXELS);
spawnWalls(level);
spawnDebugPowers(1);
spawnVillagers(5); // Spawn 5 villagers initially
// Start corruption process
lastCorruptionTime = Date.now();
// Reset game state
score = 0;
corruptionLevel = 0;
level = 1;
gameActive = true;
// Update UI
updateUI();
// Play background music
LK.playMusic('gameTheme');
}
function clearGameElements() {
// Remove all existing game elements
if (player) {
player.destroy();
player = null;
}
if (dummy1) {
// Clear Dummy1
dummy1.destroy();
dummy1 = null;
}
for (var i = 0; i < pixels.length; i++) {
pixels[i].destroy();
}
pixels = [];
for (var i = 0; i < enemies.length; i++) {
enemies[i].destroy();
}
enemies = [];
for (var i = 0; i < walls.length; i++) {
walls[i].destroy();
}
walls = [];
for (var i = 0; i < debugPowers.length; i++) {
debugPowers[i].destroy();
}
debugPowers = [];
// Clear pibby glitches
for (var i = 0; i < pibbyGlitches.length; i++) {
pibbyGlitches[i].destroy();
}
pibbyGlitches = [];
lastGlitchSpawn = 0;
pibbySpawnInterval = 5000;
}
for (var i = 0; i < villagers.length; i++) {
villagers[i].destroy();
}
villagers = [];
function createUI() {
// Score text
scoreText = new Text2('Score: 0', {
size: 60,
fill: 0xFFFFFF
});
scoreText.anchor.set(0, 0);
scoreText.x = 120;
scoreText.y = 50;
LK.gui.addChild(scoreText);
// Level text
levelText = new Text2('Level: 1', {
size: 60,
fill: 0xFFFFFF
});
levelText.anchor.set(0.5, 0);
levelText.x = GAME_WIDTH / 2;
levelText.y = 50;
LK.gui.addChild(levelText);
// Debug power counter
debugPowerText = new Text2('Debug Powers: 0', {
size: 60,
fill: 0xFFFF00
});
debugPowerText.anchor.set(1, 0);
debugPowerText.x = GAME_WIDTH - 120;
debugPowerText.y = 50;
LK.gui.addChild(debugPowerText);
// Health bar background
healthBarBg = LK.getAsset('playerShape', {
anchorX: 0,
anchorY: 0,
width: 400,
height: 30,
tint: 0x666666
});
healthBarBg.x = GAME_WIDTH / 2 - 200;
healthBarBg.y = 120;
LK.gui.addChild(healthBarBg);
// Health bar
healthBar = LK.getAsset('playerShape', {
anchorX: 0,
anchorY: 0,
width: 400,
height: 30,
tint: 0x00ff00
});
healthBar.x = GAME_WIDTH / 2 - 200;
healthBar.y = 120;
LK.gui.addChild(healthBar);
// Corruption text
corruptionText = new Text2('Corruption: 0%', {
size: 50,
fill: 0xFF00FF
});
corruptionText.anchor.set(0.5, 0);
corruptionText.x = GAME_WIDTH / 2;
corruptionText.y = 160;
LK.gui.addChild(corruptionText);
}
function updateUI() {
// Update score display
scoreText.setText('Score: ' + score);
// Update health bar
healthBar.width = player.health / 100 * 400;
healthBar.tint = player.health > 50 ? 0x00ff00 : player.health > 25 ? 0xffff00 : 0xff0000;
// Update level display
levelText.setText('Level: ' + level);
// Update debug power counter
debugPowerText.setText('Debug Powers: ' + player.debugPower);
// Update corruption display
corruptionText.setText('Corruption: ' + corruptionLevel + '%');
// Use setStyle instead of directly accessing style which is undefined
corruptionText.setStyle({
fill: corruptionLevel > 75 ? "#FF0000" : "#FF00FF"
});
}
function findNearestEnemy(x, y) {
var nearestEnemy = null;
var shortestDistance = Infinity;
for (var i = 0; i < enemies.length; i++) {
var enemy = enemies[i];
var dx = enemy.x - x;
var dy = enemy.y - y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < shortestDistance) {
shortestDistance = distance;
nearestEnemy = enemy;
}
}
return nearestEnemy;
}
function attackEnemy(enemy, damage) {
enemy.health -= damage; // Assuming enemies have a health property
if (enemy.health <= 0) {
enemy.destroy();
enemies.splice(enemies.indexOf(enemy), 1);
// Optionally, increase score or spawn something on enemy defeat
}
}
function spawnPixels(count) {
for (var i = 0; i < count; i++) {
var pixel = new Pixel();
pixel.x = 100 + Math.random() * (GAME_WIDTH - 200);
pixel.y = 100 + Math.random() * (GAME_HEIGHT - 200);
game.addChild(pixel);
pixels.push(pixel);
}
}
function spawnEnemies(count) {
for (var i = 0; i < count; i++) {
var enemy;
var enemyType = Math.random();
// Add a small chance to spawn anime character
if (enemyType < 0.1) {
// 10% chance to spawn anime character
enemy = new Anime();
// Make anime characters appear with special effect
LK.effects.flashObject(enemy, 0xffccff, 500);
} else if (enemyType < 0.3) {
// 20% chance to spawn original enemy
enemy = new Enemy();
} else if (enemyType < 0.5) {
// 20% chance to spawn Enemyshape2
enemy = new Enemyshape2();
} else if (enemyType < 0.7) {
// 20% chance to spawn Enemy2
enemy = new Enemy2();
} else if (enemyType < 0.9) {
// 20% chance to spawn Enemy3
enemy = new Enemy3();
} else {
// 10% chance to spawn Enemy4
enemy = new Enemy4();
}
// Spawn from edges
if (Math.random() < 0.5) {
enemy.x = Math.random() < 0.5 ? 50 : GAME_WIDTH - 50;
enemy.y = 50 + Math.random() * (GAME_HEIGHT - 100);
} else {
enemy.x = 50 + Math.random() * (GAME_WIDTH - 100);
enemy.y = Math.random() < 0.5 ? 50 : GAME_HEIGHT - 50;
}
// Special entrance for Anime characters
if (enemy instanceof Anime && Math.random() < 0.5) {
// Teleport anime to center with special effect
enemy.x = GAME_WIDTH / 2 + (Math.random() * 200 - 100);
enemy.y = GAME_HEIGHT / 2 + (Math.random() * 200 - 100);
}
game.addChild(enemy);
enemies.push(enemy);
}
}
function spawnWalls(count) {
for (var i = 0; i < count; i++) {
var wall = new GlitchWall();
wall.x = 200 + Math.random() * (GAME_WIDTH - 400);
wall.y = 200 + Math.random() * (GAME_HEIGHT - 400);
// Randomize rotation
wall.rotation = Math.random() * Math.PI * 2;
game.addChild(wall);
walls.push(wall);
}
}
function spawnDebugPowers(count) {
for (var i = 0; i < count; i++) {
var power = new DebugPower();
power.x = 100 + Math.random() * (GAME_WIDTH - 200);
power.y = 100 + Math.random() * (GAME_HEIGHT - 200);
game.addChild(power);
debugPowers.push(power);
}
}
function spawnPibbyGlitch() {
// Create a new pibby glitch at a random position
var glitch = new PibbyGlitch();
// Position it near an edge for more dramatic entry
if (Math.random() < 0.5) {
glitch.x = Math.random() < 0.5 ? 100 : GAME_WIDTH - 100;
glitch.y = 100 + Math.random() * (GAME_HEIGHT - 200);
} else {
glitch.x = 100 + Math.random() * (GAME_WIDTH - 200);
glitch.y = Math.random() < 0.5 ? 100 : GAME_HEIGHT - 100;
}
// Add glitch visual effect
game.addChild(glitch);
// Visual feedback
LK.effects.flashObject(glitch, 0xff00ff, 500);
// Add to tracking array
pibbyGlitches.push(glitch);
// Play sound effect
LK.getSound('hurt').play();
return glitch;
}
function increaseCorruption() {
corruptionLevel += 5;
if (corruptionLevel >= 100) {
gameOver();
return;
}
// Visual feedback for corruption increase
LK.effects.flashScreen(0xff00ff, 300);
// Spawn more enemies as corruption increases
var enemiesToSpawn = Math.min(3, MAX_ENEMIES - enemies.length);
if (enemiesToSpawn > 0) {
spawnEnemies(enemiesToSpawn);
}
// Higher chance to spawn Pibby glitches as corruption increases
if (corruptionLevel > 30 && Math.random() < corruptionLevel / 100) {
// Spawn a pibby glitch if we don't have too many already
if (pibbyGlitches.length < 3) {
var newGlitch = spawnPibbyGlitch();
// Make the glitch more intense based on corruption
newGlitch.glitchIntensity = Math.min(80, corruptionLevel);
} else {
// If we already have maximum glitches, intensify an existing one
var randomGlitch = pibbyGlitches[Math.floor(Math.random() * pibbyGlitches.length)];
randomGlitch.intensify(10);
LK.effects.flashObject(randomGlitch, 0xff00ff, 300);
}
}
// Update UI
updateUI();
}
function spawnVillagers(count) {
for (var i = 0; i < count; i++) {
var villager = new Villager();
villager.x = 100 + Math.random() * (GAME_WIDTH - 200);
villager.y = 100 + Math.random() * (GAME_HEIGHT - 200);
// Small chance to spawn a pre-glitched villager based on corruption level
if (Math.random() < pibbyGlitchChance * (corruptionLevel / 50)) {
// Start the villager in glitched state
villager.startGlitching();
// Progress the glitch transformation timer
villager.transformationTimer = Math.floor(Math.random() * 20); // Random progress in transformation
}
game.addChild(villager);
villagers.push(villager);
}
}
function levelUp() {
level++;
// Spawn new walls
spawnWalls(1);
// Spawn debug power
if (level % 2 === 0 && debugPowers.length < MAX_DEBUG_POWERS) {
spawnDebugPowers(1);
}
// Visual feedback for level up
LK.effects.flashScreen(0x00ffff, 500);
// Update UI
updateUI();
}
function useDebugPower() {
if (player.useDebugPower()) {
// Clear nearby enemies
var powerRadius = 300;
for (var i = enemies.length - 1; i >= 0; i--) {
var enemy = enemies[i];
var dx = enemy.x - player.x;
var dy = enemy.y - player.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < powerRadius) {
enemy.destroy();
enemies.splice(i, 1);
}
}
// Visual effect
LK.effects.flashScreen(0xffff00, 300);
// Update UI
updateUI();
return true;
}
return false;
}
function gameOver() {
gameActive = false;
LK.showGameOver();
}
function checkCollisions() {
// Check player collision with pixels
for (var i = pixels.length - 1; i >= 0; i--) {
if (player.intersects(pixels[i])) {
player.collectPixel();
pixels[i].destroy();
pixels.splice(i, 1);
// Increment score
score++;
LK.setScore(score);
// Check for level up
if (score % LEVEL_UP_SCORE === 0) {
levelUp();
}
// Spawn new pixel if below max
if (pixels.length < MAX_PIXELS) {
spawnPixels(1);
}
updateUI();
}
}
// Check player collision with pibby glitches
for (var i = pibbyGlitches.length - 1; i >= 0; i--) {
if (player.intersects(pibbyGlitches[i])) {
// Touching a glitch hurts the player
player.takeDamage(5 + Math.floor(pibbyGlitches[i].glitchIntensity / 10));
// Visual glitch effect
LK.effects.flashObject(player, 0xff00ff, 300);
// Using debug power on a glitch removes it
if (player.debugPower > 0) {
if (player.useDebugPower()) {
pibbyGlitches[i].destroy();
pibbyGlitches.splice(i, 1);
// Visual feedback
LK.effects.flashScreen(0xffff00, 500);
continue;
}
}
// Otherwise the glitch grows stronger
pibbyGlitches[i].intensify(5);
// Push player away from glitch
var dx = player.x - pibbyGlitches[i].x;
var dy = player.y - pibbyGlitches[i].y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
var pushX = dx / distance * 30;
var pushY = dy / distance * 30;
player.x += pushX;
player.y += pushY;
}
}
}
// Check player collision with enemies
for (var i = 0; i < enemies.length; i++) {
if (player.intersects(enemies[i])) {
// Special handling for anime characters
if (enemies[i] instanceof Anime) {
// Anime characters deal more damage but have chance to power up player temporarily
player.takeDamage(enemies[i].damage * 1.5);
if (Math.random() < 0.3) {
// 30% chance to gain temporary invulnerability
player.isInvulnerable = true;
// Use direct player reference instead of undefined playerGraphics
player.alpha = 0.5;
LK.setTimeout(function () {
player.isInvulnerable = false;
player.alpha = 1.0;
}, 3000);
LK.effects.flashObject(player, 0xffccff, 500);
}
} else {
// Regular damage for normal enemies
player.takeDamage(enemies[i].damage);
}
updateUI();
}
}
// Check Dummy1 collision with enemies (Optional, Dummy1's attack is handled in its update)
// Check player collision with walls
for (var i = 0; i < walls.length; i++) {
if (player.intersects(walls[i])) {
player.takeDamage(5);
// Push player away from wall
var dx = player.x - walls[i].x;
var dy = player.y - walls[i].y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
var pushX = dx / distance * 30;
var pushY = dy / distance * 30;
player.x += pushX;
player.y += pushY;
}
updateUI();
}
}
// Check player collision with debug powers
for (var i = debugPowers.length - 1; i >= 0; i--) {
if (player.intersects(debugPowers[i])) {
player.collectDebugPower();
debugPowers[i].destroy();
debugPowers.splice(i, 1);
updateUI();
}
}
// Check villager collisions with enemies
// Note: This is now handled directly in the Villager.update method for better control
}
// Handle player movement
function handlePlayerMovement(x, y) {
if (gameActive) {
player.moveTowards(x, y);
}
}
// Game input handlers
game.down = function (x, y, obj) {
handlePlayerMovement(x, y);
// Use debug power on double tap
if (Date.now() - lastTapTime < 300) {
useDebugPower();
}
lastTapTime = Date.now();
};
game.move = function (x, y, obj) {
if (player.isMoving) {
handlePlayerMovement(x, y);
}
};
game.up = function (x, y, obj) {
player.stopMoving();
};
var lastTapTime = 0;
// Main game update loop
game.update = function () {
if (!gameActive) return;
// Update player
player.update();
// Update Dummy1
if (dummy1) {
dummy1.update();
}
// Update game objects
for (var i = 0; i < pixels.length; i++) {
pixels[i].update();
}
for (var i = 0; i < enemies.length; i++) {
enemies[i].update();
}
for (var i = 0; i < walls.length; i++) {
walls[i].update();
}
for (var i = 0; i < debugPowers.length; i++) {
debugPowers[i].update();
}
// Update pibby glitches
for (var i = 0; i < pibbyGlitches.length; i++) {
pibbyGlitches[i].update();
}
// Update villagers
for (var i = 0; i < villagers.length; i++) {
villagers[i].update();
}
// Check collisions
checkCollisions();
// Boundary check for player
if (player.x < 50) player.x = 50;
if (player.x > GAME_WIDTH - 50) player.x = GAME_WIDTH - 50;
if (player.y < 50) player.y = 50;
if (player.y > GAME_HEIGHT - 50) player.y = GAME_HEIGHT - 50;
// Check if we need to increase corruption
var currentTime = Date.now();
if (currentTime - lastCorruptionTime > CORRUPTION_INTERVAL) {
increaseCorruption();
lastCorruptionTime = currentTime;
}
// Check if we should spawn a new pibby glitch
if (currentTime - lastGlitchSpawn > pibbySpawnInterval) {
// Probability increases with corruption level
var spawnChance = pibbyGlitchChance + corruptionLevel / 100;
if (Math.random() < spawnChance && pibbyGlitches.length < 3) {
spawnPibbyGlitch();
lastGlitchSpawn = currentTime;
// Increase spawn interval if we already have multiple glitches
if (pibbyGlitches.length > 1) {
pibbySpawnInterval = 8000; // 8 seconds if we have multiple glitches
} else {
pibbySpawnInterval = 5000; // Reset to 5 seconds
}
}
}
// Spawn enemies over time based on corruption level
if (LK.ticks % 180 === 0 && enemies.length < MAX_ENEMIES) {
var spawnChance = 0.2 + corruptionLevel / 100 * 0.5;
if (Math.random() < spawnChance) {
spawnEnemies(1);
}
}
// Special anime-style attack when enemies reach a threshold
if (LK.ticks % 300 === 0 && enemies.length >= 8) {
// Find any anime characters
var animeCharacters = [];
for (var i = 0; i < enemies.length; i++) {
if (enemies[i] instanceof Anime) {
animeCharacters.push(enemies[i]);
}
}
// If we have anime characters, do special attack
if (animeCharacters.length > 0) {
var anime = animeCharacters[Math.floor(Math.random() * animeCharacters.length)];
anime.powerUp();
anime.useSpecialAttack();
// Add dramatic effect
LK.effects.flashScreen(0xff88ff, 500);
}
}
// Occasionally spawn pixels if below max
if (LK.ticks % 300 === 0 && pixels.length < MAX_PIXELS) {
spawnPixels(1);
}
};
// Initialize the game
initializeGame();
Modern App Store icon, high definition, square with rounded corners, for a game titled "Glitch Escape: Cartoon Apocalypse" and with the description "Navigate a cartoon character through a world being consumed by digital corruption. Dodge glitched enemies, collect uncorrupted pixels, and use debugging powers to survive the spreading digital apocalypse. Race against time to reach the source code and save the cartoon universe from total corruption.". No text on icon!
Pibby. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
Pibby glitch wall. In-Game asset. High contrast. No shadows
Pibby glitch pomni. In-Game asset. High contrast. No shadows
DebugPower. In-Game asset. High contrast. No shadows
Little pibby glitch. In-Game asset. 2d. High contrast. No shadows
Pixel shape. In-Game asset. 2d. High contrast. No shadows
Corrupted among Us. In-Game asset. High contrast. No shadows
Pibby finn. In-Game asset. High contrast. No shadows