User prompt
Please fix the bug: 'TypeError: Cannot set properties of undefined (setting 'fill')' in or related to this line: 'alignmentIndicator.style.fill = '#FFFFFF';' Line Number: 458
Code edit (1 edits merged)
Please save this source code
User prompt
Wasteland Wanderer: The Artifact's Call
Initial prompt
In a post-apocalyptic world, you play as a mysterious stranger with supernatural powers, exploring a vast, crumbling Earth rendered in charming 2D pixel art. Traverse beautifully crafted pixelated landscapes, from barren wastelands to dark underground caves and ruined cities, each filled with detail and atmosphere. Control a fully animated 2D pixel-art character with a distinct face, body, and expressive design, wielding psychic abilities that let you manipulate blocks, create shimmering energy shields, and unleash devastating blasts against grotesque mutated creatures. Every character you meet — friend or foe — is brought to life with unique pixelated sprites that show their faces, bodies, and personalities, making each encounter memorable. Along the way, you’ll encounter desperate survivors who present you with moral choices that shape your powers, your appearance, and the fate of the world itself. Will you help rebuild, or seize power for yourself? Collect scattered fragments of an ancient world-healing artifact, hidden deep underground or high atop dangerous cliffs. Gather energy crystals to replenish your strength and unlock new psychic abilities as you solve environmental puzzles and battle waves of mutants that roam, especially under the cover of night. Balance exploration, crafting, and combat as you dig, climb, and fight through procedurally-generated, fully destructible 2D worlds. Your journey culminates in assembling the complete artifact and triggering the restoration of the world — or letting it collapse further into ruin, depending on the choices you’ve made.
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var ArtifactFragment = Container.expand(function () {
var self = Container.call(this);
var fragmentGraphics = self.attachAsset('artifactFragment', {
anchorX: 0.5,
anchorY: 0.5
});
self.collected = false;
self.rotationSpeed = 0.05;
self.update = function () {
// Rotation animation
fragmentGraphics.rotation += self.rotationSpeed;
// Check collection
if (!self.collected && self.intersects(player)) {
self.collected = true;
player.collectFragment();
self.visible = false;
}
};
return self;
});
var EnergyBlast = Container.expand(function () {
var self = Container.call(this);
var blastGraphics = self.attachAsset('energyBlast', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 8;
self.damage = 30;
self.directionX = 0;
self.directionY = 0;
self.active = true;
self.setTarget = function (targetX, targetY) {
var dx = targetX - self.x;
var dy = targetY - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
self.directionX = dx / distance * self.speed;
self.directionY = dy / distance * self.speed;
}
};
self.update = function () {
if (self.active) {
self.x += self.directionX;
self.y += self.directionY;
// Check bounds
if (self.x < 0 || self.x > 2048 || self.y < 0 || self.y > 2732) {
self.active = false;
}
}
};
return self;
});
var EnergyCrystal = Container.expand(function () {
var self = Container.call(this);
var crystalGraphics = self.attachAsset('energyCrystal', {
anchorX: 0.5,
anchorY: 0.5
});
self.collected = false;
self.pulseTime = 0;
self.update = function () {
// Pulsing animation
self.pulseTime += 0.1;
crystalGraphics.scaleX = 1 + Math.sin(self.pulseTime) * 0.2;
crystalGraphics.scaleY = 1 + Math.sin(self.pulseTime) * 0.2;
// Check collection
if (!self.collected && self.intersects(player)) {
self.collected = true;
player.collectCrystal();
self.visible = false;
}
};
return self;
});
var EnergyShield = Container.expand(function () {
var self = Container.call(this);
var shieldGraphics = self.attachAsset('energyShield', {
anchorX: 0.5,
anchorY: 0.5
});
self.alpha = 0.3;
self.pulseTime = 0;
self.update = function () {
// Follow player
self.x = player.x;
self.y = player.y;
// Pulsing effect
self.pulseTime += 0.2;
shieldGraphics.alpha = 0.3 + Math.sin(self.pulseTime) * 0.1;
// Visibility based on shield status
self.visible = player.shieldActive;
};
return self;
});
var Mutant = Container.expand(function () {
var self = Container.call(this);
var mutantGraphics = self.attachAsset('mutant', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 50;
self.speed = 2;
self.lastAttackTime = 0;
self.attackCooldown = 120; // 2 seconds
self.aggroRange = 200;
self.attackRange = 64;
self.update = function () {
var dx = player.x - self.x;
var dy = player.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < self.aggroRange) {
// Move towards player
if (distance > self.attackRange) {
var moveX = dx / distance * self.speed;
var moveY = dy / distance * self.speed;
self.x += moveX;
self.y += moveY;
}
// Attack if in range
if (distance < self.attackRange && LK.ticks - self.lastAttackTime > self.attackCooldown) {
self.lastAttackTime = LK.ticks;
var playerDied = player.takeDamage(20);
if (playerDied) {
LK.showGameOver();
}
}
}
};
self.takeDamage = function (damage) {
self.health -= damage;
if (self.health <= 0) {
LK.getSound('mutantDeath').play();
return true; // Mutant died
}
return false;
};
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
var playerGraphics = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 100;
self.energy = 100;
self.maxEnergy = 100;
self.speed = 4;
self.lastShieldTime = 0;
self.shieldActive = false;
self.artifactFragments = 0;
self.moralAlignment = 0; // -100 to 100, negative = destructive, positive = constructive
self.moveLeft = function () {
if (self.x > 32) {
self.x -= self.speed;
}
};
self.moveRight = function () {
if (self.x < 2048 - 32) {
self.x += self.speed;
}
};
self.moveUp = function () {
if (self.y > 32) {
self.y -= self.speed;
}
};
self.moveDown = function () {
if (self.y < 2732 - 32) {
self.y += self.speed;
}
};
self.createEnergyBlast = function (targetX, targetY) {
if (self.energy >= 20) {
self.energy -= 20;
return {
x: self.x,
y: self.y,
targetX: targetX,
targetY: targetY,
active: true
};
}
return null;
};
self.activateShield = function () {
if (self.energy >= 30 && !self.shieldActive) {
self.energy -= 30;
self.shieldActive = true;
self.lastShieldTime = LK.ticks;
return true;
}
return false;
};
self.takeDamage = function (damage) {
if (!self.shieldActive) {
self.health -= damage;
if (self.health <= 0) {
self.health = 0;
return true; // Player died
}
}
return false;
};
self.collectCrystal = function () {
self.energy = Math.min(self.maxEnergy, self.energy + 25);
LK.getSound('collect').play();
};
self.collectFragment = function () {
self.artifactFragments++;
LK.getSound('powerup').play();
};
self.update = function () {
// Shield duration
if (self.shieldActive && LK.ticks - self.lastShieldTime > 180) {
// 3 seconds
self.shieldActive = false;
}
// Energy regeneration
if (self.energy < self.maxEnergy) {
self.energy = Math.min(self.maxEnergy, self.energy + 0.1);
}
// Update visual based on moral alignment
if (self.moralAlignment > 50) {
playerGraphics.tint = 0x4169E1; // Royal blue for good
} else if (self.moralAlignment < -50) {
playerGraphics.tint = 0x8B0000; // Dark red for evil
} else {
playerGraphics.tint = 0xFFFFFF; // White for neutral
}
};
return self;
});
var Survivor = Container.expand(function () {
var self = Container.call(this);
var survivorGraphics = self.attachAsset('survivor', {
anchorX: 0.5,
anchorY: 0.5
});
self.hasInteracted = false;
self.choiceType = 'shareFood'; // 'shareFood', 'helpRepair', 'defendBase'
self.down = function (x, y, obj) {
if (!self.hasInteracted && self.intersects(player)) {
self.hasInteracted = true;
self.presentChoice();
}
};
self.presentChoice = function () {
// Simple choice system - in a full game this would be a proper UI
if (self.choiceType === 'shareFood') {
// Positive choice: share food
player.moralAlignment += 20;
player.health = Math.min(100, player.health + 30);
} else if (self.choiceType === 'helpRepair') {
// Neutral choice: help repair
player.moralAlignment += 10;
player.maxEnergy += 20;
} else if (self.choiceType === 'defendBase') {
// Negative choice: take supplies
player.moralAlignment -= 15;
player.energy = player.maxEnergy;
}
survivorGraphics.tint = 0x808080; // Gray out after interaction
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x2F2F2F
});
/****
* Game Code
****/
// Game state variables
var player;
var mutants = [];
var energyBlasts = [];
var energyCrystals = [];
var artifactFragments = [];
var survivors = [];
var energyShield;
var gameStarted = false;
var spawnTimer = 0;
var crystalSpawnTimer = 0;
var fragmentSpawnTimer = 0;
var survivorSpawnTimer = 0;
// UI Elements
var healthBar;
var energyBar;
var fragmentCounter;
var alignmentIndicator;
// Initialize UI
function initializeUI() {
healthBar = new Text2('Health: 100', {
size: 48,
fill: '#FF0000'
});
healthBar.anchor.set(0, 0);
healthBar.x = 120;
healthBar.y = 50;
LK.gui.topLeft.addChild(healthBar);
energyBar = new Text2('Energy: 100', {
size: 48,
fill: '#00FFFF'
});
energyBar.anchor.set(0, 0);
energyBar.x = 120;
energyBar.y = 110;
LK.gui.topLeft.addChild(energyBar);
fragmentCounter = new Text2('Fragments: 0/10', {
size: 48,
fill: '#FFD700'
});
fragmentCounter.anchor.set(1, 0);
fragmentCounter.x = -50;
fragmentCounter.y = 50;
LK.gui.topRight.addChild(fragmentCounter);
alignmentIndicator = new Text2('Neutral', {
size: 48,
fill: '#FFFFFF'
});
alignmentIndicator.anchor.set(0.5, 0);
alignmentIndicator.x = 0;
alignmentIndicator.y = 50;
LK.gui.top.addChild(alignmentIndicator);
}
// Initialize game world
function initializeWorld() {
// Create player
player = game.addChild(new Player());
player.x = 1024;
player.y = 1366;
// Create energy shield
energyShield = game.addChild(new EnergyShield());
// Create some initial ground elements
for (var i = 0; i < 20; i++) {
var ground = game.addChild(LK.getAsset('ground', {
anchorX: 0.5,
anchorY: 0.5
}));
ground.x = Math.random() * 2048;
ground.y = 2600 + Math.random() * 132;
}
// Create some walls
for (var i = 0; i < 15; i++) {
var wall = game.addChild(LK.getAsset('wall', {
anchorX: 0.5,
anchorY: 0.5
}));
wall.x = Math.random() * 2048;
wall.y = Math.random() * 2732;
}
// Spawn initial crystals
for (var i = 0; i < 5; i++) {
spawnEnergyCrystal();
}
// Spawn initial fragments
for (var i = 0; i < 3; i++) {
spawnArtifactFragment();
}
// Spawn initial survivor
spawnSurvivor();
}
// Spawn functions
function spawnMutant() {
var mutant = game.addChild(new Mutant());
var edge = Math.floor(Math.random() * 4);
switch (edge) {
case 0:
// Top
mutant.x = Math.random() * 2048;
mutant.y = 0;
break;
case 1:
// Right
mutant.x = 2048;
mutant.y = Math.random() * 2732;
break;
case 2:
// Bottom
mutant.x = Math.random() * 2048;
mutant.y = 2732;
break;
case 3:
// Left
mutant.x = 0;
mutant.y = Math.random() * 2732;
break;
}
mutants.push(mutant);
}
function spawnEnergyCrystal() {
var crystal = game.addChild(new EnergyCrystal());
crystal.x = Math.random() * 1800 + 124;
crystal.y = Math.random() * 2500 + 116;
energyCrystals.push(crystal);
}
function spawnArtifactFragment() {
var fragment = game.addChild(new ArtifactFragment());
fragment.x = Math.random() * 1800 + 124;
fragment.y = Math.random() * 2500 + 116;
artifactFragments.push(fragment);
}
function spawnSurvivor() {
var survivor = game.addChild(new Survivor());
survivor.x = Math.random() * 1800 + 124;
survivor.y = Math.random() * 2500 + 116;
var choiceTypes = ['shareFood', 'helpRepair', 'defendBase'];
survivor.choiceType = choiceTypes[Math.floor(Math.random() * choiceTypes.length)];
survivors.push(survivor);
}
// Update UI
function updateUI() {
healthBar.setText('Health: ' + Math.floor(player.health));
energyBar.setText('Energy: ' + Math.floor(player.energy));
fragmentCounter.setText('Fragments: ' + player.artifactFragments + '/10');
// Update alignment indicator
if (player.moralAlignment > 50) {
alignmentIndicator.setText('Savior');
alignmentIndicator.style.fill = '#4169E1';
} else if (player.moralAlignment < -50) {
alignmentIndicator.setText('Destroyer');
alignmentIndicator.style.fill = '#8B0000';
} else {
alignmentIndicator.setText('Neutral');
alignmentIndicator.style.fill = '#FFFFFF';
}
}
// Movement tracking
var moveLeft = false;
var moveRight = false;
var moveUp = false;
var moveDown = false;
// Game controls
game.down = function (x, y, obj) {
// Check if clicking on survivor
for (var i = 0; i < survivors.length; i++) {
if (survivors[i].intersects(player)) {
survivors[i].down(x, y, obj);
return;
}
}
// Create energy blast
var blastData = player.createEnergyBlast(x, y);
if (blastData) {
var blast = game.addChild(new EnergyBlast());
blast.x = blastData.x;
blast.y = blastData.y;
blast.setTarget(blastData.targetX, blastData.targetY);
energyBlasts.push(blast);
LK.getSound('blast').play();
}
};
game.move = function (x, y, obj) {
// Simple movement - move towards touch/mouse position
var dx = x - player.x;
var dy = y - player.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 50) {
// Dead zone
if (Math.abs(dx) > Math.abs(dy)) {
if (dx > 0) {
moveRight = true;
moveLeft = false;
} else {
moveLeft = true;
moveRight = false;
}
} else {
if (dy > 0) {
moveDown = true;
moveUp = false;
} else {
moveUp = true;
moveDown = false;
}
}
}
};
game.up = function (x, y, obj) {
// Stop movement
moveLeft = false;
moveRight = false;
moveUp = false;
moveDown = false;
// Try to activate shield
player.activateShield();
};
// Main game loop
game.update = function () {
if (!gameStarted) {
initializeUI();
initializeWorld();
gameStarted = true;
LK.playMusic('wastelandTheme');
}
// Handle movement
if (moveLeft) player.moveLeft();
if (moveRight) player.moveRight();
if (moveUp) player.moveUp();
if (moveDown) player.moveDown();
// Spawn enemies
spawnTimer++;
if (spawnTimer > 180) {
// Every 3 seconds
spawnMutant();
spawnTimer = 0;
}
// Spawn crystals
crystalSpawnTimer++;
if (crystalSpawnTimer > 600) {
// Every 10 seconds
spawnEnergyCrystal();
crystalSpawnTimer = 0;
}
// Spawn fragments
fragmentSpawnTimer++;
if (fragmentSpawnTimer > 900) {
// Every 15 seconds
spawnArtifactFragment();
fragmentSpawnTimer = 0;
}
// Spawn survivors
survivorSpawnTimer++;
if (survivorSpawnTimer > 1800) {
// Every 30 seconds
spawnSurvivor();
survivorSpawnTimer = 0;
}
// Update energy blasts and check collisions
for (var i = energyBlasts.length - 1; i >= 0; i--) {
var blast = energyBlasts[i];
if (!blast.active) {
blast.destroy();
energyBlasts.splice(i, 1);
continue;
}
// Check collision with mutants
for (var j = mutants.length - 1; j >= 0; j--) {
var mutant = mutants[j];
if (blast.intersects(mutant)) {
var mutantDied = mutant.takeDamage(blast.damage);
if (mutantDied) {
mutant.destroy();
mutants.splice(j, 1);
LK.setScore(LK.getScore() + 10);
}
blast.active = false;
break;
}
}
}
// Clean up collected crystals
for (var i = energyCrystals.length - 1; i >= 0; i--) {
if (energyCrystals[i].collected) {
energyCrystals[i].destroy();
energyCrystals.splice(i, 1);
}
}
// Clean up collected fragments
for (var i = artifactFragments.length - 1; i >= 0; i--) {
if (artifactFragments[i].collected) {
artifactFragments[i].destroy();
artifactFragments.splice(i, 1);
}
}
// Check win condition
if (player.artifactFragments >= 10) {
if (player.moralAlignment > 0) {
// Good ending - heal the world
LK.showYouWin();
} else {
// Bad ending - destroy the world
LK.showGameOver();
}
}
// Update UI
updateUI();
// Reset movement flags
moveLeft = false;
moveRight = false;
moveUp = false;
moveDown = false;
}; ===================================================================
--- original.js
+++ change.js
@@ -1,6 +1,597 @@
-/****
+/****
+* Plugins
+****/
+var tween = LK.import("@upit/tween.v1");
+var storage = LK.import("@upit/storage.v1");
+
+/****
+* Classes
+****/
+var ArtifactFragment = Container.expand(function () {
+ var self = Container.call(this);
+ var fragmentGraphics = self.attachAsset('artifactFragment', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.collected = false;
+ self.rotationSpeed = 0.05;
+ self.update = function () {
+ // Rotation animation
+ fragmentGraphics.rotation += self.rotationSpeed;
+ // Check collection
+ if (!self.collected && self.intersects(player)) {
+ self.collected = true;
+ player.collectFragment();
+ self.visible = false;
+ }
+ };
+ return self;
+});
+var EnergyBlast = Container.expand(function () {
+ var self = Container.call(this);
+ var blastGraphics = self.attachAsset('energyBlast', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.speed = 8;
+ self.damage = 30;
+ self.directionX = 0;
+ self.directionY = 0;
+ self.active = true;
+ self.setTarget = function (targetX, targetY) {
+ var dx = targetX - self.x;
+ var dy = targetY - self.y;
+ var distance = Math.sqrt(dx * dx + dy * dy);
+ if (distance > 0) {
+ self.directionX = dx / distance * self.speed;
+ self.directionY = dy / distance * self.speed;
+ }
+ };
+ self.update = function () {
+ if (self.active) {
+ self.x += self.directionX;
+ self.y += self.directionY;
+ // Check bounds
+ if (self.x < 0 || self.x > 2048 || self.y < 0 || self.y > 2732) {
+ self.active = false;
+ }
+ }
+ };
+ return self;
+});
+var EnergyCrystal = Container.expand(function () {
+ var self = Container.call(this);
+ var crystalGraphics = self.attachAsset('energyCrystal', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.collected = false;
+ self.pulseTime = 0;
+ self.update = function () {
+ // Pulsing animation
+ self.pulseTime += 0.1;
+ crystalGraphics.scaleX = 1 + Math.sin(self.pulseTime) * 0.2;
+ crystalGraphics.scaleY = 1 + Math.sin(self.pulseTime) * 0.2;
+ // Check collection
+ if (!self.collected && self.intersects(player)) {
+ self.collected = true;
+ player.collectCrystal();
+ self.visible = false;
+ }
+ };
+ return self;
+});
+var EnergyShield = Container.expand(function () {
+ var self = Container.call(this);
+ var shieldGraphics = self.attachAsset('energyShield', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.alpha = 0.3;
+ self.pulseTime = 0;
+ self.update = function () {
+ // Follow player
+ self.x = player.x;
+ self.y = player.y;
+ // Pulsing effect
+ self.pulseTime += 0.2;
+ shieldGraphics.alpha = 0.3 + Math.sin(self.pulseTime) * 0.1;
+ // Visibility based on shield status
+ self.visible = player.shieldActive;
+ };
+ return self;
+});
+var Mutant = Container.expand(function () {
+ var self = Container.call(this);
+ var mutantGraphics = self.attachAsset('mutant', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.health = 50;
+ self.speed = 2;
+ self.lastAttackTime = 0;
+ self.attackCooldown = 120; // 2 seconds
+ self.aggroRange = 200;
+ self.attackRange = 64;
+ self.update = function () {
+ var dx = player.x - self.x;
+ var dy = player.y - self.y;
+ var distance = Math.sqrt(dx * dx + dy * dy);
+ if (distance < self.aggroRange) {
+ // Move towards player
+ if (distance > self.attackRange) {
+ var moveX = dx / distance * self.speed;
+ var moveY = dy / distance * self.speed;
+ self.x += moveX;
+ self.y += moveY;
+ }
+ // Attack if in range
+ if (distance < self.attackRange && LK.ticks - self.lastAttackTime > self.attackCooldown) {
+ self.lastAttackTime = LK.ticks;
+ var playerDied = player.takeDamage(20);
+ if (playerDied) {
+ LK.showGameOver();
+ }
+ }
+ }
+ };
+ self.takeDamage = function (damage) {
+ self.health -= damage;
+ if (self.health <= 0) {
+ LK.getSound('mutantDeath').play();
+ return true; // Mutant died
+ }
+ return false;
+ };
+ return self;
+});
+var Player = Container.expand(function () {
+ var self = Container.call(this);
+ var playerGraphics = self.attachAsset('player', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.health = 100;
+ self.energy = 100;
+ self.maxEnergy = 100;
+ self.speed = 4;
+ self.lastShieldTime = 0;
+ self.shieldActive = false;
+ self.artifactFragments = 0;
+ self.moralAlignment = 0; // -100 to 100, negative = destructive, positive = constructive
+ self.moveLeft = function () {
+ if (self.x > 32) {
+ self.x -= self.speed;
+ }
+ };
+ self.moveRight = function () {
+ if (self.x < 2048 - 32) {
+ self.x += self.speed;
+ }
+ };
+ self.moveUp = function () {
+ if (self.y > 32) {
+ self.y -= self.speed;
+ }
+ };
+ self.moveDown = function () {
+ if (self.y < 2732 - 32) {
+ self.y += self.speed;
+ }
+ };
+ self.createEnergyBlast = function (targetX, targetY) {
+ if (self.energy >= 20) {
+ self.energy -= 20;
+ return {
+ x: self.x,
+ y: self.y,
+ targetX: targetX,
+ targetY: targetY,
+ active: true
+ };
+ }
+ return null;
+ };
+ self.activateShield = function () {
+ if (self.energy >= 30 && !self.shieldActive) {
+ self.energy -= 30;
+ self.shieldActive = true;
+ self.lastShieldTime = LK.ticks;
+ return true;
+ }
+ return false;
+ };
+ self.takeDamage = function (damage) {
+ if (!self.shieldActive) {
+ self.health -= damage;
+ if (self.health <= 0) {
+ self.health = 0;
+ return true; // Player died
+ }
+ }
+ return false;
+ };
+ self.collectCrystal = function () {
+ self.energy = Math.min(self.maxEnergy, self.energy + 25);
+ LK.getSound('collect').play();
+ };
+ self.collectFragment = function () {
+ self.artifactFragments++;
+ LK.getSound('powerup').play();
+ };
+ self.update = function () {
+ // Shield duration
+ if (self.shieldActive && LK.ticks - self.lastShieldTime > 180) {
+ // 3 seconds
+ self.shieldActive = false;
+ }
+ // Energy regeneration
+ if (self.energy < self.maxEnergy) {
+ self.energy = Math.min(self.maxEnergy, self.energy + 0.1);
+ }
+ // Update visual based on moral alignment
+ if (self.moralAlignment > 50) {
+ playerGraphics.tint = 0x4169E1; // Royal blue for good
+ } else if (self.moralAlignment < -50) {
+ playerGraphics.tint = 0x8B0000; // Dark red for evil
+ } else {
+ playerGraphics.tint = 0xFFFFFF; // White for neutral
+ }
+ };
+ return self;
+});
+var Survivor = Container.expand(function () {
+ var self = Container.call(this);
+ var survivorGraphics = self.attachAsset('survivor', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.hasInteracted = false;
+ self.choiceType = 'shareFood'; // 'shareFood', 'helpRepair', 'defendBase'
+ self.down = function (x, y, obj) {
+ if (!self.hasInteracted && self.intersects(player)) {
+ self.hasInteracted = true;
+ self.presentChoice();
+ }
+ };
+ self.presentChoice = function () {
+ // Simple choice system - in a full game this would be a proper UI
+ if (self.choiceType === 'shareFood') {
+ // Positive choice: share food
+ player.moralAlignment += 20;
+ player.health = Math.min(100, player.health + 30);
+ } else if (self.choiceType === 'helpRepair') {
+ // Neutral choice: help repair
+ player.moralAlignment += 10;
+ player.maxEnergy += 20;
+ } else if (self.choiceType === 'defendBase') {
+ // Negative choice: take supplies
+ player.moralAlignment -= 15;
+ player.energy = player.maxEnergy;
+ }
+ survivorGraphics.tint = 0x808080; // Gray out after interaction
+ };
+ return self;
+});
+
+/****
* Initialize Game
-****/
+****/
var game = new LK.Game({
- backgroundColor: 0x000000
-});
\ No newline at end of file
+ backgroundColor: 0x2F2F2F
+});
+
+/****
+* Game Code
+****/
+// Game state variables
+var player;
+var mutants = [];
+var energyBlasts = [];
+var energyCrystals = [];
+var artifactFragments = [];
+var survivors = [];
+var energyShield;
+var gameStarted = false;
+var spawnTimer = 0;
+var crystalSpawnTimer = 0;
+var fragmentSpawnTimer = 0;
+var survivorSpawnTimer = 0;
+// UI Elements
+var healthBar;
+var energyBar;
+var fragmentCounter;
+var alignmentIndicator;
+// Initialize UI
+function initializeUI() {
+ healthBar = new Text2('Health: 100', {
+ size: 48,
+ fill: '#FF0000'
+ });
+ healthBar.anchor.set(0, 0);
+ healthBar.x = 120;
+ healthBar.y = 50;
+ LK.gui.topLeft.addChild(healthBar);
+ energyBar = new Text2('Energy: 100', {
+ size: 48,
+ fill: '#00FFFF'
+ });
+ energyBar.anchor.set(0, 0);
+ energyBar.x = 120;
+ energyBar.y = 110;
+ LK.gui.topLeft.addChild(energyBar);
+ fragmentCounter = new Text2('Fragments: 0/10', {
+ size: 48,
+ fill: '#FFD700'
+ });
+ fragmentCounter.anchor.set(1, 0);
+ fragmentCounter.x = -50;
+ fragmentCounter.y = 50;
+ LK.gui.topRight.addChild(fragmentCounter);
+ alignmentIndicator = new Text2('Neutral', {
+ size: 48,
+ fill: '#FFFFFF'
+ });
+ alignmentIndicator.anchor.set(0.5, 0);
+ alignmentIndicator.x = 0;
+ alignmentIndicator.y = 50;
+ LK.gui.top.addChild(alignmentIndicator);
+}
+// Initialize game world
+function initializeWorld() {
+ // Create player
+ player = game.addChild(new Player());
+ player.x = 1024;
+ player.y = 1366;
+ // Create energy shield
+ energyShield = game.addChild(new EnergyShield());
+ // Create some initial ground elements
+ for (var i = 0; i < 20; i++) {
+ var ground = game.addChild(LK.getAsset('ground', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ }));
+ ground.x = Math.random() * 2048;
+ ground.y = 2600 + Math.random() * 132;
+ }
+ // Create some walls
+ for (var i = 0; i < 15; i++) {
+ var wall = game.addChild(LK.getAsset('wall', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ }));
+ wall.x = Math.random() * 2048;
+ wall.y = Math.random() * 2732;
+ }
+ // Spawn initial crystals
+ for (var i = 0; i < 5; i++) {
+ spawnEnergyCrystal();
+ }
+ // Spawn initial fragments
+ for (var i = 0; i < 3; i++) {
+ spawnArtifactFragment();
+ }
+ // Spawn initial survivor
+ spawnSurvivor();
+}
+// Spawn functions
+function spawnMutant() {
+ var mutant = game.addChild(new Mutant());
+ var edge = Math.floor(Math.random() * 4);
+ switch (edge) {
+ case 0:
+ // Top
+ mutant.x = Math.random() * 2048;
+ mutant.y = 0;
+ break;
+ case 1:
+ // Right
+ mutant.x = 2048;
+ mutant.y = Math.random() * 2732;
+ break;
+ case 2:
+ // Bottom
+ mutant.x = Math.random() * 2048;
+ mutant.y = 2732;
+ break;
+ case 3:
+ // Left
+ mutant.x = 0;
+ mutant.y = Math.random() * 2732;
+ break;
+ }
+ mutants.push(mutant);
+}
+function spawnEnergyCrystal() {
+ var crystal = game.addChild(new EnergyCrystal());
+ crystal.x = Math.random() * 1800 + 124;
+ crystal.y = Math.random() * 2500 + 116;
+ energyCrystals.push(crystal);
+}
+function spawnArtifactFragment() {
+ var fragment = game.addChild(new ArtifactFragment());
+ fragment.x = Math.random() * 1800 + 124;
+ fragment.y = Math.random() * 2500 + 116;
+ artifactFragments.push(fragment);
+}
+function spawnSurvivor() {
+ var survivor = game.addChild(new Survivor());
+ survivor.x = Math.random() * 1800 + 124;
+ survivor.y = Math.random() * 2500 + 116;
+ var choiceTypes = ['shareFood', 'helpRepair', 'defendBase'];
+ survivor.choiceType = choiceTypes[Math.floor(Math.random() * choiceTypes.length)];
+ survivors.push(survivor);
+}
+// Update UI
+function updateUI() {
+ healthBar.setText('Health: ' + Math.floor(player.health));
+ energyBar.setText('Energy: ' + Math.floor(player.energy));
+ fragmentCounter.setText('Fragments: ' + player.artifactFragments + '/10');
+ // Update alignment indicator
+ if (player.moralAlignment > 50) {
+ alignmentIndicator.setText('Savior');
+ alignmentIndicator.style.fill = '#4169E1';
+ } else if (player.moralAlignment < -50) {
+ alignmentIndicator.setText('Destroyer');
+ alignmentIndicator.style.fill = '#8B0000';
+ } else {
+ alignmentIndicator.setText('Neutral');
+ alignmentIndicator.style.fill = '#FFFFFF';
+ }
+}
+// Movement tracking
+var moveLeft = false;
+var moveRight = false;
+var moveUp = false;
+var moveDown = false;
+// Game controls
+game.down = function (x, y, obj) {
+ // Check if clicking on survivor
+ for (var i = 0; i < survivors.length; i++) {
+ if (survivors[i].intersects(player)) {
+ survivors[i].down(x, y, obj);
+ return;
+ }
+ }
+ // Create energy blast
+ var blastData = player.createEnergyBlast(x, y);
+ if (blastData) {
+ var blast = game.addChild(new EnergyBlast());
+ blast.x = blastData.x;
+ blast.y = blastData.y;
+ blast.setTarget(blastData.targetX, blastData.targetY);
+ energyBlasts.push(blast);
+ LK.getSound('blast').play();
+ }
+};
+game.move = function (x, y, obj) {
+ // Simple movement - move towards touch/mouse position
+ var dx = x - player.x;
+ var dy = y - player.y;
+ var distance = Math.sqrt(dx * dx + dy * dy);
+ if (distance > 50) {
+ // Dead zone
+ if (Math.abs(dx) > Math.abs(dy)) {
+ if (dx > 0) {
+ moveRight = true;
+ moveLeft = false;
+ } else {
+ moveLeft = true;
+ moveRight = false;
+ }
+ } else {
+ if (dy > 0) {
+ moveDown = true;
+ moveUp = false;
+ } else {
+ moveUp = true;
+ moveDown = false;
+ }
+ }
+ }
+};
+game.up = function (x, y, obj) {
+ // Stop movement
+ moveLeft = false;
+ moveRight = false;
+ moveUp = false;
+ moveDown = false;
+ // Try to activate shield
+ player.activateShield();
+};
+// Main game loop
+game.update = function () {
+ if (!gameStarted) {
+ initializeUI();
+ initializeWorld();
+ gameStarted = true;
+ LK.playMusic('wastelandTheme');
+ }
+ // Handle movement
+ if (moveLeft) player.moveLeft();
+ if (moveRight) player.moveRight();
+ if (moveUp) player.moveUp();
+ if (moveDown) player.moveDown();
+ // Spawn enemies
+ spawnTimer++;
+ if (spawnTimer > 180) {
+ // Every 3 seconds
+ spawnMutant();
+ spawnTimer = 0;
+ }
+ // Spawn crystals
+ crystalSpawnTimer++;
+ if (crystalSpawnTimer > 600) {
+ // Every 10 seconds
+ spawnEnergyCrystal();
+ crystalSpawnTimer = 0;
+ }
+ // Spawn fragments
+ fragmentSpawnTimer++;
+ if (fragmentSpawnTimer > 900) {
+ // Every 15 seconds
+ spawnArtifactFragment();
+ fragmentSpawnTimer = 0;
+ }
+ // Spawn survivors
+ survivorSpawnTimer++;
+ if (survivorSpawnTimer > 1800) {
+ // Every 30 seconds
+ spawnSurvivor();
+ survivorSpawnTimer = 0;
+ }
+ // Update energy blasts and check collisions
+ for (var i = energyBlasts.length - 1; i >= 0; i--) {
+ var blast = energyBlasts[i];
+ if (!blast.active) {
+ blast.destroy();
+ energyBlasts.splice(i, 1);
+ continue;
+ }
+ // Check collision with mutants
+ for (var j = mutants.length - 1; j >= 0; j--) {
+ var mutant = mutants[j];
+ if (blast.intersects(mutant)) {
+ var mutantDied = mutant.takeDamage(blast.damage);
+ if (mutantDied) {
+ mutant.destroy();
+ mutants.splice(j, 1);
+ LK.setScore(LK.getScore() + 10);
+ }
+ blast.active = false;
+ break;
+ }
+ }
+ }
+ // Clean up collected crystals
+ for (var i = energyCrystals.length - 1; i >= 0; i--) {
+ if (energyCrystals[i].collected) {
+ energyCrystals[i].destroy();
+ energyCrystals.splice(i, 1);
+ }
+ }
+ // Clean up collected fragments
+ for (var i = artifactFragments.length - 1; i >= 0; i--) {
+ if (artifactFragments[i].collected) {
+ artifactFragments[i].destroy();
+ artifactFragments.splice(i, 1);
+ }
+ }
+ // Check win condition
+ if (player.artifactFragments >= 10) {
+ if (player.moralAlignment > 0) {
+ // Good ending - heal the world
+ LK.showYouWin();
+ } else {
+ // Bad ending - destroy the world
+ LK.showGameOver();
+ }
+ }
+ // Update UI
+ updateUI();
+ // Reset movement flags
+ moveLeft = false;
+ moveRight = false;
+ moveUp = false;
+ moveDown = false;
+};
\ No newline at end of file