/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Monster class
var Monster = Container.expand(function () {
var self = Container.call(this);
// Default monster uses 'monster' asset
var monsterBody = self.attachAsset('monster', {
anchorX: 0.5,
anchorY: 0.5
});
// Monster hit overlay (hidden by default)
var monsterHit = self.attachAsset('monsterHit', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0
});
// Health values
self.maxHealth = 10;
self.health = self.maxHealth;
// Hit animation
self.hitAnim = function () {
// Show hit overlay quickly, then fade out
monsterHit.alpha = 0.6;
tween(monsterHit, {
alpha: 0
}, {
duration: 180,
easing: tween.linear
});
// Slight scale pop
tween.stop(monsterBody, {
scaleX: true,
scaleY: true
});
monsterBody.scaleX = 1.1;
monsterBody.scaleY = 1.1;
tween(monsterBody, {
scaleX: 1,
scaleY: 1
}, {
duration: 120,
easing: tween.easeOut
});
};
// Take damage
self.takeDamage = function (amount) {
self.health -= amount;
if (self.health < 0) {
self.health = 0;
}
self.hitAnim();
var hitSound = LK.getSound('hit');
if (hitSound && typeof hitSound.play === "function") {
hitSound.play();
}
};
// Reset monster health
self.resetHealth = function (newMax) {
self.maxHealth = newMax;
self.health = self.maxHealth;
};
// On tap/click
self.down = function (x, y, obj) {
self.takeDamage(1);
};
// Initialize health bar
return self;
});
// Monster2 class
var Monster2 = Container.expand(function () {
var self = Container.call(this);
var monsterBody = self.attachAsset('monster2', {
anchorX: 0.5,
anchorY: 0.5
});
var monsterHit = self.attachAsset('monster2', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.3
});
self.maxHealth = 12;
self.health = self.maxHealth;
self.hitAnim = function () {
monsterHit.alpha = 0.7;
tween(monsterHit, {
alpha: 0.3
}, {
duration: 180,
easing: tween.linear
});
tween.stop(monsterBody, {
scaleX: true,
scaleY: true
});
monsterBody.scaleX = 1.15;
monsterBody.scaleY = 1.15;
tween(monsterBody, {
scaleX: 1,
scaleY: 1
}, {
duration: 120,
easing: tween.easeOut
});
};
self.takeDamage = function (amount) {
self.health -= amount;
if (self.health < 0) {
self.health = 0;
}
self.hitAnim();
var hitSound = LK.getSound('hit');
if (hitSound && typeof hitSound.play === "function") {
hitSound.play();
}
};
self.resetHealth = function (newMax) {
self.maxHealth = newMax;
self.health = self.maxHealth;
};
self.down = function (x, y, obj) {
self.takeDamage(1);
};
return self;
});
// Monster3 class
var Monster3 = Container.expand(function () {
var self = Container.call(this);
var monsterBody = self.attachAsset('monster3', {
anchorX: 0.5,
anchorY: 0.5
});
var monsterHit = self.attachAsset('monster3', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.3
});
self.maxHealth = 15;
self.health = self.maxHealth;
self.hitAnim = function () {
monsterHit.alpha = 0.7;
tween(monsterHit, {
alpha: 0.3
}, {
duration: 180,
easing: tween.linear
});
tween.stop(monsterBody, {
scaleX: true,
scaleY: true
});
monsterBody.scaleX = 1.2;
monsterBody.scaleY = 1.2;
tween(monsterBody, {
scaleX: 1,
scaleY: 1
}, {
duration: 120,
easing: tween.easeOut
});
};
self.takeDamage = function (amount) {
self.health -= amount;
if (self.health < 0) {
self.health = 0;
}
self.hitAnim();
var hitSound = LK.getSound('hit');
if (hitSound && typeof hitSound.play === "function") {
hitSound.play();
}
};
self.resetHealth = function (newMax) {
self.maxHealth = newMax;
self.health = self.maxHealth;
};
self.down = function (x, y, obj) {
self.takeDamage(1);
};
return self;
});
// Monster4 class
var Monster4 = Container.expand(function () {
var self = Container.call(this);
var monsterBody = self.attachAsset('monster4', {
anchorX: 0.5,
anchorY: 0.5
});
var monsterHit = self.attachAsset('monster4', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.3
});
self.maxHealth = 18;
self.health = self.maxHealth;
self.hitAnim = function () {
monsterHit.alpha = 0.7;
tween(monsterHit, {
alpha: 0.3
}, {
duration: 180,
easing: tween.linear
});
tween.stop(monsterBody, {
scaleX: true,
scaleY: true
});
monsterBody.scaleX = 1.25;
monsterBody.scaleY = 1.25;
tween(monsterBody, {
scaleX: 1,
scaleY: 1
}, {
duration: 120,
easing: tween.easeOut
});
};
self.takeDamage = function (amount) {
self.health -= amount;
if (self.health < 0) {
self.health = 0;
}
self.hitAnim();
var hitSound = LK.getSound('hit');
if (hitSound && typeof hitSound.play === "function") {
hitSound.play();
}
};
self.resetHealth = function (newMax) {
self.maxHealth = newMax;
self.health = self.maxHealth;
};
self.down = function (x, y, obj) {
self.takeDamage(1);
};
return self;
});
// Monster5 class (using 'monster5' asset)
var Monster5 = Container.expand(function () {
var self = Container.call(this);
var monsterBody = self.attachAsset('monster5', {
anchorX: 0.5,
anchorY: 0.5
});
var monsterHit = self.attachAsset('monster5', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.3
});
self.maxHealth = 20;
self.health = self.maxHealth;
self.hitAnim = function () {
monsterHit.alpha = 0.7;
tween(monsterHit, {
alpha: 0.3
}, {
duration: 180,
easing: tween.linear
});
tween.stop(monsterBody, {
scaleX: true,
scaleY: true
});
monsterBody.scaleX = 1.3;
monsterBody.scaleY = 1.3;
tween(monsterBody, {
scaleX: 1,
scaleY: 1
}, {
duration: 120,
easing: tween.easeOut
});
};
self.takeDamage = function (amount) {
self.health -= amount;
if (self.health < 0) {
self.health = 0;
}
self.hitAnim();
var hitSound = LK.getSound('hit');
if (hitSound && typeof hitSound.play === "function") {
hitSound.play();
}
};
self.resetHealth = function (newMax) {
self.maxHealth = newMax;
self.health = self.maxHealth;
};
self.down = function (x, y, obj) {
self.takeDamage(1);
};
return self;
});
/****
* Initialize Game
****/
// MonsterFactory to spawn a random monster type
var game = new LK.Game({
backgroundColor: 0x181818
});
/****
* Game Code
****/
// Keep track of last monster type index
// MonsterFactory to spawn a random monster type
var lastMonsterIdx = -1;
function MonsterFactory() {
// List of monster constructors, one for each asset
// We'll define Monster5 inline below
var monsterTypes = [Monster, Monster2, Monster3, Monster4, Monster5];
var idx;
// Pick a random type different from last
if (monsterTypes.length > 1) {
do {
idx = Math.floor(Math.random() * monsterTypes.length);
} while (idx === lastMonsterIdx);
} else {
idx = 0;
}
lastMonsterIdx = idx;
return new monsterTypes[idx]();
}
// --- PRE-GAME AREA ---
var preGameContainer = new Container();
preGameContainer.width = 2048;
preGameContainer.height = 2732;
// Add pre-game-area image as background
var preBg = LK.getAsset('pre-game-area', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2,
width: 2048,
height: 2732
});
preGameContainer.addChild(preBg);
// Instruction text at the top
var instructionText = new Text2("Continue until you reach 25 points!", {
size: 90,
fill: "#fff",
font: "'Impact','Arial Black',Tahoma"
});
instructionText.anchor.set(0.5, 0);
instructionText.x = 2048 / 2;
instructionText.y = 120;
preGameContainer.addChild(instructionText);
// Title text
var titleText = new Text2("Monster Tapper", {
size: 180,
fill: "#fff",
font: "'Impact','Arial Black',Tahoma"
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 2048 / 2;
titleText.y = 700;
preGameContainer.addChild(titleText);
// Play button
var playBtnWidth = 600;
var playBtnHeight = 200;
var playBtnY = 1400;
var playBtn = LK.getAsset('goldBgRect', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: playBtnY,
width: playBtnWidth,
height: playBtnHeight
});
preGameContainer.addChild(playBtn);
playBtn.visible = true;
playBtn.interactive = true;
playBtn.buttonMode = true;
var playBtnText = new Text2("PLAY", {
size: 120,
fill: 0x181818,
font: "'Impact','Arial Black',Tahoma"
});
playBtnText.anchor.set(0.5, 0.5);
playBtnText.x = 2048 / 2;
playBtnText.y = playBtnY;
preGameContainer.addChild(playBtnText);
playBtnText.visible = true;
playBtn.interactive = true;
playBtn.buttonMode = true;
// Removed accidental early game start and pre-game screen hide here.
// Game will only start and pre-game screen will only hide in startGame(), which is called by playBtn.down
// Add pre-game container to game as the last child to ensure it's on top of everything, including background
game.addChild(preGameContainer, game.children.length); // Always add as last child so it's the top layer
// Hide all game UI until play is pressed
preGameContainer.visible = true;
var gameStarted = false;
var score = 0;
var scoreTxt = new Text2('0', {
size: 120,
fill: "#fff",
font: "'Impact','Arial Black',Tahoma"
});
scoreTxt.anchor.set(0.5, 0);
// Place at top center, but not in top 100px (avoid menu)
scoreTxt.y = 20;
LK.gui.top.addChild(scoreTxt);
scoreTxt.visible = false;
var countdownSeconds = 40;
var timerTxt = new Text2('01:00', {
size: 60,
fill: "#fff",
font: "'Impact','Arial Black',Tahoma"
});
timerTxt.anchor.set(0.5, 0);
timerTxt.y = 140;
LK.gui.top.addChild(timerTxt);
timerTxt.visible = false;
var timerInterval = null;
var timerRunning = false;
// Ensure pre-game-area stays visible and game does not start until Play is pressed
// (Handled by only setting gameStarted = true and hiding preGameContainer in startGame, which is only called by playBtn.down)
// Game does not start until Play is pressed; all UI and monster spawning is hidden until then
// Only show horse icon after game starts
var horseIcon = LK.getAsset('horse', {
anchorX: 1,
anchorY: 0,
x: LK.gui.width - 20,
y: 20,
width: 120,
height: 120
});
LK.gui.topRight.addChild(horseIcon);
horseIcon.visible = false;
function updateTimerDisplay() {
var min = Math.floor(countdownSeconds / 60);
var sec = countdownSeconds % 60;
var minStr = min < 10 ? "0" + min : "" + min;
var secStr = sec < 10 ? "0" + sec : "" + sec;
timerTxt.setText(minStr + ":" + secStr);
}
updateTimerDisplay();
function startCountdown() {
if (timerInterval) {
LK.clearInterval(timerInterval);
}
timerRunning = true;
timerInterval = LK.setInterval(function () {
if (!timerRunning) {
return;
}
countdownSeconds--;
updateTimerDisplay();
if (countdownSeconds <= 0) {
timerRunning = false;
LK.clearInterval(timerInterval);
LK.showGameOver();
}
}, 500);
}
// Start game function (called when play is pressed)
function startGame() {
// Only start the game and hide pre-game-area when Play is pressed
gameStarted = true;
preGameContainer.visible = false;
score = 0;
countdownSeconds = 40;
updateTimerDisplay();
scoreTxt.setText(score);
scoreTxt.visible = true;
timerTxt.visible = true;
horseIcon.visible = true;
timerRunning = true;
startCountdown();
spawnMonster();
// Game only starts after Play is pressed
}
// Play button event
playBtn.down = function (x, y, obj) {
// Only start the game and hide pre-game-area when Play is pressed
startGame();
};
// (Gold UI removed)
var gold = 0;
// Function to show +3s popup
function showGoldPopup(x, y) {
// Pick a random position anywhere on the screen, avoiding the top 100px (menu area)
var minX = 120;
var maxX = 2048 - 120;
var minY = 120;
var maxY = 2732 - 120;
var randX = Math.floor(Math.random() * (maxX - minX)) + minX;
var randY = Math.floor(Math.random() * (maxY - minY)) + minY;
// Show '+1s' popup at random position, animating upward
var popup = new Text2('+1s', {
size: 180,
fill: 0xFFD700,
font: "'Impact','Arial Black',Tahoma"
});
popup.anchor.set(0.5, 1);
popup.x = randX;
popup.y = randY + 120;
// Always add as the last child so it is in front of all monsters and health bars
game.addChild(popup, game.children.length);
// Move popup to the topmost layer every frame during animation to guarantee it's always in front
tween(popup, {
y: popup.y - 120,
alpha: 0
}, {
duration: 900,
easing: tween.easeOut,
onUpdate: function onUpdate() {
// Remove and re-add to ensure it's the last child (topmost)
if (popup.parent) {
popup.parent.removeChild(popup);
game.addChild(popup, game.children.length);
}
},
onComplete: function onComplete() {
popup.destroy();
}
});
}
// Horse icon already defined and added above
// (Gold icon and text removed)
// Add background image as a background layer, scaled to always fill the phone screen (game area 2048x2732)
var background = LK.getAsset('background', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2,
width: 2048,
height: 2732
});
// Always add background as the very first child so it is always behind everything, including pre-game area
game.addChild(background, 0); // Add at index 0 to ensure it's behind everything
// Only allow background movement after PLAY is pressed
background.canMove = false;
// Center position for monster (adjusted for large monster size)
var centerX = 2048 / 2;
var centerY = 2732 / 2 + 100;
// Current monster
var monster = null;
// Function to spawn a new monster
function spawnMonster() {
// Remove old monster if exists
if (monster) {
monster.destroy();
monster = null;
}
// Remove old health bar if exists
if (game.monsterHealthBarBg) {
game.monsterHealthBarBg.destroy();
game.monsterHealthBarBg = null;
}
if (game.monsterHealthBarFg) {
game.monsterHealthBarFg.destroy();
game.monsterHealthBarFg = null;
}
// Increase difficulty: every 10 monsters, +2 health
var baseHealth = 10 + Math.floor(score / 10) * 2;
// Use MonsterFactory to get a random monster type
monster = MonsterFactory();
monster.x = centerX;
monster.y = centerY;
// Set health scaling for all monsters
if (typeof monster.resetHealth === "function") {
monster.resetHealth(baseHealth);
}
game.addChild(monster);
// Add health bar background and foreground above monster
var barWidth = 600;
var barHeight = 60;
var barOffsetY = -monster.height / 2 - 60; // above monster
// Health bar background
var healthBarBg = LK.getAsset('healthBarBg', {
anchorX: 0.5,
anchorY: 0.5,
width: barWidth,
height: barHeight,
x: monster.x,
y: monster.y + barOffsetY
});
game.addChild(healthBarBg);
// Health bar foreground
var healthBarFg = LK.getAsset('healthBarFg', {
anchorX: 0.5,
anchorY: 0.5,
width: barWidth - 16,
height: barHeight - 16,
x: monster.x,
y: monster.y + barOffsetY
});
game.addChild(healthBarFg);
// Store for update/removal
game.monsterHealthBarBg = healthBarBg;
game.monsterHealthBarFg = healthBarFg;
// Attach update function to monster for health bar
monster.updateHealthBar = function () {
// Update bar position to follow monster
healthBarBg.x = monster.x;
healthBarBg.y = monster.y + barOffsetY;
healthBarFg.x = monster.x;
healthBarFg.y = monster.y + barOffsetY;
// Update bar width to reflect health
var pct = Math.max(0, monster.health / monster.maxHealth);
healthBarFg.width = (barWidth - 16) * pct;
};
}
// Game update loop
game.update = function () {
// Do not run game logic until Play is pressed and pre-game-area is closed
if (!gameStarted || preGameContainer.visible) {
// Pause timer if game is not running
timerRunning = false;
// Prevent background from moving before PLAY is pressed
if (background && background.canMove !== undefined) {
background.canMove = false;
}
return;
}
// Allow background to move after PLAY is pressed
if (background && background.canMove !== undefined) {
background.canMove = true;
}
if (!monster) {
// Pause timer if game is not running
timerRunning = false;
return;
}
// If monster is dead, increment score and spawn new
if (monster.health <= 0) {
score += 1;
scoreTxt.setText(score);
// Her canavar öldüğünde bu fonksiyon çağrılmalı
onEnemyDefeated();
// Show +10 gold popup centered on the screen
showGoldPopup(2048 / 2, 2732 / 2);
// Check for win condition: score reaches 5 before countdown ends
if (score >= 25 && countdownSeconds > 0) {
timerRunning = false;
LK.clearInterval(timerInterval);
LK.showYouWin("Good Job my friend! You just ate the game!");
return;
}
spawnMonster();
} else if (monster && typeof monster.updateHealthBar === "function") {
monster.updateHealthBar();
}
// Keep gold HUD at top right (in case of resize)
// goldHudContainer is not used; gold HUD elements are positioned directly.
};
// Start first monster
// spawnMonster();//{58} -- now only called after play is pressed
// Her canavar öldüğünde bu fonksiyon çağrılmalı
function onEnemyDefeated() {
// Add 1 second to the countdown timer (max 40s)
countdownSeconds = Math.min(countdownSeconds + 1, 40);
updateTimerDisplay();
} /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Monster class
var Monster = Container.expand(function () {
var self = Container.call(this);
// Default monster uses 'monster' asset
var monsterBody = self.attachAsset('monster', {
anchorX: 0.5,
anchorY: 0.5
});
// Monster hit overlay (hidden by default)
var monsterHit = self.attachAsset('monsterHit', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0
});
// Health values
self.maxHealth = 10;
self.health = self.maxHealth;
// Hit animation
self.hitAnim = function () {
// Show hit overlay quickly, then fade out
monsterHit.alpha = 0.6;
tween(monsterHit, {
alpha: 0
}, {
duration: 180,
easing: tween.linear
});
// Slight scale pop
tween.stop(monsterBody, {
scaleX: true,
scaleY: true
});
monsterBody.scaleX = 1.1;
monsterBody.scaleY = 1.1;
tween(monsterBody, {
scaleX: 1,
scaleY: 1
}, {
duration: 120,
easing: tween.easeOut
});
};
// Take damage
self.takeDamage = function (amount) {
self.health -= amount;
if (self.health < 0) {
self.health = 0;
}
self.hitAnim();
var hitSound = LK.getSound('hit');
if (hitSound && typeof hitSound.play === "function") {
hitSound.play();
}
};
// Reset monster health
self.resetHealth = function (newMax) {
self.maxHealth = newMax;
self.health = self.maxHealth;
};
// On tap/click
self.down = function (x, y, obj) {
self.takeDamage(1);
};
// Initialize health bar
return self;
});
// Monster2 class
var Monster2 = Container.expand(function () {
var self = Container.call(this);
var monsterBody = self.attachAsset('monster2', {
anchorX: 0.5,
anchorY: 0.5
});
var monsterHit = self.attachAsset('monster2', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.3
});
self.maxHealth = 12;
self.health = self.maxHealth;
self.hitAnim = function () {
monsterHit.alpha = 0.7;
tween(monsterHit, {
alpha: 0.3
}, {
duration: 180,
easing: tween.linear
});
tween.stop(monsterBody, {
scaleX: true,
scaleY: true
});
monsterBody.scaleX = 1.15;
monsterBody.scaleY = 1.15;
tween(monsterBody, {
scaleX: 1,
scaleY: 1
}, {
duration: 120,
easing: tween.easeOut
});
};
self.takeDamage = function (amount) {
self.health -= amount;
if (self.health < 0) {
self.health = 0;
}
self.hitAnim();
var hitSound = LK.getSound('hit');
if (hitSound && typeof hitSound.play === "function") {
hitSound.play();
}
};
self.resetHealth = function (newMax) {
self.maxHealth = newMax;
self.health = self.maxHealth;
};
self.down = function (x, y, obj) {
self.takeDamage(1);
};
return self;
});
// Monster3 class
var Monster3 = Container.expand(function () {
var self = Container.call(this);
var monsterBody = self.attachAsset('monster3', {
anchorX: 0.5,
anchorY: 0.5
});
var monsterHit = self.attachAsset('monster3', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.3
});
self.maxHealth = 15;
self.health = self.maxHealth;
self.hitAnim = function () {
monsterHit.alpha = 0.7;
tween(monsterHit, {
alpha: 0.3
}, {
duration: 180,
easing: tween.linear
});
tween.stop(monsterBody, {
scaleX: true,
scaleY: true
});
monsterBody.scaleX = 1.2;
monsterBody.scaleY = 1.2;
tween(monsterBody, {
scaleX: 1,
scaleY: 1
}, {
duration: 120,
easing: tween.easeOut
});
};
self.takeDamage = function (amount) {
self.health -= amount;
if (self.health < 0) {
self.health = 0;
}
self.hitAnim();
var hitSound = LK.getSound('hit');
if (hitSound && typeof hitSound.play === "function") {
hitSound.play();
}
};
self.resetHealth = function (newMax) {
self.maxHealth = newMax;
self.health = self.maxHealth;
};
self.down = function (x, y, obj) {
self.takeDamage(1);
};
return self;
});
// Monster4 class
var Monster4 = Container.expand(function () {
var self = Container.call(this);
var monsterBody = self.attachAsset('monster4', {
anchorX: 0.5,
anchorY: 0.5
});
var monsterHit = self.attachAsset('monster4', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.3
});
self.maxHealth = 18;
self.health = self.maxHealth;
self.hitAnim = function () {
monsterHit.alpha = 0.7;
tween(monsterHit, {
alpha: 0.3
}, {
duration: 180,
easing: tween.linear
});
tween.stop(monsterBody, {
scaleX: true,
scaleY: true
});
monsterBody.scaleX = 1.25;
monsterBody.scaleY = 1.25;
tween(monsterBody, {
scaleX: 1,
scaleY: 1
}, {
duration: 120,
easing: tween.easeOut
});
};
self.takeDamage = function (amount) {
self.health -= amount;
if (self.health < 0) {
self.health = 0;
}
self.hitAnim();
var hitSound = LK.getSound('hit');
if (hitSound && typeof hitSound.play === "function") {
hitSound.play();
}
};
self.resetHealth = function (newMax) {
self.maxHealth = newMax;
self.health = self.maxHealth;
};
self.down = function (x, y, obj) {
self.takeDamage(1);
};
return self;
});
// Monster5 class (using 'monster5' asset)
var Monster5 = Container.expand(function () {
var self = Container.call(this);
var monsterBody = self.attachAsset('monster5', {
anchorX: 0.5,
anchorY: 0.5
});
var monsterHit = self.attachAsset('monster5', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.3
});
self.maxHealth = 20;
self.health = self.maxHealth;
self.hitAnim = function () {
monsterHit.alpha = 0.7;
tween(monsterHit, {
alpha: 0.3
}, {
duration: 180,
easing: tween.linear
});
tween.stop(monsterBody, {
scaleX: true,
scaleY: true
});
monsterBody.scaleX = 1.3;
monsterBody.scaleY = 1.3;
tween(monsterBody, {
scaleX: 1,
scaleY: 1
}, {
duration: 120,
easing: tween.easeOut
});
};
self.takeDamage = function (amount) {
self.health -= amount;
if (self.health < 0) {
self.health = 0;
}
self.hitAnim();
var hitSound = LK.getSound('hit');
if (hitSound && typeof hitSound.play === "function") {
hitSound.play();
}
};
self.resetHealth = function (newMax) {
self.maxHealth = newMax;
self.health = self.maxHealth;
};
self.down = function (x, y, obj) {
self.takeDamage(1);
};
return self;
});
/****
* Initialize Game
****/
// MonsterFactory to spawn a random monster type
var game = new LK.Game({
backgroundColor: 0x181818
});
/****
* Game Code
****/
// Keep track of last monster type index
// MonsterFactory to spawn a random monster type
var lastMonsterIdx = -1;
function MonsterFactory() {
// List of monster constructors, one for each asset
// We'll define Monster5 inline below
var monsterTypes = [Monster, Monster2, Monster3, Monster4, Monster5];
var idx;
// Pick a random type different from last
if (monsterTypes.length > 1) {
do {
idx = Math.floor(Math.random() * monsterTypes.length);
} while (idx === lastMonsterIdx);
} else {
idx = 0;
}
lastMonsterIdx = idx;
return new monsterTypes[idx]();
}
// --- PRE-GAME AREA ---
var preGameContainer = new Container();
preGameContainer.width = 2048;
preGameContainer.height = 2732;
// Add pre-game-area image as background
var preBg = LK.getAsset('pre-game-area', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2,
width: 2048,
height: 2732
});
preGameContainer.addChild(preBg);
// Instruction text at the top
var instructionText = new Text2("Continue until you reach 25 points!", {
size: 90,
fill: "#fff",
font: "'Impact','Arial Black',Tahoma"
});
instructionText.anchor.set(0.5, 0);
instructionText.x = 2048 / 2;
instructionText.y = 120;
preGameContainer.addChild(instructionText);
// Title text
var titleText = new Text2("Monster Tapper", {
size: 180,
fill: "#fff",
font: "'Impact','Arial Black',Tahoma"
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 2048 / 2;
titleText.y = 700;
preGameContainer.addChild(titleText);
// Play button
var playBtnWidth = 600;
var playBtnHeight = 200;
var playBtnY = 1400;
var playBtn = LK.getAsset('goldBgRect', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: playBtnY,
width: playBtnWidth,
height: playBtnHeight
});
preGameContainer.addChild(playBtn);
playBtn.visible = true;
playBtn.interactive = true;
playBtn.buttonMode = true;
var playBtnText = new Text2("PLAY", {
size: 120,
fill: 0x181818,
font: "'Impact','Arial Black',Tahoma"
});
playBtnText.anchor.set(0.5, 0.5);
playBtnText.x = 2048 / 2;
playBtnText.y = playBtnY;
preGameContainer.addChild(playBtnText);
playBtnText.visible = true;
playBtn.interactive = true;
playBtn.buttonMode = true;
// Removed accidental early game start and pre-game screen hide here.
// Game will only start and pre-game screen will only hide in startGame(), which is called by playBtn.down
// Add pre-game container to game as the last child to ensure it's on top of everything, including background
game.addChild(preGameContainer, game.children.length); // Always add as last child so it's the top layer
// Hide all game UI until play is pressed
preGameContainer.visible = true;
var gameStarted = false;
var score = 0;
var scoreTxt = new Text2('0', {
size: 120,
fill: "#fff",
font: "'Impact','Arial Black',Tahoma"
});
scoreTxt.anchor.set(0.5, 0);
// Place at top center, but not in top 100px (avoid menu)
scoreTxt.y = 20;
LK.gui.top.addChild(scoreTxt);
scoreTxt.visible = false;
var countdownSeconds = 40;
var timerTxt = new Text2('01:00', {
size: 60,
fill: "#fff",
font: "'Impact','Arial Black',Tahoma"
});
timerTxt.anchor.set(0.5, 0);
timerTxt.y = 140;
LK.gui.top.addChild(timerTxt);
timerTxt.visible = false;
var timerInterval = null;
var timerRunning = false;
// Ensure pre-game-area stays visible and game does not start until Play is pressed
// (Handled by only setting gameStarted = true and hiding preGameContainer in startGame, which is only called by playBtn.down)
// Game does not start until Play is pressed; all UI and monster spawning is hidden until then
// Only show horse icon after game starts
var horseIcon = LK.getAsset('horse', {
anchorX: 1,
anchorY: 0,
x: LK.gui.width - 20,
y: 20,
width: 120,
height: 120
});
LK.gui.topRight.addChild(horseIcon);
horseIcon.visible = false;
function updateTimerDisplay() {
var min = Math.floor(countdownSeconds / 60);
var sec = countdownSeconds % 60;
var minStr = min < 10 ? "0" + min : "" + min;
var secStr = sec < 10 ? "0" + sec : "" + sec;
timerTxt.setText(minStr + ":" + secStr);
}
updateTimerDisplay();
function startCountdown() {
if (timerInterval) {
LK.clearInterval(timerInterval);
}
timerRunning = true;
timerInterval = LK.setInterval(function () {
if (!timerRunning) {
return;
}
countdownSeconds--;
updateTimerDisplay();
if (countdownSeconds <= 0) {
timerRunning = false;
LK.clearInterval(timerInterval);
LK.showGameOver();
}
}, 500);
}
// Start game function (called when play is pressed)
function startGame() {
// Only start the game and hide pre-game-area when Play is pressed
gameStarted = true;
preGameContainer.visible = false;
score = 0;
countdownSeconds = 40;
updateTimerDisplay();
scoreTxt.setText(score);
scoreTxt.visible = true;
timerTxt.visible = true;
horseIcon.visible = true;
timerRunning = true;
startCountdown();
spawnMonster();
// Game only starts after Play is pressed
}
// Play button event
playBtn.down = function (x, y, obj) {
// Only start the game and hide pre-game-area when Play is pressed
startGame();
};
// (Gold UI removed)
var gold = 0;
// Function to show +3s popup
function showGoldPopup(x, y) {
// Pick a random position anywhere on the screen, avoiding the top 100px (menu area)
var minX = 120;
var maxX = 2048 - 120;
var minY = 120;
var maxY = 2732 - 120;
var randX = Math.floor(Math.random() * (maxX - minX)) + minX;
var randY = Math.floor(Math.random() * (maxY - minY)) + minY;
// Show '+1s' popup at random position, animating upward
var popup = new Text2('+1s', {
size: 180,
fill: 0xFFD700,
font: "'Impact','Arial Black',Tahoma"
});
popup.anchor.set(0.5, 1);
popup.x = randX;
popup.y = randY + 120;
// Always add as the last child so it is in front of all monsters and health bars
game.addChild(popup, game.children.length);
// Move popup to the topmost layer every frame during animation to guarantee it's always in front
tween(popup, {
y: popup.y - 120,
alpha: 0
}, {
duration: 900,
easing: tween.easeOut,
onUpdate: function onUpdate() {
// Remove and re-add to ensure it's the last child (topmost)
if (popup.parent) {
popup.parent.removeChild(popup);
game.addChild(popup, game.children.length);
}
},
onComplete: function onComplete() {
popup.destroy();
}
});
}
// Horse icon already defined and added above
// (Gold icon and text removed)
// Add background image as a background layer, scaled to always fill the phone screen (game area 2048x2732)
var background = LK.getAsset('background', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2,
width: 2048,
height: 2732
});
// Always add background as the very first child so it is always behind everything, including pre-game area
game.addChild(background, 0); // Add at index 0 to ensure it's behind everything
// Only allow background movement after PLAY is pressed
background.canMove = false;
// Center position for monster (adjusted for large monster size)
var centerX = 2048 / 2;
var centerY = 2732 / 2 + 100;
// Current monster
var monster = null;
// Function to spawn a new monster
function spawnMonster() {
// Remove old monster if exists
if (monster) {
monster.destroy();
monster = null;
}
// Remove old health bar if exists
if (game.monsterHealthBarBg) {
game.monsterHealthBarBg.destroy();
game.monsterHealthBarBg = null;
}
if (game.monsterHealthBarFg) {
game.monsterHealthBarFg.destroy();
game.monsterHealthBarFg = null;
}
// Increase difficulty: every 10 monsters, +2 health
var baseHealth = 10 + Math.floor(score / 10) * 2;
// Use MonsterFactory to get a random monster type
monster = MonsterFactory();
monster.x = centerX;
monster.y = centerY;
// Set health scaling for all monsters
if (typeof monster.resetHealth === "function") {
monster.resetHealth(baseHealth);
}
game.addChild(monster);
// Add health bar background and foreground above monster
var barWidth = 600;
var barHeight = 60;
var barOffsetY = -monster.height / 2 - 60; // above monster
// Health bar background
var healthBarBg = LK.getAsset('healthBarBg', {
anchorX: 0.5,
anchorY: 0.5,
width: barWidth,
height: barHeight,
x: monster.x,
y: monster.y + barOffsetY
});
game.addChild(healthBarBg);
// Health bar foreground
var healthBarFg = LK.getAsset('healthBarFg', {
anchorX: 0.5,
anchorY: 0.5,
width: barWidth - 16,
height: barHeight - 16,
x: monster.x,
y: monster.y + barOffsetY
});
game.addChild(healthBarFg);
// Store for update/removal
game.monsterHealthBarBg = healthBarBg;
game.monsterHealthBarFg = healthBarFg;
// Attach update function to monster for health bar
monster.updateHealthBar = function () {
// Update bar position to follow monster
healthBarBg.x = monster.x;
healthBarBg.y = monster.y + barOffsetY;
healthBarFg.x = monster.x;
healthBarFg.y = monster.y + barOffsetY;
// Update bar width to reflect health
var pct = Math.max(0, monster.health / monster.maxHealth);
healthBarFg.width = (barWidth - 16) * pct;
};
}
// Game update loop
game.update = function () {
// Do not run game logic until Play is pressed and pre-game-area is closed
if (!gameStarted || preGameContainer.visible) {
// Pause timer if game is not running
timerRunning = false;
// Prevent background from moving before PLAY is pressed
if (background && background.canMove !== undefined) {
background.canMove = false;
}
return;
}
// Allow background to move after PLAY is pressed
if (background && background.canMove !== undefined) {
background.canMove = true;
}
if (!monster) {
// Pause timer if game is not running
timerRunning = false;
return;
}
// If monster is dead, increment score and spawn new
if (monster.health <= 0) {
score += 1;
scoreTxt.setText(score);
// Her canavar öldüğünde bu fonksiyon çağrılmalı
onEnemyDefeated();
// Show +10 gold popup centered on the screen
showGoldPopup(2048 / 2, 2732 / 2);
// Check for win condition: score reaches 5 before countdown ends
if (score >= 25 && countdownSeconds > 0) {
timerRunning = false;
LK.clearInterval(timerInterval);
LK.showYouWin("Good Job my friend! You just ate the game!");
return;
}
spawnMonster();
} else if (monster && typeof monster.updateHealthBar === "function") {
monster.updateHealthBar();
}
// Keep gold HUD at top right (in case of resize)
// goldHudContainer is not used; gold HUD elements are positioned directly.
};
// Start first monster
// spawnMonster();//{58} -- now only called after play is pressed
// Her canavar öldüğünde bu fonksiyon çağrılmalı
function onEnemyDefeated() {
// Add 1 second to the countdown timer (max 40s)
countdownSeconds = Math.min(countdownSeconds + 1, 40);
updateTimerDisplay();
}