/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Bird = Container.expand(function () {
var self = Container.call(this);
var birdGraphics = self.attachAsset('bird', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = Math.random() * 2 + 1;
self.direction = Math.random() > 0.5 ? 1 : -1;
self.flapTimer = 0;
self.update = function () {
self.x += self.speed * self.direction;
// Flap animation
self.flapTimer++;
if (self.flapTimer < 15) {
birdGraphics.scaleY = 0.8;
} else if (self.flapTimer < 30) {
birdGraphics.scaleY = 1.2;
} else {
self.flapTimer = 0;
}
// Remove if off screen
if (self.x < -50 || self.x > 2098) {
self.destroy();
birds.splice(birds.indexOf(self), 1);
}
};
return self;
});
var Boss = Container.expand(function () {
var self = Container.call(this);
var bossGraphics = self.attachAsset('boss', {
anchorX: 0.5,
anchorY: 1.0
});
self.health = 300;
self.maxHealth = 300;
self.speed = 1.5;
self.attackDamage = 20;
self.attackCooldown = 0;
self.maxAttackCooldown = 120;
self.direction = 1;
self.lastIntersecting = false;
self.update = function () {
// Move back and forth
self.x += self.speed * self.direction;
if (self.x <= 200 || self.x >= 1848) {
self.direction *= -1;
}
// Attack monster
if (self.attackCooldown > 0) {
self.attackCooldown--;
}
var currentIntersecting = self.intersects(monster);
if (currentIntersecting && self.attackCooldown <= 0) {
monster.takeDamage(self.attackDamage);
LK.getSound('attack').play();
self.attackCooldown = self.maxAttackCooldown;
}
// Check if monster jumps on boss - monster takes no damage when landing on boss
if (!self.lastIntersecting && currentIntersecting && monster.velocityY > 0) {
self.takeDamage(50);
// Monster doesn't take damage when landing on boss
}
self.lastIntersecting = currentIntersecting;
};
self.takeDamage = function (damage) {
self.health -= damage;
LK.getSound('boss_hit').play();
LK.effects.flashObject(self, 0xff0000, 300);
if (self.health <= 0) {
LK.setScore(LK.getScore() + 1000);
self.destroy();
boss = null;
level++;
startLevel();
}
};
return self;
});
var Building = Container.expand(function () {
var self = Container.call(this);
self.heightLevel = Math.floor(Math.random() * 3) + 1; // 1, 2, or 3
self.assetNames = ['building_small', 'building_medium', 'building_large'];
self.buildingHeights = [80, 160, 240];
self.buildingType = Math.floor(Math.random() * 3); // 0=tech, 1=ottoman, 2=cave
self.buildingTypes = ['tech', 'ottoman', 'cave'];
self.projectileTypes = ['rocket', 'cannonball', 'arrow'];
self.attackCooldown = 0;
self.maxAttackCooldown = 450; // 7.5 seconds at 60fps
var buildingGraphics = self.attachAsset(self.assetNames[self.heightLevel - 1], {
anchorX: 0.5,
anchorY: 1.0
});
self.lastIntersecting = false;
self.update = function () {
// Check collision with monster
var currentIntersecting = self.intersects(monster);
if (!self.lastIntersecting && currentIntersecting && monster.velocityY > 0) {
self.stomp();
}
self.lastIntersecting = currentIntersecting;
// Attack monster with projectiles
if (self.attackCooldown > 0) {
self.attackCooldown--;
}
if (self.attackCooldown <= 0) {
self.fireProjectile();
self.attackCooldown = self.maxAttackCooldown;
}
};
self.stomp = function () {
LK.getSound('stomp').play();
LK.setScore(LK.getScore() + 10);
// Monster doesn't take damage when stomping on buildings
// Shrink building by one level
self.heightLevel--;
if (self.heightLevel <= 0) {
// Building destroyed
self.destroy();
buildings.splice(buildings.indexOf(self), 1);
buildingsDestroyed++;
} else {
// Replace with smaller building
self.removeChild(buildingGraphics);
buildingGraphics = self.attachAsset(self.assetNames[self.heightLevel - 1], {
anchorX: 0.5,
anchorY: 1.0
});
}
};
self.fireProjectile = function () {
var projectile = new Projectile();
// Fire projectile based on building height level: 3=rocket, 2=cannonball, 1=arrow
if (self.heightLevel === 3) {
projectile.type = 'rocket';
} else if (self.heightLevel === 2) {
projectile.type = 'cannonball';
} else {
projectile.type = 'arrow';
}
var projectileGraphics = projectile.attachAsset(projectile.type, {
anchorX: 0.5,
anchorY: 0.5
});
projectile.x = self.x;
projectile.y = self.y - self.buildingHeights[self.heightLevel - 1] / 2;
// Calculate direction to monster
var dx = monster.x - projectile.x;
var dy = monster.y - projectile.y;
var distance = Math.sqrt(dx * dx + dy * dy);
projectile.velocityX = dx / distance * projectile.speed;
projectile.velocityY = dy / distance * projectile.speed;
// Rotate projectile to face monster
projectileGraphics.rotation = Math.atan2(dy, dx);
projectiles.push(projectile);
game.addChild(projectile);
};
return self;
});
var Cloud = Container.expand(function () {
var self = Container.call(this);
var cloudGraphics = self.attachAsset('cloud', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = Math.random() * 0.5 + 0.2;
self.alpha = Math.random() * 0.4 + 0.6;
cloudGraphics.alpha = self.alpha;
self.update = function () {
self.x += self.speed;
// Remove if off screen
if (self.x > 2098 + 150) {
self.destroy();
clouds.splice(clouds.indexOf(self), 1);
}
};
return self;
});
var HealthPack = Container.expand(function () {
var self = Container.call(this);
var healthPackGraphics = self.attachAsset('healthPack', {
anchorX: 0.5,
anchorY: 0.5
});
self.velocityY = 0;
self.gravity = 0.8;
self.groundY = 2500;
self.hasLanded = false;
self.lifetime = 0;
self.maxLifetime = 600; // 10 seconds
self.lastIntersecting = false;
self.pulseTimer = 0;
self.update = function () {
// Apply gravity until hitting ground
if (!self.hasLanded) {
self.velocityY += self.gravity;
self.y += self.velocityY;
// Check ground collision
if (self.y >= self.groundY) {
self.y = self.groundY;
self.hasLanded = true;
self.velocityY = 0;
}
}
// Pulse animation when on ground
if (self.hasLanded) {
self.pulseTimer++;
var pulseScale = 1 + Math.sin(self.pulseTimer * 0.2) * 0.2;
healthPackGraphics.scaleX = pulseScale;
healthPackGraphics.scaleY = pulseScale;
self.lifetime++;
// Check collision with monster
var currentIntersecting = self.intersects(monster);
if (!self.lastIntersecting && currentIntersecting) {
// Monster picks up health pack
monster.health += 100;
if (monster.health > monster.maxHealth) {
monster.health = monster.maxHealth;
}
LK.getSound('health_pickup').play();
LK.effects.flashObject(monster, 0x00ff00, 500);
self.destroy();
healthPacks.splice(healthPacks.indexOf(self), 1);
return;
}
self.lastIntersecting = currentIntersecting;
// Fade out near end of lifetime
if (self.lifetime > self.maxLifetime - 120) {
healthPackGraphics.alpha = (self.maxLifetime - self.lifetime) / 120;
}
// Remove after lifetime expires
if (self.lifetime >= self.maxLifetime) {
self.destroy();
healthPacks.splice(healthPacks.indexOf(self), 1);
}
}
};
return self;
});
var Helicopter = Container.expand(function () {
var self = Container.call(this);
var helicopterGraphics = self.attachAsset('helicopter', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 3;
self.targetX = 0;
self.hasDropped = false;
self.rotorTimer = 0;
self.update = function () {
// Rotor animation
self.rotorTimer++;
if (self.rotorTimer < 10) {
helicopterGraphics.scaleY = 0.8;
} else if (self.rotorTimer < 20) {
helicopterGraphics.scaleY = 1.2;
} else {
self.rotorTimer = 0;
}
// Move towards target
if (self.x < self.targetX) {
self.x += self.speed;
} else if (self.x > self.targetX) {
self.x -= self.speed;
}
// Drop health pack when close to target
if (!self.hasDropped && Math.abs(self.x - self.targetX) < 20) {
self.dropHealthPack();
self.hasDropped = true;
}
// If this is a Zeus pack helicopter, destroy after dropping
if (self.hasDropped && self.isZeusPack) {
tween(self, {
alpha: 0,
scaleX: 0.5,
scaleY: 0.5
}, {
duration: 1000,
onFinish: function onFinish() {
self.destroy();
helicopters.splice(helicopters.indexOf(self), 1);
}
});
self.isZeusPack = false; // Prevent multiple tweens
}
// Remove if off screen after dropping
if (self.hasDropped && !self.isZeusPack && (self.x < -100 || self.x > 2148)) {
self.destroy();
helicopters.splice(helicopters.indexOf(self), 1);
}
};
self.dropHealthPack = function () {
// If this is a Zeus pack helicopter, always drop Zeus pack
if (self.isZeusPack) {
var zeusPack = new ZeusPack();
zeusPack.x = self.x;
zeusPack.y = self.y + 50;
zeusPacks.push(zeusPack);
game.addChild(zeusPack);
} else {
var healthPack = new HealthPack();
healthPack.x = self.x;
healthPack.y = self.y + 50;
healthPacks.push(healthPack);
game.addChild(healthPack);
}
};
return self;
});
var LavaParticle = Container.expand(function () {
var self = Container.call(this);
var lavaGraphics = self.attachAsset('lava', {
anchorX: 0.5,
anchorY: 0.5
});
self.velocityX = 0;
self.velocityY = 0;
self.gravity = 0.5;
self.bounceCount = 0;
self.maxBounces = 2;
self.update = function () {
self.velocityY += self.gravity;
self.x += self.velocityX;
self.y += self.velocityY;
// Bounce on ground
if (self.y >= 2500 && self.velocityY > 0) {
if (self.bounceCount < self.maxBounces) {
self.velocityY *= -0.6;
self.velocityX *= 0.8;
self.bounceCount++;
} else {
self.velocityY = 0;
self.velocityX = 0;
}
}
// Fade out over time
lavaGraphics.alpha -= 0.01;
// Remove when faded or off screen
if (lavaGraphics.alpha <= 0 || self.x < -50 || self.x > 2098 || self.y > 2600) {
self.destroy();
lavaParticles.splice(lavaParticles.indexOf(self), 1);
}
};
return self;
});
var Lightning = Container.expand(function () {
var self = Container.call(this);
var lightningGraphics = self.attachAsset('lightning', {
anchorX: 0.5,
anchorY: 0.0
});
self.duration = 0;
self.maxDuration = 10; // Very short flash
self.hasStruck = false;
self.update = function () {
self.duration++;
// Check for strikes only once when lightning appears
if (!self.hasStruck && self.duration === 1) {
self.hasStruck = true;
// Check if lightning hits any buildings
for (var i = buildings.length - 1; i >= 0; i--) {
var building = buildings[i];
if (Math.abs(self.x - building.x) < 60) {
// Lightning width tolerance
// Building hit by lightning - explode and destroy
LK.effects.flashScreen(0xffff00, 500);
tween(building, {
scaleX: 1.5,
scaleY: 1.5,
alpha: 0
}, {
duration: 300,
onFinish: function onFinish() {
building.destroy();
buildings.splice(buildings.indexOf(building), 1);
buildingsDestroyed++;
}
});
break;
}
}
// Check if lightning hits monster
if (Math.abs(self.x - monster.x) < 90) {
// Monster width tolerance
// Monster hit by lightning - burp/roar
LK.getSound('burp').play();
LK.effects.flashObject(monster, 0xffff00, 400);
tween(monster, {
scaleX: 1.3,
scaleY: 0.8
}, {
duration: 150,
onFinish: function onFinish() {
tween(monster, {
scaleX: 1,
scaleY: 1
}, {
duration: 150
});
}
});
}
}
// Flash effect
if (self.duration < 5) {
lightningGraphics.alpha = 1.0;
} else {
lightningGraphics.alpha = 0.5;
}
// Remove after duration
if (self.duration >= self.maxDuration) {
self.destroy();
lightningBolts.splice(lightningBolts.indexOf(self), 1);
}
};
return self;
});
var Monster = Container.expand(function () {
var self = Container.call(this);
var monsterGraphics = self.attachAsset('monster', {
anchorX: 0.5,
anchorY: 1.0
});
self.velocityY = 0;
self.isJumping = false;
self.minJumpPower = -15;
self.maxJumpPower = -35; // Higher than tallest building (240px)
self.gravity = 1.2;
self.groundY = 2500;
self.speed = 8;
self.health = 300;
self.maxHealth = 300;
self.isCharging = false;
self.chargeStartTime = 0;
self.maxChargeTime = 60; // 1 second at 60fps
self.update = function () {
// Apply gravity
self.velocityY += self.gravity;
self.y += self.velocityY;
// Ground collision
if (self.y >= self.groundY) {
self.y = self.groundY;
self.velocityY = 0;
self.isJumping = false;
}
// Keep monster on screen
if (self.x < 90) self.x = 90;
if (self.x > 1958) self.x = 1958;
};
self.startCharging = function () {
if (!self.isJumping && !self.isCharging) {
self.isCharging = true;
self.chargeStartTime = LK.ticks;
}
};
self.jump = function () {
if (self.isCharging) {
var chargeTime = Math.min(LK.ticks - self.chargeStartTime, self.maxChargeTime);
var chargeRatio = chargeTime / self.maxChargeTime;
var jumpPower = self.minJumpPower + (self.maxJumpPower - self.minJumpPower) * chargeRatio;
self.velocityY = jumpPower;
self.isJumping = true;
self.isCharging = false;
}
};
self.takeDamage = function (damage, projectileType) {
self.health -= damage;
if (self.health <= 0) {
self.health = 0;
LK.showGameOver();
}
// Flash red when taking damage
LK.effects.flashObject(self, 0xff0000, 500);
// Different effects based on projectile type
if (projectileType === 'arrow') {
// Light scream for arrow
LK.getSound('attack').play();
} else if (projectileType === 'cannonball') {
// Explosion effect and stronger roar for cannonball
LK.effects.flashScreen(0xff4400, 300);
tween(self, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 200,
onFinish: function onFinish() {
tween(self, {
scaleX: 1,
scaleY: 1
}, {
duration: 200
});
}
});
LK.getSound('boss_hit').play();
} else if (projectileType === 'rocket') {
// Dinosaur roars loudly and big explosion for rocket
LK.effects.flashScreen(0xff0000, 500);
tween(self, {
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 300,
onFinish: function onFinish() {
tween(self, {
scaleX: 1,
scaleY: 1
}, {
duration: 300
});
}
});
LK.getSound('stomp').play();
}
};
return self;
});
var Projectile = Container.expand(function () {
var self = Container.call(this);
self.type = 'rocket'; // 'rocket', 'cannonball', 'arrow'
self.speed = 5;
self.damage = 10;
self.lastIntersecting = false;
self.velocityX = 0;
self.velocityY = 0;
self.update = function () {
// Move projectile
self.x += self.velocityX;
self.y += self.velocityY;
// Check collision with monster
var currentIntersecting = self.intersects(monster);
if (!self.lastIntersecting && currentIntersecting) {
monster.takeDamage(self.damage, self.type);
self.destroy();
projectiles.splice(projectiles.indexOf(self), 1);
}
self.lastIntersecting = currentIntersecting;
// Remove if off screen
if (self.x < -50 || self.x > 2098 || self.y < -50 || self.y > 2782) {
self.destroy();
projectiles.splice(projectiles.indexOf(self), 1);
}
};
return self;
});
var Sun = Container.expand(function () {
var self = Container.call(this);
var sunGraphics = self.attachAsset('sun', {
anchorX: 0.5,
anchorY: 0.5
});
self.isDay = true;
self.cycleTimer = 0;
self.cycleDuration = 1800; // 30 seconds for full day/night cycle
self.update = function () {
self.cycleTimer++;
// Calculate sun position in arc across sky
var cycleProgress = self.cycleTimer / self.cycleDuration;
var angle = cycleProgress * Math.PI * 2;
// Sun moves in arc across top of screen
self.x = 1024 + Math.cos(angle) * 800;
self.y = 400 + Math.sin(angle) * 200;
// Determine if it's day or night based on sun position
var wasDay = self.isDay;
self.isDay = self.y < 600; // Day when sun is high
// Update sky brightness based on sun position
if (self.isDay) {
skyBrightness = 0.7 + (600 - self.y) / 600 * 0.3;
} else {
skyBrightness = 0.3 + (self.y - 600) / 600 * 0.2;
}
// Clamp brightness values
if (skyBrightness > 1.0) skyBrightness = 1.0;
if (skyBrightness < 0.3) skyBrightness = 0.3;
// Reset cycle
if (self.cycleTimer >= self.cycleDuration) {
self.cycleTimer = 0;
}
// Show/hide sun based on position
sunGraphics.alpha = self.y < 700 ? 1.0 : 0.0;
};
return self;
});
var Tornado = Container.expand(function () {
var self = Container.call(this);
var tornadoGraphics = self.attachAsset('tornado', {
anchorX: 0.5,
anchorY: 1.0
});
self.speed = Math.random() * 2 + 1;
self.direction = Math.random() > 0.5 ? 1 : -1;
self.rotationSpeed = 0.2;
self.lifetime = 0;
self.maxLifetime = 600; // 10 seconds
self.update = function () {
// Move horizontally (left/right)
self.x += self.speed * self.direction;
// Bounce off screen edges
if (self.x <= 0 || self.x >= 2048) {
self.direction *= -1;
}
self.lifetime++;
// Fade out as it ages
tornadoGraphics.alpha = 1 - self.lifetime / self.maxLifetime;
// Vertical movement pattern: ground to clouds to ground
var cycleDuration = 200; // How long each cycle takes
var cyclePosition = self.lifetime % cycleDuration / cycleDuration;
var baseY = 2500; // Ground level
var cloudY = 800; // Cloud level
// Create wave pattern: 0 -> 1 -> 0 over cycle
var waveValue = Math.sin(cyclePosition * Math.PI * 2);
// Convert wave to vertical position
if (waveValue >= 0) {
// Moving up from ground to clouds
self.y = baseY - waveValue * (baseY - cloudY);
} else {
// Moving down from clouds to ground
self.y = cloudY + Math.abs(waveValue) * (baseY - cloudY);
}
// Check collision with buildings
for (var i = buildings.length - 1; i >= 0; i--) {
var building = buildings[i];
if (self.intersects(building)) {
self.shrinkBuilding(building);
}
}
// Remove when lifetime is over or off screen
if (self.lifetime >= self.maxLifetime || self.x < -100 || self.x > 2148) {
self.destroy();
tornadoes.splice(tornadoes.indexOf(self), 1);
}
};
self.shrinkBuilding = function (building) {
if (building.heightLevel > 1) {
building.heightLevel--;
LK.getSound('tornado_wind').play();
LK.effects.flashObject(building, 0x696969, 200);
// Replace with smaller building
var oldGraphics = building.children[0];
if (oldGraphics) {
building.removeChild(oldGraphics);
}
var newGraphics = building.attachAsset(building.assetNames[building.heightLevel - 1], {
anchorX: 0.5,
anchorY: 1.0
});
// Spin effect
tween(building, {
rotation: Math.PI * 2
}, {
duration: 500,
onFinish: function onFinish() {
building.rotation = 0;
}
});
} else {
// Building completely destroyed by tornado
building.destroy();
buildings.splice(buildings.indexOf(building), 1);
buildingsDestroyed++;
}
};
return self;
});
var Volcano = Container.expand(function () {
var self = Container.call(this);
var volcanoGraphics = self.attachAsset('volcano', {
anchorX: 0.5,
anchorY: 1.0
});
self.eruptionCooldown = 0;
self.maxEruptionCooldown = 1200; // 20 seconds
self.isErupting = false;
self.eruptionDuration = 0;
self.maxEruptionDuration = 180; // 3 seconds
self.update = function () {
if (self.eruptionCooldown > 0) {
self.eruptionCooldown--;
}
if (self.isErupting) {
self.eruptionDuration++;
// Spawn lava particles during eruption
if (self.eruptionDuration % 3 === 0) {
self.spawnLava();
}
// Flash volcano red during eruption
volcanoGraphics.tint = 0xFF4500;
if (self.eruptionDuration >= self.maxEruptionDuration) {
self.isErupting = false;
self.eruptionDuration = 0;
self.eruptionCooldown = self.maxEruptionCooldown;
volcanoGraphics.tint = 0xFFFFFF;
}
} else if (self.eruptionCooldown <= 0 && Math.random() < 0.005) {
self.startEruption();
}
};
self.startEruption = function () {
self.isErupting = true;
self.eruptionDuration = 0;
LK.getSound('volcano_eruption').play();
LK.effects.flashScreen(0xFF4500, 300);
// Shake effect
tween(self, {
x: self.x + 10
}, {
duration: 100,
onFinish: function onFinish() {
tween(self, {
x: self.x - 10
}, {
duration: 100,
onFinish: function onFinish() {
tween(self, {
x: self.x
}, {
duration: 100
});
}
});
}
});
};
self.spawnLava = function () {
var lava = new LavaParticle();
lava.x = self.x + (Math.random() - 0.5) * 50;
lava.y = self.y - 150;
lava.velocityX = (Math.random() - 0.5) * 8;
lava.velocityY = -(Math.random() * 8 + 5);
lavaParticles.push(lava);
game.addChild(lava);
};
return self;
});
var WeatherParticle = Container.expand(function () {
var self = Container.call(this);
self.type = 'rain'; // 'rain' or 'snow'
self.speed = 0;
self.particleGraphics = null;
self.init = function (type) {
self.type = type;
if (type === 'rain') {
self.particleGraphics = self.attachAsset('rainDrop', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = Math.random() * 8 + 12;
} else {
self.particleGraphics = self.attachAsset('snowFlake', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = Math.random() * 3 + 2;
}
};
self.update = function () {
self.y += self.speed;
if (self.type === 'snow') {
self.x += Math.sin(self.y * 0.01) * 0.5;
}
// Remove if off screen
if (self.y > 2782) {
self.destroy();
weatherParticles.splice(weatherParticles.indexOf(self), 1);
}
};
return self;
});
var ZeusPack = Container.expand(function () {
var self = Container.call(this);
var zeusPackGraphics = self.attachAsset('zeusPack', {
anchorX: 0.5,
anchorY: 0.5
});
self.velocityY = 0;
self.gravity = 0.8;
self.groundY = 2500;
self.hasLanded = false;
self.lifetime = 0;
self.maxLifetime = 600; // 10 seconds
self.lastIntersecting = false;
self.pulseTimer = 0;
self.update = function () {
// Apply gravity until hitting ground
if (!self.hasLanded) {
self.velocityY += self.gravity;
self.y += self.velocityY;
// Check ground collision
if (self.y >= self.groundY) {
self.y = self.groundY;
self.hasLanded = true;
self.velocityY = 0;
}
}
// Pulse animation when on ground
if (self.hasLanded) {
self.pulseTimer++;
var pulseScale = 1 + Math.sin(self.pulseTimer * 0.3) * 0.3;
zeusPackGraphics.scaleX = pulseScale;
zeusPackGraphics.scaleY = pulseScale;
// Golden glow effect
zeusPackGraphics.tint = 0xFFD700;
self.lifetime++;
// Check collision with monster
var currentIntersecting = self.intersects(monster);
if (!self.lastIntersecting && currentIntersecting) {
// Monster picks up Zeus pack
self.activateZeusPower();
self.destroy();
zeusPacks.splice(zeusPacks.indexOf(self), 1);
return;
}
self.lastIntersecting = currentIntersecting;
// Fade out near end of lifetime
if (self.lifetime > self.maxLifetime - 120) {
zeusPackGraphics.alpha = (self.maxLifetime - self.lifetime) / 120;
}
// Remove after lifetime expires
if (self.lifetime >= self.maxLifetime) {
self.destroy();
zeusPacks.splice(zeusPacks.indexOf(self), 1);
}
}
};
self.activateZeusPower = function () {
LK.getSound('zeus_power').play();
LK.effects.flashScreen(0xFFD700, 800);
LK.effects.flashObject(monster, 0xFFD700, 1000);
// Destroy all enemies with lightning effect
for (var i = buildings.length - 1; i >= 0; i--) {
var building = buildings[i];
self.strikeWithLightning(building);
}
if (boss) {
self.strikeWithLightning(boss);
}
// Stop enemy spawning for 10 seconds
enemySpawnBlocked = true;
enemySpawnBlockTimer = 600; // 10 seconds at 60fps
};
self.strikeWithLightning = function (target) {
// Create lightning effect
var lightning = new Lightning();
lightning.x = target.x;
lightning.y = 0;
lightningBolts.push(lightning);
game.addChild(lightning);
// Destroy target with delay
LK.setTimeout(function () {
if (target === boss) {
boss.takeDamage(999);
} else {
target.destroy();
buildings.splice(buildings.indexOf(target), 1);
buildingsDestroyed++;
}
}, 100);
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87ceeb
});
/****
* Game Code
****/
var monster;
var buildings = [];
var projectiles = [];
var boss = null;
var buildingsDestroyed = 0;
var level = 1;
var spawnTimer = 0;
var maxSpawnTimer = 180;
var birds = [];
var clouds = [];
var weatherParticles = [];
var skyBrightness = 1.0;
var skyDirection = -1;
var weatherType = 'none'; // 'none', 'rain', 'snow'
var weatherTimer = 0;
var weatherDuration = 0;
var birdSpawnTimer = 0;
var cloudSpawnTimer = 0;
var lightningBolts = [];
var lightningTimer = 0;
var lightningCooldown = 0;
var volcano = null;
var lavaParticles = [];
var tornadoes = [];
var tornadoTimer = 0;
var tornadoCooldown = 0;
var helicopters = [];
var healthPacks = [];
var helicopterCooldown = 0;
var lastHealthCheckTrigger = false;
var sun = null;
var lightningTargetCounter = 0;
var zeusPacks = [];
var zeusPackCooldown = 0;
var enemySpawnBlocked = false;
var enemySpawnBlockTimer = 0;
var lastZeusHealthTrigger = false;
var zeusPackTimer = 0;
var zeusPackSpawnCooldown = 1500; // 25 seconds at 60fps
// Create ground
var ground = game.addChild(LK.getAsset('ground', {
anchorX: 0.5,
anchorY: 1.0,
x: 1024,
y: 2600
}));
// Create monster
monster = game.addChild(new Monster());
monster.x = 1024;
monster.y = 2500;
// Create score display
var scoreTxt = new Text2('Score: 0', {
size: 80,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Create health display
var healthTxt = new Text2('Health: 300', {
size: 60,
fill: 0xFF0000
});
healthTxt.anchor.set(0, 0);
healthTxt.x = 120;
healthTxt.y = 120;
LK.gui.topLeft.addChild(healthTxt);
// Create level display
var levelTxt = new Text2('Level: 1', {
size: 60,
fill: 0xFFFFFF
});
levelTxt.anchor.set(1, 0);
LK.gui.topRight.addChild(levelTxt);
// Create volcano in corner
volcano = new Volcano();
volcano.x = 150;
volcano.y = 2500;
game.addChild(volcano);
// Create sun
sun = new Sun();
game.addChild(sun);
function spawnBuilding() {
var building = new Building();
var spawnX = Math.random() * 1800 + 124;
building.x = spawnX;
building.y = 2500;
buildings.push(building);
game.addChild(building);
}
function spawnBoss() {
boss = new Boss();
boss.x = 1024;
boss.y = 2500;
game.addChild(boss);
}
function spawnBird() {
var bird = new Bird();
bird.x = bird.direction > 0 ? -50 : 2098;
bird.y = Math.random() * 800 + 200;
birds.push(bird);
game.addChild(bird);
}
function spawnCloud() {
var cloud = new Cloud();
cloud.x = -150;
cloud.y = Math.random() * 600 + 100;
clouds.push(cloud);
game.addChild(cloud);
}
function spawnWeatherParticle() {
if (weatherType !== 'none') {
var particle = new WeatherParticle();
particle.init(weatherType);
particle.x = Math.random() * 2048;
particle.y = -20;
weatherParticles.push(particle);
game.addChild(particle);
}
}
function spawnLightning() {
// Play thunder sound first
LK.getSound('thunder').play();
// Flash screen white briefly for lightning
LK.effects.flashScreen(0xffffff, 200);
// Create lightning bolt
var lightning = new Lightning();
// Every second lightning targets the monster
lightningTargetCounter++;
if (lightningTargetCounter % 2 === 0) {
// Target monster
lightning.x = monster.x;
} else {
// Random position
lightning.x = Math.random() * 1800 + 124;
}
lightning.y = 0;
lightningBolts.push(lightning);
game.addChild(lightning);
}
function spawnTornado() {
var tornado = new Tornado();
tornado.x = tornado.direction > 0 ? -100 : 2148;
tornado.y = 2500;
tornadoes.push(tornado);
game.addChild(tornado);
LK.getSound('tornado_wind').play();
}
function spawnHelicopter() {
var helicopter = new Helicopter();
helicopter.x = -120;
helicopter.y = 400;
helicopter.targetX = monster.x;
helicopters.push(helicopter);
game.addChild(helicopter);
LK.getSound('helicopter_sound').play();
}
function spawnZeusPackHelicopter() {
var helicopter = new Helicopter();
helicopter.x = -120;
helicopter.y = 400;
helicopter.targetX = monster.x;
helicopter.isZeusPack = true; // Mark as Zeus pack helicopter
helicopters.push(helicopter);
game.addChild(helicopter);
LK.getSound('helicopter_sound').play();
}
function updateSky() {
// Sky brightness is now controlled by sun position
var skyColor = Math.floor(135 * skyBrightness) << 16 | Math.floor(206 * skyBrightness) << 8 | Math.floor(235 * skyBrightness);
game.setBackgroundColor(skyColor);
}
function updateWeather() {
weatherTimer++;
if (weatherTimer >= weatherDuration) {
// Change weather
var weatherTypes = ['none', 'rain', 'snow'];
weatherType = weatherTypes[Math.floor(Math.random() * 3)];
weatherTimer = 0;
weatherDuration = Math.random() * 1800 + 600; // 10-40 seconds
}
}
function startLevel() {
buildingsDestroyed = 0;
levelTxt.setText('Level: ' + level);
// Clear existing entities
for (var i = buildings.length - 1; i >= 0; i--) {
buildings[i].destroy();
}
buildings = [];
for (var j = projectiles.length - 1; j >= 0; j--) {
projectiles[j].destroy();
}
projectiles = [];
if (boss) {
boss.destroy();
boss = null;
}
// Spawn initial buildings
for (var k = 0; k < 3; k++) {
LK.setTimeout(function () {
spawnBuilding();
}, k * 1000);
}
}
// Start first level
startLevel();
// Game controls
game.down = function (x, y, obj) {
monster.startCharging();
};
game.up = function (x, y, obj) {
monster.jump();
};
game.move = function (x, y, obj) {
// Move monster towards touch position
if (x < monster.x) {
monster.x -= monster.speed;
} else if (x > monster.x) {
monster.x += monster.speed;
}
};
// Keyboard state tracking
var keys = {
ArrowLeft: false,
ArrowRight: false,
Space: false
};
// Main game loop
game.update = function () {
// Handle keyboard input (fallback to touch controls for mobile)
// Note: Keyboard controls are not available in LK sandbox, using touch controls instead
// Update score display
scoreTxt.setText('Score: ' + LK.getScore());
// Update health display
healthTxt.setText('Health: ' + monster.health);
// Update sky brightness
updateSky();
// Update weather
updateWeather();
// Spawn birds periodically
birdSpawnTimer++;
if (birdSpawnTimer >= 240) {
// Every 4 seconds
spawnBird();
birdSpawnTimer = 0;
}
// Spawn clouds periodically
cloudSpawnTimer++;
if (cloudSpawnTimer >= 300) {
// Every 5 seconds
spawnCloud();
cloudSpawnTimer = 0;
}
// Spawn weather particles
if (weatherType !== 'none' && Math.random() < 0.3) {
spawnWeatherParticle();
}
// Lightning and thunder system
lightningTimer++;
if (lightningCooldown > 0) {
lightningCooldown--;
}
// Chance for lightning during storms or dark sky
if (lightningCooldown <= 0 && (weatherType === 'rain' || skyBrightness < 0.6)) {
if (Math.random() < 0.008) {
// Small chance each frame
spawnLightning();
lightningCooldown = 180 + Math.random() * 300; // 3-8 seconds cooldown
}
}
// Tornado system
tornadoTimer++;
if (tornadoCooldown > 0) {
tornadoCooldown--;
}
// Chance for tornado during storms
if (tornadoCooldown <= 0 && weatherType !== 'none') {
if (Math.random() < 0.003) {
spawnTornado();
tornadoCooldown = 900 + Math.random() * 600; // 15-25 seconds cooldown
}
}
// Helicopter system - spawn when monster health drops to 50 or below
if (helicopterCooldown > 0) {
helicopterCooldown--;
}
var currentHealthTrigger = monster.health <= 50;
if (!lastHealthCheckTrigger && currentHealthTrigger && helicopterCooldown <= 0) {
spawnHelicopter();
helicopterCooldown = 1800; // 30 seconds cooldown
}
lastHealthCheckTrigger = currentHealthTrigger;
// Zeus pack timer system - spawn every 15 seconds
zeusPackTimer++;
if (zeusPackTimer >= zeusPackSpawnCooldown) {
spawnZeusPackHelicopter();
zeusPackTimer = 0;
}
// Handle Zeus pack spawn blocking
if (enemySpawnBlocked) {
enemySpawnBlockTimer--;
if (enemySpawnBlockTimer <= 0) {
enemySpawnBlocked = false;
}
}
// Spawn new buildings periodically (blocked during Zeus power)
if (!boss && buildings.length < 5 && !enemySpawnBlocked) {
spawnTimer++;
if (spawnTimer >= maxSpawnTimer) {
spawnBuilding();
spawnTimer = 0;
}
}
// Check for boss spawn condition (blocked during Zeus power)
if (!boss && buildingsDestroyed >= 5 + level * 2 && !enemySpawnBlocked) {
spawnBoss();
}
// Remove destroyed projectiles
for (var i = projectiles.length - 1; i >= 0; i--) {
if (!projectiles[i].parent) {
projectiles.splice(i, 1);
}
}
// Remove destroyed buildings
for (var j = buildings.length - 1; j >= 0; j--) {
if (!buildings[j].parent) {
buildings.splice(j, 1);
}
}
// Remove destroyed birds
for (var k = birds.length - 1; k >= 0; k--) {
if (!birds[k].parent) {
birds.splice(k, 1);
}
}
// Remove destroyed clouds
for (var l = clouds.length - 1; l >= 0; l--) {
if (!clouds[l].parent) {
clouds.splice(l, 1);
}
}
// Remove destroyed weather particles
for (var m = weatherParticles.length - 1; m >= 0; m--) {
if (!weatherParticles[m].parent) {
weatherParticles.splice(m, 1);
}
}
// Remove destroyed lightning bolts
for (var n = lightningBolts.length - 1; n >= 0; n--) {
if (!lightningBolts[n].parent) {
lightningBolts.splice(n, 1);
}
}
// Remove destroyed lava particles
for (var o = lavaParticles.length - 1; o >= 0; o--) {
if (!lavaParticles[o].parent) {
lavaParticles.splice(o, 1);
}
}
// Remove destroyed tornadoes
for (var p = tornadoes.length - 1; p >= 0; p--) {
if (!tornadoes[p].parent) {
tornadoes.splice(p, 1);
}
}
// Remove destroyed helicopters
for (var q = helicopters.length - 1; q >= 0; q--) {
if (!helicopters[q].parent) {
helicopters.splice(q, 1);
}
}
// Remove destroyed health packs
for (var r = healthPacks.length - 1; r >= 0; r--) {
if (!healthPacks[r].parent) {
healthPacks.splice(r, 1);
}
}
// Remove destroyed Zeus packs
for (var s = zeusPacks.length - 1; s >= 0; s--) {
if (!zeusPacks[s].parent) {
zeusPacks.splice(s, 1);
}
}
}; /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Bird = Container.expand(function () {
var self = Container.call(this);
var birdGraphics = self.attachAsset('bird', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = Math.random() * 2 + 1;
self.direction = Math.random() > 0.5 ? 1 : -1;
self.flapTimer = 0;
self.update = function () {
self.x += self.speed * self.direction;
// Flap animation
self.flapTimer++;
if (self.flapTimer < 15) {
birdGraphics.scaleY = 0.8;
} else if (self.flapTimer < 30) {
birdGraphics.scaleY = 1.2;
} else {
self.flapTimer = 0;
}
// Remove if off screen
if (self.x < -50 || self.x > 2098) {
self.destroy();
birds.splice(birds.indexOf(self), 1);
}
};
return self;
});
var Boss = Container.expand(function () {
var self = Container.call(this);
var bossGraphics = self.attachAsset('boss', {
anchorX: 0.5,
anchorY: 1.0
});
self.health = 300;
self.maxHealth = 300;
self.speed = 1.5;
self.attackDamage = 20;
self.attackCooldown = 0;
self.maxAttackCooldown = 120;
self.direction = 1;
self.lastIntersecting = false;
self.update = function () {
// Move back and forth
self.x += self.speed * self.direction;
if (self.x <= 200 || self.x >= 1848) {
self.direction *= -1;
}
// Attack monster
if (self.attackCooldown > 0) {
self.attackCooldown--;
}
var currentIntersecting = self.intersects(monster);
if (currentIntersecting && self.attackCooldown <= 0) {
monster.takeDamage(self.attackDamage);
LK.getSound('attack').play();
self.attackCooldown = self.maxAttackCooldown;
}
// Check if monster jumps on boss - monster takes no damage when landing on boss
if (!self.lastIntersecting && currentIntersecting && monster.velocityY > 0) {
self.takeDamage(50);
// Monster doesn't take damage when landing on boss
}
self.lastIntersecting = currentIntersecting;
};
self.takeDamage = function (damage) {
self.health -= damage;
LK.getSound('boss_hit').play();
LK.effects.flashObject(self, 0xff0000, 300);
if (self.health <= 0) {
LK.setScore(LK.getScore() + 1000);
self.destroy();
boss = null;
level++;
startLevel();
}
};
return self;
});
var Building = Container.expand(function () {
var self = Container.call(this);
self.heightLevel = Math.floor(Math.random() * 3) + 1; // 1, 2, or 3
self.assetNames = ['building_small', 'building_medium', 'building_large'];
self.buildingHeights = [80, 160, 240];
self.buildingType = Math.floor(Math.random() * 3); // 0=tech, 1=ottoman, 2=cave
self.buildingTypes = ['tech', 'ottoman', 'cave'];
self.projectileTypes = ['rocket', 'cannonball', 'arrow'];
self.attackCooldown = 0;
self.maxAttackCooldown = 450; // 7.5 seconds at 60fps
var buildingGraphics = self.attachAsset(self.assetNames[self.heightLevel - 1], {
anchorX: 0.5,
anchorY: 1.0
});
self.lastIntersecting = false;
self.update = function () {
// Check collision with monster
var currentIntersecting = self.intersects(monster);
if (!self.lastIntersecting && currentIntersecting && monster.velocityY > 0) {
self.stomp();
}
self.lastIntersecting = currentIntersecting;
// Attack monster with projectiles
if (self.attackCooldown > 0) {
self.attackCooldown--;
}
if (self.attackCooldown <= 0) {
self.fireProjectile();
self.attackCooldown = self.maxAttackCooldown;
}
};
self.stomp = function () {
LK.getSound('stomp').play();
LK.setScore(LK.getScore() + 10);
// Monster doesn't take damage when stomping on buildings
// Shrink building by one level
self.heightLevel--;
if (self.heightLevel <= 0) {
// Building destroyed
self.destroy();
buildings.splice(buildings.indexOf(self), 1);
buildingsDestroyed++;
} else {
// Replace with smaller building
self.removeChild(buildingGraphics);
buildingGraphics = self.attachAsset(self.assetNames[self.heightLevel - 1], {
anchorX: 0.5,
anchorY: 1.0
});
}
};
self.fireProjectile = function () {
var projectile = new Projectile();
// Fire projectile based on building height level: 3=rocket, 2=cannonball, 1=arrow
if (self.heightLevel === 3) {
projectile.type = 'rocket';
} else if (self.heightLevel === 2) {
projectile.type = 'cannonball';
} else {
projectile.type = 'arrow';
}
var projectileGraphics = projectile.attachAsset(projectile.type, {
anchorX: 0.5,
anchorY: 0.5
});
projectile.x = self.x;
projectile.y = self.y - self.buildingHeights[self.heightLevel - 1] / 2;
// Calculate direction to monster
var dx = monster.x - projectile.x;
var dy = monster.y - projectile.y;
var distance = Math.sqrt(dx * dx + dy * dy);
projectile.velocityX = dx / distance * projectile.speed;
projectile.velocityY = dy / distance * projectile.speed;
// Rotate projectile to face monster
projectileGraphics.rotation = Math.atan2(dy, dx);
projectiles.push(projectile);
game.addChild(projectile);
};
return self;
});
var Cloud = Container.expand(function () {
var self = Container.call(this);
var cloudGraphics = self.attachAsset('cloud', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = Math.random() * 0.5 + 0.2;
self.alpha = Math.random() * 0.4 + 0.6;
cloudGraphics.alpha = self.alpha;
self.update = function () {
self.x += self.speed;
// Remove if off screen
if (self.x > 2098 + 150) {
self.destroy();
clouds.splice(clouds.indexOf(self), 1);
}
};
return self;
});
var HealthPack = Container.expand(function () {
var self = Container.call(this);
var healthPackGraphics = self.attachAsset('healthPack', {
anchorX: 0.5,
anchorY: 0.5
});
self.velocityY = 0;
self.gravity = 0.8;
self.groundY = 2500;
self.hasLanded = false;
self.lifetime = 0;
self.maxLifetime = 600; // 10 seconds
self.lastIntersecting = false;
self.pulseTimer = 0;
self.update = function () {
// Apply gravity until hitting ground
if (!self.hasLanded) {
self.velocityY += self.gravity;
self.y += self.velocityY;
// Check ground collision
if (self.y >= self.groundY) {
self.y = self.groundY;
self.hasLanded = true;
self.velocityY = 0;
}
}
// Pulse animation when on ground
if (self.hasLanded) {
self.pulseTimer++;
var pulseScale = 1 + Math.sin(self.pulseTimer * 0.2) * 0.2;
healthPackGraphics.scaleX = pulseScale;
healthPackGraphics.scaleY = pulseScale;
self.lifetime++;
// Check collision with monster
var currentIntersecting = self.intersects(monster);
if (!self.lastIntersecting && currentIntersecting) {
// Monster picks up health pack
monster.health += 100;
if (monster.health > monster.maxHealth) {
monster.health = monster.maxHealth;
}
LK.getSound('health_pickup').play();
LK.effects.flashObject(monster, 0x00ff00, 500);
self.destroy();
healthPacks.splice(healthPacks.indexOf(self), 1);
return;
}
self.lastIntersecting = currentIntersecting;
// Fade out near end of lifetime
if (self.lifetime > self.maxLifetime - 120) {
healthPackGraphics.alpha = (self.maxLifetime - self.lifetime) / 120;
}
// Remove after lifetime expires
if (self.lifetime >= self.maxLifetime) {
self.destroy();
healthPacks.splice(healthPacks.indexOf(self), 1);
}
}
};
return self;
});
var Helicopter = Container.expand(function () {
var self = Container.call(this);
var helicopterGraphics = self.attachAsset('helicopter', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 3;
self.targetX = 0;
self.hasDropped = false;
self.rotorTimer = 0;
self.update = function () {
// Rotor animation
self.rotorTimer++;
if (self.rotorTimer < 10) {
helicopterGraphics.scaleY = 0.8;
} else if (self.rotorTimer < 20) {
helicopterGraphics.scaleY = 1.2;
} else {
self.rotorTimer = 0;
}
// Move towards target
if (self.x < self.targetX) {
self.x += self.speed;
} else if (self.x > self.targetX) {
self.x -= self.speed;
}
// Drop health pack when close to target
if (!self.hasDropped && Math.abs(self.x - self.targetX) < 20) {
self.dropHealthPack();
self.hasDropped = true;
}
// If this is a Zeus pack helicopter, destroy after dropping
if (self.hasDropped && self.isZeusPack) {
tween(self, {
alpha: 0,
scaleX: 0.5,
scaleY: 0.5
}, {
duration: 1000,
onFinish: function onFinish() {
self.destroy();
helicopters.splice(helicopters.indexOf(self), 1);
}
});
self.isZeusPack = false; // Prevent multiple tweens
}
// Remove if off screen after dropping
if (self.hasDropped && !self.isZeusPack && (self.x < -100 || self.x > 2148)) {
self.destroy();
helicopters.splice(helicopters.indexOf(self), 1);
}
};
self.dropHealthPack = function () {
// If this is a Zeus pack helicopter, always drop Zeus pack
if (self.isZeusPack) {
var zeusPack = new ZeusPack();
zeusPack.x = self.x;
zeusPack.y = self.y + 50;
zeusPacks.push(zeusPack);
game.addChild(zeusPack);
} else {
var healthPack = new HealthPack();
healthPack.x = self.x;
healthPack.y = self.y + 50;
healthPacks.push(healthPack);
game.addChild(healthPack);
}
};
return self;
});
var LavaParticle = Container.expand(function () {
var self = Container.call(this);
var lavaGraphics = self.attachAsset('lava', {
anchorX: 0.5,
anchorY: 0.5
});
self.velocityX = 0;
self.velocityY = 0;
self.gravity = 0.5;
self.bounceCount = 0;
self.maxBounces = 2;
self.update = function () {
self.velocityY += self.gravity;
self.x += self.velocityX;
self.y += self.velocityY;
// Bounce on ground
if (self.y >= 2500 && self.velocityY > 0) {
if (self.bounceCount < self.maxBounces) {
self.velocityY *= -0.6;
self.velocityX *= 0.8;
self.bounceCount++;
} else {
self.velocityY = 0;
self.velocityX = 0;
}
}
// Fade out over time
lavaGraphics.alpha -= 0.01;
// Remove when faded or off screen
if (lavaGraphics.alpha <= 0 || self.x < -50 || self.x > 2098 || self.y > 2600) {
self.destroy();
lavaParticles.splice(lavaParticles.indexOf(self), 1);
}
};
return self;
});
var Lightning = Container.expand(function () {
var self = Container.call(this);
var lightningGraphics = self.attachAsset('lightning', {
anchorX: 0.5,
anchorY: 0.0
});
self.duration = 0;
self.maxDuration = 10; // Very short flash
self.hasStruck = false;
self.update = function () {
self.duration++;
// Check for strikes only once when lightning appears
if (!self.hasStruck && self.duration === 1) {
self.hasStruck = true;
// Check if lightning hits any buildings
for (var i = buildings.length - 1; i >= 0; i--) {
var building = buildings[i];
if (Math.abs(self.x - building.x) < 60) {
// Lightning width tolerance
// Building hit by lightning - explode and destroy
LK.effects.flashScreen(0xffff00, 500);
tween(building, {
scaleX: 1.5,
scaleY: 1.5,
alpha: 0
}, {
duration: 300,
onFinish: function onFinish() {
building.destroy();
buildings.splice(buildings.indexOf(building), 1);
buildingsDestroyed++;
}
});
break;
}
}
// Check if lightning hits monster
if (Math.abs(self.x - monster.x) < 90) {
// Monster width tolerance
// Monster hit by lightning - burp/roar
LK.getSound('burp').play();
LK.effects.flashObject(monster, 0xffff00, 400);
tween(monster, {
scaleX: 1.3,
scaleY: 0.8
}, {
duration: 150,
onFinish: function onFinish() {
tween(monster, {
scaleX: 1,
scaleY: 1
}, {
duration: 150
});
}
});
}
}
// Flash effect
if (self.duration < 5) {
lightningGraphics.alpha = 1.0;
} else {
lightningGraphics.alpha = 0.5;
}
// Remove after duration
if (self.duration >= self.maxDuration) {
self.destroy();
lightningBolts.splice(lightningBolts.indexOf(self), 1);
}
};
return self;
});
var Monster = Container.expand(function () {
var self = Container.call(this);
var monsterGraphics = self.attachAsset('monster', {
anchorX: 0.5,
anchorY: 1.0
});
self.velocityY = 0;
self.isJumping = false;
self.minJumpPower = -15;
self.maxJumpPower = -35; // Higher than tallest building (240px)
self.gravity = 1.2;
self.groundY = 2500;
self.speed = 8;
self.health = 300;
self.maxHealth = 300;
self.isCharging = false;
self.chargeStartTime = 0;
self.maxChargeTime = 60; // 1 second at 60fps
self.update = function () {
// Apply gravity
self.velocityY += self.gravity;
self.y += self.velocityY;
// Ground collision
if (self.y >= self.groundY) {
self.y = self.groundY;
self.velocityY = 0;
self.isJumping = false;
}
// Keep monster on screen
if (self.x < 90) self.x = 90;
if (self.x > 1958) self.x = 1958;
};
self.startCharging = function () {
if (!self.isJumping && !self.isCharging) {
self.isCharging = true;
self.chargeStartTime = LK.ticks;
}
};
self.jump = function () {
if (self.isCharging) {
var chargeTime = Math.min(LK.ticks - self.chargeStartTime, self.maxChargeTime);
var chargeRatio = chargeTime / self.maxChargeTime;
var jumpPower = self.minJumpPower + (self.maxJumpPower - self.minJumpPower) * chargeRatio;
self.velocityY = jumpPower;
self.isJumping = true;
self.isCharging = false;
}
};
self.takeDamage = function (damage, projectileType) {
self.health -= damage;
if (self.health <= 0) {
self.health = 0;
LK.showGameOver();
}
// Flash red when taking damage
LK.effects.flashObject(self, 0xff0000, 500);
// Different effects based on projectile type
if (projectileType === 'arrow') {
// Light scream for arrow
LK.getSound('attack').play();
} else if (projectileType === 'cannonball') {
// Explosion effect and stronger roar for cannonball
LK.effects.flashScreen(0xff4400, 300);
tween(self, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 200,
onFinish: function onFinish() {
tween(self, {
scaleX: 1,
scaleY: 1
}, {
duration: 200
});
}
});
LK.getSound('boss_hit').play();
} else if (projectileType === 'rocket') {
// Dinosaur roars loudly and big explosion for rocket
LK.effects.flashScreen(0xff0000, 500);
tween(self, {
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 300,
onFinish: function onFinish() {
tween(self, {
scaleX: 1,
scaleY: 1
}, {
duration: 300
});
}
});
LK.getSound('stomp').play();
}
};
return self;
});
var Projectile = Container.expand(function () {
var self = Container.call(this);
self.type = 'rocket'; // 'rocket', 'cannonball', 'arrow'
self.speed = 5;
self.damage = 10;
self.lastIntersecting = false;
self.velocityX = 0;
self.velocityY = 0;
self.update = function () {
// Move projectile
self.x += self.velocityX;
self.y += self.velocityY;
// Check collision with monster
var currentIntersecting = self.intersects(monster);
if (!self.lastIntersecting && currentIntersecting) {
monster.takeDamage(self.damage, self.type);
self.destroy();
projectiles.splice(projectiles.indexOf(self), 1);
}
self.lastIntersecting = currentIntersecting;
// Remove if off screen
if (self.x < -50 || self.x > 2098 || self.y < -50 || self.y > 2782) {
self.destroy();
projectiles.splice(projectiles.indexOf(self), 1);
}
};
return self;
});
var Sun = Container.expand(function () {
var self = Container.call(this);
var sunGraphics = self.attachAsset('sun', {
anchorX: 0.5,
anchorY: 0.5
});
self.isDay = true;
self.cycleTimer = 0;
self.cycleDuration = 1800; // 30 seconds for full day/night cycle
self.update = function () {
self.cycleTimer++;
// Calculate sun position in arc across sky
var cycleProgress = self.cycleTimer / self.cycleDuration;
var angle = cycleProgress * Math.PI * 2;
// Sun moves in arc across top of screen
self.x = 1024 + Math.cos(angle) * 800;
self.y = 400 + Math.sin(angle) * 200;
// Determine if it's day or night based on sun position
var wasDay = self.isDay;
self.isDay = self.y < 600; // Day when sun is high
// Update sky brightness based on sun position
if (self.isDay) {
skyBrightness = 0.7 + (600 - self.y) / 600 * 0.3;
} else {
skyBrightness = 0.3 + (self.y - 600) / 600 * 0.2;
}
// Clamp brightness values
if (skyBrightness > 1.0) skyBrightness = 1.0;
if (skyBrightness < 0.3) skyBrightness = 0.3;
// Reset cycle
if (self.cycleTimer >= self.cycleDuration) {
self.cycleTimer = 0;
}
// Show/hide sun based on position
sunGraphics.alpha = self.y < 700 ? 1.0 : 0.0;
};
return self;
});
var Tornado = Container.expand(function () {
var self = Container.call(this);
var tornadoGraphics = self.attachAsset('tornado', {
anchorX: 0.5,
anchorY: 1.0
});
self.speed = Math.random() * 2 + 1;
self.direction = Math.random() > 0.5 ? 1 : -1;
self.rotationSpeed = 0.2;
self.lifetime = 0;
self.maxLifetime = 600; // 10 seconds
self.update = function () {
// Move horizontally (left/right)
self.x += self.speed * self.direction;
// Bounce off screen edges
if (self.x <= 0 || self.x >= 2048) {
self.direction *= -1;
}
self.lifetime++;
// Fade out as it ages
tornadoGraphics.alpha = 1 - self.lifetime / self.maxLifetime;
// Vertical movement pattern: ground to clouds to ground
var cycleDuration = 200; // How long each cycle takes
var cyclePosition = self.lifetime % cycleDuration / cycleDuration;
var baseY = 2500; // Ground level
var cloudY = 800; // Cloud level
// Create wave pattern: 0 -> 1 -> 0 over cycle
var waveValue = Math.sin(cyclePosition * Math.PI * 2);
// Convert wave to vertical position
if (waveValue >= 0) {
// Moving up from ground to clouds
self.y = baseY - waveValue * (baseY - cloudY);
} else {
// Moving down from clouds to ground
self.y = cloudY + Math.abs(waveValue) * (baseY - cloudY);
}
// Check collision with buildings
for (var i = buildings.length - 1; i >= 0; i--) {
var building = buildings[i];
if (self.intersects(building)) {
self.shrinkBuilding(building);
}
}
// Remove when lifetime is over or off screen
if (self.lifetime >= self.maxLifetime || self.x < -100 || self.x > 2148) {
self.destroy();
tornadoes.splice(tornadoes.indexOf(self), 1);
}
};
self.shrinkBuilding = function (building) {
if (building.heightLevel > 1) {
building.heightLevel--;
LK.getSound('tornado_wind').play();
LK.effects.flashObject(building, 0x696969, 200);
// Replace with smaller building
var oldGraphics = building.children[0];
if (oldGraphics) {
building.removeChild(oldGraphics);
}
var newGraphics = building.attachAsset(building.assetNames[building.heightLevel - 1], {
anchorX: 0.5,
anchorY: 1.0
});
// Spin effect
tween(building, {
rotation: Math.PI * 2
}, {
duration: 500,
onFinish: function onFinish() {
building.rotation = 0;
}
});
} else {
// Building completely destroyed by tornado
building.destroy();
buildings.splice(buildings.indexOf(building), 1);
buildingsDestroyed++;
}
};
return self;
});
var Volcano = Container.expand(function () {
var self = Container.call(this);
var volcanoGraphics = self.attachAsset('volcano', {
anchorX: 0.5,
anchorY: 1.0
});
self.eruptionCooldown = 0;
self.maxEruptionCooldown = 1200; // 20 seconds
self.isErupting = false;
self.eruptionDuration = 0;
self.maxEruptionDuration = 180; // 3 seconds
self.update = function () {
if (self.eruptionCooldown > 0) {
self.eruptionCooldown--;
}
if (self.isErupting) {
self.eruptionDuration++;
// Spawn lava particles during eruption
if (self.eruptionDuration % 3 === 0) {
self.spawnLava();
}
// Flash volcano red during eruption
volcanoGraphics.tint = 0xFF4500;
if (self.eruptionDuration >= self.maxEruptionDuration) {
self.isErupting = false;
self.eruptionDuration = 0;
self.eruptionCooldown = self.maxEruptionCooldown;
volcanoGraphics.tint = 0xFFFFFF;
}
} else if (self.eruptionCooldown <= 0 && Math.random() < 0.005) {
self.startEruption();
}
};
self.startEruption = function () {
self.isErupting = true;
self.eruptionDuration = 0;
LK.getSound('volcano_eruption').play();
LK.effects.flashScreen(0xFF4500, 300);
// Shake effect
tween(self, {
x: self.x + 10
}, {
duration: 100,
onFinish: function onFinish() {
tween(self, {
x: self.x - 10
}, {
duration: 100,
onFinish: function onFinish() {
tween(self, {
x: self.x
}, {
duration: 100
});
}
});
}
});
};
self.spawnLava = function () {
var lava = new LavaParticle();
lava.x = self.x + (Math.random() - 0.5) * 50;
lava.y = self.y - 150;
lava.velocityX = (Math.random() - 0.5) * 8;
lava.velocityY = -(Math.random() * 8 + 5);
lavaParticles.push(lava);
game.addChild(lava);
};
return self;
});
var WeatherParticle = Container.expand(function () {
var self = Container.call(this);
self.type = 'rain'; // 'rain' or 'snow'
self.speed = 0;
self.particleGraphics = null;
self.init = function (type) {
self.type = type;
if (type === 'rain') {
self.particleGraphics = self.attachAsset('rainDrop', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = Math.random() * 8 + 12;
} else {
self.particleGraphics = self.attachAsset('snowFlake', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = Math.random() * 3 + 2;
}
};
self.update = function () {
self.y += self.speed;
if (self.type === 'snow') {
self.x += Math.sin(self.y * 0.01) * 0.5;
}
// Remove if off screen
if (self.y > 2782) {
self.destroy();
weatherParticles.splice(weatherParticles.indexOf(self), 1);
}
};
return self;
});
var ZeusPack = Container.expand(function () {
var self = Container.call(this);
var zeusPackGraphics = self.attachAsset('zeusPack', {
anchorX: 0.5,
anchorY: 0.5
});
self.velocityY = 0;
self.gravity = 0.8;
self.groundY = 2500;
self.hasLanded = false;
self.lifetime = 0;
self.maxLifetime = 600; // 10 seconds
self.lastIntersecting = false;
self.pulseTimer = 0;
self.update = function () {
// Apply gravity until hitting ground
if (!self.hasLanded) {
self.velocityY += self.gravity;
self.y += self.velocityY;
// Check ground collision
if (self.y >= self.groundY) {
self.y = self.groundY;
self.hasLanded = true;
self.velocityY = 0;
}
}
// Pulse animation when on ground
if (self.hasLanded) {
self.pulseTimer++;
var pulseScale = 1 + Math.sin(self.pulseTimer * 0.3) * 0.3;
zeusPackGraphics.scaleX = pulseScale;
zeusPackGraphics.scaleY = pulseScale;
// Golden glow effect
zeusPackGraphics.tint = 0xFFD700;
self.lifetime++;
// Check collision with monster
var currentIntersecting = self.intersects(monster);
if (!self.lastIntersecting && currentIntersecting) {
// Monster picks up Zeus pack
self.activateZeusPower();
self.destroy();
zeusPacks.splice(zeusPacks.indexOf(self), 1);
return;
}
self.lastIntersecting = currentIntersecting;
// Fade out near end of lifetime
if (self.lifetime > self.maxLifetime - 120) {
zeusPackGraphics.alpha = (self.maxLifetime - self.lifetime) / 120;
}
// Remove after lifetime expires
if (self.lifetime >= self.maxLifetime) {
self.destroy();
zeusPacks.splice(zeusPacks.indexOf(self), 1);
}
}
};
self.activateZeusPower = function () {
LK.getSound('zeus_power').play();
LK.effects.flashScreen(0xFFD700, 800);
LK.effects.flashObject(monster, 0xFFD700, 1000);
// Destroy all enemies with lightning effect
for (var i = buildings.length - 1; i >= 0; i--) {
var building = buildings[i];
self.strikeWithLightning(building);
}
if (boss) {
self.strikeWithLightning(boss);
}
// Stop enemy spawning for 10 seconds
enemySpawnBlocked = true;
enemySpawnBlockTimer = 600; // 10 seconds at 60fps
};
self.strikeWithLightning = function (target) {
// Create lightning effect
var lightning = new Lightning();
lightning.x = target.x;
lightning.y = 0;
lightningBolts.push(lightning);
game.addChild(lightning);
// Destroy target with delay
LK.setTimeout(function () {
if (target === boss) {
boss.takeDamage(999);
} else {
target.destroy();
buildings.splice(buildings.indexOf(target), 1);
buildingsDestroyed++;
}
}, 100);
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87ceeb
});
/****
* Game Code
****/
var monster;
var buildings = [];
var projectiles = [];
var boss = null;
var buildingsDestroyed = 0;
var level = 1;
var spawnTimer = 0;
var maxSpawnTimer = 180;
var birds = [];
var clouds = [];
var weatherParticles = [];
var skyBrightness = 1.0;
var skyDirection = -1;
var weatherType = 'none'; // 'none', 'rain', 'snow'
var weatherTimer = 0;
var weatherDuration = 0;
var birdSpawnTimer = 0;
var cloudSpawnTimer = 0;
var lightningBolts = [];
var lightningTimer = 0;
var lightningCooldown = 0;
var volcano = null;
var lavaParticles = [];
var tornadoes = [];
var tornadoTimer = 0;
var tornadoCooldown = 0;
var helicopters = [];
var healthPacks = [];
var helicopterCooldown = 0;
var lastHealthCheckTrigger = false;
var sun = null;
var lightningTargetCounter = 0;
var zeusPacks = [];
var zeusPackCooldown = 0;
var enemySpawnBlocked = false;
var enemySpawnBlockTimer = 0;
var lastZeusHealthTrigger = false;
var zeusPackTimer = 0;
var zeusPackSpawnCooldown = 1500; // 25 seconds at 60fps
// Create ground
var ground = game.addChild(LK.getAsset('ground', {
anchorX: 0.5,
anchorY: 1.0,
x: 1024,
y: 2600
}));
// Create monster
monster = game.addChild(new Monster());
monster.x = 1024;
monster.y = 2500;
// Create score display
var scoreTxt = new Text2('Score: 0', {
size: 80,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Create health display
var healthTxt = new Text2('Health: 300', {
size: 60,
fill: 0xFF0000
});
healthTxt.anchor.set(0, 0);
healthTxt.x = 120;
healthTxt.y = 120;
LK.gui.topLeft.addChild(healthTxt);
// Create level display
var levelTxt = new Text2('Level: 1', {
size: 60,
fill: 0xFFFFFF
});
levelTxt.anchor.set(1, 0);
LK.gui.topRight.addChild(levelTxt);
// Create volcano in corner
volcano = new Volcano();
volcano.x = 150;
volcano.y = 2500;
game.addChild(volcano);
// Create sun
sun = new Sun();
game.addChild(sun);
function spawnBuilding() {
var building = new Building();
var spawnX = Math.random() * 1800 + 124;
building.x = spawnX;
building.y = 2500;
buildings.push(building);
game.addChild(building);
}
function spawnBoss() {
boss = new Boss();
boss.x = 1024;
boss.y = 2500;
game.addChild(boss);
}
function spawnBird() {
var bird = new Bird();
bird.x = bird.direction > 0 ? -50 : 2098;
bird.y = Math.random() * 800 + 200;
birds.push(bird);
game.addChild(bird);
}
function spawnCloud() {
var cloud = new Cloud();
cloud.x = -150;
cloud.y = Math.random() * 600 + 100;
clouds.push(cloud);
game.addChild(cloud);
}
function spawnWeatherParticle() {
if (weatherType !== 'none') {
var particle = new WeatherParticle();
particle.init(weatherType);
particle.x = Math.random() * 2048;
particle.y = -20;
weatherParticles.push(particle);
game.addChild(particle);
}
}
function spawnLightning() {
// Play thunder sound first
LK.getSound('thunder').play();
// Flash screen white briefly for lightning
LK.effects.flashScreen(0xffffff, 200);
// Create lightning bolt
var lightning = new Lightning();
// Every second lightning targets the monster
lightningTargetCounter++;
if (lightningTargetCounter % 2 === 0) {
// Target monster
lightning.x = monster.x;
} else {
// Random position
lightning.x = Math.random() * 1800 + 124;
}
lightning.y = 0;
lightningBolts.push(lightning);
game.addChild(lightning);
}
function spawnTornado() {
var tornado = new Tornado();
tornado.x = tornado.direction > 0 ? -100 : 2148;
tornado.y = 2500;
tornadoes.push(tornado);
game.addChild(tornado);
LK.getSound('tornado_wind').play();
}
function spawnHelicopter() {
var helicopter = new Helicopter();
helicopter.x = -120;
helicopter.y = 400;
helicopter.targetX = monster.x;
helicopters.push(helicopter);
game.addChild(helicopter);
LK.getSound('helicopter_sound').play();
}
function spawnZeusPackHelicopter() {
var helicopter = new Helicopter();
helicopter.x = -120;
helicopter.y = 400;
helicopter.targetX = monster.x;
helicopter.isZeusPack = true; // Mark as Zeus pack helicopter
helicopters.push(helicopter);
game.addChild(helicopter);
LK.getSound('helicopter_sound').play();
}
function updateSky() {
// Sky brightness is now controlled by sun position
var skyColor = Math.floor(135 * skyBrightness) << 16 | Math.floor(206 * skyBrightness) << 8 | Math.floor(235 * skyBrightness);
game.setBackgroundColor(skyColor);
}
function updateWeather() {
weatherTimer++;
if (weatherTimer >= weatherDuration) {
// Change weather
var weatherTypes = ['none', 'rain', 'snow'];
weatherType = weatherTypes[Math.floor(Math.random() * 3)];
weatherTimer = 0;
weatherDuration = Math.random() * 1800 + 600; // 10-40 seconds
}
}
function startLevel() {
buildingsDestroyed = 0;
levelTxt.setText('Level: ' + level);
// Clear existing entities
for (var i = buildings.length - 1; i >= 0; i--) {
buildings[i].destroy();
}
buildings = [];
for (var j = projectiles.length - 1; j >= 0; j--) {
projectiles[j].destroy();
}
projectiles = [];
if (boss) {
boss.destroy();
boss = null;
}
// Spawn initial buildings
for (var k = 0; k < 3; k++) {
LK.setTimeout(function () {
spawnBuilding();
}, k * 1000);
}
}
// Start first level
startLevel();
// Game controls
game.down = function (x, y, obj) {
monster.startCharging();
};
game.up = function (x, y, obj) {
monster.jump();
};
game.move = function (x, y, obj) {
// Move monster towards touch position
if (x < monster.x) {
monster.x -= monster.speed;
} else if (x > monster.x) {
monster.x += monster.speed;
}
};
// Keyboard state tracking
var keys = {
ArrowLeft: false,
ArrowRight: false,
Space: false
};
// Main game loop
game.update = function () {
// Handle keyboard input (fallback to touch controls for mobile)
// Note: Keyboard controls are not available in LK sandbox, using touch controls instead
// Update score display
scoreTxt.setText('Score: ' + LK.getScore());
// Update health display
healthTxt.setText('Health: ' + monster.health);
// Update sky brightness
updateSky();
// Update weather
updateWeather();
// Spawn birds periodically
birdSpawnTimer++;
if (birdSpawnTimer >= 240) {
// Every 4 seconds
spawnBird();
birdSpawnTimer = 0;
}
// Spawn clouds periodically
cloudSpawnTimer++;
if (cloudSpawnTimer >= 300) {
// Every 5 seconds
spawnCloud();
cloudSpawnTimer = 0;
}
// Spawn weather particles
if (weatherType !== 'none' && Math.random() < 0.3) {
spawnWeatherParticle();
}
// Lightning and thunder system
lightningTimer++;
if (lightningCooldown > 0) {
lightningCooldown--;
}
// Chance for lightning during storms or dark sky
if (lightningCooldown <= 0 && (weatherType === 'rain' || skyBrightness < 0.6)) {
if (Math.random() < 0.008) {
// Small chance each frame
spawnLightning();
lightningCooldown = 180 + Math.random() * 300; // 3-8 seconds cooldown
}
}
// Tornado system
tornadoTimer++;
if (tornadoCooldown > 0) {
tornadoCooldown--;
}
// Chance for tornado during storms
if (tornadoCooldown <= 0 && weatherType !== 'none') {
if (Math.random() < 0.003) {
spawnTornado();
tornadoCooldown = 900 + Math.random() * 600; // 15-25 seconds cooldown
}
}
// Helicopter system - spawn when monster health drops to 50 or below
if (helicopterCooldown > 0) {
helicopterCooldown--;
}
var currentHealthTrigger = monster.health <= 50;
if (!lastHealthCheckTrigger && currentHealthTrigger && helicopterCooldown <= 0) {
spawnHelicopter();
helicopterCooldown = 1800; // 30 seconds cooldown
}
lastHealthCheckTrigger = currentHealthTrigger;
// Zeus pack timer system - spawn every 15 seconds
zeusPackTimer++;
if (zeusPackTimer >= zeusPackSpawnCooldown) {
spawnZeusPackHelicopter();
zeusPackTimer = 0;
}
// Handle Zeus pack spawn blocking
if (enemySpawnBlocked) {
enemySpawnBlockTimer--;
if (enemySpawnBlockTimer <= 0) {
enemySpawnBlocked = false;
}
}
// Spawn new buildings periodically (blocked during Zeus power)
if (!boss && buildings.length < 5 && !enemySpawnBlocked) {
spawnTimer++;
if (spawnTimer >= maxSpawnTimer) {
spawnBuilding();
spawnTimer = 0;
}
}
// Check for boss spawn condition (blocked during Zeus power)
if (!boss && buildingsDestroyed >= 5 + level * 2 && !enemySpawnBlocked) {
spawnBoss();
}
// Remove destroyed projectiles
for (var i = projectiles.length - 1; i >= 0; i--) {
if (!projectiles[i].parent) {
projectiles.splice(i, 1);
}
}
// Remove destroyed buildings
for (var j = buildings.length - 1; j >= 0; j--) {
if (!buildings[j].parent) {
buildings.splice(j, 1);
}
}
// Remove destroyed birds
for (var k = birds.length - 1; k >= 0; k--) {
if (!birds[k].parent) {
birds.splice(k, 1);
}
}
// Remove destroyed clouds
for (var l = clouds.length - 1; l >= 0; l--) {
if (!clouds[l].parent) {
clouds.splice(l, 1);
}
}
// Remove destroyed weather particles
for (var m = weatherParticles.length - 1; m >= 0; m--) {
if (!weatherParticles[m].parent) {
weatherParticles.splice(m, 1);
}
}
// Remove destroyed lightning bolts
for (var n = lightningBolts.length - 1; n >= 0; n--) {
if (!lightningBolts[n].parent) {
lightningBolts.splice(n, 1);
}
}
// Remove destroyed lava particles
for (var o = lavaParticles.length - 1; o >= 0; o--) {
if (!lavaParticles[o].parent) {
lavaParticles.splice(o, 1);
}
}
// Remove destroyed tornadoes
for (var p = tornadoes.length - 1; p >= 0; p--) {
if (!tornadoes[p].parent) {
tornadoes.splice(p, 1);
}
}
// Remove destroyed helicopters
for (var q = helicopters.length - 1; q >= 0; q--) {
if (!helicopters[q].parent) {
helicopters.splice(q, 1);
}
}
// Remove destroyed health packs
for (var r = healthPacks.length - 1; r >= 0; r--) {
if (!healthPacks[r].parent) {
healthPacks.splice(r, 1);
}
}
// Remove destroyed Zeus packs
for (var s = zeusPacks.length - 1; s >= 0; s--) {
if (!zeusPacks[s].parent) {
zeusPacks.splice(s, 1);
}
}
};
Spinosaurus, yeşil, ağzı açık. In-Game asset. 2d. High contrast. No shadows
büyük modern bir bina, bazı camlarında silahlı insanlar var, çatısında roket atar var.. In-Game asset. 2d. High contrast. No shadows
ilk insanların içinde yaşadığı bir mağara. kapısında elinde mızrak olan ilkel bir insan var. In-Game asset. 2d. High contrast. No shadows
tripleks bir osmanlı evi çiz. Çatısında top mermisi ateşlemek üzere olan bir yeniçeri askeri olsun. In-Game asset. 2d. High contrast. No shadows
mavi bir Argentinosaurus, ağzında biraz kan ve yüzünde çizikler var. In-Game asset. 2d. High contrast. No shadows
yatayda hareket eden bir Agni-V füzesi çiz In-Game asset. 2d. High contrast. No shadows
sivri uçlu, hafif yıpranmış bir mızrak, yatayda hareket ederken çiz In-Game asset. 2d. High contrast. No shadows
en büyük aktif volkanı çiz. In-Game asset. 2d. High contrast. No shadows
skorski helikopteri çiz. In-Game asset. 2d. High contrast. No shadows
pubg gibi oyunlarda olan gökyüzünden düşen sağlık paketi çiz. In-Game asset. 2d. High contrast. No shadows
kasırga partikülleri çizmeni istiyorum. In-Game asset. 2d. High contrast. No shadows
güçlü bir yıldırım tanrısı olan zeus çiz. In-Game asset. 2d. High contrast. No shadows
yıldırım ışığı çiz. In-Game asset. 2d. High contrast. No shadows
hafifi kızarmış bir dolunay çiz. In-Game asset. 2d. High contrast. No shadows
dağınık bulut çiz. In-Game asset. 2d. High contrast. No shadows