/**** 
* Plugins
****/ 
var tween = LK.import("@upit/tween.v1");
/**** 
* Classes
****/ 
var Adventurer = Container.expand(function () {
	var self = Container.call(this);
	var adventurerGraphics = self.attachAsset('adventurer', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.maxHealth = 100;
	self.health = self.maxHealth;
	self.takeDamage = function (damage) {
		self.health -= damage;
		if (self.health <= 0) {
			self.health = 0;
			LK.showGameOver();
		}
		LK.effects.flashObject(self, 0xFF0000, 500);
	};
	self.castSpell = function () {
		var bolt = game.addChild(new MagicBolt());
		bolt.x = self.x;
		bolt.y = self.y - 30;
		bolt.damage = 15;
		magicBolts.push(bolt);
		LK.getSound('magicCast').play();
		LK.effects.flashObject(self, 0xFFD700, 300);
	};
	return self;
});
var MagicBolt = Container.expand(function () {
	var self = Container.call(this);
	var boltGraphics = self.attachAsset('magicBolt', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.speed = 20;
	self.damage = 10;
	self.update = function () {
		self.y -= self.speed;
	};
	return self;
});
var MonsterAttack = Container.expand(function () {
	var self = Container.call(this);
	var attackGraphics = self.attachAsset('monsterAttack', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.speed = 12;
	self.damage = 35;
	self.update = function () {
		// Use calculated velocity if available, otherwise default downward movement
		if (self.velocityX !== undefined && self.velocityY !== undefined) {
			self.x += self.velocityX;
			self.y += self.velocityY;
		} else {
			self.y += self.speed;
		}
		self.rotation += 0.2;
	};
	return self;
});
var RockMonster = Container.expand(function () {
	var self = Container.call(this);
	var monsterGraphics = self.attachAsset('rockMonster', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.maxHealth = 500;
	self.health = self.maxHealth;
	self.attackTimer = 0;
	self.attackCooldown = 200;
	self.moveDirection = 1;
	self.moveSpeed = 2;
	self.takeDamage = function (damage) {
		self.health -= damage;
		if (self.health <= 0) {
			self.health = 0;
			LK.showYouWin();
		}
		LK.getSound('monsterHit').play();
	};
	self.attack = function () {
		var attack = game.addChild(new MonsterAttack());
		attack.x = self.x;
		attack.y = self.y + 120;
		// Calculate direction towards adventurer
		var dx = adventurer.x - self.x;
		var dy = adventurer.y - self.y;
		var distance = Math.sqrt(dx * dx + dy * dy);
		// Normalize direction and set velocity
		if (distance > 0) {
			attack.velocityX = dx / distance * attack.speed;
			attack.velocityY = dy / distance * attack.speed;
		} else {
			attack.velocityX = 0;
			attack.velocityY = attack.speed;
		}
		monsterAttacks.push(attack);
	};
	self.update = function () {
		// Move side to side with boundary safety
		self.x += self.moveDirection * self.moveSpeed;
		if (self.x <= 200) {
			self.x = 200;
			self.moveDirection = 1;
		} else if (self.x >= 1848) {
			self.x = 1848;
			self.moveDirection = -1;
		}
		// Attack timer with better safety check
		self.attackTimer++;
		if (self.attackTimer >= self.attackCooldown) {
			self.attack();
			self.attackTimer = 0;
		}
	};
	return self;
});
/**** 
* Initialize Game
****/ 
var game = new LK.Game({
	backgroundColor: 0x2C3E50
});
/**** 
* Game Code
****/ 
var background = game.addChild(LK.getAsset('background', {
	anchorX: 0,
	anchorY: 0,
	x: 0,
	y: 0
}));
var adventurer = game.addChild(new Adventurer());
adventurer.x = 1024;
adventurer.y = 2200;
var rockMonster = game.addChild(new RockMonster());
rockMonster.x = 1024;
rockMonster.y = 400;
var magicBolts = [];
var monsterAttacks = [];
var dragNode = null;
var shootCooldown = 0;
var autoShootTimer = 0;
var autoShootInterval = 60; // 1 second at 60 FPS
var enemyAutoShootTimer = 0;
var enemyAutoShootInterval = 60; // 1 second at 60 FPS for enemy
var lastMoveX = 0;
var lastMoveY = 0;
// Health bars
var adventurerHealthBar = new Text2('Health: 100', {
	size: 60,
	fill: 0x00FF00
});
adventurerHealthBar.anchor.set(0, 0);
LK.gui.bottomLeft.addChild(adventurerHealthBar);
var monsterHealthBar = new Text2('Monster: 500', {
	size: 60,
	fill: 0xFF0000
});
monsterHealthBar.anchor.set(0.5, 0);
LK.gui.top.addChild(monsterHealthBar);
function handleMove(x, y, obj) {
	// Calculate movement delta for scroll control
	var deltaX = x - lastMoveX;
	var deltaY = y - lastMoveY;
	// Move adventurer based on touch/mouse movement
	if (dragNode) {
		var moveSpeed = 1.5;
		var newX = adventurer.x + deltaX * moveSpeed;
		var newY = adventurer.y + deltaY * moveSpeed;
		adventurer.x = Math.max(40, Math.min(2008, newX));
		adventurer.y = Math.max(1500, Math.min(2680, newY));
	}
	lastMoveX = x;
	lastMoveY = y;
}
// Start background music
LK.playMusic('1epicpertarunganpagi');
game.move = handleMove;
game.down = function (x, y, obj) {
	// Start drag control for movement
	dragNode = adventurer;
	lastMoveX = x;
	lastMoveY = y;
};
game.up = function (x, y, obj) {
	// Stop drag control
	dragNode = null;
};
game.update = function () {
	// Update magic bolts with safety checks
	for (var i = magicBolts.length - 1; i >= 0; i--) {
		var bolt = magicBolts[i];
		// Safety check for destroyed objects
		if (!bolt || !bolt.parent) {
			magicBolts.splice(i, 1);
			continue;
		}
		// Initialize collision tracking
		if (bolt.hasHitMonster === undefined) {
			bolt.hasHitMonster = false;
		}
		if (bolt.y < -50) {
			bolt.destroy();
			magicBolts.splice(i, 1);
			continue;
		}
		if (!bolt.hasHitMonster && rockMonster && rockMonster.parent && bolt.intersects(rockMonster)) {
			bolt.hasHitMonster = true;
			rockMonster.takeDamage(bolt.damage);
			bolt.destroy();
			magicBolts.splice(i, 1);
		}
	}
	// Update monster attacks with safety checks
	for (var j = monsterAttacks.length - 1; j >= 0; j--) {
		var attack = monsterAttacks[j];
		// Safety check for destroyed objects
		if (!attack || !attack.parent) {
			monsterAttacks.splice(j, 1);
			continue;
		}
		// Initialize collision tracking
		if (attack.hasHitAdventurer === undefined) {
			attack.hasHitAdventurer = false;
		}
		if (attack.y > 2800) {
			attack.destroy();
			monsterAttacks.splice(j, 1);
			continue;
		}
		if (!attack.hasHitAdventurer && adventurer && adventurer.parent && attack.intersects(adventurer)) {
			attack.hasHitAdventurer = true;
			adventurer.takeDamage(attack.damage);
			LK.getSound('playerHit').play();
			attack.destroy();
			monsterAttacks.splice(j, 1);
		}
	}
	// Update shoot cooldown
	if (shootCooldown > 0) {
		shootCooldown--;
	}
	// Auto shoot timer - player shoots automatically every 1 second
	autoShootTimer++;
	if (autoShootTimer >= autoShootInterval) {
		adventurer.castSpell();
		autoShootTimer = 0;
	}
	// Enemy auto shoot timer - enemy shoots automatically every 1 second
	enemyAutoShootTimer++;
	if (enemyAutoShootTimer >= enemyAutoShootInterval && rockMonster && rockMonster.parent) {
		rockMonster.attack();
		enemyAutoShootTimer = 0;
	}
	// Update health displays with safety checks
	if (adventurerHealthBar && adventurer) {
		adventurerHealthBar.setText('Health: ' + adventurer.health);
	}
	if (monsterHealthBar && rockMonster) {
		monsterHealthBar.setText('Monster: ' + rockMonster.health);
	}
}; /**** 
* Plugins
****/ 
var tween = LK.import("@upit/tween.v1");
/**** 
* Classes
****/ 
var Adventurer = Container.expand(function () {
	var self = Container.call(this);
	var adventurerGraphics = self.attachAsset('adventurer', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.maxHealth = 100;
	self.health = self.maxHealth;
	self.takeDamage = function (damage) {
		self.health -= damage;
		if (self.health <= 0) {
			self.health = 0;
			LK.showGameOver();
		}
		LK.effects.flashObject(self, 0xFF0000, 500);
	};
	self.castSpell = function () {
		var bolt = game.addChild(new MagicBolt());
		bolt.x = self.x;
		bolt.y = self.y - 30;
		bolt.damage = 15;
		magicBolts.push(bolt);
		LK.getSound('magicCast').play();
		LK.effects.flashObject(self, 0xFFD700, 300);
	};
	return self;
});
var MagicBolt = Container.expand(function () {
	var self = Container.call(this);
	var boltGraphics = self.attachAsset('magicBolt', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.speed = 20;
	self.damage = 10;
	self.update = function () {
		self.y -= self.speed;
	};
	return self;
});
var MonsterAttack = Container.expand(function () {
	var self = Container.call(this);
	var attackGraphics = self.attachAsset('monsterAttack', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.speed = 12;
	self.damage = 35;
	self.update = function () {
		// Use calculated velocity if available, otherwise default downward movement
		if (self.velocityX !== undefined && self.velocityY !== undefined) {
			self.x += self.velocityX;
			self.y += self.velocityY;
		} else {
			self.y += self.speed;
		}
		self.rotation += 0.2;
	};
	return self;
});
var RockMonster = Container.expand(function () {
	var self = Container.call(this);
	var monsterGraphics = self.attachAsset('rockMonster', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.maxHealth = 500;
	self.health = self.maxHealth;
	self.attackTimer = 0;
	self.attackCooldown = 200;
	self.moveDirection = 1;
	self.moveSpeed = 2;
	self.takeDamage = function (damage) {
		self.health -= damage;
		if (self.health <= 0) {
			self.health = 0;
			LK.showYouWin();
		}
		LK.getSound('monsterHit').play();
	};
	self.attack = function () {
		var attack = game.addChild(new MonsterAttack());
		attack.x = self.x;
		attack.y = self.y + 120;
		// Calculate direction towards adventurer
		var dx = adventurer.x - self.x;
		var dy = adventurer.y - self.y;
		var distance = Math.sqrt(dx * dx + dy * dy);
		// Normalize direction and set velocity
		if (distance > 0) {
			attack.velocityX = dx / distance * attack.speed;
			attack.velocityY = dy / distance * attack.speed;
		} else {
			attack.velocityX = 0;
			attack.velocityY = attack.speed;
		}
		monsterAttacks.push(attack);
	};
	self.update = function () {
		// Move side to side with boundary safety
		self.x += self.moveDirection * self.moveSpeed;
		if (self.x <= 200) {
			self.x = 200;
			self.moveDirection = 1;
		} else if (self.x >= 1848) {
			self.x = 1848;
			self.moveDirection = -1;
		}
		// Attack timer with better safety check
		self.attackTimer++;
		if (self.attackTimer >= self.attackCooldown) {
			self.attack();
			self.attackTimer = 0;
		}
	};
	return self;
});
/**** 
* Initialize Game
****/ 
var game = new LK.Game({
	backgroundColor: 0x2C3E50
});
/**** 
* Game Code
****/ 
var background = game.addChild(LK.getAsset('background', {
	anchorX: 0,
	anchorY: 0,
	x: 0,
	y: 0
}));
var adventurer = game.addChild(new Adventurer());
adventurer.x = 1024;
adventurer.y = 2200;
var rockMonster = game.addChild(new RockMonster());
rockMonster.x = 1024;
rockMonster.y = 400;
var magicBolts = [];
var monsterAttacks = [];
var dragNode = null;
var shootCooldown = 0;
var autoShootTimer = 0;
var autoShootInterval = 60; // 1 second at 60 FPS
var enemyAutoShootTimer = 0;
var enemyAutoShootInterval = 60; // 1 second at 60 FPS for enemy
var lastMoveX = 0;
var lastMoveY = 0;
// Health bars
var adventurerHealthBar = new Text2('Health: 100', {
	size: 60,
	fill: 0x00FF00
});
adventurerHealthBar.anchor.set(0, 0);
LK.gui.bottomLeft.addChild(adventurerHealthBar);
var monsterHealthBar = new Text2('Monster: 500', {
	size: 60,
	fill: 0xFF0000
});
monsterHealthBar.anchor.set(0.5, 0);
LK.gui.top.addChild(monsterHealthBar);
function handleMove(x, y, obj) {
	// Calculate movement delta for scroll control
	var deltaX = x - lastMoveX;
	var deltaY = y - lastMoveY;
	// Move adventurer based on touch/mouse movement
	if (dragNode) {
		var moveSpeed = 1.5;
		var newX = adventurer.x + deltaX * moveSpeed;
		var newY = adventurer.y + deltaY * moveSpeed;
		adventurer.x = Math.max(40, Math.min(2008, newX));
		adventurer.y = Math.max(1500, Math.min(2680, newY));
	}
	lastMoveX = x;
	lastMoveY = y;
}
// Start background music
LK.playMusic('1epicpertarunganpagi');
game.move = handleMove;
game.down = function (x, y, obj) {
	// Start drag control for movement
	dragNode = adventurer;
	lastMoveX = x;
	lastMoveY = y;
};
game.up = function (x, y, obj) {
	// Stop drag control
	dragNode = null;
};
game.update = function () {
	// Update magic bolts with safety checks
	for (var i = magicBolts.length - 1; i >= 0; i--) {
		var bolt = magicBolts[i];
		// Safety check for destroyed objects
		if (!bolt || !bolt.parent) {
			magicBolts.splice(i, 1);
			continue;
		}
		// Initialize collision tracking
		if (bolt.hasHitMonster === undefined) {
			bolt.hasHitMonster = false;
		}
		if (bolt.y < -50) {
			bolt.destroy();
			magicBolts.splice(i, 1);
			continue;
		}
		if (!bolt.hasHitMonster && rockMonster && rockMonster.parent && bolt.intersects(rockMonster)) {
			bolt.hasHitMonster = true;
			rockMonster.takeDamage(bolt.damage);
			bolt.destroy();
			magicBolts.splice(i, 1);
		}
	}
	// Update monster attacks with safety checks
	for (var j = monsterAttacks.length - 1; j >= 0; j--) {
		var attack = monsterAttacks[j];
		// Safety check for destroyed objects
		if (!attack || !attack.parent) {
			monsterAttacks.splice(j, 1);
			continue;
		}
		// Initialize collision tracking
		if (attack.hasHitAdventurer === undefined) {
			attack.hasHitAdventurer = false;
		}
		if (attack.y > 2800) {
			attack.destroy();
			monsterAttacks.splice(j, 1);
			continue;
		}
		if (!attack.hasHitAdventurer && adventurer && adventurer.parent && attack.intersects(adventurer)) {
			attack.hasHitAdventurer = true;
			adventurer.takeDamage(attack.damage);
			LK.getSound('playerHit').play();
			attack.destroy();
			monsterAttacks.splice(j, 1);
		}
	}
	// Update shoot cooldown
	if (shootCooldown > 0) {
		shootCooldown--;
	}
	// Auto shoot timer - player shoots automatically every 1 second
	autoShootTimer++;
	if (autoShootTimer >= autoShootInterval) {
		adventurer.castSpell();
		autoShootTimer = 0;
	}
	// Enemy auto shoot timer - enemy shoots automatically every 1 second
	enemyAutoShootTimer++;
	if (enemyAutoShootTimer >= enemyAutoShootInterval && rockMonster && rockMonster.parent) {
		rockMonster.attack();
		enemyAutoShootTimer = 0;
	}
	// Update health displays with safety checks
	if (adventurerHealthBar && adventurer) {
		adventurerHealthBar.setText('Health: ' + adventurer.health);
	}
	if (monsterHealthBar && rockMonster) {
		monsterHealthBar.setText('Monster: ' + rockMonster.health);
	}
};
:quality(85)/https://cdn.frvr.ai/687295e2845ffb6889ad905a.png%3F3) 
 16 bit image litle girl ride flyng broom stick. In-Game asset. 2d.
:quality(85)/https://cdn.frvr.ai/6872965f845ffb6889ad9070.png%3F3) 
 16 bit image evil black gray cloud monster. In-Game asset. 2d.
:quality(85)/https://cdn.frvr.ai/687296b0845ffb6889ad908d.png%3F3) 
 16 bit image black dark lighting orb ball In-Game asset. 2d.
:quality(85)/https://cdn.frvr.ai/68729709845ffb6889ad909a.png%3F3) 
 16 bit image langit biru cerah, daerah hutan luas, di kejauhan ada pedesaaan sederhana. suasana pagi hari langit biru. In-Game asset. 2d.