User prompt
Score and goal should be in the top left corner of the screen
User prompt
level and seconds should be in the top right corner of the screen
User prompt
Score and requested score should be in the upper left corner
User prompt
The level text should be at the top right of the screen.
User prompt
When the rope is empty it should go up faster
User prompt
There should be sections that get harder as you level up.
User prompt
When the rope is empty it should go up faster
User prompt
There should be more gold, more diamonds and more rocks on the screen.
User prompt
the rope should go further down
User prompt
make the background brown
User prompt
make the background light brown
Code edit (1 edits merged)
Please save this source code
User prompt
Gold Miner Classic
Initial prompt
can you make a gold miner game?
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ // Claw class var Claw = Container.expand(function () { var self = Container.call(this); // Arm var arm = self.attachAsset('clawArm', { anchorX: 0.5, anchorY: 0, x: 0, y: 0 }); // Claw head var head = self.attachAsset('clawHead', { anchorX: 0.5, anchorY: 0, x: 0, y: arm.height }); // State self.swingAngle = 0; // in radians self.swingDir = 1; // 1 or -1 self.swingSpeed = 0.025; // radians per tick self.swingMax = Math.PI / 3; // 60 deg left/right self.state = 'swing'; // 'swing', 'extend', 'retract', 'grabbed' self.length = arm.height; // current arm length self.baseLength = arm.height; self.maxLength = GAME_HEIGHT - 100; // how far the claw can extend (let rope go to bottom) self.speed = 32; // pixels per tick when extending self.retractSpeed = 32; // default retract speed self.grabbedObj = null; // reference to grabbed object // Update arm and head positions based on length and angle self.updateClaw = function () { var dx = Math.sin(self.swingAngle) * self.length; var dy = Math.cos(self.swingAngle) * self.length; arm.rotation = -self.swingAngle; arm.height = self.length; head.x = dx; head.y = dy; head.rotation = -self.swingAngle; if (self.grabbedObj) { self.grabbedObj.x = self.x + dx; self.grabbedObj.y = self.y + dy + head.height / 2; } }; // Called every tick self.update = function () { if (self.state === 'swing') { self.swingAngle += self.swingDir * self.swingSpeed; if (self.swingAngle > self.swingMax) { self.swingAngle = self.swingMax; self.swingDir = -1; } if (self.swingAngle < -self.swingMax) { self.swingAngle = -self.swingMax; self.swingDir = 1; } } else if (self.state === 'extend') { self.length += self.speed; if (self.length >= self.maxLength) { self.length = self.maxLength; self.state = 'retract'; } } else if (self.state === 'retract') { self.length -= self.retractSpeed; if (self.length <= self.baseLength) { self.length = self.baseLength; self.state = 'swing'; if (self.grabbedObj) { // Drop object at top self.grabbedObj.onCollected(); self.grabbedObj = null; } } } else if (self.state === 'grabbed') { // Wait for retract to finish self.length -= self.retractSpeed; if (self.length <= self.baseLength) { self.length = self.baseLength; self.state = 'swing'; if (self.grabbedObj) { self.grabbedObj.onCollected(); self.grabbedObj = null; } } } self.updateClaw(); }; // Start extending self.startExtend = function () { if (self.state === 'swing') { self.state = 'extend'; // Bag remains on the hook; do not remove it when extending } }; // Called when an object is grabbed self.grabObject = function (obj) { self.grabbedObj = obj; self.state = 'grabbed'; // Set retract speed based on object type self.retractSpeed = obj.retractSpeed; }; // Called when nothing is grabbed (hit ground) self.miss = function () { self.state = 'retract'; self.retractSpeed = 64; //{L} // Faster retract when empty }; return self; }); // Moving Target class var Target = Container.expand(function () { var self = Container.call(this); // Draw as a different asset (targetBox image asset) var boxAsset = self.attachAsset('targetBox', { anchorX: 0.5, anchorY: 0.5, scaleX: 1, scaleY: 1 }); // Optionally, you can adjust scaleX/scaleY if you want it smaller/larger self.value = 2; self.speed = 8; // medium speed self.direction = 1; // 1 = right, -1 = left self.y = GROUND_Y - 100; self.x = 400; self.lastX = self.x; self.update = function () { // Move horizontally self.x += self.speed * self.direction; if (self.lastX <= GAME_WIDTH - 200 && self.x > GAME_WIDTH - 200 || self.lastX >= 200 && self.x < 200) { self.direction *= -1; } // Clamp position if (self.x > GAME_WIDTH - 200) self.x = GAME_WIDTH - 200; if (self.x < 200) self.x = 200; self.lastX = self.x; }; // Add a no-op onCollected method to prevent errors if called by Claw self.onCollected = function () { // No-op for moving target }; return self; }); // Base class for all underground objects var UndergroundObject = Container.expand(function () { var self = Container.call(this); self.value = 0; self.retractSpeed = 32; self.grabSound = 'grab'; self.collectedSound = 'collect'; self.collected = false; // Called when collected self.onCollected = function () { if (self.collected) return; self.collected = true; // Play money sound when pulling up captured objects LK.getSound('money').play(); self.visible = false; if (typeof self.onScore === 'function') self.onScore(); if (typeof score !== 'undefined') { score += self.value; LK.setScore(score); if (typeof scoreTxt !== 'undefined') scoreTxt.setText(score); } self.destroy(); }; return self; }); // Rock var Rock = UndergroundObject.expand(function () { var self = UndergroundObject.call(this); var rock = self.attachAsset('rock', { anchorX: 0.5, anchorY: 0.5 }); self.value = 50; self.retractSpeed = 6; // very slow self.grabSound = 'rockhit'; self.collectedSound = 'rockhit'; self.onCollected = function () { if (self.collected) return; self.collected = true; LK.getSound('money').play(); self.visible = false; if (typeof self.onScore === 'function') self.onScore(); self.destroy(); }; return self; }); // Pig var Pig = UndergroundObject.expand(function () { var self = UndergroundObject.call(this); var pig = self.attachAsset('pig', { anchorX: 0.5, anchorY: 0.5 }); self.value = 1200; self.retractSpeed = 20; // medium-fast self.grabSound = 'grab'; self.collectedSound = 'collect'; self.onCollected = function () { if (self.collected) return; self.collected = true; // Play explosion sound and flash screen like dynamite LK.getSound('dynamite').play(); LK.effects.flashScreen(0xff0000, 800); // Remove some score as penalty (like dynamite, but you can adjust penalty if desired) score = Math.max(0, score - 400); LK.setScore(score); if (typeof scoreTxt !== 'undefined') scoreTxt.setText(score); self.visible = false; if (typeof self.onScore === 'function') self.onScore(); // Explode nearby pigs if (typeof objects !== "undefined" && Array.isArray(objects)) { for (var i = 0; i < objects.length; i++) { var obj = objects[i]; if (obj === self) continue; if (obj && obj.visible !== false && obj instanceof Pig && !obj.collected) { // Distance between pigs var dx = obj.x - self.x; var dy = obj.y - self.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist < 250) { // 250px radius for explosion obj.onCollected(); } } } } self.destroy(); }; return self; }); // Small gold nugget var GoldSmall = UndergroundObject.expand(function () { var self = UndergroundObject.call(this); var gold = self.attachAsset('goldSmall', { anchorX: 0.5, anchorY: 0.5 }); self.value = 250; self.retractSpeed = 24; // medium self.grabSound = 'grab'; self.collectedSound = 'collect'; self.onCollected = function () { if (self.collected) return; self.collected = true; LK.getSound('money').play(); self.visible = false; if (typeof self.onScore === 'function') self.onScore(); self.destroy(); }; return self; }); // Gold nugget var Gold = UndergroundObject.expand(function () { var self = UndergroundObject.call(this); var gold = self.attachAsset('gold', { anchorX: 0.5, anchorY: 0.5 }); self.value = 500; self.retractSpeed = 8; // slower self.grabSound = 'grab'; self.collectedSound = 'collect'; self.onCollected = function () { if (self.collected) return; self.collected = true; LK.getSound('money').play(); self.visible = false; if (typeof self.onScore === 'function') self.onScore(); self.destroy(); }; return self; }); // Gem var Gem = UndergroundObject.expand(function () { var self = UndergroundObject.call(this); var gem = self.attachAsset('gem', { anchorX: 0.5, anchorY: 0.5 }); self.value = 800; self.retractSpeed = 32; // fast self.grabSound = 'grab'; self.collectedSound = 'collect'; self.onCollected = function () { if (self.collected) return; self.collected = true; LK.getSound('money').play(); self.visible = false; if (typeof self.onScore === 'function') self.onScore(); self.destroy(); }; return self; }); // Dynamite trap var Dynamite = UndergroundObject.expand(function () { var self = UndergroundObject.call(this); var dynamite = self.attachAsset('dynamite', { anchorX: 0.5, anchorY: 0.5 }); self.value = 0; self.retractSpeed = 40; // fast retract self.grabSound = 'dynamite'; self.collectedSound = 'dynamite'; self.onCollected = function () { if (self.collected) return; self.collected = true; LK.getSound(self.collectedSound).play(); // Flash screen red to indicate explosion LK.effects.flashScreen(0xff0000, 800); // Remove some score as penalty score = Math.max(0, score - 400); LK.setScore(score); if (typeof scoreTxt !== 'undefined') scoreTxt.setText(score); self.visible = false; self.destroy(); }; return self; }); // Bag (Torba) var Bag = UndergroundObject.expand(function () { var self = UndergroundObject.call(this); var bag = self.attachAsset('torba', { anchorX: 0.5, anchorY: 0.5 }); self.value = 1000; self.retractSpeed = 18; // medium-slow self.grabSound = 'grab'; self.collectedSound = 'collect'; self.onCollected = function () { if (self.collected) return; self.collected = true; LK.getSound('money').play(); self.visible = false; if (typeof self.onScore === 'function') self.onScore(); self.destroy(); }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x8B5A2B // brown }); /**** * Game Code ****/ // Game constants // Claw arm (rectangle) // Claw head (ellipse) // Gold nugget (ellipse) // Small gold nugget // Rock (ellipse) // Gem (ellipse) // Sound for grabbing // Sound for collecting // Sound for hitting rock // Music var GAME_WIDTH = 2048; var GAME_HEIGHT = 2732; var GROUND_Y = 700; // y position where underground objects start var LEVEL_TIME = 60; // seconds var LEVEL_GOAL = 1500; // gold needed to win // Level and difficulty progression var level = 1; var maxLevel = 10; var objects = []; var claw = null; var score = 0; var timer = 0; var timeLeft = LEVEL_TIME; var goal = LEVEL_GOAL; var gameActive = true; // Add multiple moving targets var targets = []; // GUI // Level text (very small, upper right corner) var levelTxt = new Text2('Level ' + level, { size: 40, fill: "#fff" }); levelTxt.anchor.set(1, 0); // right-top levelTxt.x = -8; // 8px from the right edge of gui.topRight levelTxt.y = 0; LK.gui.topRight.addChild(levelTxt); // Goal text (very small, just above the score number) var goalTxt = new Text2('Goal: ' + goal, { size: 32, fill: "#fff" }); goalTxt.anchor.set(1, 0); // right-top goalTxt.x = levelTxt.x - levelTxt.width - 16; // align with score goalTxt.y = 0; // align to top since dollars label is removed LK.gui.topRight.addChild(goalTxt); // Score text (small, right next to level text, to the left) var scoreTxt = new Text2('0', { size: 40, fill: "#fff" }); scoreTxt.anchor.set(1, 0); // right-top scoreTxt.x = levelTxt.x - levelTxt.width - 16; // 16px padding between score and level scoreTxt.y = goalTxt.y + goalTxt.height + 2; // just below goal text LK.gui.topRight.addChild(scoreTxt); // Countdown timer text (small, just below level text) var countdownTxt = new Text2(timeLeft + 's', { size: 32, fill: "#fff" }); countdownTxt.anchor.set(1, 0); // right-top countdownTxt.x = levelTxt.x; countdownTxt.y = levelTxt.height + 4; // 4px below level text LK.gui.topRight.addChild(countdownTxt); // Timer interval to update countdown var countdownInterval = LK.setInterval(function () { if (!gameActive) return; timeLeft--; if (timeLeft < 0) timeLeft = 0; countdownTxt.setText(timeLeft + 's'); if (timeLeft === 0 && gameActive) { gameActive = false; LK.effects.flashScreen(0xff0000, 800); LK.showGameOver(); } }, 1000); // Place claw at top center claw = new Claw(); claw.x = GAME_WIDTH / 2; claw.y = 0; game.addChild(claw); // (Bag is not attached to the hook) // Underground object spawn positions function spawnObjects() { // Clear previous for (var i = 0; i < objects.length; i++) { objects[i].destroy(); } objects = []; // Difficulty scaling var bigGoldCount = 4 + Math.floor(level / 2); var smallGoldCount = 6 + level; var rockCount = 6 + level * 2; var gemCount = 3 + Math.floor(level / 2); var dynamiteCount = 2 + Math.floor(level / 2); // Create all objects in order: gold, diamonds, dynamite, rocks, bags, pigs, then mix var allObjs = []; // Gold (big) for (var i = 0; i < bigGoldCount; i++) { var g = new Gold(); g.onScore = function () { score += this.value; LK.setScore(score); if (scoreTxt) scoreTxt.setText(score); }; allObjs.push(g); } // Gold (small) for (var i = 0; i < smallGoldCount; i++) { var gs = new GoldSmall(); gs.onScore = function () { score += this.value; LK.setScore(score); if (scoreTxt) scoreTxt.setText(score); }; allObjs.push(gs); } // Gems for (var i = 0; i < gemCount; i++) { var gem = new Gem(); gem.onScore = function () { score += this.value; LK.setScore(score); if (scoreTxt) scoreTxt.setText(score); }; allObjs.push(gem); } // Bags (torba) var bagCount = 2 + Math.floor(level / 2); for (var i = 0; i < bagCount; i++) { var bag = new Bag(); bag.onScore = function () { score += this.value; LK.setScore(score); if (scoreTxt) scoreTxt.setText(score); }; allObjs.push(bag); } // Pigs var pigCount = 2 + Math.floor(level / 2); for (var i = 0; i < pigCount; i++) { var pig = new Pig(); pig.onScore = function () { score += this.value; LK.setScore(score); if (scoreTxt) scoreTxt.setText(score); }; allObjs.push(pig); } // Dynamite for (var i = 0; i < dynamiteCount; i++) { var d = new Dynamite(); allObjs.push(d); } // Rocks for (var i = 0; i < rockCount; i++) { var r = new Rock(); r.onScore = function () { score += this.value; LK.setScore(score); if (scoreTxt) scoreTxt.setText(score); }; allObjs.push(r); } // Shuffle allObjs array for (var i = allObjs.length - 1; i > 0; i--) { var j = Math.floor(Math.random() * (i + 1)); var temp = allObjs[i]; allObjs[i] = allObjs[j]; allObjs[j] = temp; } // Place objects in the play area, avoiding overlap var gridCols = 8; var gridRows = Math.ceil(allObjs.length / gridCols); var cellW = Math.floor((GAME_WIDTH - 400) / gridCols); var cellH = Math.floor((GAME_HEIGHT - GROUND_Y - 400) / gridRows); var usedCells = []; for (var i = 0; i < allObjs.length; i++) { var obj = allObjs[i]; // Find a free cell var placed = false; var attempts = 0; while (!placed && attempts < 30) { var col = Math.floor(Math.random() * gridCols); var row = Math.floor(Math.random() * gridRows); var cellIdx = row * gridCols + col; if (usedCells.indexOf(cellIdx) === -1) { usedCells.push(cellIdx); obj.x = 200 + col * cellW + Math.floor(cellW / 2); obj.y = GROUND_Y + 200 + row * cellH + Math.floor(cellH / 2); placed = true; } attempts++; } game.addChild(obj); objects.push(obj); } } spawnObjects(); // Create and add multiple moving targets at specific parts of the screen // Destroy old targets if any if (targets && targets.length) { for (var i = 0; i < targets.length; i++) { if (targets[i]) targets[i].destroy(); } } targets = []; // Place fewer moving targets at the top, and more in the middle section var targetPositions = [ // Only one at the top left { x: 300, y: GROUND_Y + 100 }, // Add more to the middle section { x: 600, y: GROUND_Y + 400 }, { x: GAME_WIDTH - 600, y: GROUND_Y + 400 }, { x: 400, y: GROUND_Y + 700 }, { x: GAME_WIDTH - 400, y: GROUND_Y + 700 }, { x: GAME_WIDTH / 2, y: GROUND_Y + 900 }]; for (var i = 0; i < targetPositions.length; i++) { var t = new Target(); t.x = targetPositions[i].x; t.y = targetPositions[i].y; t.direction = i % 2 === 0 ? 1 : -1; targets.push(t); game.addChild(t); } // Add moving TL objects to the top left of the screen var tlObjects = []; var tlCount = 2; // Number of TL objects to add/move for (var i = 0; i < tlCount; i++) { var tl = new Container(); var tlImg = tl.attachAsset('TL', { anchorX: 0.5, anchorY: 0.5 }); tl.x = 120 + i * 120; // Space out horizontally, keep away from top left 100x100 tl.y = 120; tl.speed = 6 + Math.floor(Math.random() * 4); tl.direction = Math.random() < 0.5 ? 1 : -1; tl.lastX = tl.x; tl.update = function () { if (typeof this.lastX !== "number") this.lastX = this.x; this.x += this.speed * this.direction; // Bounce at left/right margin (keep inside 120 to 400 px) if (this.lastX <= 120 && this.x > 120) this.direction = 1; if (this.lastX >= 400 && this.x < 400) this.direction = -1; if (this.x > 400) this.x = 400; if (this.x < 120) this.x = 120; this.lastX = this.x; }; tlObjects.push(tl); game.addChild(tl); } // Draw a dot at the top center to send the rope down var dropDot = LK.getAsset('centerCircle', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.5, scaleY: 0.5, x: GAME_WIDTH / 2, y: 80 }); game.addChild(dropDot); // Only trigger on dot press, not anywhere dropDot.down = function (x, y, obj) { if (!gameActive) return; if (claw.state === 'swing') { claw.startExtend(); } }; // Touch/click anywhere else does nothing game.down = function (x, y, obj) { // No-op, handled by dropDot }; // Main update loop game.update = function () { if (!gameActive) return; // Claw update handled in class // If claw is extending, check for collision with objects if (claw.state === 'extend') { // Get claw head position var dx = Math.sin(claw.swingAngle) * claw.length; var dy = Math.cos(claw.swingAngle) * claw.length; var cx = claw.x + dx; var cy = claw.y + dy + 30; // 30: half head height // Check for collision with any object var grabbed = false; for (var i = 0; i < objects.length; i++) { var obj = objects[i]; if (obj.collected) continue; // Simple circle collision var dist = Math.sqrt((obj.x - cx) * (obj.x - cx) + (obj.y - cy) * (obj.y - cy)); var r = 60; // approx radius if (dist < r + 40) { // If it's a pig, trigger explosion immediately and do not attach to claw if (obj instanceof Pig) { obj.onCollected(); grabbed = true; break; } // Grab object claw.grabObject(obj); // Dynamite handles penalty in its onCollected grabbed = true; break; } } // Check for collision with any moving target if not already grabbed something if (!grabbed && targets && targets.length) { for (var ti = 0; ti < targets.length; ti++) { var t = targets[ti]; if (!t.visible) continue; if (typeof t.x !== 'number' || typeof t.y !== 'number') continue; var tdist = Math.sqrt((t.x - cx) * (t.x - cx) + (t.y - cy) * (t.y - cy)); var tr = 100; // slightly larger radius for target if (tdist < tr) { // "Grab" the target: treat as a special object claw.grabbedObj = t; claw.state = 'grabbed'; claw.retractSpeed = 32; // Optionally, you can add a sound or effect here // Remove the target visually and respawn after a delay t.visible = false; (function (targetToRespawn) { LK.setTimeout(function () { if (targetToRespawn) { targetToRespawn.x = 400 + Math.floor(Math.random() * (GAME_WIDTH - 800)); targetToRespawn.y = GROUND_Y - 100 - Math.floor(Math.random() * 120); targetToRespawn.visible = true; } }, 2000); })(t); grabbed = true; break; } } } // If reached max length and nothing grabbed, retract if (claw.length >= claw.maxLength && claw.state === 'extend') { claw.miss(); } } // Win condition if (score >= goal && gameActive) { gameActive = false; LK.effects.flashScreen(0xffff00, 800); // Level up logic if (level < maxLevel) { level += 1; // Play level up sound LK.getSound('level').play(); // Increase goal and decrease time for next level goal = LEVEL_GOAL + level * 800; timeLeft = LEVEL_TIME - Math.min(level * 3, 30); // reduce time, but not below 30s score = 0; LK.setScore(score); if (scoreTxt) scoreTxt.setText(score); // Update level text if (levelTxt) levelTxt.setText('Level ' + level); // Update goal text if (goalTxt) goalTxt.setText('Goal: ' + goal); // Reset countdown timer text and timeLeft timeLeft = LEVEL_TIME - Math.min(level * 3, 30); if (countdownTxt) countdownTxt.setText(timeLeft + 's'); // Respawn objects for new level spawnObjects(); gameActive = true; } else { LK.showYouWin(); } } // Update all moving targets if (targets && targets.length) { for (var ti = 0; ti < targets.length; ti++) { if (targets[ti] && typeof targets[ti].update === 'function') { targets[ti].update(); } } } // Update all TL objects if (typeof tlObjects !== "undefined" && tlObjects.length) { for (var i = 0; i < tlObjects.length; i++) { if (tlObjects[i] && typeof tlObjects[i].update === "function") { tlObjects[i].update(); } } } }; // Play background music LK.playMusic('goldminerbg', { fade: { start: 0, end: 1, duration: 1000 } });
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Claw class
var Claw = Container.expand(function () {
var self = Container.call(this);
// Arm
var arm = self.attachAsset('clawArm', {
anchorX: 0.5,
anchorY: 0,
x: 0,
y: 0
});
// Claw head
var head = self.attachAsset('clawHead', {
anchorX: 0.5,
anchorY: 0,
x: 0,
y: arm.height
});
// State
self.swingAngle = 0; // in radians
self.swingDir = 1; // 1 or -1
self.swingSpeed = 0.025; // radians per tick
self.swingMax = Math.PI / 3; // 60 deg left/right
self.state = 'swing'; // 'swing', 'extend', 'retract', 'grabbed'
self.length = arm.height; // current arm length
self.baseLength = arm.height;
self.maxLength = GAME_HEIGHT - 100; // how far the claw can extend (let rope go to bottom)
self.speed = 32; // pixels per tick when extending
self.retractSpeed = 32; // default retract speed
self.grabbedObj = null; // reference to grabbed object
// Update arm and head positions based on length and angle
self.updateClaw = function () {
var dx = Math.sin(self.swingAngle) * self.length;
var dy = Math.cos(self.swingAngle) * self.length;
arm.rotation = -self.swingAngle;
arm.height = self.length;
head.x = dx;
head.y = dy;
head.rotation = -self.swingAngle;
if (self.grabbedObj) {
self.grabbedObj.x = self.x + dx;
self.grabbedObj.y = self.y + dy + head.height / 2;
}
};
// Called every tick
self.update = function () {
if (self.state === 'swing') {
self.swingAngle += self.swingDir * self.swingSpeed;
if (self.swingAngle > self.swingMax) {
self.swingAngle = self.swingMax;
self.swingDir = -1;
}
if (self.swingAngle < -self.swingMax) {
self.swingAngle = -self.swingMax;
self.swingDir = 1;
}
} else if (self.state === 'extend') {
self.length += self.speed;
if (self.length >= self.maxLength) {
self.length = self.maxLength;
self.state = 'retract';
}
} else if (self.state === 'retract') {
self.length -= self.retractSpeed;
if (self.length <= self.baseLength) {
self.length = self.baseLength;
self.state = 'swing';
if (self.grabbedObj) {
// Drop object at top
self.grabbedObj.onCollected();
self.grabbedObj = null;
}
}
} else if (self.state === 'grabbed') {
// Wait for retract to finish
self.length -= self.retractSpeed;
if (self.length <= self.baseLength) {
self.length = self.baseLength;
self.state = 'swing';
if (self.grabbedObj) {
self.grabbedObj.onCollected();
self.grabbedObj = null;
}
}
}
self.updateClaw();
};
// Start extending
self.startExtend = function () {
if (self.state === 'swing') {
self.state = 'extend';
// Bag remains on the hook; do not remove it when extending
}
};
// Called when an object is grabbed
self.grabObject = function (obj) {
self.grabbedObj = obj;
self.state = 'grabbed';
// Set retract speed based on object type
self.retractSpeed = obj.retractSpeed;
};
// Called when nothing is grabbed (hit ground)
self.miss = function () {
self.state = 'retract';
self.retractSpeed = 64; //{L} // Faster retract when empty
};
return self;
});
// Moving Target class
var Target = Container.expand(function () {
var self = Container.call(this);
// Draw as a different asset (targetBox image asset)
var boxAsset = self.attachAsset('targetBox', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1,
scaleY: 1
});
// Optionally, you can adjust scaleX/scaleY if you want it smaller/larger
self.value = 2;
self.speed = 8; // medium speed
self.direction = 1; // 1 = right, -1 = left
self.y = GROUND_Y - 100;
self.x = 400;
self.lastX = self.x;
self.update = function () {
// Move horizontally
self.x += self.speed * self.direction;
if (self.lastX <= GAME_WIDTH - 200 && self.x > GAME_WIDTH - 200 || self.lastX >= 200 && self.x < 200) {
self.direction *= -1;
}
// Clamp position
if (self.x > GAME_WIDTH - 200) self.x = GAME_WIDTH - 200;
if (self.x < 200) self.x = 200;
self.lastX = self.x;
};
// Add a no-op onCollected method to prevent errors if called by Claw
self.onCollected = function () {
// No-op for moving target
};
return self;
});
// Base class for all underground objects
var UndergroundObject = Container.expand(function () {
var self = Container.call(this);
self.value = 0;
self.retractSpeed = 32;
self.grabSound = 'grab';
self.collectedSound = 'collect';
self.collected = false;
// Called when collected
self.onCollected = function () {
if (self.collected) return;
self.collected = true;
// Play money sound when pulling up captured objects
LK.getSound('money').play();
self.visible = false;
if (typeof self.onScore === 'function') self.onScore();
if (typeof score !== 'undefined') {
score += self.value;
LK.setScore(score);
if (typeof scoreTxt !== 'undefined') scoreTxt.setText(score);
}
self.destroy();
};
return self;
});
// Rock
var Rock = UndergroundObject.expand(function () {
var self = UndergroundObject.call(this);
var rock = self.attachAsset('rock', {
anchorX: 0.5,
anchorY: 0.5
});
self.value = 50;
self.retractSpeed = 6; // very slow
self.grabSound = 'rockhit';
self.collectedSound = 'rockhit';
self.onCollected = function () {
if (self.collected) return;
self.collected = true;
LK.getSound('money').play();
self.visible = false;
if (typeof self.onScore === 'function') self.onScore();
self.destroy();
};
return self;
});
// Pig
var Pig = UndergroundObject.expand(function () {
var self = UndergroundObject.call(this);
var pig = self.attachAsset('pig', {
anchorX: 0.5,
anchorY: 0.5
});
self.value = 1200;
self.retractSpeed = 20; // medium-fast
self.grabSound = 'grab';
self.collectedSound = 'collect';
self.onCollected = function () {
if (self.collected) return;
self.collected = true;
// Play explosion sound and flash screen like dynamite
LK.getSound('dynamite').play();
LK.effects.flashScreen(0xff0000, 800);
// Remove some score as penalty (like dynamite, but you can adjust penalty if desired)
score = Math.max(0, score - 400);
LK.setScore(score);
if (typeof scoreTxt !== 'undefined') scoreTxt.setText(score);
self.visible = false;
if (typeof self.onScore === 'function') self.onScore();
// Explode nearby pigs
if (typeof objects !== "undefined" && Array.isArray(objects)) {
for (var i = 0; i < objects.length; i++) {
var obj = objects[i];
if (obj === self) continue;
if (obj && obj.visible !== false && obj instanceof Pig && !obj.collected) {
// Distance between pigs
var dx = obj.x - self.x;
var dy = obj.y - self.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist < 250) {
// 250px radius for explosion
obj.onCollected();
}
}
}
}
self.destroy();
};
return self;
});
// Small gold nugget
var GoldSmall = UndergroundObject.expand(function () {
var self = UndergroundObject.call(this);
var gold = self.attachAsset('goldSmall', {
anchorX: 0.5,
anchorY: 0.5
});
self.value = 250;
self.retractSpeed = 24; // medium
self.grabSound = 'grab';
self.collectedSound = 'collect';
self.onCollected = function () {
if (self.collected) return;
self.collected = true;
LK.getSound('money').play();
self.visible = false;
if (typeof self.onScore === 'function') self.onScore();
self.destroy();
};
return self;
});
// Gold nugget
var Gold = UndergroundObject.expand(function () {
var self = UndergroundObject.call(this);
var gold = self.attachAsset('gold', {
anchorX: 0.5,
anchorY: 0.5
});
self.value = 500;
self.retractSpeed = 8; // slower
self.grabSound = 'grab';
self.collectedSound = 'collect';
self.onCollected = function () {
if (self.collected) return;
self.collected = true;
LK.getSound('money').play();
self.visible = false;
if (typeof self.onScore === 'function') self.onScore();
self.destroy();
};
return self;
});
// Gem
var Gem = UndergroundObject.expand(function () {
var self = UndergroundObject.call(this);
var gem = self.attachAsset('gem', {
anchorX: 0.5,
anchorY: 0.5
});
self.value = 800;
self.retractSpeed = 32; // fast
self.grabSound = 'grab';
self.collectedSound = 'collect';
self.onCollected = function () {
if (self.collected) return;
self.collected = true;
LK.getSound('money').play();
self.visible = false;
if (typeof self.onScore === 'function') self.onScore();
self.destroy();
};
return self;
});
// Dynamite trap
var Dynamite = UndergroundObject.expand(function () {
var self = UndergroundObject.call(this);
var dynamite = self.attachAsset('dynamite', {
anchorX: 0.5,
anchorY: 0.5
});
self.value = 0;
self.retractSpeed = 40; // fast retract
self.grabSound = 'dynamite';
self.collectedSound = 'dynamite';
self.onCollected = function () {
if (self.collected) return;
self.collected = true;
LK.getSound(self.collectedSound).play();
// Flash screen red to indicate explosion
LK.effects.flashScreen(0xff0000, 800);
// Remove some score as penalty
score = Math.max(0, score - 400);
LK.setScore(score);
if (typeof scoreTxt !== 'undefined') scoreTxt.setText(score);
self.visible = false;
self.destroy();
};
return self;
});
// Bag (Torba)
var Bag = UndergroundObject.expand(function () {
var self = UndergroundObject.call(this);
var bag = self.attachAsset('torba', {
anchorX: 0.5,
anchorY: 0.5
});
self.value = 1000;
self.retractSpeed = 18; // medium-slow
self.grabSound = 'grab';
self.collectedSound = 'collect';
self.onCollected = function () {
if (self.collected) return;
self.collected = true;
LK.getSound('money').play();
self.visible = false;
if (typeof self.onScore === 'function') self.onScore();
self.destroy();
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x8B5A2B // brown
});
/****
* Game Code
****/
// Game constants
// Claw arm (rectangle)
// Claw head (ellipse)
// Gold nugget (ellipse)
// Small gold nugget
// Rock (ellipse)
// Gem (ellipse)
// Sound for grabbing
// Sound for collecting
// Sound for hitting rock
// Music
var GAME_WIDTH = 2048;
var GAME_HEIGHT = 2732;
var GROUND_Y = 700; // y position where underground objects start
var LEVEL_TIME = 60; // seconds
var LEVEL_GOAL = 1500; // gold needed to win
// Level and difficulty progression
var level = 1;
var maxLevel = 10;
var objects = [];
var claw = null;
var score = 0;
var timer = 0;
var timeLeft = LEVEL_TIME;
var goal = LEVEL_GOAL;
var gameActive = true;
// Add multiple moving targets
var targets = [];
// GUI
// Level text (very small, upper right corner)
var levelTxt = new Text2('Level ' + level, {
size: 40,
fill: "#fff"
});
levelTxt.anchor.set(1, 0); // right-top
levelTxt.x = -8; // 8px from the right edge of gui.topRight
levelTxt.y = 0;
LK.gui.topRight.addChild(levelTxt);
// Goal text (very small, just above the score number)
var goalTxt = new Text2('Goal: ' + goal, {
size: 32,
fill: "#fff"
});
goalTxt.anchor.set(1, 0); // right-top
goalTxt.x = levelTxt.x - levelTxt.width - 16; // align with score
goalTxt.y = 0; // align to top since dollars label is removed
LK.gui.topRight.addChild(goalTxt);
// Score text (small, right next to level text, to the left)
var scoreTxt = new Text2('0', {
size: 40,
fill: "#fff"
});
scoreTxt.anchor.set(1, 0); // right-top
scoreTxt.x = levelTxt.x - levelTxt.width - 16; // 16px padding between score and level
scoreTxt.y = goalTxt.y + goalTxt.height + 2; // just below goal text
LK.gui.topRight.addChild(scoreTxt);
// Countdown timer text (small, just below level text)
var countdownTxt = new Text2(timeLeft + 's', {
size: 32,
fill: "#fff"
});
countdownTxt.anchor.set(1, 0); // right-top
countdownTxt.x = levelTxt.x;
countdownTxt.y = levelTxt.height + 4; // 4px below level text
LK.gui.topRight.addChild(countdownTxt);
// Timer interval to update countdown
var countdownInterval = LK.setInterval(function () {
if (!gameActive) return;
timeLeft--;
if (timeLeft < 0) timeLeft = 0;
countdownTxt.setText(timeLeft + 's');
if (timeLeft === 0 && gameActive) {
gameActive = false;
LK.effects.flashScreen(0xff0000, 800);
LK.showGameOver();
}
}, 1000);
// Place claw at top center
claw = new Claw();
claw.x = GAME_WIDTH / 2;
claw.y = 0;
game.addChild(claw);
// (Bag is not attached to the hook)
// Underground object spawn positions
function spawnObjects() {
// Clear previous
for (var i = 0; i < objects.length; i++) {
objects[i].destroy();
}
objects = [];
// Difficulty scaling
var bigGoldCount = 4 + Math.floor(level / 2);
var smallGoldCount = 6 + level;
var rockCount = 6 + level * 2;
var gemCount = 3 + Math.floor(level / 2);
var dynamiteCount = 2 + Math.floor(level / 2);
// Create all objects in order: gold, diamonds, dynamite, rocks, bags, pigs, then mix
var allObjs = [];
// Gold (big)
for (var i = 0; i < bigGoldCount; i++) {
var g = new Gold();
g.onScore = function () {
score += this.value;
LK.setScore(score);
if (scoreTxt) scoreTxt.setText(score);
};
allObjs.push(g);
}
// Gold (small)
for (var i = 0; i < smallGoldCount; i++) {
var gs = new GoldSmall();
gs.onScore = function () {
score += this.value;
LK.setScore(score);
if (scoreTxt) scoreTxt.setText(score);
};
allObjs.push(gs);
}
// Gems
for (var i = 0; i < gemCount; i++) {
var gem = new Gem();
gem.onScore = function () {
score += this.value;
LK.setScore(score);
if (scoreTxt) scoreTxt.setText(score);
};
allObjs.push(gem);
}
// Bags (torba)
var bagCount = 2 + Math.floor(level / 2);
for (var i = 0; i < bagCount; i++) {
var bag = new Bag();
bag.onScore = function () {
score += this.value;
LK.setScore(score);
if (scoreTxt) scoreTxt.setText(score);
};
allObjs.push(bag);
}
// Pigs
var pigCount = 2 + Math.floor(level / 2);
for (var i = 0; i < pigCount; i++) {
var pig = new Pig();
pig.onScore = function () {
score += this.value;
LK.setScore(score);
if (scoreTxt) scoreTxt.setText(score);
};
allObjs.push(pig);
}
// Dynamite
for (var i = 0; i < dynamiteCount; i++) {
var d = new Dynamite();
allObjs.push(d);
}
// Rocks
for (var i = 0; i < rockCount; i++) {
var r = new Rock();
r.onScore = function () {
score += this.value;
LK.setScore(score);
if (scoreTxt) scoreTxt.setText(score);
};
allObjs.push(r);
}
// Shuffle allObjs array
for (var i = allObjs.length - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
var temp = allObjs[i];
allObjs[i] = allObjs[j];
allObjs[j] = temp;
}
// Place objects in the play area, avoiding overlap
var gridCols = 8;
var gridRows = Math.ceil(allObjs.length / gridCols);
var cellW = Math.floor((GAME_WIDTH - 400) / gridCols);
var cellH = Math.floor((GAME_HEIGHT - GROUND_Y - 400) / gridRows);
var usedCells = [];
for (var i = 0; i < allObjs.length; i++) {
var obj = allObjs[i];
// Find a free cell
var placed = false;
var attempts = 0;
while (!placed && attempts < 30) {
var col = Math.floor(Math.random() * gridCols);
var row = Math.floor(Math.random() * gridRows);
var cellIdx = row * gridCols + col;
if (usedCells.indexOf(cellIdx) === -1) {
usedCells.push(cellIdx);
obj.x = 200 + col * cellW + Math.floor(cellW / 2);
obj.y = GROUND_Y + 200 + row * cellH + Math.floor(cellH / 2);
placed = true;
}
attempts++;
}
game.addChild(obj);
objects.push(obj);
}
}
spawnObjects();
// Create and add multiple moving targets at specific parts of the screen
// Destroy old targets if any
if (targets && targets.length) {
for (var i = 0; i < targets.length; i++) {
if (targets[i]) targets[i].destroy();
}
}
targets = [];
// Place fewer moving targets at the top, and more in the middle section
var targetPositions = [
// Only one at the top left
{
x: 300,
y: GROUND_Y + 100
},
// Add more to the middle section
{
x: 600,
y: GROUND_Y + 400
}, {
x: GAME_WIDTH - 600,
y: GROUND_Y + 400
}, {
x: 400,
y: GROUND_Y + 700
}, {
x: GAME_WIDTH - 400,
y: GROUND_Y + 700
}, {
x: GAME_WIDTH / 2,
y: GROUND_Y + 900
}];
for (var i = 0; i < targetPositions.length; i++) {
var t = new Target();
t.x = targetPositions[i].x;
t.y = targetPositions[i].y;
t.direction = i % 2 === 0 ? 1 : -1;
targets.push(t);
game.addChild(t);
}
// Add moving TL objects to the top left of the screen
var tlObjects = [];
var tlCount = 2; // Number of TL objects to add/move
for (var i = 0; i < tlCount; i++) {
var tl = new Container();
var tlImg = tl.attachAsset('TL', {
anchorX: 0.5,
anchorY: 0.5
});
tl.x = 120 + i * 120; // Space out horizontally, keep away from top left 100x100
tl.y = 120;
tl.speed = 6 + Math.floor(Math.random() * 4);
tl.direction = Math.random() < 0.5 ? 1 : -1;
tl.lastX = tl.x;
tl.update = function () {
if (typeof this.lastX !== "number") this.lastX = this.x;
this.x += this.speed * this.direction;
// Bounce at left/right margin (keep inside 120 to 400 px)
if (this.lastX <= 120 && this.x > 120) this.direction = 1;
if (this.lastX >= 400 && this.x < 400) this.direction = -1;
if (this.x > 400) this.x = 400;
if (this.x < 120) this.x = 120;
this.lastX = this.x;
};
tlObjects.push(tl);
game.addChild(tl);
}
// Draw a dot at the top center to send the rope down
var dropDot = LK.getAsset('centerCircle', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.5,
scaleY: 0.5,
x: GAME_WIDTH / 2,
y: 80
});
game.addChild(dropDot);
// Only trigger on dot press, not anywhere
dropDot.down = function (x, y, obj) {
if (!gameActive) return;
if (claw.state === 'swing') {
claw.startExtend();
}
};
// Touch/click anywhere else does nothing
game.down = function (x, y, obj) {
// No-op, handled by dropDot
};
// Main update loop
game.update = function () {
if (!gameActive) return;
// Claw update handled in class
// If claw is extending, check for collision with objects
if (claw.state === 'extend') {
// Get claw head position
var dx = Math.sin(claw.swingAngle) * claw.length;
var dy = Math.cos(claw.swingAngle) * claw.length;
var cx = claw.x + dx;
var cy = claw.y + dy + 30; // 30: half head height
// Check for collision with any object
var grabbed = false;
for (var i = 0; i < objects.length; i++) {
var obj = objects[i];
if (obj.collected) continue;
// Simple circle collision
var dist = Math.sqrt((obj.x - cx) * (obj.x - cx) + (obj.y - cy) * (obj.y - cy));
var r = 60; // approx radius
if (dist < r + 40) {
// If it's a pig, trigger explosion immediately and do not attach to claw
if (obj instanceof Pig) {
obj.onCollected();
grabbed = true;
break;
}
// Grab object
claw.grabObject(obj);
// Dynamite handles penalty in its onCollected
grabbed = true;
break;
}
}
// Check for collision with any moving target if not already grabbed something
if (!grabbed && targets && targets.length) {
for (var ti = 0; ti < targets.length; ti++) {
var t = targets[ti];
if (!t.visible) continue;
if (typeof t.x !== 'number' || typeof t.y !== 'number') continue;
var tdist = Math.sqrt((t.x - cx) * (t.x - cx) + (t.y - cy) * (t.y - cy));
var tr = 100; // slightly larger radius for target
if (tdist < tr) {
// "Grab" the target: treat as a special object
claw.grabbedObj = t;
claw.state = 'grabbed';
claw.retractSpeed = 32;
// Optionally, you can add a sound or effect here
// Remove the target visually and respawn after a delay
t.visible = false;
(function (targetToRespawn) {
LK.setTimeout(function () {
if (targetToRespawn) {
targetToRespawn.x = 400 + Math.floor(Math.random() * (GAME_WIDTH - 800));
targetToRespawn.y = GROUND_Y - 100 - Math.floor(Math.random() * 120);
targetToRespawn.visible = true;
}
}, 2000);
})(t);
grabbed = true;
break;
}
}
}
// If reached max length and nothing grabbed, retract
if (claw.length >= claw.maxLength && claw.state === 'extend') {
claw.miss();
}
}
// Win condition
if (score >= goal && gameActive) {
gameActive = false;
LK.effects.flashScreen(0xffff00, 800);
// Level up logic
if (level < maxLevel) {
level += 1;
// Play level up sound
LK.getSound('level').play();
// Increase goal and decrease time for next level
goal = LEVEL_GOAL + level * 800;
timeLeft = LEVEL_TIME - Math.min(level * 3, 30); // reduce time, but not below 30s
score = 0;
LK.setScore(score);
if (scoreTxt) scoreTxt.setText(score);
// Update level text
if (levelTxt) levelTxt.setText('Level ' + level);
// Update goal text
if (goalTxt) goalTxt.setText('Goal: ' + goal);
// Reset countdown timer text and timeLeft
timeLeft = LEVEL_TIME - Math.min(level * 3, 30);
if (countdownTxt) countdownTxt.setText(timeLeft + 's');
// Respawn objects for new level
spawnObjects();
gameActive = true;
} else {
LK.showYouWin();
}
}
// Update all moving targets
if (targets && targets.length) {
for (var ti = 0; ti < targets.length; ti++) {
if (targets[ti] && typeof targets[ti].update === 'function') {
targets[ti].update();
}
}
}
// Update all TL objects
if (typeof tlObjects !== "undefined" && tlObjects.length) {
for (var i = 0; i < tlObjects.length; i++) {
if (tlObjects[i] && typeof tlObjects[i].update === "function") {
tlObjects[i].update();
}
}
}
};
// Play background music
LK.playMusic('goldminerbg', {
fade: {
start: 0,
end: 1,
duration: 1000
}
});
gold. In-Game asset. 2d. High contrast. No shadows
diamond. In-Game asset. 2d. High contrast. No shadows
big rock. In-Game asset. 2d. High contrast. No shadows
upright long rope. In-Game asset. 2d. High contrast. No shadows
double pointed hook. In-Game asset. 2d. High contrast. No shadows
big piece of gold. In-Game asset. 2d. High contrast. No shadows
dynamite. In-Game asset. 2d. High contrast. No shadows
pig. In-Game asset. 2d. High contrast. No shadows
soru isฬงareti olan bir torba. In-Game asset. 2d. High contrast. No shadows
Pig with dollar in mouth. In-Game asset. 2d. High contrast. No shadows
tnt yazฤฑlฤฑ varil. In-Game asset. 2d. High contrast. No shadows