User prompt
timer will be on top. time will go up.
User prompt
Please fix the bug: 'Cannot set properties of undefined (setting 'fill')' in or related to this line: 'stageTexts[i].style.fill = i === stageActiveIndex ? "#fff" : "#888";' Line Number: 355
User prompt
there will be a time on right top. and under time there will be 5 stages: Very easy, easy, medium, hard, very hard. very easy will be between times of 0:00-0:15. easy; 0:15:0:45. medium; 0:45-1:30. hard; 1:30-2:30. very hard; 2:30-end of the game.
User prompt
over time timer will go faster and spawn rate will be faster
User prompt
make spawn rate higher sometimes and sometimes make it lower
User prompt
make different variations of mobs and make some of them faster and some of them slower
Code edit (1 edits merged)
Please save this source code
User prompt
Monster Tap Frenzy
Initial prompt
Random monsters will spawn on the map or will walk in the map and my mission is to kill them by clicking on them. there will be a timer and when I kill a mob timer will add some seconds
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ // Monster class var Monster = Container.expand(function () { var self = Container.call(this); // Monster type: "normal", "fast", "slow", "giant", "tiny", "shadow", "jumbo" self.type = "normal"; // Attach monster asset (default to normal, will be replaced in updateTypeVisual) var monsterSprite = self.attachAsset('monster_normal', { anchorX: 0.5, anchorY: 0.5 }); // Color by type after setType is called self.updateTypeVisual = function () { // Remove old sprite if present if (monsterSprite && self.children.indexOf(monsterSprite) !== -1) { self.removeChild(monsterSprite); } // Choose asset and size by type if (self.type === "fast") { monsterSprite = self.attachAsset('monster_fast', { anchorX: 0.5, anchorY: 0.5 }); monsterSprite.width = 160; monsterSprite.height = 160; } else if (self.type === "slow") { monsterSprite = self.attachAsset('monster_slow', { anchorX: 0.5, anchorY: 0.5 }); monsterSprite.width = 160; monsterSprite.height = 160; } else if (self.type === "giant") { monsterSprite = self.attachAsset('monster_giant', { anchorX: 0.5, anchorY: 0.5 }); monsterSprite.width = 240; monsterSprite.height = 240; } else if (self.type === "tiny") { monsterSprite = self.attachAsset('monster_tiny', { anchorX: 0.5, anchorY: 0.5 }); monsterSprite.width = 80; monsterSprite.height = 80; } else if (self.type === "shadow") { monsterSprite = self.attachAsset('monster_shadow', { anchorX: 0.5, anchorY: 0.5 }); monsterSprite.width = 120; monsterSprite.height = 120; } else if (self.type === "jumbo") { monsterSprite = self.attachAsset('monster_jumbo', { anchorX: 0.5, anchorY: 0.5 }); monsterSprite.width = 320; monsterSprite.height = 320; } else { monsterSprite = self.attachAsset('monster_normal', { anchorX: 0.5, anchorY: 0.5 }); monsterSprite.width = 160; monsterSprite.height = 160; } // Always reset position and alpha monsterSprite.x = 0; monsterSprite.y = 0; monsterSprite.alpha = 1; }; var _oldSetType = self.setType; self.setType = function (type) { _oldSetType(type); self.updateTypeVisual(); }; // Movement speed (pixels per tick) self.speed = 0; // Store base speed for stage scaling self.speedBase = 0; // Movement direction (radians) self.direction = 0; // Is monster alive self.alive = true; // Set monster type and speed self.setType = function (type) { self.type = type; if (type === "fast") { // Fast monsters: 5-8 px/tick self.speed = 5 + Math.random() * 3; } else if (type === "slow") { // Slow monsters: 1-2.5 px/tick self.speed = 1 + Math.random() * 1.5; } else if (type === "giant") { // Giant monsters: 1-2 px/tick (slow, big) self.speed = 1 + Math.random(); } else if (type === "tiny") { // Tiny monsters: 7 + Math.random() * 4; self.speed = 7 + Math.random() * 4; } else if (type === "shadow") { // Shadow monsters: 9-12 px/tick (very fast, small) self.speed = 9 + Math.random() * 3; } else if (type === "jumbo") { // Jumbo monsters: 0.7-1.2 px/tick (very slow, very big) self.speed = 0.7 + Math.random() * 0.5; } else { // Normal monsters: 2-6 px/tick self.speed = 2 + Math.random() * 4; } // Store base speed and apply stage multiplier self.speedBase = self.speed; var speedMultiplier = Math.pow(1.2, typeof stage !== "undefined" ? stage : 0); self.speed = self.speedBase * speedMultiplier; }; // Set random movement self.setRandomMovement = function () { // Randomly assign type var r = Math.random(); if (r < 0.14) { self.setType("fast"); } else if (r < 0.28) { self.setType("slow"); } else if (r < 0.42) { self.setType("giant"); } else if (r < 0.56) { self.setType("tiny"); } else if (r < 0.70) { self.setType("shadow"); } else if (r < 0.84) { self.setType("jumbo"); } else { self.setType("normal"); } // Direction: 0-2PI self.direction = Math.random() * Math.PI * 2; }; // Monster state for explosion logic self.timeSinceSpawn = 0; self.state = "normal"; // "normal", "red", "vibrating", "exploded" self.vibrateDir = 1; self.vibrateTick = 0; // Move monster self.update = function () { if (!self.alive) return; // Track time since spawn if (typeof self.timeSinceSpawn !== "number") self.timeSinceSpawn = 0; self.timeSinceSpawn += 1 / 60; // Handle state transitions if (self.state === "normal" && self.timeSinceSpawn >= 5) { // Turn red self.state = "red"; monsterSprite.tint = 0xff2222; // Optionally: flash or pulse tween(monsterSprite, { alpha: 0.5 }, { duration: 150, yoyo: true, repeat: 2, onFinish: function onFinish() { monsterSprite.alpha = 1; } }); } if (self.state === "red" && self.timeSinceSpawn >= 7) { // Start vibrating self.state = "vibrating"; self.vibrateTick = 0; } if (self.state === "vibrating") { // Vibrate effect: shake X/Y self.vibrateTick++; var shake = 8 + Math.random() * 4; if (self.vibrateTick % 2 === 0) { monsterSprite.x = shake * (Math.random() > 0.5 ? 1 : -1); monsterSprite.y = shake * (Math.random() > 0.5 ? 1 : -1); } else { monsterSprite.x = 0; monsterSprite.y = 0; } // After 1s of vibrating (60 ticks), explode if (self.timeSinceSpawn >= 8) { self.state = "exploded"; // Remove 5 seconds from timer addTime(-5); // Animate explosion (flash, fade out) tween(monsterSprite, { alpha: 0 }, { duration: 250, onFinish: function onFinish() { self.destroy(); } }); // Remove from monsters array for (var i = 0; i < monsters.length; ++i) { if (monsters[i] === self) { monsters.splice(i, 1); break; } } return; } } else { // Reset shake if not vibrating monsterSprite.x = 0; monsterSprite.y = 0; } // Move self.x += Math.cos(self.direction) * self.speed; self.y += Math.sin(self.direction) * self.speed; // Bounce off walls // Left if (self.x - monsterSprite.width / 2 < 0) { self.x = monsterSprite.width / 2; self.direction = Math.PI - self.direction; } // Right if (self.x + monsterSprite.width / 2 > 2048) { self.x = 2048 - monsterSprite.width / 2; self.direction = Math.PI - self.direction; } // Top if (self.y - monsterSprite.height / 2 < 100) { // leave top 100px for menu self.y = 100 + monsterSprite.height / 2; self.direction = -self.direction; } // Bottom if (self.y + monsterSprite.height / 2 > 2732) { self.y = 2732 - monsterSprite.height / 2; self.direction = -self.direction; } }; // Handle tap self.down = function (x, y, obj) { if (!self.alive) return; self.alive = false; // Cancel explosion/vibration/red state self.state = "shot"; if (monsterSprite) { monsterSprite.x = 0; monsterSprite.y = 0; self.vibrateTick = 0; } // Show hit effect var hitColor = 0xff4444; if (self.type === "fast") hitColor = 0x3e8ecf;else if (self.type === "slow") hitColor = 0xcfb53e;else if (self.type === "giant") hitColor = 0x8e44ad;else if (self.type === "tiny") hitColor = 0xffffff;else if (self.type === "shadow") hitColor = 0x222222;else if (self.type === "jumbo") hitColor = 0xff8800; var hit = LK.getAsset('monsterHit', { anchorX: 0.5, anchorY: 0.5, x: 0, y: 0, scaleX: 1, scaleY: 1, alpha: 1, tint: hitColor }); self.addChild(hit); // Animate hit effect tween(hit, { scaleX: 1.5, scaleY: 1.5, alpha: 0 }, { duration: 300, easing: tween.easeOut, onFinish: function onFinish() { hit.destroy(); } }); // Animate monster fade out tween(monsterSprite, { alpha: 0 }, { duration: 200, onFinish: function onFinish() { self.destroy(); } }); // Add time and score if (self.type === "fast") { addTime(3); // fast: +3s } else if (self.type === "slow") { addTime(1); // slow: +1s } else if (self.type === "giant") { addTime(5); // giant: +5s } else if (self.type === "tiny") { addTime(0.5); // tiny: +0.5s } else if (self.type === "shadow") { addTime(0.2); // shadow: +0.2s } else if (self.type === "jumbo") { addTime(8); // jumbo: +8s } else { addTime(2); // normal: +2s } setScore(getScore() + 1); updateScoreText(); // Remove from monsters array for (var i = 0; i < monsters.length; ++i) { if (monsters[i] === self) { monsters.splice(i, 1); break; } } }; return self; }); // Tap effect class var TapEffect = Container.expand(function () { var self = Container.call(this); var tap = self.attachAsset('tapEffect', { anchorX: 0.5, anchorY: 0.5, scaleX: 1, scaleY: 1, alpha: 0.7 }); // Animate tween(tap, { scaleX: 2, scaleY: 2, alpha: 0 }, { duration: 300, easing: tween.easeOut, onFinish: function onFinish() { self.destroy(); } }); return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x181c2a }); /**** * Game Code ****/ // Tap effect: yellow ellipse, 100x100 // Monster hit effect: red ellipse, 160x160 // Monster: green ellipse, 160x160 // Global variables var monsters = []; var monsterSpawnInterval = 120; // ticks between spawns (2s) var monsterSpawnIntervalTarget = 120; // target interval for smooth transitions var monsterSpawnIntervalChangeTimer = 0; // ticks until next interval change var monsterMax = 6; // max monsters on screen var timerMax = 20; // seconds to start var timer = timerMax; // current timer (seconds) var timerInterval = null; var timerBar = null; var timerBarBg = null; var timerText = null; var score = 0; var scoreText = null; var lastTick = 0; // Stage system var stage = 0; // 0: Very Easy, 1: Easy, 2: Medium, 3: Hard, 4: Very Hard var stageNames = ["Very Easy", "Easy", "Medium", "Hard", "Very Hard"]; var stageText = null; var stageBarBg = null; var stageBar = null; var stageTime = 0; // seconds since game start var stageDuration = 20; // seconds per stage // Helper: get/set score function getScore() { return score; } function setScore(val) { score = val; } function updateScoreText() { scoreText.setText(score + ""); } // Helper: add time function addTime(sec) { timer += sec; if (timer > 99) timer = 99; updateTimerText(); } // Helper: update timer text function updateTimerText() { timerText.setText(timer > 0 ? Math.ceil(timer) + "" : "0"); } // Helper: update timer bar function updateTimerBar() { var pct = Math.max(0, Math.min(1, timer / timerMax)); timerBar.width = 800 * pct; if (pct > 0.5) timerBar.tint = 0x3ecf4c;else if (pct > 0.2) timerBar.tint = 0xffe066;else timerBar.tint = 0xff4444; } // Spawn a monster at random position function spawnMonster() { if (monsters.length >= monsterMax) return; var m = new Monster(); // Avoid top 100px (menu) var margin = 100 + 80; m.x = margin + Math.random() * (2048 - margin * 2); m.y = margin + Math.random() * (2732 - margin * 2); m.setRandomMovement(); m.updateTypeVisual && m.updateTypeVisual(); // Store base speed and apply stage multiplier m.speedBase = m.speed; var speedMultiplier = Math.pow(1.2, stage); m.speed = m.speedBase * speedMultiplier; // Reset monster state for explosion logic m.timeSinceSpawn = 0; m.state = "normal"; m.vibrateTick = 0; // No need to override asset or tint here; Monster class handles correct asset and visuals monsters.push(m); game.addChild(m); } // GUI: Score scoreText = new Text2("0", { size: 120, fill: "#fff" }); scoreText.anchor.set(0.5, 0); LK.gui.top.addChild(scoreText); // GUI: Timer bar background timerBarBg = LK.getAsset('monster', { anchorX: 0, anchorY: 0.5, x: 624, y: 100, width: 800, height: 40, tint: 0x222222 }); timerBarBg.alpha = 0.5; game.addChild(timerBarBg); // GUI: Timer bar timerBar = LK.getAsset('monster', { anchorX: 0, anchorY: 0.5, x: 624, y: 100, width: 800, height: 40, tint: 0x3ecf4c }); game.addChild(timerBar); // GUI: Timer text timerText = new Text2(timerMax + "", { size: 90, fill: "#fff" }); timerText.anchor.set(0.5, 0.5); timerText.x = 2048 / 2; timerText.y = 100 + 20; game.addChild(timerText); // Position score at top center, below 100px scoreText.x = 2048 / 2; scoreText.y = 10 + 100; // GUI: Stage label and progress bar (right top, under timer bar) stageText = new Text2(stageNames[stage], { size: 70, fill: "#fff" }); stageText.anchor.set(1, 0); // right align stageText.x = 2048 - 40; stageText.y = 160; game.addChild(stageText); // Spawn initial monsters for (var i = 0; i < 3; ++i) { spawnMonster(); } // Timer tick function timerTick() { // Timer speed multiplier: 1.0 at stage 0, 1.2 at stage 1, 1.44 at stage 2, etc. var timerSpeedMultiplier = Math.pow(1.2, stage); timer -= 0.1 * timerSpeedMultiplier; if (timer < 0) timer = 0; updateTimerText(); updateTimerBar(); if (timer <= 0) { // Game over LK.showGameOver(); } // --- Stage progression logic --- stageTime += 0.1; var newStage = Math.floor(stageTime / stageDuration); if (newStage > 4) newStage = 4; if (newStage !== stage) { stage = newStage; stageText.setText(stageNames[stage]); // Optionally: make game harder here (e.g. increase monsterMax, spawn rate, etc) // Example: increase monsterMax by 1 per stage monsterMax = 6 + stage; // Increase monster speed for all alive monsters var speedMultiplier = Math.pow(1.2, stage); for (var i = 0; i < monsters.length; ++i) { if (monsters[i].alive) { monsters[i].speed = monsters[i].speedBase * speedMultiplier; } } } } // Start timer interval timerInterval = LK.setInterval(timerTick, 100); // Game update game.update = function () { // Randomly change spawn interval every 3-6 seconds if (monsterSpawnIntervalChangeTimer <= 0) { // Pick a new target interval between 40 and 180 ticks (0.67s to 3s) monsterSpawnIntervalTarget = 40 + Math.floor(Math.random() * 140); // Next change in 180-360 ticks (3-6s) monsterSpawnIntervalChangeTimer = 180 + Math.floor(Math.random() * 180); } monsterSpawnIntervalChangeTimer--; // Smoothly approach target interval for a less abrupt change if (monsterSpawnInterval !== monsterSpawnIntervalTarget) { if (monsterSpawnInterval < monsterSpawnIntervalTarget) monsterSpawnInterval++;else monsterSpawnInterval--; } // Spawn monsters if (LK.ticks - lastTick >= monsterSpawnInterval) { spawnMonster(); lastTick = LK.ticks; } // Move monsters for (var i = 0; i < monsters.length; ++i) { monsters[i].update(); } // Update timer bar updateTimerBar(); }; // Handle tap on monsters or empty space game.down = function (x, y, obj) { // Check if tap hits a monster (from topmost to bottom) var tapped = false; for (var i = monsters.length - 1; i >= 0; --i) { var m = monsters[i]; // Only alive monsters if (!m.alive) continue; // Convert tap to monster local coords var local = m.toLocal(game.toGlobal({ x: x, y: y })); // Check if inside monster ellipse var rx = m.children[0].width / 2; var ry = m.children[0].height / 2; if (local.x * local.x / (rx * rx) + local.y * local.y / (ry * ry) <= 1) { m.down(x, y, obj); tapped = true; break; } } // Tap effect var tapFx = new TapEffect(); tapFx.x = x; tapFx.y = y; game.addChild(tapFx); }; // Clean up on game over game.on('destroy', function () { LK.clearInterval(timerInterval); monsters = []; score = 0; timer = timerMax; updateScoreText(); updateTimerText(); updateTimerBar(); // Reset stage system stage = 0; stageTime = 0; stageText.setText(stageNames[stage]); monsterMax = 6; });
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Monster class
var Monster = Container.expand(function () {
var self = Container.call(this);
// Monster type: "normal", "fast", "slow", "giant", "tiny", "shadow", "jumbo"
self.type = "normal";
// Attach monster asset (default to normal, will be replaced in updateTypeVisual)
var monsterSprite = self.attachAsset('monster_normal', {
anchorX: 0.5,
anchorY: 0.5
});
// Color by type after setType is called
self.updateTypeVisual = function () {
// Remove old sprite if present
if (monsterSprite && self.children.indexOf(monsterSprite) !== -1) {
self.removeChild(monsterSprite);
}
// Choose asset and size by type
if (self.type === "fast") {
monsterSprite = self.attachAsset('monster_fast', {
anchorX: 0.5,
anchorY: 0.5
});
monsterSprite.width = 160;
monsterSprite.height = 160;
} else if (self.type === "slow") {
monsterSprite = self.attachAsset('monster_slow', {
anchorX: 0.5,
anchorY: 0.5
});
monsterSprite.width = 160;
monsterSprite.height = 160;
} else if (self.type === "giant") {
monsterSprite = self.attachAsset('monster_giant', {
anchorX: 0.5,
anchorY: 0.5
});
monsterSprite.width = 240;
monsterSprite.height = 240;
} else if (self.type === "tiny") {
monsterSprite = self.attachAsset('monster_tiny', {
anchorX: 0.5,
anchorY: 0.5
});
monsterSprite.width = 80;
monsterSprite.height = 80;
} else if (self.type === "shadow") {
monsterSprite = self.attachAsset('monster_shadow', {
anchorX: 0.5,
anchorY: 0.5
});
monsterSprite.width = 120;
monsterSprite.height = 120;
} else if (self.type === "jumbo") {
monsterSprite = self.attachAsset('monster_jumbo', {
anchorX: 0.5,
anchorY: 0.5
});
monsterSprite.width = 320;
monsterSprite.height = 320;
} else {
monsterSprite = self.attachAsset('monster_normal', {
anchorX: 0.5,
anchorY: 0.5
});
monsterSprite.width = 160;
monsterSprite.height = 160;
}
// Always reset position and alpha
monsterSprite.x = 0;
monsterSprite.y = 0;
monsterSprite.alpha = 1;
};
var _oldSetType = self.setType;
self.setType = function (type) {
_oldSetType(type);
self.updateTypeVisual();
};
// Movement speed (pixels per tick)
self.speed = 0;
// Store base speed for stage scaling
self.speedBase = 0;
// Movement direction (radians)
self.direction = 0;
// Is monster alive
self.alive = true;
// Set monster type and speed
self.setType = function (type) {
self.type = type;
if (type === "fast") {
// Fast monsters: 5-8 px/tick
self.speed = 5 + Math.random() * 3;
} else if (type === "slow") {
// Slow monsters: 1-2.5 px/tick
self.speed = 1 + Math.random() * 1.5;
} else if (type === "giant") {
// Giant monsters: 1-2 px/tick (slow, big)
self.speed = 1 + Math.random();
} else if (type === "tiny") {
// Tiny monsters: 7 + Math.random() * 4;
self.speed = 7 + Math.random() * 4;
} else if (type === "shadow") {
// Shadow monsters: 9-12 px/tick (very fast, small)
self.speed = 9 + Math.random() * 3;
} else if (type === "jumbo") {
// Jumbo monsters: 0.7-1.2 px/tick (very slow, very big)
self.speed = 0.7 + Math.random() * 0.5;
} else {
// Normal monsters: 2-6 px/tick
self.speed = 2 + Math.random() * 4;
}
// Store base speed and apply stage multiplier
self.speedBase = self.speed;
var speedMultiplier = Math.pow(1.2, typeof stage !== "undefined" ? stage : 0);
self.speed = self.speedBase * speedMultiplier;
};
// Set random movement
self.setRandomMovement = function () {
// Randomly assign type
var r = Math.random();
if (r < 0.14) {
self.setType("fast");
} else if (r < 0.28) {
self.setType("slow");
} else if (r < 0.42) {
self.setType("giant");
} else if (r < 0.56) {
self.setType("tiny");
} else if (r < 0.70) {
self.setType("shadow");
} else if (r < 0.84) {
self.setType("jumbo");
} else {
self.setType("normal");
}
// Direction: 0-2PI
self.direction = Math.random() * Math.PI * 2;
};
// Monster state for explosion logic
self.timeSinceSpawn = 0;
self.state = "normal"; // "normal", "red", "vibrating", "exploded"
self.vibrateDir = 1;
self.vibrateTick = 0;
// Move monster
self.update = function () {
if (!self.alive) return;
// Track time since spawn
if (typeof self.timeSinceSpawn !== "number") self.timeSinceSpawn = 0;
self.timeSinceSpawn += 1 / 60;
// Handle state transitions
if (self.state === "normal" && self.timeSinceSpawn >= 5) {
// Turn red
self.state = "red";
monsterSprite.tint = 0xff2222;
// Optionally: flash or pulse
tween(monsterSprite, {
alpha: 0.5
}, {
duration: 150,
yoyo: true,
repeat: 2,
onFinish: function onFinish() {
monsterSprite.alpha = 1;
}
});
}
if (self.state === "red" && self.timeSinceSpawn >= 7) {
// Start vibrating
self.state = "vibrating";
self.vibrateTick = 0;
}
if (self.state === "vibrating") {
// Vibrate effect: shake X/Y
self.vibrateTick++;
var shake = 8 + Math.random() * 4;
if (self.vibrateTick % 2 === 0) {
monsterSprite.x = shake * (Math.random() > 0.5 ? 1 : -1);
monsterSprite.y = shake * (Math.random() > 0.5 ? 1 : -1);
} else {
monsterSprite.x = 0;
monsterSprite.y = 0;
}
// After 1s of vibrating (60 ticks), explode
if (self.timeSinceSpawn >= 8) {
self.state = "exploded";
// Remove 5 seconds from timer
addTime(-5);
// Animate explosion (flash, fade out)
tween(monsterSprite, {
alpha: 0
}, {
duration: 250,
onFinish: function onFinish() {
self.destroy();
}
});
// Remove from monsters array
for (var i = 0; i < monsters.length; ++i) {
if (monsters[i] === self) {
monsters.splice(i, 1);
break;
}
}
return;
}
} else {
// Reset shake if not vibrating
monsterSprite.x = 0;
monsterSprite.y = 0;
}
// Move
self.x += Math.cos(self.direction) * self.speed;
self.y += Math.sin(self.direction) * self.speed;
// Bounce off walls
// Left
if (self.x - monsterSprite.width / 2 < 0) {
self.x = monsterSprite.width / 2;
self.direction = Math.PI - self.direction;
}
// Right
if (self.x + monsterSprite.width / 2 > 2048) {
self.x = 2048 - monsterSprite.width / 2;
self.direction = Math.PI - self.direction;
}
// Top
if (self.y - monsterSprite.height / 2 < 100) {
// leave top 100px for menu
self.y = 100 + monsterSprite.height / 2;
self.direction = -self.direction;
}
// Bottom
if (self.y + monsterSprite.height / 2 > 2732) {
self.y = 2732 - monsterSprite.height / 2;
self.direction = -self.direction;
}
};
// Handle tap
self.down = function (x, y, obj) {
if (!self.alive) return;
self.alive = false;
// Cancel explosion/vibration/red state
self.state = "shot";
if (monsterSprite) {
monsterSprite.x = 0;
monsterSprite.y = 0;
self.vibrateTick = 0;
}
// Show hit effect
var hitColor = 0xff4444;
if (self.type === "fast") hitColor = 0x3e8ecf;else if (self.type === "slow") hitColor = 0xcfb53e;else if (self.type === "giant") hitColor = 0x8e44ad;else if (self.type === "tiny") hitColor = 0xffffff;else if (self.type === "shadow") hitColor = 0x222222;else if (self.type === "jumbo") hitColor = 0xff8800;
var hit = LK.getAsset('monsterHit', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: 0,
scaleX: 1,
scaleY: 1,
alpha: 1,
tint: hitColor
});
self.addChild(hit);
// Animate hit effect
tween(hit, {
scaleX: 1.5,
scaleY: 1.5,
alpha: 0
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
hit.destroy();
}
});
// Animate monster fade out
tween(monsterSprite, {
alpha: 0
}, {
duration: 200,
onFinish: function onFinish() {
self.destroy();
}
});
// Add time and score
if (self.type === "fast") {
addTime(3); // fast: +3s
} else if (self.type === "slow") {
addTime(1); // slow: +1s
} else if (self.type === "giant") {
addTime(5); // giant: +5s
} else if (self.type === "tiny") {
addTime(0.5); // tiny: +0.5s
} else if (self.type === "shadow") {
addTime(0.2); // shadow: +0.2s
} else if (self.type === "jumbo") {
addTime(8); // jumbo: +8s
} else {
addTime(2); // normal: +2s
}
setScore(getScore() + 1);
updateScoreText();
// Remove from monsters array
for (var i = 0; i < monsters.length; ++i) {
if (monsters[i] === self) {
monsters.splice(i, 1);
break;
}
}
};
return self;
});
// Tap effect class
var TapEffect = Container.expand(function () {
var self = Container.call(this);
var tap = self.attachAsset('tapEffect', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1,
scaleY: 1,
alpha: 0.7
});
// Animate
tween(tap, {
scaleX: 2,
scaleY: 2,
alpha: 0
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
self.destroy();
}
});
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x181c2a
});
/****
* Game Code
****/
// Tap effect: yellow ellipse, 100x100
// Monster hit effect: red ellipse, 160x160
// Monster: green ellipse, 160x160
// Global variables
var monsters = [];
var monsterSpawnInterval = 120; // ticks between spawns (2s)
var monsterSpawnIntervalTarget = 120; // target interval for smooth transitions
var monsterSpawnIntervalChangeTimer = 0; // ticks until next interval change
var monsterMax = 6; // max monsters on screen
var timerMax = 20; // seconds to start
var timer = timerMax; // current timer (seconds)
var timerInterval = null;
var timerBar = null;
var timerBarBg = null;
var timerText = null;
var score = 0;
var scoreText = null;
var lastTick = 0;
// Stage system
var stage = 0; // 0: Very Easy, 1: Easy, 2: Medium, 3: Hard, 4: Very Hard
var stageNames = ["Very Easy", "Easy", "Medium", "Hard", "Very Hard"];
var stageText = null;
var stageBarBg = null;
var stageBar = null;
var stageTime = 0; // seconds since game start
var stageDuration = 20; // seconds per stage
// Helper: get/set score
function getScore() {
return score;
}
function setScore(val) {
score = val;
}
function updateScoreText() {
scoreText.setText(score + "");
}
// Helper: add time
function addTime(sec) {
timer += sec;
if (timer > 99) timer = 99;
updateTimerText();
}
// Helper: update timer text
function updateTimerText() {
timerText.setText(timer > 0 ? Math.ceil(timer) + "" : "0");
}
// Helper: update timer bar
function updateTimerBar() {
var pct = Math.max(0, Math.min(1, timer / timerMax));
timerBar.width = 800 * pct;
if (pct > 0.5) timerBar.tint = 0x3ecf4c;else if (pct > 0.2) timerBar.tint = 0xffe066;else timerBar.tint = 0xff4444;
}
// Spawn a monster at random position
function spawnMonster() {
if (monsters.length >= monsterMax) return;
var m = new Monster();
// Avoid top 100px (menu)
var margin = 100 + 80;
m.x = margin + Math.random() * (2048 - margin * 2);
m.y = margin + Math.random() * (2732 - margin * 2);
m.setRandomMovement();
m.updateTypeVisual && m.updateTypeVisual();
// Store base speed and apply stage multiplier
m.speedBase = m.speed;
var speedMultiplier = Math.pow(1.2, stage);
m.speed = m.speedBase * speedMultiplier;
// Reset monster state for explosion logic
m.timeSinceSpawn = 0;
m.state = "normal";
m.vibrateTick = 0;
// No need to override asset or tint here; Monster class handles correct asset and visuals
monsters.push(m);
game.addChild(m);
}
// GUI: Score
scoreText = new Text2("0", {
size: 120,
fill: "#fff"
});
scoreText.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreText);
// GUI: Timer bar background
timerBarBg = LK.getAsset('monster', {
anchorX: 0,
anchorY: 0.5,
x: 624,
y: 100,
width: 800,
height: 40,
tint: 0x222222
});
timerBarBg.alpha = 0.5;
game.addChild(timerBarBg);
// GUI: Timer bar
timerBar = LK.getAsset('monster', {
anchorX: 0,
anchorY: 0.5,
x: 624,
y: 100,
width: 800,
height: 40,
tint: 0x3ecf4c
});
game.addChild(timerBar);
// GUI: Timer text
timerText = new Text2(timerMax + "", {
size: 90,
fill: "#fff"
});
timerText.anchor.set(0.5, 0.5);
timerText.x = 2048 / 2;
timerText.y = 100 + 20;
game.addChild(timerText);
// Position score at top center, below 100px
scoreText.x = 2048 / 2;
scoreText.y = 10 + 100;
// GUI: Stage label and progress bar (right top, under timer bar)
stageText = new Text2(stageNames[stage], {
size: 70,
fill: "#fff"
});
stageText.anchor.set(1, 0); // right align
stageText.x = 2048 - 40;
stageText.y = 160;
game.addChild(stageText);
// Spawn initial monsters
for (var i = 0; i < 3; ++i) {
spawnMonster();
}
// Timer tick
function timerTick() {
// Timer speed multiplier: 1.0 at stage 0, 1.2 at stage 1, 1.44 at stage 2, etc.
var timerSpeedMultiplier = Math.pow(1.2, stage);
timer -= 0.1 * timerSpeedMultiplier;
if (timer < 0) timer = 0;
updateTimerText();
updateTimerBar();
if (timer <= 0) {
// Game over
LK.showGameOver();
}
// --- Stage progression logic ---
stageTime += 0.1;
var newStage = Math.floor(stageTime / stageDuration);
if (newStage > 4) newStage = 4;
if (newStage !== stage) {
stage = newStage;
stageText.setText(stageNames[stage]);
// Optionally: make game harder here (e.g. increase monsterMax, spawn rate, etc)
// Example: increase monsterMax by 1 per stage
monsterMax = 6 + stage;
// Increase monster speed for all alive monsters
var speedMultiplier = Math.pow(1.2, stage);
for (var i = 0; i < monsters.length; ++i) {
if (monsters[i].alive) {
monsters[i].speed = monsters[i].speedBase * speedMultiplier;
}
}
}
}
// Start timer interval
timerInterval = LK.setInterval(timerTick, 100);
// Game update
game.update = function () {
// Randomly change spawn interval every 3-6 seconds
if (monsterSpawnIntervalChangeTimer <= 0) {
// Pick a new target interval between 40 and 180 ticks (0.67s to 3s)
monsterSpawnIntervalTarget = 40 + Math.floor(Math.random() * 140);
// Next change in 180-360 ticks (3-6s)
monsterSpawnIntervalChangeTimer = 180 + Math.floor(Math.random() * 180);
}
monsterSpawnIntervalChangeTimer--;
// Smoothly approach target interval for a less abrupt change
if (monsterSpawnInterval !== monsterSpawnIntervalTarget) {
if (monsterSpawnInterval < monsterSpawnIntervalTarget) monsterSpawnInterval++;else monsterSpawnInterval--;
}
// Spawn monsters
if (LK.ticks - lastTick >= monsterSpawnInterval) {
spawnMonster();
lastTick = LK.ticks;
}
// Move monsters
for (var i = 0; i < monsters.length; ++i) {
monsters[i].update();
}
// Update timer bar
updateTimerBar();
};
// Handle tap on monsters or empty space
game.down = function (x, y, obj) {
// Check if tap hits a monster (from topmost to bottom)
var tapped = false;
for (var i = monsters.length - 1; i >= 0; --i) {
var m = monsters[i];
// Only alive monsters
if (!m.alive) continue;
// Convert tap to monster local coords
var local = m.toLocal(game.toGlobal({
x: x,
y: y
}));
// Check if inside monster ellipse
var rx = m.children[0].width / 2;
var ry = m.children[0].height / 2;
if (local.x * local.x / (rx * rx) + local.y * local.y / (ry * ry) <= 1) {
m.down(x, y, obj);
tapped = true;
break;
}
}
// Tap effect
var tapFx = new TapEffect();
tapFx.x = x;
tapFx.y = y;
game.addChild(tapFx);
};
// Clean up on game over
game.on('destroy', function () {
LK.clearInterval(timerInterval);
monsters = [];
score = 0;
timer = timerMax;
updateScoreText();
updateTimerText();
updateTimerBar();
// Reset stage system
stage = 0;
stageTime = 0;
stageText.setText(stageNames[stage]);
monsterMax = 6;
});
round shaped monster. his mouth is open and his tongue is out . No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
make it angry and blue
make it cocky and white
make it purple and suspicious
make it dark green and idiot
make it black and idioter
make it happy and cyan
skeletons, skull, death city, war, crime, illegal . No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat