User prompt
Make more ores appear over time in endless mode ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Make ores unable to appear on counters or the pause button
User prompt
Make the endless mode difficulty higher than normal and lower than hard
User prompt
Make the lives in endless mode 5 and regenerate over time ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Create a text below the difficulty buttons that says Tap the ores to mine them
User prompt
Create a pickaxe that follows the player's touch, the pickaxe is decorative ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Increase the amount of points needed to win on each difficulty
User prompt
Separate the difficulty buttons a little more
User prompt
Change the text color of difficulties to black
User prompt
Create a black outline for texts
User prompt
Remove the text below the difficulty buttons
User prompt
Make all difficulties give the same points
User prompt
Make it so that only one life is spent per ore
User prompt
Add lives
User prompt
Separate the buttons a little
User prompt
Create a different image for the buttons
User prompt
Create an image for the background
User prompt
Change the size of the background image to the size of the screen
User prompt
Create an image for the background
User prompt
Create a menu with different difficulties, easy, normal and hard, the harder the more points and difficulty, also add an endless mode to the menu
User prompt
Make ores cannot appear on the counters and on the pause button.
User prompt
Rename the "collect" sound to "mine." Also remove the "rare_collect" sound and make the collect or mine sound play when mining an ore.
Code edit (1 edits merged)
Please save this source code
User prompt
Crystal Rush Miner
Initial prompt
Hi Ava, I would like to make a mining game. Make minerals appear every so often and if they are not mined in a while they disappear. Make each mineral have a different rarity, with different probabilities of appearing.
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var MenuButton = Container.expand(function (text, difficulty, x, y) {
var self = Container.call(this);
self.difficulty = difficulty;
// Create button background with difficulty-specific asset
var buttonAsset = 'button_' + difficulty;
var buttonBg = self.attachAsset(buttonAsset, {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2,
scaleY: 1.5
});
// Create button text
var buttonText = new Text2(text, {
size: 60,
fill: 0xFFFFFF
});
buttonText.anchor.set(0.5, 0.5);
self.addChild(buttonText);
// Position button
self.x = x;
self.y = y;
// Button press handler
self.down = function (x, y, obj) {
// Visual feedback
tween(self, {
scaleX: 0.95,
scaleY: 0.95
}, {
duration: 100,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(self, {
scaleX: 1,
scaleY: 1
}, {
duration: 100,
easing: tween.easeOut
});
}
});
// Start game with selected difficulty
startGameWithDifficulty(self.difficulty);
};
return self;
});
var Mineral = Container.expand(function (type) {
var self = Container.call(this);
self.type = type;
self.mineralData = mineralTypes[type];
var mineralGraphics = self.attachAsset(type, {
anchorX: 0.5,
anchorY: 0.5
});
// Initialize properties
self.timeLeft = self.mineralData.duration;
self.maxTime = self.mineralData.duration;
self.isCollected = false;
// Add sparkle effect for rare minerals
if (self.mineralData.rarity >= 3) {
tween(mineralGraphics, {
alpha: 0.7
}, {
duration: 500,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(mineralGraphics, {
alpha: 1
}, {
duration: 500,
easing: tween.easeInOut
});
}
});
}
self.update = function () {
if (self.isCollected) return;
self.timeLeft -= 16.67; // Roughly 60 FPS
// Flash when time is running out
if (self.timeLeft < 1000) {
var flashAlpha = Math.sin(LK.ticks * 0.5) * 0.3 + 0.7;
mineralGraphics.alpha = flashAlpha;
}
// Remove when time expires
if (self.timeLeft <= 0) {
self.expire();
}
};
self.collect = function () {
if (self.isCollected) return;
self.isCollected = true;
// Add score
var points = self.mineralData.points * scoreMultiplier;
LK.setScore(LK.getScore() + points);
// Increase multiplier
scoreMultiplier = Math.min(scoreMultiplier + 0.1, 5);
consecutiveCollections++;
// Play sound
LK.getSound('mine').play();
// Animation
tween(mineralGraphics, {
scaleX: 1.5,
scaleY: 1.5,
alpha: 0
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
self.destroy();
}
});
// Remove from minerals array
for (var i = minerals.length - 1; i >= 0; i--) {
if (minerals[i] === self) {
minerals.splice(i, 1);
break;
}
}
// Update UI
updateScoreDisplay();
};
self.expire = function () {
// Reset multiplier on missed mineral
scoreMultiplier = 1;
consecutiveCollections = 0;
// Lose a life
currentLives--;
updateScoreDisplay();
// Check game over
if (currentLives <= 0) {
LK.showGameOver();
return;
}
// Fade out animation
tween(mineralGraphics, {
alpha: 0,
scaleX: 0.5,
scaleY: 0.5
}, {
duration: 200,
onFinish: function onFinish() {
self.destroy();
}
});
// Remove from minerals array
for (var i = minerals.length - 1; i >= 0; i--) {
if (minerals[i] === self) {
minerals.splice(i, 1);
break;
}
}
};
self.down = function (x, y, obj) {
self.collect();
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x1a1a2e
});
/****
* Game Code
****/
// Add mining background
var backgroundImage = game.attachAsset('mining_background', {
x: 0,
y: 0,
anchorX: 0,
anchorY: 0
});
// Game state
var gameState = 'menu'; // 'menu' or 'playing'
var currentDifficulty = 'normal';
// Game variables
var minerals = [];
var scoreMultiplier = 1;
var consecutiveCollections = 0;
var gameTime = 0;
var targetScore = 10000;
var currentLives = 3;
var maxLives = 3;
// Menu elements
var menuContainer;
var titleText;
var menuButtons = [];
// Difficulty configurations
var difficultySettings = {
easy: {
name: 'Easy',
targetScore: 5000,
pointMultiplier: 1,
spawnRateMultiplier: 1.5,
durationMultiplier: 1.5,
lives: 5
},
normal: {
name: 'Normal',
targetScore: 10000,
pointMultiplier: 1.5,
spawnRateMultiplier: 1,
durationMultiplier: 1,
lives: 3
},
hard: {
name: 'Hard',
targetScore: 20000,
pointMultiplier: 2,
spawnRateMultiplier: 0.7,
durationMultiplier: 0.8,
lives: 2
},
endless: {
name: 'Endless',
targetScore: -1,
// No target score for endless
pointMultiplier: 2.5,
spawnRateMultiplier: 0.6,
durationMultiplier: 0.7,
lives: 3
}
};
// Base mineral type definitions (will be modified by difficulty)
var baseMineralTypes = {
coal: {
points: 10,
duration: 5000,
spawnRate: 2500,
rarity: 1
},
copper: {
points: 20,
duration: 5000,
spawnRate: 3000,
rarity: 1
},
iron: {
points: 50,
duration: 4000,
spawnRate: 6000,
rarity: 2
},
silver: {
points: 80,
duration: 4000,
spawnRate: 7000,
rarity: 2
},
gold: {
points: 200,
duration: 3000,
spawnRate: 12000,
rarity: 3
},
emerald: {
points: 300,
duration: 3000,
spawnRate: 15000,
rarity: 3
},
diamond: {
points: 800,
duration: 2000,
spawnRate: 25000,
rarity: 4
},
ruby: {
points: 1000,
duration: 2000,
spawnRate: 30000,
rarity: 4
}
};
// Current mineral types (adjusted for difficulty)
var mineralTypes = {};
var mineralTypeArray = Object.keys(mineralTypes);
// Spawn timers for each mineral type
var spawnTimers = {};
for (var i = 0; i < mineralTypeArray.length; i++) {
var type = mineralTypeArray[i];
spawnTimers[type] = 0;
}
// UI Elements
var scoreTxt = new Text2('Score: 0', {
size: 80,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
var multiplierTxt = new Text2('x1.0', {
size: 60,
fill: 0xFFFF00
});
multiplierTxt.anchor.set(1, 0);
multiplierTxt.x = -20;
multiplierTxt.y = 20;
LK.gui.topRight.addChild(multiplierTxt);
var targetTxt = new Text2('Target: ' + targetScore, {
size: 50,
fill: 0x00FF00
});
targetTxt.anchor.set(0, 0);
targetTxt.x = 120;
targetTxt.y = 20;
LK.gui.topLeft.addChild(targetTxt);
var livesTxt = new Text2('Lives: ' + currentLives, {
size: 50,
fill: 0xFF0000
});
livesTxt.anchor.set(0, 0);
livesTxt.x = 120;
livesTxt.y = 80;
LK.gui.topLeft.addChild(livesTxt);
function spawnMineral(type) {
var mineral = new Mineral(type);
// Random position with margin from edges
var margin = 100;
mineral.x = margin + Math.random() * (2048 - 2 * margin);
mineral.y = margin + Math.random() * (2732 - 2 * margin);
// Ensure it doesn't overlap with existing minerals too much and avoid UI areas
var attempts = 0;
while (attempts < 10) {
var tooClose = false;
var inUIArea = false;
// Check if mineral overlaps with UI areas
// Top-left pause button area (100x100)
if (mineral.x < 160 && mineral.y < 160) {
inUIArea = true;
}
// Top score area
if (mineral.y < 120) {
inUIArea = true;
}
// Top-right multiplier area
if (mineral.x > 1888 && mineral.y < 120) {
inUIArea = true;
}
// Top-left target score area
if (mineral.x < 400 && mineral.y < 120) {
inUIArea = true;
}
// Check distance from existing minerals
for (var i = 0; i < minerals.length; i++) {
var existingMineral = minerals[i];
var dx = mineral.x - existingMineral.x;
var dy = mineral.y - existingMineral.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 200) {
tooClose = true;
break;
}
}
if (!tooClose && !inUIArea) break;
mineral.x = margin + Math.random() * (2048 - 2 * margin);
mineral.y = margin + Math.random() * (2732 - 2 * margin);
attempts++;
}
minerals.push(mineral);
game.addChild(mineral);
// Spawn animation
mineral.scaleX = 0;
mineral.scaleY = 0;
tween(mineral, {
scaleX: 1,
scaleY: 1
}, {
duration: 300,
easing: tween.easeOut
});
}
function createMenu() {
menuContainer = new Container();
game.addChild(menuContainer);
// Title
titleText = new Text2('Crystal Rush Miner', {
size: 120,
fill: 0x00CCFF
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 1024;
titleText.y = 600;
menuContainer.addChild(titleText);
// Subtitle
var subtitleText = new Text2('Select Difficulty', {
size: 80,
fill: 0xFFFFFF
});
subtitleText.anchor.set(0.5, 0.5);
subtitleText.x = 1024;
subtitleText.y = 750;
menuContainer.addChild(subtitleText);
// Create difficulty buttons
var buttonY = 1000;
var buttonSpacing = 350;
var easyBtn = new MenuButton('Easy\n5,000 pts', 'easy', 1024 - buttonSpacing * 1.5, buttonY);
var normalBtn = new MenuButton('Normal\n10,000 pts', 'normal', 1024 - buttonSpacing * 0.5, buttonY);
var hardBtn = new MenuButton('Hard\n20,000 pts', 'hard', 1024 + buttonSpacing * 0.5, buttonY);
var endlessBtn = new MenuButton('Endless\nNo Limit', 'endless', 1024 + buttonSpacing * 1.5, buttonY);
menuButtons.push(easyBtn, normalBtn, hardBtn, endlessBtn);
menuContainer.addChild(easyBtn);
menuContainer.addChild(normalBtn);
menuContainer.addChild(hardBtn);
menuContainer.addChild(endlessBtn);
// Description text
var descText = new Text2('Harder difficulties give more points but faster gameplay!', {
size: 50,
fill: 0xCCCCCC
});
descText.anchor.set(0.5, 0.5);
descText.x = 1024;
descText.y = 1400;
menuContainer.addChild(descText);
}
function startGameWithDifficulty(difficulty) {
currentDifficulty = difficulty;
gameState = 'playing';
// Hide menu
if (menuContainer) {
menuContainer.visible = false;
}
// Apply difficulty settings
var settings = difficultySettings[difficulty];
targetScore = settings.targetScore;
// Scale mineral types based on difficulty
mineralTypes = {};
var baseTypes = Object.keys(baseMineralTypes);
for (var i = 0; i < baseTypes.length; i++) {
var type = baseTypes[i];
var base = baseMineralTypes[type];
mineralTypes[type] = {
points: Math.floor(base.points * settings.pointMultiplier),
duration: Math.floor(base.duration * settings.durationMultiplier),
spawnRate: Math.floor(base.spawnRate * settings.spawnRateMultiplier),
rarity: base.rarity
};
}
// Reset game variables
minerals = [];
scoreMultiplier = 1;
consecutiveCollections = 0;
gameTime = 0;
currentLives = settings.lives;
maxLives = settings.lives;
LK.setScore(0);
// Initialize spawn timers
mineralTypeArray = Object.keys(mineralTypes);
spawnTimers = {};
for (var i = 0; i < mineralTypeArray.length; i++) {
var type = mineralTypeArray[i];
spawnTimers[type] = 0;
}
// Update UI
updateScoreDisplay();
// Start background music
LK.playMusic('mining_ambient');
}
function updateScoreDisplay() {
scoreTxt.setText('Score: ' + LK.getScore());
multiplierTxt.setText('x' + scoreMultiplier.toFixed(1));
livesTxt.setText('Lives: ' + currentLives);
// Update target display based on difficulty
if (currentDifficulty === 'endless') {
targetTxt.setText('Mode: Endless');
} else {
targetTxt.setText('Target: ' + targetScore);
}
// Check win condition (only for non-endless modes)
if (currentDifficulty !== 'endless' && LK.getScore() >= targetScore) {
LK.showYouWin();
}
}
// Initialize menu
createMenu();
game.update = function () {
// Only update game logic when playing
if (gameState !== 'playing') return;
gameTime += 16.67; // Roughly 60 FPS
// Update spawn timers and spawn minerals
for (var i = 0; i < mineralTypeArray.length; i++) {
var type = mineralTypeArray[i];
var mineralData = mineralTypes[type];
spawnTimers[type] += 16.67;
if (spawnTimers[type] >= mineralData.spawnRate) {
spawnTimers[type] = 0;
spawnMineral(type);
}
}
// Gradually decrease multiplier if no collections for a while
if (consecutiveCollections === 0 && gameTime % 3000 < 16.67) {
scoreMultiplier = Math.max(scoreMultiplier - 0.1, 1);
updateScoreDisplay();
}
}; ===================================================================
--- original.js
+++ change.js
@@ -130,8 +130,16 @@
self.expire = function () {
// Reset multiplier on missed mineral
scoreMultiplier = 1;
consecutiveCollections = 0;
+ // Lose a life
+ currentLives--;
+ updateScoreDisplay();
+ // Check game over
+ if (currentLives <= 0) {
+ LK.showGameOver();
+ return;
+ }
// Fade out animation
tween(mineralGraphics, {
alpha: 0,
scaleX: 0.5,
@@ -181,8 +189,10 @@
var scoreMultiplier = 1;
var consecutiveCollections = 0;
var gameTime = 0;
var targetScore = 10000;
+var currentLives = 3;
+var maxLives = 3;
// Menu elements
var menuContainer;
var titleText;
var menuButtons = [];
@@ -192,31 +202,35 @@
name: 'Easy',
targetScore: 5000,
pointMultiplier: 1,
spawnRateMultiplier: 1.5,
- durationMultiplier: 1.5
+ durationMultiplier: 1.5,
+ lives: 5
},
normal: {
name: 'Normal',
targetScore: 10000,
pointMultiplier: 1.5,
spawnRateMultiplier: 1,
- durationMultiplier: 1
+ durationMultiplier: 1,
+ lives: 3
},
hard: {
name: 'Hard',
targetScore: 20000,
pointMultiplier: 2,
spawnRateMultiplier: 0.7,
- durationMultiplier: 0.8
+ durationMultiplier: 0.8,
+ lives: 2
},
endless: {
name: 'Endless',
targetScore: -1,
// No target score for endless
pointMultiplier: 2.5,
spawnRateMultiplier: 0.6,
- durationMultiplier: 0.7
+ durationMultiplier: 0.7,
+ lives: 3
}
};
// Base mineral type definitions (will be modified by difficulty)
var baseMineralTypes = {
@@ -300,8 +314,16 @@
targetTxt.anchor.set(0, 0);
targetTxt.x = 120;
targetTxt.y = 20;
LK.gui.topLeft.addChild(targetTxt);
+var livesTxt = new Text2('Lives: ' + currentLives, {
+ size: 50,
+ fill: 0xFF0000
+});
+livesTxt.anchor.set(0, 0);
+livesTxt.x = 120;
+livesTxt.y = 80;
+LK.gui.topLeft.addChild(livesTxt);
function spawnMineral(type) {
var mineral = new Mineral(type);
// Random position with margin from edges
var margin = 100;
@@ -428,8 +450,10 @@
minerals = [];
scoreMultiplier = 1;
consecutiveCollections = 0;
gameTime = 0;
+ currentLives = settings.lives;
+ maxLives = settings.lives;
LK.setScore(0);
// Initialize spawn timers
mineralTypeArray = Object.keys(mineralTypes);
spawnTimers = {};
@@ -444,8 +468,9 @@
}
function updateScoreDisplay() {
scoreTxt.setText('Score: ' + LK.getScore());
multiplierTxt.setText('x' + scoreMultiplier.toFixed(1));
+ livesTxt.setText('Lives: ' + currentLives);
// Update target display based on difficulty
if (currentDifficulty === 'endless') {
targetTxt.setText('Mode: Endless');
} else {