Code edit (1 edits merged)
Please save this source code
Code edit (1 edits merged)
Please save this source code
Code edit (3 edits merged)
Please save this source code
User prompt
Please fix the bug: 'Uncaught ReferenceError: resultMessage is not defined' in or related to this line: 'var resultTitle = new Text2(resultMessage, {' Line Number: 863
Code edit (9 edits merged)
Please save this source code
User prompt
Please fix the bug: 'orbitContainer.removeAllChildren is not a function' in or related to this line: 'orbitContainer.removeAllChildren();' Line Number: 534
Code edit (1 edits merged)
Please save this source code
User prompt
Please fix the bug: 'levelContainer.updateCost is not a function' in or related to this line: 'levelContainer.updateCost();' Line Number: 549
Code edit (1 edits merged)
Please save this source code
User prompt
Corrige: - Disminuye la velocidad de los ticks a una cuarta parte. - Los botones de los niveles no funcionan, deben gastar creditos y aumentar la velocidad de la ganancia por tick. - El pull del gacha no funciona, debe de indicar que personaje ganaste - La galeria de personajes no despliega nada
User prompt
Please fix the bug: 'Error: Invalid value. Only literals or 1-level deep objects/arrays containing literals are allowed.' in or related to this line: 'storage.gameState = gameState;' Line Number: 441 ↪💡 Consider importing and using the following plugins: @upit/storage.v1
Code edit (1 edits merged)
Please save this source code
User prompt
Elemental Idle: Character Gacha
Initial prompt
Haremos un juego tipo idle/gacha, donde se obtienen personajes tipo anime, la subinspiración serán los elementos naturales, con la rareza: - Tierra (común) - Agua (común) - Fuego (común) - Viento (común) - Planta (poco común) - Lava (poco común) - Arena (poco común) - Vapor (poco común) - Lodo (poco común) - Ceniza (poco común) - Hielo (raro) - Metal (raro) - Electricidad (raro) - Arena (raro) - Cristal (raro) - Veneno (raro) - Niebla (raro) - Sangre (raro) - Sonido (ultrararo) - Luz (ultrararo) - Obscuridad (ultrararo) - Plasma (ultrararo) - Magnetismo (ultrararo) - Gravedad (ultrararo) - Espejismo (ultrararo) - Radiación (ultrararo) - Vida (legendario) - Muerte (legendario) - Tiempo (legendario) - Espacio (legendario) - Alma (legendario) -Sueño (legendario) - Vacío (único) - Éter (único) - Caos (único) - Orden (único) Se inicia sin personajes, y se puede realizar una tirada aleatoria cada 1000 creditos. En cada tirada se puede obtener un personaje repetido, en ese caso no se desbloquea nada nuevo. Los personajes desbloqueados se pueden ver en una ventana emergente que se despliega con un botón. Los porcentajes de obtención son: 50% común 20% poco común 15% raro 10% ultrararo 4% legendario 1% único Cada rareza da un multiplicador general: común - x2 raro - x3 poco común Al ser un idle, se debe mejorar con créditos ciertos niveles (de momento solo crea 10 niveles genéricos que sumen créditos +1, +2, +3, +5, +10, +20, +50, +100, +200, +300) De momento como no hay sprites se crea un asset con el nombre del elemento que representan.
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
/**** * Classes
****/
// Character class for displaying collected elements
var Character = Container.expand(function () {
var self = Container.call(this);
self.init = function (elementId, elementName, rarity, assetId, multiplier) {
var graphic = self.attachAsset(assetId, {
anchorX: 0.5,
anchorY: 0.5
});
var nameText = new Text2(elementName, {
size: 28,
fill: '#ffffff'
});
nameText.anchor.set(0.5, 0);
nameText.y = 70;
self.addChild(nameText);
var rarityText = new Text2(rarity, {
size: 20,
fill: '#FFD700'
});
rarityText.anchor.set(0.5, 0);
rarityText.y = 100;
self.addChild(rarityText);
};
return self;
});
// Clase de Efecto Visual: Floating Text
var FloatingText = Container.expand(function () {
var self = Container.call(this);
self.init = function (textValue, startX, startY, color) {
self.x = startX;
self.y = startY;
var txt = new Text2(textValue, {
size: 48,
fill: color || '#ffffff'
});
txt.anchor.set(0.5, 0.5);
self.addChild(txt);
tween(self, {
y: self.y - 150,
alpha: 0
}, {
duration: 800,
onFinish: function onFinish() {
self.destroy();
}
});
};
return self;
});
// Clases de UI: Income Level
var IncomeLevel = Container.expand(function () {
var self = Container.call(this);
self.levelIndex = 0;
self.baseIncome = 0;
self.baseCost = 0;
self.currentCost = 0;
self.init = function (levelIndex, baseIncome) {
self.levelIndex = levelIndex;
self.baseIncome = baseIncome;
self.baseCost = 50 * (levelIndex + 1);
var bg = self.attachAsset('upgrade_button', {
anchorX: 0.5,
anchorY: 0.5
});
bg.scale.set(1.5, 1.5);
var levelText = new Text2('', {
size: 30,
fill: '#ffffff'
});
levelText.anchor.set(0.5, 0.5);
levelText.y = -20;
self.addChild(levelText);
self.levelText = levelText;
var costText = new Text2('', {
size: 24,
fill: '#FFD700'
});
costText.anchor.set(0.5, 0.5);
costText.y = 20;
self.addChild(costText);
self.costText = costText;
};
self.updateData = function (purchases) {
self.currentCost = Math.floor(self.baseCost * Math.pow(1.5, purchases));
self.costText.setText('Cost: ' + self.currentCost);
self.levelText.setText('Lvl ' + (self.levelIndex + 1) + ' (x' + purchases + '): +' + self.baseIncome + '/t');
};
return self;
});
/****
* Initialize Game
****/
/**** * Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x111122
});
/****
* Game Code
****/
/**** * CONFIGURACIÓN CENTRALIZADA
****/
/**** * Plugins
****/
/**** * Databases
****/
var GAME_CONFIG = {
BASE_GACHA_COST: 1000,
GACHA_COST_MULTIPLIER: 1.15,
// Aumenta 15% el costo por cada personaje nuevo
FPS: 60,
SAVE_INTERVAL: 300,
// Guardar cada 300 frames (5 segundos)
MAX_EQUIPPED: 3,
// Límite de personajes en pantalla orbitando
ORBIT_RADIUS: 280,
// Distancia desde el centro (núcleo)
ORBIT_SPEED: 0.012 // Velocidad de la órbita
};
var characterDatabase = [{
id: 0,
name: 'Fire',
rarity: 'Common',
asset: 'fire_common',
multiplier: 2
}, {
id: 1,
name: 'Water',
rarity: 'Common',
asset: 'water_common',
multiplier: 2
}, {
id: 2,
name: 'Earth',
rarity: 'Common',
asset: 'earth_common',
multiplier: 2
}, {
id: 3,
name: 'Wind',
rarity: 'Common',
asset: 'wind_common',
multiplier: 2
}, {
id: 4,
name: 'Lightning',
rarity: 'Uncommon',
asset: 'lightning_uncommon',
multiplier: 3
}, {
id: 5,
name: 'Ice',
rarity: 'Uncommon',
asset: 'ice_uncommon',
multiplier: 3
}, {
id: 6,
name: 'Nature',
rarity: 'Uncommon',
asset: 'nature_uncommon',
multiplier: 3
}, {
id: 7,
name: 'Metal',
rarity: 'Uncommon',
asset: 'metal_uncommon',
multiplier: 3
}, {
id: 8,
name: 'Sand',
rarity: 'Uncommon',
asset: 'sand_uncommon',
multiplier: 3
}, {
id: 9,
name: 'Steam',
rarity: 'Uncommon',
asset: 'steam_uncommon',
multiplier: 3
}, {
id: 10,
name: 'Magma',
rarity: 'Rare',
asset: 'magma_rare',
multiplier: 4
}, {
id: 11,
name: 'Frost',
rarity: 'Rare',
asset: 'frost_rare',
multiplier: 4
}, {
id: 12,
name: 'Crystal',
rarity: 'Rare',
asset: 'crystal_rare',
multiplier: 4
}, {
id: 13,
name: 'Storm',
rarity: 'Rare',
asset: 'storm_rare',
multiplier: 4
}, {
id: 14,
name: 'Coral',
rarity: 'Rare',
asset: 'coral_rare',
multiplier: 4
}, {
id: 15,
name: 'Forest',
rarity: 'Rare',
asset: 'forest_rare',
multiplier: 4
}, {
id: 16,
name: 'Shadow',
rarity: 'Rare',
asset: 'shadow_rare',
multiplier: 4
}, {
id: 17,
name: 'Plasma',
rarity: 'Ultra-Rare',
asset: 'plasma_ultra',
multiplier: 5
}, {
id: 18,
name: 'Abyss',
rarity: 'Ultra-Rare',
asset: 'abyss_ultra',
multiplier: 5
}, {
id: 19,
name: 'Aurora',
rarity: 'Ultra-Rare',
asset: 'aurora_ultra',
multiplier: 5
}, {
id: 20,
name: 'Inferno',
rarity: 'Ultra-Rare',
asset: 'inferno_ultra',
multiplier: 5
}, {
id: 21,
name: 'Glacier',
rarity: 'Ultra-Rare',
asset: 'glacier_ultra',
multiplier: 5
}, {
id: 22,
name: 'Mirage',
rarity: 'Ultra-Rare',
asset: 'mirage_ultra',
multiplier: 5
}, {
id: 23,
name: 'Celestial',
rarity: 'Legendary',
asset: 'celestial_legendary',
multiplier: 7
}, {
id: 24,
name: 'Cosmic',
rarity: 'Legendary',
asset: 'cosmic_legendary',
multiplier: 7
}, {
id: 25,
name: 'Void',
rarity: 'Legendary',
asset: 'void_legendary',
multiplier: 7
}, {
id: 26,
name: 'Radiance',
rarity: 'Legendary',
asset: 'radiance_legendary',
multiplier: 7
}, {
id: 27,
name: 'Eclipse',
rarity: 'Legendary',
asset: 'eclipse_legendary',
multiplier: 7
}, {
id: 28,
name: 'Genesis',
rarity: 'Unique',
asset: 'genesis_unique',
multiplier: 10
}, {
id: 29,
name: 'Apocalypse',
rarity: 'Unique',
asset: 'apocalypse_unique',
multiplier: 10
}, {
id: 30,
name: 'Paradox',
rarity: 'Unique',
asset: 'paradox_unique',
multiplier: 10
}, {
id: 31,
name: 'Nova',
rarity: 'Special',
asset: 'nova_special',
multiplier: 6
}, {
id: 32,
name: 'Nebula',
rarity: 'Special',
asset: 'nebula_special',
multiplier: 6
}, {
id: 33,
name: 'Titan',
rarity: 'Special',
asset: 'titan_special',
multiplier: 6
}, {
id: 34,
name: 'Phantom',
rarity: 'Special',
asset: 'phantom_special',
multiplier: 6
}, {
id: 35,
name: 'Sphinx',
rarity: 'Special',
asset: 'sphinx_special',
multiplier: 6
}, {
id: 36,
name: 'Oracle',
rarity: 'Special',
asset: 'oracle_special',
multiplier: 6
}];
var dropRates = [{
rarity: 'Common',
chance: 50,
ids: [0, 1, 2, 3]
}, {
rarity: 'Uncommon',
chance: 20,
ids: [4, 5, 6, 7, 8, 9]
}, {
rarity: 'Rare',
chance: 15,
ids: [10, 11, 12, 13, 14, 15, 16]
}, {
rarity: 'Ultra-Rare',
chance: 10,
ids: [17, 18, 19, 20, 21, 22]
}, {
rarity: 'Legendary',
chance: 4,
ids: [23, 24, 25, 26, 27]
}, {
rarity: 'Unique',
chance: 1,
ids: [28, 29, 30]
}];
var gameState = {
credits: 0,
incomePerTick: 1,
collectedCharacters: {},
totalCharactersCollected: 0,
incomeLevels: [],
tickCounter: 0,
equippedCharacters: []
};
// --- Funciones Base de Estado ---
function getGachaCost() {
return Math.floor(GAME_CONFIG.BASE_GACHA_COST * Math.pow(GAME_CONFIG.GACHA_COST_MULTIPLIER, gameState.totalCharactersCollected));
}
function loadGame() {
gameState.collectedCharacters = {};
gameState.incomeLevels = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
gameState.equippedCharacters = [];
if (storage.credits !== undefined) {
gameState.credits = storage.credits;
gameState.incomePerTick = storage.incomePerTick;
gameState.totalCharactersCollected = storage.totalCharactersCollected;
gameState.tickCounter = storage.tickCounter || 0;
var collectedIds = (storage.collectedCharacterIds || '').split(',');
for (var i = 0; i < collectedIds.length; i++) {
if (collectedIds[i] !== '') {
gameState.collectedCharacters[parseInt(collectedIds[i])] = true;
}
}
var upgradedLevels = (storage.upgradedLevelCounts || '').split(',');
for (var j = 0; j < upgradedLevels.length; j++) {
if (upgradedLevels[j] !== '') {
gameState.incomeLevels[j] = parseInt(upgradedLevels[j]) || 0;
}
}
var equippedStr = storage.equippedCharactersIds || '';
if (equippedStr !== '') {
var eqSplit = equippedStr.split(',');
for (var k = 0; k < eqSplit.length; k++) {
if (eqSplit[k] !== '') {
gameState.equippedCharacters.push(parseInt(eqSplit[k]));
}
}
}
}
}
function saveGame() {
storage.credits = gameState.credits;
storage.incomePerTick = gameState.incomePerTick;
storage.totalCharactersCollected = gameState.totalCharactersCollected;
storage.tickCounter = gameState.tickCounter;
var collectedIds = '';
for (var charId in gameState.collectedCharacters) {
if (gameState.collectedCharacters[charId]) {
collectedIds += charId + ',';
}
}
storage.collectedCharacterIds = collectedIds;
var upgradedLevels = '';
for (var i = 0; i < gameState.incomeLevels.length; i++) {
upgradedLevels += gameState.incomeLevels[i] + ',';
}
storage.upgradedLevelCounts = upgradedLevels;
var equippedIds = '';
for (var e = 0; e < gameState.equippedCharacters.length; e++) {
equippedIds += gameState.equippedCharacters[e] + ',';
}
storage.equippedCharactersIds = equippedIds;
}
loadGame();
// --- UI Construction ---
var creditsText = new Text2('Credits: 0', {
size: 70,
fill: '#FFD700'
});
creditsText.anchor.set(0.5, 0);
creditsText.x = 1024;
creditsText.y = 50;
game.addChild(creditsText);
var incomeText = new Text2('Income: 1/tick', {
size: 45,
fill: '#00FF00'
});
incomeText.anchor.set(0.5, 0);
incomeText.x = 1024;
incomeText.y = 140;
game.addChild(incomeText);
var collectionText = new Text2('Collection: 0/37', {
size: 40,
fill: '#87CEEB'
});
collectionText.anchor.set(0.5, 0);
collectionText.x = 1024;
collectionText.y = 210;
game.addChild(collectionText);
// --- SISTEMA DE ÓRBITA ---
var orbitContainer = new Container();
orbitContainer.x = 1024;
orbitContainer.y = 500;
game.addChild(orbitContainer); // Detrás del core central
var orbitingSprites = [];
var orbitAngle = 0;
function updateEquippedDisplay() {
while (orbitContainer.children.length > 0) {
orbitContainer.children[0].destroy();
}
orbitingSprites = [];
for (var i = 0; i < gameState.equippedCharacters.length; i++) {
var charId = gameState.equippedCharacters[i];
var charData = characterDatabase[charId];
var sprite = LK.getAsset(charData.asset, {
anchorX: 0.5,
anchorY: 0.5
});
sprite.scale.set(0.8, 0.8);
orbitContainer.addChild(sprite);
orbitingSprites.push(sprite);
}
}
updateEquippedDisplay();
// --- Manual Clicker (Core) ---
var coreGraphic = LK.getAsset('core_crystal', {
anchorX: 0.5,
anchorY: 0.5
});
var coreButton = new Container();
coreButton.addChild(coreGraphic);
coreButton.x = 1024;
coreButton.y = 500;
game.addChild(coreButton); // Delante de la órbita
var coreText = new Text2('TAP', {
size: 50,
fill: '#ffffff'
});
coreText.anchor.set(0.5, 0.5);
coreButton.addChild(coreText);
// Gacha Button
var gachaBtnGraphic = LK.getAsset('gacha_button', {
anchorX: 0.5,
anchorY: 0.5
});
gachaBtnGraphic.scale.set(1.5, 1.5);
var gachaButton = new Container();
gachaButton.addChild(gachaBtnGraphic);
gachaButton.x = 1024;
gachaButton.y = 2500;
game.addChild(gachaButton);
var gachaText = new Text2('PULL (' + getGachaCost() + ')', {
size: 60,
fill: '#ffffff'
});
gachaText.anchor.set(0.5, 0.5);
gachaButton.addChild(gachaText);
var gachaEnabled = false;
// Gallery Button
var galleryBtnGraphic = LK.getAsset('gallery_button', {
anchorX: 0.5,
anchorY: 0.5
});
var galleryButton = new Container();
galleryButton.addChild(galleryBtnGraphic);
galleryButton.x = 300;
galleryButton.y = 2550;
game.addChild(galleryButton);
var galleryText = new Text2('GALLERY', {
size: 30,
fill: '#ffffff'
});
galleryText.anchor.set(0.5, 0.5);
galleryButton.addChild(galleryText);
// Debug Reset Button
var debugBtnGraphic = LK.getAsset('button_bg', {
anchorX: 0.5,
anchorY: 0.5
});
var debugButton = new Container();
debugButton.addChild(debugBtnGraphic);
debugButton.x = 300;
debugButton.y = 100;
game.addChild(debugButton);
var debugText = new Text2('RESET', {
size: 40,
fill: '#ff4444'
});
debugText.anchor.set(0.5, 0.5);
debugButton.addChild(debugText);
// Upgrade Levels Container
var levelContainers = [];
var levelStartY = 850;
var levelSpacing = 150;
for (var i = 0; i < 10; i++) {
var levelContainer = new IncomeLevel();
levelContainer.init(i, [1, 2, 3, 5, 10, 20, 50, 100, 200, 300][i]);
levelContainer.updateData(gameState.incomeLevels[i]);
levelContainer.x = 1024;
levelContainer.y = levelStartY + i * levelSpacing;
game.addChild(levelContainer);
levelContainers.push(levelContainer);
}
// Modal Variables
var modalOpen = false;
var modalContainer = null;
// --- Funciones Lógicas ---
function openGallery() {
if (modalOpen) return;
modalOpen = true;
modalContainer = new Container();
var modalBg = LK.getAsset('modal_bg', {
anchorX: 0.5,
anchorY: 0.5
});
modalContainer.addChild(modalBg);
modalContainer.x = 1024;
modalContainer.y = 1366;
var galleryTitle = new Text2('Element Gallery', {
size: 80,
fill: '#FFD700'
});
galleryTitle.anchor.set(0.5, 0);
galleryTitle.x = 0;
galleryTitle.y = -1100;
modalContainer.addChild(galleryTitle);
var closeBtnGraphic = LK.getAsset('modal_close_btn', {
anchorX: 0.5,
anchorY: 0.5
});
var closeBtn = new Container();
closeBtn.addChild(closeBtnGraphic);
closeBtn.x = 800;
closeBtn.y = -1050;
modalContainer.addChild(closeBtn);
var closeBtnText = new Text2('X', {
size: 60,
fill: '#ffffff'
});
closeBtnText.anchor.set(0.5, 0.5);
closeBtn.addChild(closeBtnText);
closeBtn.down = function () {
closeModal();
LK.getSound('ui_click').play();
};
var yOffset = -900;
var xOffset = -700;
var colCount = 0;
for (var charId = 0; charId < characterDatabase.length; charId++) {
if (gameState.collectedCharacters[charId]) {
var charData = characterDatabase[charId];
var displayChar = new Character();
displayChar.init(charId, charData.name, charData.rarity, charData.asset, charData.multiplier);
displayChar.x = xOffset + colCount % 5 * 350;
displayChar.y = yOffset + Math.floor(colCount / 5) * 250;
// Indicador visual si está equipado
if (gameState.equippedCharacters.indexOf(charId) > -1) {
displayChar.alpha = 0.5;
}
// Lógica de equipar/desequipar al hacer Tap
(function (currentId, charRef) {
charRef.down = function () {
var index = gameState.equippedCharacters.indexOf(currentId);
if (index > -1) {
// Desequipar
gameState.equippedCharacters.splice(index, 1);
} else {
// Equipar (Reemplaza el más viejo si ya hay el máximo)
if (gameState.equippedCharacters.length >= GAME_CONFIG.MAX_EQUIPPED) {
gameState.equippedCharacters.shift();
}
gameState.equippedCharacters.push(currentId);
}
updateEquippedDisplay();
saveGame();
LK.getSound('ui_click').play();
// Re-renderizamos la galería
closeModal();
openGallery();
};
})(charId, displayChar);
modalContainer.addChild(displayChar);
colCount++;
}
}
var uncollectedText = new Text2('Uncollected: ' + (37 - gameState.totalCharactersCollected), {
size: 40,
fill: '#FF6666'
});
uncollectedText.anchor.set(0.5, 0);
uncollectedText.x = 0;
uncollectedText.y = 1000;
modalContainer.addChild(uncollectedText);
game.addChild(modalContainer);
}
function closeModal() {
if (modalContainer) {
modalContainer.destroy();
modalOpen = false;
}
}
function performGachaPull() {
var currentCost = getGachaCost();
if (gameState.credits < currentCost) return;
gameState.credits -= currentCost;
var roll = Math.random() * 100;
var selectedRarity = null;
var cumulativeChance = 0;
for (var i = 0; i < dropRates.length; i++) {
cumulativeChance += dropRates[i].chance;
if (roll <= cumulativeChance) {
selectedRarity = dropRates[i];
break;
}
}
var characterIdArray = selectedRarity.ids;
var selectedCharacterId = characterIdArray[Math.floor(Math.random() * characterIdArray.length)];
var wasNew = false;
var charData = characterDatabase[selectedCharacterId];
if (!gameState.collectedCharacters[selectedCharacterId]) {
gameState.collectedCharacters[selectedCharacterId] = true;
gameState.totalCharactersCollected++;
wasNew = true;
gameState.incomePerTick += charData.multiplier;
}
saveGame();
LK.getSound('gacha_pull').play();
var resultMessage = wasNew ? 'NEW: ' + charData.name + '!' : 'Duplicate: ' + charData.name;
var resultColor = wasNew ? '#00FF00' : '#FFD700';
var resultContainer = new Container();
var resultBg = LK.getAsset('modal_bg', {
anchorX: 0.5,
anchorY: 0.5
});
resultContainer.addChild(resultBg);
resultContainer.x = 1024;
resultContainer.y = 1366;
resultContainer.scale.set(0.1, 0.1);
tween(resultContainer, {
scaleX: 1,
scaleY: 1
}, {
duration: 300
});
// --- Gráfico Escaneado y Cálculo Dinámico ---
var resultGraphic = LK.getAsset(charData.asset, {
anchorX: 0.5,
anchorY: 0.5
});
var scaleTarget = 4; // Asset muy grande
resultGraphic.scale.set(scaleTarget, scaleTarget);
resultGraphic.y = 0;
resultContainer.addChild(resultGraphic);
// Calculamos el espacio libre necesario basándonos en la escala
var safePadding = 120 * scaleTarget / 2 + 80;
var resultTitle = new Text2(resultMessage, {
size: 90,
fill: resultColor
});
resultTitle.anchor.set(0.5, 0.5);
resultTitle.y = -safePadding;
resultContainer.addChild(resultTitle);
var resultRarity = new Text2('[' + charData.rarity + ']', {
size: 60,
fill: '#FFD700'
});
resultRarity.anchor.set(0.5, 0.5);
resultRarity.y = safePadding;
resultContainer.addChild(resultRarity);
game.addChild(resultContainer);
LK.setTimeout(function () {
tween(resultContainer, {
alpha: 0,
scaleX: 0.5,
scaleY: 0.5
}, {
duration: 200,
onFinish: function onFinish() {
resultContainer.destroy();
}
});
}, 2000);
}
function upgradeIncomeLevel(levelIndex) {
var level = levelContainers[levelIndex];
if (gameState.credits >= level.currentCost) {
gameState.credits -= level.currentCost;
gameState.incomeLevels[levelIndex]++;
gameState.incomePerTick += level.baseIncome;
level.updateData(gameState.incomeLevels[levelIndex]);
saveGame();
LK.getSound('level_up').play();
}
}
// --- Event Handlers Directos ---
gachaButton.down = function () {
if (modalOpen) return;
if (gachaEnabled) {
performGachaPull();
LK.getSound('ui_click').play();
}
};
galleryButton.down = function () {
if (modalOpen) return;
openGallery();
LK.getSound('ui_click').play();
};
debugButton.down = function () {
if (modalOpen) return;
gameState.credits = 0;
gameState.incomePerTick = 1;
gameState.collectedCharacters = {};
gameState.totalCharactersCollected = 0;
gameState.incomeLevels = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
gameState.equippedCharacters = [];
for (var i = 0; i < levelContainers.length; i++) {
levelContainers[i].updateData(0);
}
updateEquippedDisplay();
saveGame();
LK.getSound('ui_click').play();
};
coreButton.down = function () {
if (modalOpen) return;
var clickGain = 1 + Math.floor(gameState.incomePerTick * 0.2);
gameState.credits += clickGain;
var floatText = new FloatingText('+' + clickGain, coreButton.x + (Math.random() * 100 - 50), coreButton.y - 100, '#00ffff');
game.addChild(floatText);
tween(coreGraphic, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 50,
onFinish: function onFinish() {
tween(coreGraphic, {
scaleX: 1,
scaleY: 1
}, {
duration: 50
});
}
});
};
for (var i = 0; i < levelContainers.length; i++) {
(function (index) {
levelContainers[index].down = function () {
if (modalOpen) return;
upgradeIncomeLevel(index);
};
})(i);
}
// --- Variables para el Main Loop ---
var pulseTimer = 0;
var lastDisplayedCredits = -1;
var lastDisplayedIncome = -1;
var lastDisplayedCollection = -1;
var lastDisplayedGachaCost = -1;
// --- Main Game Loop Optimizado ---
game.update = function () {
gameState.tickCounter++;
// LÓGICA DE ÓRBITA (NUEVO)
var numOrbiting = orbitingSprites.length;
if (numOrbiting > 0) {
orbitAngle += GAME_CONFIG.ORBIT_SPEED;
var angleStep = Math.PI * 2 / numOrbiting;
for (var o = 0; o < numOrbiting; o++) {
var currentAngle = orbitAngle + o * angleStep;
orbitingSprites[o].x = Math.cos(currentAngle) * GAME_CONFIG.ORBIT_RADIUS;
orbitingSprites[o].y = Math.sin(currentAngle) * GAME_CONFIG.ORBIT_RADIUS;
// Pequeña rotación sobre su eje
orbitingSprites[o].rotation += 0.01;
}
}
// Generar créditos pasivos
if (gameState.tickCounter % GAME_CONFIG.FPS === 0) {
gameState.credits += gameState.incomePerTick;
}
var currentCredits = Math.floor(gameState.credits);
var currentGachaCost = getGachaCost();
// Actualizar textos SOLO si han cambiado sus valores
if (currentCredits !== lastDisplayedCredits) {
creditsText.setText('Credits: ' + currentCredits);
lastDisplayedCredits = currentCredits;
}
if (gameState.incomePerTick !== lastDisplayedIncome) {
incomeText.setText('Income: ' + gameState.incomePerTick + '/tick');
lastDisplayedIncome = gameState.incomePerTick;
}
if (gameState.totalCharactersCollected !== lastDisplayedCollection) {
collectionText.setText('Collection: ' + gameState.totalCharactersCollected + '/37');
lastDisplayedCollection = gameState.totalCharactersCollected;
}
if (currentGachaCost !== lastDisplayedGachaCost) {
gachaText.setText('PULL (' + currentGachaCost + ')');
lastDisplayedGachaCost = currentGachaCost;
}
// Estado Gacha
gachaEnabled = gameState.credits >= currentGachaCost;
if (gachaEnabled) {
gachaBtnGraphic.tint = 0xFF1493;
gachaText.tint = 0xFFFFFF;
pulseTimer += 0.05;
var scale = 1.5 + Math.sin(pulseTimer) * 0.05;
gachaBtnGraphic.scale.set(scale, scale);
} else {
gachaBtnGraphic.tint = 0x883366;
gachaText.tint = 0xAAAAAA;
gachaBtnGraphic.scale.set(1.5, 1.5);
}
// Estado Tienda
for (var j = 0; j < levelContainers.length; j++) {
var level = levelContainers[j];
if (gameState.credits >= level.currentCost) {
level.children[0].tint = 0x32CD32;
} else {
level.children[0].tint = 0x666666;
}
}
// Guardado Automático
if (gameState.tickCounter % GAME_CONFIG.SAVE_INTERVAL === 0) {
saveGame();
}
}; ===================================================================
--- original.js
+++ change.js
@@ -45,9 +45,8 @@
fill: color || '#ffffff'
});
txt.anchor.set(0.5, 0.5);
self.addChild(txt);
- // Animación hacia arriba y desvanecimiento
tween(self, {
y: self.y - 150,
alpha: 0
}, {
@@ -111,12 +110,27 @@
/****
* Game Code
****/
+/**** * CONFIGURACIÓN CENTRALIZADA
+****/
/**** * Plugins
****/
-// Nuevo Asset
-// Database
+/**** * Databases
+****/
+var GAME_CONFIG = {
+ BASE_GACHA_COST: 1000,
+ GACHA_COST_MULTIPLIER: 1.15,
+ // Aumenta 15% el costo por cada personaje nuevo
+ FPS: 60,
+ SAVE_INTERVAL: 300,
+ // Guardar cada 300 frames (5 segundos)
+ MAX_EQUIPPED: 3,
+ // Límite de personajes en pantalla orbitando
+ ORBIT_RADIUS: 280,
+ // Distancia desde el centro (núcleo)
+ ORBIT_SPEED: 0.012 // Velocidad de la órbita
+};
var characterDatabase = [{
id: 0,
name: 'Fire',
rarity: 'Common',
@@ -369,27 +383,45 @@
incomePerTick: 1,
collectedCharacters: {},
totalCharactersCollected: 0,
incomeLevels: [],
- tickCounter: 0
+ tickCounter: 0,
+ equippedCharacters: []
};
-// State Management
+// --- Funciones Base de Estado ---
+function getGachaCost() {
+ return Math.floor(GAME_CONFIG.BASE_GACHA_COST * Math.pow(GAME_CONFIG.GACHA_COST_MULTIPLIER, gameState.totalCharactersCollected));
+}
function loadGame() {
gameState.collectedCharacters = {};
gameState.incomeLevels = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
+ gameState.equippedCharacters = [];
if (storage.credits !== undefined) {
gameState.credits = storage.credits;
gameState.incomePerTick = storage.incomePerTick;
gameState.totalCharactersCollected = storage.totalCharactersCollected;
gameState.tickCounter = storage.tickCounter || 0;
var collectedIds = (storage.collectedCharacterIds || '').split(',');
for (var i = 0; i < collectedIds.length; i++) {
- if (collectedIds[i] !== '') gameState.collectedCharacters[parseInt(collectedIds[i])] = true;
+ if (collectedIds[i] !== '') {
+ gameState.collectedCharacters[parseInt(collectedIds[i])] = true;
+ }
}
var upgradedLevels = (storage.upgradedLevelCounts || '').split(',');
for (var j = 0; j < upgradedLevels.length; j++) {
- if (upgradedLevels[j] !== '') gameState.incomeLevels[j] = parseInt(upgradedLevels[j]) || 0;
+ if (upgradedLevels[j] !== '') {
+ gameState.incomeLevels[j] = parseInt(upgradedLevels[j]) || 0;
+ }
}
+ var equippedStr = storage.equippedCharactersIds || '';
+ if (equippedStr !== '') {
+ var eqSplit = equippedStr.split(',');
+ for (var k = 0; k < eqSplit.length; k++) {
+ if (eqSplit[k] !== '') {
+ gameState.equippedCharacters.push(parseInt(eqSplit[k]));
+ }
+ }
+ }
}
}
function saveGame() {
storage.credits = gameState.credits;
@@ -397,16 +429,23 @@
storage.totalCharactersCollected = gameState.totalCharactersCollected;
storage.tickCounter = gameState.tickCounter;
var collectedIds = '';
for (var charId in gameState.collectedCharacters) {
- if (gameState.collectedCharacters[charId]) collectedIds += charId + ',';
+ if (gameState.collectedCharacters[charId]) {
+ collectedIds += charId + ',';
+ }
}
storage.collectedCharacterIds = collectedIds;
var upgradedLevels = '';
for (var i = 0; i < gameState.incomeLevels.length; i++) {
upgradedLevels += gameState.incomeLevels[i] + ',';
}
storage.upgradedLevelCounts = upgradedLevels;
+ var equippedIds = '';
+ for (var e = 0; e < gameState.equippedCharacters.length; e++) {
+ equippedIds += gameState.equippedCharacters[e] + ',';
+ }
+ storage.equippedCharactersIds = equippedIds;
}
loadGame();
// --- UI Construction ---
var creditsText = new Text2('Credits: 0', {
@@ -432,18 +471,43 @@
collectionText.anchor.set(0.5, 0);
collectionText.x = 1024;
collectionText.y = 210;
game.addChild(collectionText);
-// Manual Clicker (Core)
+// --- SISTEMA DE ÓRBITA ---
+var orbitContainer = new Container();
+orbitContainer.x = 1024;
+orbitContainer.y = 500;
+game.addChild(orbitContainer); // Detrás del core central
+var orbitingSprites = [];
+var orbitAngle = 0;
+function updateEquippedDisplay() {
+ while (orbitContainer.children.length > 0) {
+ orbitContainer.children[0].destroy();
+ }
+ orbitingSprites = [];
+ for (var i = 0; i < gameState.equippedCharacters.length; i++) {
+ var charId = gameState.equippedCharacters[i];
+ var charData = characterDatabase[charId];
+ var sprite = LK.getAsset(charData.asset, {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ sprite.scale.set(0.8, 0.8);
+ orbitContainer.addChild(sprite);
+ orbitingSprites.push(sprite);
+ }
+}
+updateEquippedDisplay();
+// --- Manual Clicker (Core) ---
var coreGraphic = LK.getAsset('core_crystal', {
anchorX: 0.5,
anchorY: 0.5
});
var coreButton = new Container();
coreButton.addChild(coreGraphic);
coreButton.x = 1024;
-coreButton.y = 500; // Posicionado al centro superior
-game.addChild(coreButton);
+coreButton.y = 500;
+game.addChild(coreButton); // Delante de la órbita
var coreText = new Text2('TAP', {
size: 50,
fill: '#ffffff'
});
@@ -459,9 +523,9 @@
gachaButton.addChild(gachaBtnGraphic);
gachaButton.x = 1024;
gachaButton.y = 2500;
game.addChild(gachaButton);
-var gachaText = new Text2('PULL (1000)', {
+var gachaText = new Text2('PULL (' + getGachaCost() + ')', {
size: 60,
fill: '#ffffff'
});
gachaText.anchor.set(0.5, 0.5);
@@ -500,9 +564,9 @@
debugText.anchor.set(0.5, 0.5);
debugButton.addChild(debugText);
// Upgrade Levels Container
var levelContainers = [];
-var levelStartY = 850; // Desplazado hacia abajo para dar espacio al Núcleo
+var levelStartY = 850;
var levelSpacing = 150;
for (var i = 0; i < 10; i++) {
var levelContainer = new IncomeLevel();
levelContainer.init(i, [1, 2, 3, 5, 10, 20, 50, 100, 200, 300][i]);
@@ -563,8 +627,34 @@
var displayChar = new Character();
displayChar.init(charId, charData.name, charData.rarity, charData.asset, charData.multiplier);
displayChar.x = xOffset + colCount % 5 * 350;
displayChar.y = yOffset + Math.floor(colCount / 5) * 250;
+ // Indicador visual si está equipado
+ if (gameState.equippedCharacters.indexOf(charId) > -1) {
+ displayChar.alpha = 0.5;
+ }
+ // Lógica de equipar/desequipar al hacer Tap
+ (function (currentId, charRef) {
+ charRef.down = function () {
+ var index = gameState.equippedCharacters.indexOf(currentId);
+ if (index > -1) {
+ // Desequipar
+ gameState.equippedCharacters.splice(index, 1);
+ } else {
+ // Equipar (Reemplaza el más viejo si ya hay el máximo)
+ if (gameState.equippedCharacters.length >= GAME_CONFIG.MAX_EQUIPPED) {
+ gameState.equippedCharacters.shift();
+ }
+ gameState.equippedCharacters.push(currentId);
+ }
+ updateEquippedDisplay();
+ saveGame();
+ LK.getSound('ui_click').play();
+ // Re-renderizamos la galería
+ closeModal();
+ openGallery();
+ };
+ })(charId, displayChar);
modalContainer.addChild(displayChar);
colCount++;
}
}
@@ -584,10 +674,11 @@
modalOpen = false;
}
}
function performGachaPull() {
- if (gameState.credits < 1000) return;
- gameState.credits -= 1000;
+ var currentCost = getGachaCost();
+ if (gameState.credits < currentCost) return;
+ gameState.credits -= currentCost;
var roll = Math.random() * 100;
var selectedRarity = null;
var cumulativeChance = 0;
for (var i = 0; i < dropRates.length; i++) {
@@ -618,36 +709,39 @@
});
resultContainer.addChild(resultBg);
resultContainer.x = 1024;
resultContainer.y = 1366;
- // Efecto Pop-in
resultContainer.scale.set(0.1, 0.1);
tween(resultContainer, {
scaleX: 1,
scaleY: 1
}, {
duration: 300
});
- var resultTitle = new Text2(resultMessage, {
- size: 100,
- fill: resultColor
- });
- resultTitle.anchor.set(0.5, 0.5);
- resultTitle.y = -350;
- resultContainer.addChild(resultTitle);
+ // --- Gráfico Escaneado y Cálculo Dinámico ---
var resultGraphic = LK.getAsset(charData.asset, {
anchorX: 0.5,
anchorY: 0.5
});
- resultGraphic.scale.set(3, 3);
- resultGraphic.y = -50;
+ var scaleTarget = 4; // Asset muy grande
+ resultGraphic.scale.set(scaleTarget, scaleTarget);
+ resultGraphic.y = 0;
resultContainer.addChild(resultGraphic);
+ // Calculamos el espacio libre necesario basándonos en la escala
+ var safePadding = 120 * scaleTarget / 2 + 80;
+ var resultTitle = new Text2(resultMessage, {
+ size: 90,
+ fill: resultColor
+ });
+ resultTitle.anchor.set(0.5, 0.5);
+ resultTitle.y = -safePadding;
+ resultContainer.addChild(resultTitle);
var resultRarity = new Text2('[' + charData.rarity + ']', {
- size: 70,
+ size: 60,
fill: '#FFD700'
});
resultRarity.anchor.set(0.5, 0.5);
- resultRarity.y = 200;
+ resultRarity.y = safePadding;
resultContainer.addChild(resultRarity);
game.addChild(resultContainer);
LK.setTimeout(function () {
tween(resultContainer, {
@@ -692,23 +786,22 @@
gameState.incomePerTick = 1;
gameState.collectedCharacters = {};
gameState.totalCharactersCollected = 0;
gameState.incomeLevels = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
+ gameState.equippedCharacters = [];
for (var i = 0; i < levelContainers.length; i++) {
levelContainers[i].updateData(0);
}
+ updateEquippedDisplay();
saveGame();
LK.getSound('ui_click').play();
};
coreButton.down = function () {
if (modalOpen) return;
- // El click manual da 1 crédito base + 20% del income pasivo
var clickGain = 1 + Math.floor(gameState.incomePerTick * 0.2);
gameState.credits += clickGain;
- // Feedback visual
var floatText = new FloatingText('+' + clickGain, coreButton.x + (Math.random() * 100 - 50), coreButton.y - 100, '#00ffff');
game.addChild(floatText);
- // Pequeño tween de escala para el core
tween(coreGraphic, {
scaleX: 1.1,
scaleY: 1.1
}, {
@@ -730,26 +823,58 @@
upgradeIncomeLevel(index);
};
})(i);
}
-// --- Main Game Loop ---
+// --- Variables para el Main Loop ---
var pulseTimer = 0;
+var lastDisplayedCredits = -1;
+var lastDisplayedIncome = -1;
+var lastDisplayedCollection = -1;
+var lastDisplayedGachaCost = -1;
+// --- Main Game Loop Optimizado ---
game.update = function () {
gameState.tickCounter++;
- // Generar créditos pasivos 1 vez por segundo (asumiendo 60 FPS)
- if (gameState.tickCounter % 60 === 0) {
+ // LÓGICA DE ÓRBITA (NUEVO)
+ var numOrbiting = orbitingSprites.length;
+ if (numOrbiting > 0) {
+ orbitAngle += GAME_CONFIG.ORBIT_SPEED;
+ var angleStep = Math.PI * 2 / numOrbiting;
+ for (var o = 0; o < numOrbiting; o++) {
+ var currentAngle = orbitAngle + o * angleStep;
+ orbitingSprites[o].x = Math.cos(currentAngle) * GAME_CONFIG.ORBIT_RADIUS;
+ orbitingSprites[o].y = Math.sin(currentAngle) * GAME_CONFIG.ORBIT_RADIUS;
+ // Pequeña rotación sobre su eje
+ orbitingSprites[o].rotation += 0.01;
+ }
+ }
+ // Generar créditos pasivos
+ if (gameState.tickCounter % GAME_CONFIG.FPS === 0) {
gameState.credits += gameState.incomePerTick;
}
- // Actualizar UI
- creditsText.setText('Credits: ' + Math.floor(gameState.credits));
- incomeText.setText('Income: ' + gameState.incomePerTick + '/tick');
- collectionText.setText('Collection: ' + gameState.totalCharactersCollected + '/37');
+ var currentCredits = Math.floor(gameState.credits);
+ var currentGachaCost = getGachaCost();
+ // Actualizar textos SOLO si han cambiado sus valores
+ if (currentCredits !== lastDisplayedCredits) {
+ creditsText.setText('Credits: ' + currentCredits);
+ lastDisplayedCredits = currentCredits;
+ }
+ if (gameState.incomePerTick !== lastDisplayedIncome) {
+ incomeText.setText('Income: ' + gameState.incomePerTick + '/tick');
+ lastDisplayedIncome = gameState.incomePerTick;
+ }
+ if (gameState.totalCharactersCollected !== lastDisplayedCollection) {
+ collectionText.setText('Collection: ' + gameState.totalCharactersCollected + '/37');
+ lastDisplayedCollection = gameState.totalCharactersCollected;
+ }
+ if (currentGachaCost !== lastDisplayedGachaCost) {
+ gachaText.setText('PULL (' + currentGachaCost + ')');
+ lastDisplayedGachaCost = currentGachaCost;
+ }
// Estado Gacha
- gachaEnabled = gameState.credits >= 1000;
+ gachaEnabled = gameState.credits >= currentGachaCost;
if (gachaEnabled) {
gachaBtnGraphic.tint = 0xFF1493;
gachaText.tint = 0xFFFFFF;
- // Animación de pulso cuando está habilitado
pulseTimer += 0.05;
var scale = 1.5 + Math.sin(pulseTimer) * 0.05;
gachaBtnGraphic.scale.set(scale, scale);
} else {
@@ -757,17 +882,17 @@
gachaText.tint = 0xAAAAAA;
gachaBtnGraphic.scale.set(1.5, 1.5);
}
// Estado Tienda
- for (var i = 0; i < levelContainers.length; i++) {
- var level = levelContainers[i];
+ for (var j = 0; j < levelContainers.length; j++) {
+ var level = levelContainers[j];
if (gameState.credits >= level.currentCost) {
- level.children[0].tint = 0x32CD32; // Comprable
+ level.children[0].tint = 0x32CD32;
} else {
- level.children[0].tint = 0x666666; // Sin fondos
+ level.children[0].tint = 0x666666;
}
}
// Guardado Automático
- if (gameState.tickCounter % 300 === 0) {
+ if (gameState.tickCounter % GAME_CONFIG.SAVE_INTERVAL === 0) {
saveGame();
}
};
\ No newline at end of file
Crea un rectángulo para asset de botón. Debe ser: color amarillo, rojo, verde, azul, gris, rosa dispuestos en forma diagonal irregular por el rectángulo. Los colores deben ser planos, y los bordes redondeados. In-Game asset. 2d. High contrast. No shadows. anime. simple
Crea un rectángulo para asset de botón. Debe ser: color rojo escarlata con borde en forma de rectángulo. Los colores deben ser planos, y los bordes redondeados. In-Game asset. 2d. High contrast. No shadows. anime. simple
Crea un rectángulo para asset de botón. Debe ser: color verde esmeralda con borde en forma de rectángulo. Los colores deben ser planos, y los bordes redondeados. In-Game asset. 2d. High contrast. No shadows. anime. simple
Crea un fondo de textura verde tipo anime. In-Game asset. 2d. High contrast. No shadows. Background. anime