Code edit (3 edits merged)
Please save this source code
User prompt
Slow the pulse down some more. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Slow the pulse down by half and make the scale change more pronounced.
User prompt
Give the vibe core a 4/4 time constant scale oulse. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Update with: var VibeParticle = Container.expand(function(type, index) { var self = Container.call(this); var typeConfig = PARTICLE_TYPES[type]; var assetIndex = Math.floor(Math.random() * 3); var sprite = self.attachAsset(typeConfig.assets[assetIndex], { anchorX: 0.5, anchorY: 0.5 }); // Movement properties for electron-like orbits self.angle = (Math.PI * 2 * index) / typeConfig.count; self.speed = typeConfig.baseSpeed; self.radius = typeConfig.orbitRadius; // Random orbital plane (like electron shells) self.orbitTilt = (Math.random() * Math.PI); // Random tilt self.orbitRotation = Math.random() * Math.PI * 2; // Random rotation self.update = function() { var chaosLevel = Math.min(gameState.contextCollapse / MAX_CONTEXT_COLLAPSE, 1); // Faster angle updates for electron-like movement self.angle += 0.03 * self.speed; // Calculate position on orbital plane var orbitX = Math.cos(self.angle) * self.radius; var orbitY = Math.sin(self.angle) * self.radius; // Apply orbital plane rotation for electron shell effect var x = orbitX * Math.cos(self.orbitTilt) - orbitY * Math.sin(self.orbitTilt); var y = orbitX * Math.sin(self.orbitRotation) + orbitY * Math.cos(self.orbitRotation); // Depth calculation for scaling/alpha var depth = orbitX * Math.sin(self.orbitTilt) + orbitY * Math.cos(self.orbitTilt); var scaleFactor = (depth + self.radius) / (self.radius * 2); // Add slight chaos when context collapse is high if (chaosLevel > 0) { x += (Math.random() - 0.5) * chaosLevel * 15; y += (Math.random() - 0.5) * chaosLevel * 15; } self.x = x; self.y = y; self.scale.set(0.7 + scaleFactor * 0.3); // Less scaling variation self.alpha = 0.6 + scaleFactor * 0.4; // Keep particles more visible // Update pulse effect if active if (self.pulseScale > 1) { self.pulseScale = Math.max(1, self.pulseScale - 0.05); self.scale.set(self.pulseScale * scaleFactor); } }; return self; });
User prompt
Update as needed with: var VibeParticle = Container.expand(function(type, index) { var self = Container.call(this); var typeConfig = PARTICLE_TYPES[type]; // Randomly select particle asset var assetIndex = Math.floor(Math.random() * 3); var sprite = self.attachAsset(typeConfig.assets[assetIndex], { anchorX: 0.5, anchorY: 0.5 }); // Movement properties self.angle = (Math.PI * 2 * index) / typeConfig.count; self.speed = typeConfig.baseSpeed; self.radius = typeConfig.orbitRadius * (0.8 + Math.random() * 0.4); // Random orbital plane for each particle self.orbitTilt = Math.random() * Math.PI * 2; // Random tilt angle self.orbitRotation = Math.random() * Math.PI * 2; // Random rotation of orbit self.update = function() { var chaosLevel = Math.min(gameState.contextCollapse / MAX_CONTEXT_COLLAPSE, 1); // Update angle self.angle += 0.005 * self.speed; // Slowed down movement // Calculate 3D position on tilted orbital plane var orbitX = Math.cos(self.angle) * self.radius; var orbitY = Math.sin(self.angle) * self.radius; // Apply orbital plane rotation var x = orbitX * Math.cos(self.orbitTilt) - orbitY * Math.sin(self.orbitTilt); var y = orbitX * Math.sin(self.orbitRotation) + orbitY * Math.cos(self.orbitRotation); // Scale and alpha based on position relative to "front" var depth = orbitX * Math.sin(self.orbitTilt) + orbitY * Math.cos(self.orbitTilt); var scaleFactor = (depth + self.radius) / (self.radius * 2); var alphaFactor = scaleFactor; // Add subtle chaos if (chaosLevel > 0) { x += (Math.random() - 0.5) * chaosLevel * 10; y += (Math.random() - 0.5) * chaosLevel * 10; } // Apply position and effects self.x = x; self.y = y; self.scale.set(0.6 + scaleFactor * 0.4); // Less extreme scaling self.alpha = 0.4 + alphaFactor * 0.6; // Less extreme alpha // Update pulse effect if active if (self.pulseScale > 1) { self.pulseScale = Math.max(1, self.pulseScale - 0.05); self.scale.set(self.pulseScale * scaleFactor); } }; return self; });
Code edit (2 edits merged)
Please save this source code
User prompt
Update with: var VibeParticle = Container.expand(function(type, index) { var self = Container.call(this); var typeConfig = PARTICLE_TYPES[type]; // Randomly select particle asset var assetIndex = Math.floor(Math.random() * 3); var sprite = self.attachAsset(typeConfig.assets[assetIndex], { anchorX: 0.5, anchorY: 0.5 }); // Movement properties self.angle = (Math.PI * 2 * index) / typeConfig.count; self.speed = typeConfig.baseSpeed; self.radius = typeConfig.orbitRadius * (0.9 + Math.random() * 0.2); // Add vertical angle for 3D effect self.verticalAngle = Math.random() * Math.PI * 2; self.verticalSpeed = 0.015; // Slow vertical orbit self.update = function() { var chaosLevel = Math.min(gameState.contextCollapse / MAX_CONTEXT_COLLAPSE, 1); // Update angles self.angle += 0.01 * self.speed; self.verticalAngle += self.verticalSpeed; // Calculate position with vertical offset for 3D effect var x = Math.cos(self.angle) * self.radius; var verticalOffset = Math.sin(self.verticalAngle) * self.radius * 0.5; var y = Math.sin(self.angle) * self.radius + verticalOffset; // Scale and alpha based on vertical position (behind/in front of core) var scaleFactor = (Math.sin(self.verticalAngle) + 2) / 3; // Range: 0.33 to 1 var alphaFactor = (Math.sin(self.verticalAngle) + 2) / 3; // Range: 0.33 to 1 // Add subtle chaos if (chaosLevel > 0) { x += (Math.random() - 0.5) * chaosLevel * 10; y += (Math.random() - 0.5) * chaosLevel * 10; } // Apply position and effects self.x = x; self.y = y; self.scale.set(scaleFactor); self.alpha = alphaFactor; // Update pulse effect if active if (self.pulseScale > 1) { self.pulseScale = Math.max(1, self.pulseScale - 0.05); self.scale.set(self.pulseScale * scaleFactor); } }; // Keep existing pulse function return self; });
User prompt
Update only as needed with: function playCard(card) { if (currentHand.indexOf(card) === -1) { return; } // ... existing card validation code ... // Add particle group for card type if it doesn't exist var cardType = card.type.toUpperCase(); if (!gameState.particleGroups[cardType]) { var group = new ParticleGroup(cardType); gameState.particleGroups[cardType] = group; gameState.particleContainer.addChild(group); // Fade in new particles group.alpha = 0; tween(group, { alpha: 1 }, { duration: 500 }); } else { // Pulse existing particles of this type gameState.particleGroups[cardType].pulse(); } // ... rest of existing playCard code ... // After card is absorbed into core tween(card, { x: gameState.stackArea.x, y: gameState.stackArea.y, scaleX: 0.2, scaleY: 0.2, alpha: 0 }, { duration: 300, onFinish: function onFinish() { pulseVibeCore(); gameState.cardStack.push(card); checkForBugs(card.bugChance); updateStatsDisplay(); positionCardsInHand(); if (currentHand.length < HAND_SIZE) { drawHand(); } checkGameState(); } }); } ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Update as needed with: var VibeParticle = Container.expand(function(type, index) { // ... existing initialization code ... self.update = function() { var chaosLevel = Math.min(gameState.contextCollapse / MAX_CONTEXT_COLLAPSE, 1); // Slow down time-based movement significantly var time = Date.now() * 0.0002; // Reduced from 0.001 var x, y; switch(type) { case 'BASIC': // Much slower orbital movement var orbitSpeed = 0.02; // Reduced from 0.2 self.angle += orbitSpeed * self.speed; x = Math.cos(self.angle) * self.radius; y = Math.sin(self.angle) * self.radius; // Gentler oscillation y += Math.sin(time + self.phase) * 10; // Reduced amplitude break; // ... other cases with similar 10x reductions in speed ... } // Reduce chaos movement if (chaosLevel > 0) { x += (Math.random() - 0.5) * chaosLevel * 20; // Reduced from 40 y += (Math.random() - 0.5) * chaosLevel * 20; } self.x = x; self.y = y; // Slower rotation self.rotation = Math.sin(time + self.phase) * 0.1; // Reduced from 0.2 }; return self; });
User prompt
Update as needed with: const PARTICLE_TYPES = { BASIC: { assets: ['basicparticle1', 'basicparticle2', 'basicparticle3'], color: 0x00FFFF, baseSpeed: 0.2, // Reduced from 0.5 orbitRadius: 200, count: 30 }, UI: { assets: ['uiparticle1', 'uiparticle2', 'uiparticle3'], color: 0x4A86E8, baseSpeed: 0.3, // Reduced from 0.7 orbitRadius: 250, count: 25 }, DATABASE: { assets: ['databaseparticle1', 'databaseparticle2', 'databaseparticle3'], color: 0x9C27B0, baseSpeed: 0.25, // Reduced from 0.6 orbitRadius: 230, count: 25 }, API: { assets: ['apiparticle1', 'apiparticle2', 'apiparticle3'], color: 0x4CAF50, baseSpeed: 0.3, // Reduced from 0.8 orbitRadius: 220, count: 20 }, SECURITY: { assets: ['securityparticle1', 'securityparticle2', 'securityparticle3'], color: 0xFF5252, baseSpeed: 0.2, // Reduced from 0.4 orbitRadius: 210, count: 20 } };
User prompt
Update as needed with: var VibeParticle = Container.expand(function(type, index) { var self = Container.call(this); var typeConfig = PARTICLE_TYPES[type]; // Randomly select particle asset var assetIndex = Math.floor(Math.random() * 3); var sprite = self.attachAsset(typeConfig.assets[assetIndex], { anchorX: 0.5, anchorY: 0.5 }); // Base movement properties self.angle = (Math.PI * 2 * index) / typeConfig.count; self.speed = typeConfig.baseSpeed * (0.8 + Math.random() * 0.4); self.radius = typeConfig.orbitRadius * (0.9 + Math.random() * 0.2); self.verticalOffset = Math.random() * 40 - 20; // Additional movement properties self.phase = Math.random() * Math.PI * 2; // For oscillation self.timeOffset = Math.random() * 1000; // For varied timing self.update = function() { var chaosLevel = Math.min(gameState.contextCollapse / MAX_CONTEXT_COLLAPSE, 1); var time = Date.now() * 0.001; // Current time in seconds var x, y; switch(type) { case 'BASIC': // Gentle, slow orbital rings with slight oscillation var orbitSpeed = 0.2; self.angle += orbitSpeed * self.speed; x = Math.cos(self.angle) * self.radius; y = Math.sin(self.angle) * self.radius; // Add gentle vertical oscillation y += Math.sin(time + self.phase) * 20; break; case 'UI': // Slide in smooth arc paths, occasionally forming grids var gridPhase = Math.floor((time + self.timeOffset) % 10); if (gridPhase < 5) { // Arc movement x = Math.cos(self.angle) * self.radius; y = Math.sin(self.angle * 2) * (self.radius * 0.5); } else { // Grid alignment var gridX = Math.floor(index % 5) - 2; var gridY = Math.floor(index / 5) - 2; x = gridX * 50; y = gridY * 50; } break; case 'DATABASE': // Flow in stream-like patterns var flowSpeed = time * 0.5 + self.phase; x = Math.cos(flowSpeed) * self.radius * 0.8; y = Math.sin(flowSpeed * 2) * self.radius * 0.4; // Add data-stream effect y += (index % 3) * 30 * Math.sin(time + self.phase); break; case 'API': // Extend tendrils that reach outward then retract var tendrilPhase = (Math.sin(time + self.phase) + 1) * 0.5; var baseRadius = self.radius * 0.5; var extendedRadius = self.radius * (1 + tendrilPhase); x = Math.cos(self.angle) * extendedRadius; y = Math.sin(self.angle) * extendedRadius; break; case 'SECURITY': // Form temporary protective layers var shieldPhase = time + self.phase; var shieldRadius = self.radius * (0.8 + Math.sin(shieldPhase) * 0.2); var shieldAngle = self.angle + Math.sin(shieldPhase * 0.5) * 0.5; x = Math.cos(shieldAngle) * shieldRadius; y = Math.sin(shieldAngle) * shieldRadius; break; } // Add chaos movement if (chaosLevel > 0) { x += (Math.random() - 0.5) * chaosLevel * 40; y += (Math.random() - 0.5) * chaosLevel * 40; } // Apply final position self.x = x; self.y = y; // Slow rotation of the particle itself self.rotation = Math.sin(time + self.phase) * 0.2; // Update pulse effect if (self.pulseScale > 1) { self.pulseScale = Math.max(1, self.pulseScale - 0.05); self.scale.set(self.pulseScale); } }; // Rest of the code remains the same... return self; });
User prompt
Update as needed with: game.update = function() { // Existing update code... // Update particles if (gameState.particleContainer) { Object.values(gameState.particleGroups).forEach(function(group) { group.update(); }); } };
User prompt
Update as needed with: // Update the vibeCore creation in createUI(): var vibeCore = LK.getAsset('vibecore', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2 - 200 }); // Add particle groups container var particleContainer = new Container(); particleContainer.x = vibeCore.x; particleContainer.y = vibeCore.y; vibeContainer.addChild(particleContainer); // Store references gameState.vibeCore = vibeCore; gameState.particleContainer = particleContainer; gameState.particleGroups = {}; // Add initial basic particles gameState.particleGroups.BASIC = new ParticleGroup('BASIC'); particleContainer.addChild(gameState.particleGroups.BASIC);
Code edit (1 edits merged)
Please save this source code
User prompt
Update as needed with: function playCard(card) { if (currentHand.indexOf(card) === -1) { return; } if (gameState.cardsPlayed >= gameState.maxCardsPerDay) { card.targetX = card.originalX; card.targetY = card.originalY; return; } // Check if player has enough vibe points var vibeCost = Math.max(0, -card.vibePoints + gameState.thresholdEffects.vibeCostModifier); if (gameState.vibePoints < vibeCost) { card.targetX = card.originalX; card.targetY = card.originalY; return; } // Apply all game state changes gameState.vibePoints += card.vibePoints; gameState.vibePoints -= vibeCost; gameState.codeLines += card.codeLines; gameState.contextCollapse += card.contextImpact * gameState.thresholdEffects.contextMultiplier; gameState.contextCollapse = Math.max(0, Math.min(gameState.contextCollapse, MAX_CONTEXT_COLLAPSE)); updateContextThresholdEffects(); if (card.feature) { gameState.features[card.feature] = true; } LK.getSound('cardPlace').play(); // Remove from hand var index = currentHand.indexOf(card); if (index > -1) { currentHand.splice(index, 1); discardPile.push({ type: card.type, promptText: card.promptText, codeLines: card.codeLines, vibePoints: card.vibePoints, contextImpact: card.contextImpact, bugChance: card.bugChance, feature: card.feature }); } gameState.cardsPlayed++; // Animate card being absorbed into core tween(card, { x: gameState.stackArea.x, y: gameState.stackArea.y, scaleX: 0.2, scaleY: 0.2, alpha: 0 }, { duration: 300, onFinish: function() { pulseVibeCore(); gameState.cardStack.push(card); checkForBugs(card.bugChance); updateStatsDisplay(); positionCardsInHand(); if (currentHand.length < HAND_SIZE) { drawHand(); } checkGameState(); } }); } ↪💡 Consider importing and using the following plugins: @upit/tween.v1
Code edit (1 edits merged)
Please save this source code
User prompt
Update as needed with: // When creating the core in createUI, store the reference: var vibeCore = LK.getAsset('vibecore', { anchorX: 0.5, anchorY: 0.5, x: 2048/2, y: 2732/2 - 200 }); gameState.vibeCore = vibeCore; // Store reference vibeContainer.addChild(vibeCore);
User prompt
Update as needed with: function playCard(card) { // Early returns stay the same if (currentHand.indexOf(card) === -1) { return; } if (gameState.cardsPlayed >= gameState.maxCardsPerDay) { card.targetX = card.originalX; card.targetY = card.originalY; return; } // All the game state changes stay the same // [existing code for points, lines, etc.] // Find the vibecore var vibeCore = gameState.vibeContainer.children.find(child => child.assetId === 'vibecore'); // Animate card "sinking" into core and core pulsing tween(card, { x: gameState.stackArea.x, y: gameState.stackArea.y, scaleX: 0.2, scaleY: 0.2, alpha: 0 }, { duration: 300, onFinish: function() { if (vibeCore) { tween(vibeCore.scale, { x: 1.2, y: 1.2 }, { duration: 150, onFinish: function() { tween(vibeCore.scale, { x: 1, y: 1 }, { duration: 150 }); } }); } // Rest of the finish handler stays the same gameState.cardStack.push(card); checkForBugs(card.bugChance); updateStatsDisplay(); positionCardsInHand(); if (currentHand.length < HAND_SIZE) { drawHand(); } checkGameState(); } }); } ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Change card text to white.
User prompt
Update as needed with: // In the Card class, modify the card background creation: var Card = Container.expand(function(type, promptText, codeLines, vibePoints, contextImpact, bugChance) { var self = Container.call(this); // ... existing properties ... // Replace the card background creation with: var cardAsset; switch(type.toLowerCase()) { case 'ui': cardAsset = 'uicard'; break; case 'database': cardAsset = 'databasecard'; break; case 'api': cardAsset = 'apicard'; break; case 'security': cardAsset = 'securitycard'; break; case 'refactor': case 'coffee': case 'debug': cardAsset = 'specialcard'; break; default: cardAsset = 'basiccard'; } var cardBg = self.attachAsset(cardAsset, { anchorX: 0.5, anchorY: 0.5 }); // ... rest of Card class code ... });
User prompt
Update as needed with: function createStackArea() { // Modify these parts: // When creating console window var codeConsole = new Container(); codeConsole.alpha = 0; // Set to 0 to hide it // When creating stack background var stackBg = LK.getAsset('card', { anchorX: 0.5, anchorY: 0.5, width: 450, height: 550, color: 0x1a1f26, alpha: 0 // Set to 0 to hide it }); // When creating stack label and borders stackLabel.alpha = 0; topBorder.alpha = 0; bottomBorder.alpha = 0; // In the side borders loop: leftBorder.alpha = 0; rightBorder.alpha = 0; // When creating vibe display var vibeDisplay = new Container(); vibeDisplay.alpha = 0; // Set to 0 to hide it }
User prompt
Please fix the bug: 'TypeError: undefined is not an object (evaluating 'child.text.startsWith')' in or related to this line: 'return child instanceof Text2 && child.text.startsWith("DAY");' Line Number: 1528
User prompt
Update as needed with: function updateStatsDisplay() { // [Keep all existing update code] // Update vibe day indicator if it exists if (gameState.vibeContainer) { // Find the day indicator in the vibe container's children var vibeDayIndicator = gameState.vibeContainer.children.find(child => child instanceof Text2 && child.text.startsWith("DAY")); if (vibeDayIndicator) { vibeDayIndicator.setText("DAY " + gameState.day); } } }
User prompt
Update as needed with: function createUI() { // [Keep all existing UI creation code here unchanged] // Add vibe layer after all existing UI is created // Create a top-level vibe container that sits above everything else var vibeContainer = new Container(); game.addChild(vibeContainer); // This puts it on top of existing UI // Add vibe background var vibeBackground = LK.getAsset('vibebackground', { anchorX: 0.5, anchorY: 0.5, x: 2048/2, y: 2732/2 }); vibeContainer.addChild(vibeBackground); // Add vibe core in center var vibeCore = LK.getAsset('vibecore', { anchorX: 0.5, anchorY: 0.5, x: 2048/2, y: 2732/2 - 200 // Slightly above center }); vibeContainer.addChild(vibeCore); // Stylized day counter (we can make this more vibe-appropriate later) var vibeDayIndicator = new Text2("DAY " + gameState.day, { size: 75, fill: 0x00ffff // Cyan color for vibe aesthetic }); vibeDayIndicator.anchor.set(0.5, 0.5); vibeDayIndicator.x = 1848; vibeDayIndicator.y = 200; vibeContainer.addChild(vibeDayIndicator); // Stylized end day button var vibeEndDayButton = new MenuButton("END DAY", endDay); vibeEndDayButton.x = 1848; vibeEndDayButton.y = 400; vibeEndDayButton.scale.set(1.2); // Make it slightly larger vibeContainer.addChild(vibeEndDayButton); // Store the container reference in gameState gameState.vibeContainer = vibeContainer; }
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1"); /**** * Classes ****/ var Bug = Container.expand(function () { var self = Container.call(this); var bugGraphic = self.attachAsset('bug', { anchorX: 0.5, anchorY: 0.5 }); self.codeLinesCost = Math.floor(Math.random() * 10) + 5; self.vibePointsCost = Math.floor(Math.random() * 3) + 1; var costText = new Text2("-" + self.codeLinesCost + " lines\n-" + self.vibePointsCost + " VP", { size: 50, fill: 0xFFFFFF }); costText.anchor.set(0.5, 0.5); self.addChild(costText); self.down = function (x, y, obj) { if (gameState.vibePoints >= self.vibePointsCost) { startBugFix(this); } }; return self; }); var SyntaxBug = Bug.expand(function () { var self = Bug.call(this); self.type = 'syntax'; // Add jagged red visual self.color = 0xFF0000; self.effect = function () { gameState.codeLines *= 0.9; // Reduce code generation }; return self; }); var LogicBug = Bug.expand(function () { var self = Bug.call(this); self.type = 'logic'; // Add methodical blue visual self.color = 0x4A86E8; self.effect = function () { gameState.vibePoints = Math.floor(gameState.vibePoints * 0.5); // Halve vibe points }; return self; }); var Card = Container.expand(function (type, promptText, codeLines, vibePoints, contextImpact, bugChance) { var self = Container.call(this); self.type = type || 'basic'; self.promptText = promptText || "Just a vibe, you know?"; self.codeLines = codeLines || 10; self.vibePoints = vibePoints || 1; self.contextImpact = contextImpact || 5; self.bugChance = bugChance || 0.2; // Card state tracking self.isDragging = false; self.isScaled = false; // Add preview mode properties self.previewMode = false; self.holdTimer = null; self.holdDuration = 300; // .5 seconds self.previewScale = 2.5; // Replace the card background creation with: var cardAsset; switch (type.toLowerCase()) { case 'ui': cardAsset = 'uicard'; break; case 'database': cardAsset = 'databasecard'; break; case 'api': cardAsset = 'apicard'; break; case 'security': cardAsset = 'securitycard'; break; case 'refactor': case 'coffee': case 'debug': cardAsset = 'specialcard'; break; default: cardAsset = 'basiccard'; } var cardBg = self.attachAsset(cardAsset, { anchorX: 0.5, anchorY: 0.5 }); // Card text self.titleText = new Text2(self.type.toUpperCase(), { size: 55, fill: 0xFFFFFF // Changed to white }); self.titleText.anchor.set(0.5, 0); self.titleText.x = 0; self.titleText.y = -220; self.addChild(self.titleText); self.promptTextObj = new Text2(self.promptText, { size: 45, fill: 0xFFFFFF // Changed to white }); self.promptTextObj.anchor.set(0.5, 0); self.promptTextObj.x = 0; self.promptTextObj.y = -160; self.promptTextObj.width = 350; self.addChild(self.promptTextObj); // Card stats var statsText = "Code Lines: " + self.codeLines + "\n" + "Vibe Points: " + self.vibePoints + "\n" + "Context Impact: " + self.contextImpact + "\n" + "Bug Chance: " + Math.round(self.bugChance * 100) + "%"; self.statsTextObj = new Text2(statsText, { size: 45, fill: 0xFFFFFF // Changed to white }); self.statsTextObj.anchor.set(0.5, 0); self.statsTextObj.x = 0; self.statsTextObj.y = 50; self.addChild(self.statsTextObj); // Individual card touch handlers are removed as they are handled globally by game.down, game.move, game.up self.update = function () { // Only move towards target position if NOT in preview mode if (!self.previewMode && !self.isDragging) { // Smoothly move toward target position (if this was in the original update) self.x = self.x + (self.targetX - self.x) * 0.2; self.y = self.y + (self.targetY - self.y) * 0.2; } }; return self; }); var CodeGenerator = Container.expand(function () { var self = Container.call(this); // Store lines of pseudo code that have been typed self.displayedText = ""; // Queue of code lines to generate self.codeQueue = []; // Reference to the text display element self.textDisplay = null; // Reference to cursor element self.cursor = null; // Character typing delay - reduced for faster animation self.charDelay = 20; // Current typing timer self.typingTimer = null; // Current line being typed self.currentLine = ""; // Current position in line self.currentPos = 0; // Set text display reference self.setTextDisplay = function (textElement, cursorElement) { self.textDisplay = textElement; self.cursor = cursorElement; }; // Add a line of code to generate self.addCodeLine = function (lineText) { self.codeQueue.push(lineText); if (!self.typingTimer) { self.typeNextLine(); } }; // Generate multiple lines based on card type and code lines self.generateCodeFromCard = function (card) { // Clear any existing text self.displayedText = ""; self.updateDisplay(); // Add initial comment line self.addCodeLine("// " + card.type.toUpperCase() + " IMPLEMENTATION"); // Generate pseudo code based on card type and lines if (card.type === "UI") { self.addCodeLine("function renderUI() {"); self.addCodeLine(" const elements = createElements();"); self.addCodeLine(" applyStyles(elements);"); self.addCodeLine(" return elements;"); self.addCodeLine("}"); } else if (card.type === "Database") { self.addCodeLine("class DatabaseManager {"); self.addCodeLine(" constructor() {"); self.addCodeLine(" this.connection = initDB();"); self.addCodeLine(" }"); self.addCodeLine(" query(sql) { /* ... */ }"); self.addCodeLine("}"); } else if (card.type === "API") { self.addCodeLine("async function fetchData() {"); self.addCodeLine(" const response = await fetch('/api');"); self.addCodeLine(" return response.json();"); self.addCodeLine("}"); } else if (card.type === "Security") { self.addCodeLine("function authenticate(user) {"); self.addCodeLine(" const token = generateToken(user);"); self.addCodeLine(" return validateAccess(token);"); self.addCodeLine("}"); } else if (card.type === "refactor") { self.addCodeLine("// Cleaning up code structure"); self.addCodeLine("function refactorModule() {"); self.addCodeLine(" removeDuplication();"); self.addCodeLine(" improveNaming();"); self.addCodeLine("}"); } else if (card.type === "debug") { self.addCodeLine("// Bug fixing process"); self.addCodeLine("console.log('Finding issues...');"); self.addCodeLine("debugger;"); self.addCodeLine("fixBugs();"); } else { // Generic code for other card types self.addCodeLine("function implement" + card.type + "() {"); self.addCodeLine(" // TODO: Implementation"); self.addCodeLine(" return success;"); self.addCodeLine("}"); } }; // Start typing the next line in the queue self.typeNextLine = function () { if (self.codeQueue.length === 0) { self.typingTimer = null; return; } self.currentLine = self.codeQueue.shift(); self.currentPos = 0; self.typeNextChar(); }; // Type the next character in the current line self.typeNextChar = function () { if (self.currentPos < self.currentLine.length) { // Add next character self.displayedText += self.currentLine.charAt(self.currentPos); self.currentPos++; self.updateDisplay(); // Schedule next character self.typingTimer = LK.setTimeout(self.typeNextChar, self.charDelay); } else { // Line complete, add newline self.displayedText += "\n"; self.updateDisplay(); // Schedule next line - reduced delay multiplier self.typingTimer = LK.setTimeout(self.typeNextLine, self.charDelay * 2); } }; // Update the displayed text self.updateDisplay = function () { if (self.textDisplay) { self.textDisplay.setText(self.displayedText); // Position cursor at end of text if (self.cursor) { var textWidth = self.displayedText.split("\n").pop().length * 15; var lines = self.displayedText.split("\n").length - 1; self.cursor.x = self.textDisplay.x + textWidth - 41; // Move cursor left by 2% of screen width (2048 * 0.02) self.cursor.y = self.textDisplay.y + lines * 30; } } }; return self; }); var DayIndicator = Container.expand(function () { var self = Container.call(this); var circle = self.attachAsset('dayIndicator', { anchorX: 0.5, anchorY: 0.5 }); self.dayText = new Text2("DAY\n1", { size: 65, fill: 0xFFFFFF }); self.dayText.anchor.set(0.5, 0.5); self.addChild(self.dayText); self.updateDay = function (day) { self.dayText.setText("DAY\n" + day); // Pulse animation tween(self, { scaleX: 1.2, scaleY: 1.2 }, { duration: 300, onFinish: function onFinish() { tween(self, { scaleX: 1, scaleY: 1 }, { duration: 300 }); } }); }; return self; }); var MenuButton = Container.expand(function (text, callback) { var self = Container.call(this); var buttonBg = self.attachAsset('menuButton', { anchorX: 0.5, anchorY: 0.5 }); var buttonText = new Text2(text, { size: 55, fill: 0xFFFFFF }); buttonText.anchor.set(0.5, 0.5); self.addChild(buttonText); self.down = function (x, y, obj) { tween(self, { scaleX: 0.95, scaleY: 0.95 }, { duration: 100 }); }; self.up = function (x, y, obj) { tween(self, { scaleX: 1, scaleY: 1 }, { duration: 100, onFinish: function onFinish() { if (callback) { callback(); } } }); }; return self; }); var ParticleGroup = Container.expand(function (type) { var self = Container.call(this); var config = PARTICLE_TYPES[type]; // Create particles self.particles = []; for (var i = 0; i < config.count; i++) { var particle = new VibeParticle(type, i); self.addChild(particle); self.particles.push(particle); } self.update = function () { self.particles.forEach(function (particle) { particle.update(); }); }; self.pulse = function () { self.particles.forEach(function (particle) { particle.pulse(); }); }; return self; }); var VibeParticle = Container.expand(function (type, index) { var self = Container.call(this); var typeConfig = PARTICLE_TYPES[type]; // Randomly select particle asset var assetIndex = Math.floor(Math.random() * 3); var sprite = self.attachAsset(typeConfig.assets[assetIndex], { anchorX: 0.5, anchorY: 0.5 }); // Base movement properties self.angle = Math.PI * 2 * index / typeConfig.count; self.speed = typeConfig.baseSpeed * (0.8 + Math.random() * 0.4); self.radius = typeConfig.orbitRadius * (0.9 + Math.random() * 0.2); self.verticalOffset = Math.random() * 40 - 20; // Additional movement properties self.phase = Math.random() * Math.PI * 2; // For oscillation self.timeOffset = Math.random() * 1000; // For varied timing // Visual state self.pulseScale = 1; self.update = function () { var chaosLevel = Math.min(gameState.contextCollapse / MAX_CONTEXT_COLLAPSE, 1); var time = Date.now() * 0.001; // Current time in seconds var x, y; switch (type) { case 'BASIC': // Gentle, slow orbital rings with slight oscillation var orbitSpeed = 0.2; self.angle += orbitSpeed * self.speed * (1 + chaosLevel * Math.random() * 0.5); // Add chaos to speed x = Math.cos(self.angle) * self.radius; y = Math.sin(self.angle) * self.radius; // Add gentle vertical oscillation y += Math.sin(time + self.phase) * 20; break; case 'UI': // Slide in smooth arc paths, occasionally forming grids var gridPhase = Math.floor((time + self.timeOffset) % 10); if (gridPhase < 5 - chaosLevel * 2) { // More chaos = less grid time // Arc movement self.angle += self.speed * 0.3 * (1 + chaosLevel * Math.random()); // Add chaos to speed x = Math.cos(self.angle) * self.radius; y = Math.sin(self.angle * 2 + self.phase) * (self.radius * 0.5); // Add phase } else { // Grid alignment (less stable with chaos) var gridX = Math.floor(index % 5) - 2; var gridY = Math.floor(index / 5) - 2; var targetX = gridX * 50; var targetY = gridY * 50; x = targetX + (Math.random() - 0.5) * chaosLevel * 30; // Jitter grid y = targetY + (Math.random() - 0.5) * chaosLevel * 30; } break; case 'DATABASE': // Flow in stream-like patterns var flowSpeed = time * 0.5 * (1 + chaosLevel * 0.5) + self.phase; // Chaos affects flow speed x = Math.cos(flowSpeed) * self.radius * 0.8; y = Math.sin(flowSpeed * 2) * self.radius * 0.4; // Add data-stream effect (more erratic with chaos) y += index % 3 * 30 * Math.sin(time * (1 + chaosLevel) + self.phase); break; case 'API': // Extend tendrils that reach outward then retract var tendrilPhase = (Math.sin(time * (1 + chaosLevel * 0.3) + self.phase) + 1) * 0.5; // Chaos affects speed var baseRadius = self.radius * 0.5; var extendedRadius = baseRadius + self.radius * 0.8 * tendrilPhase; // Adjusted extension range x = Math.cos(self.angle) * extendedRadius; y = Math.sin(self.angle) * extendedRadius; break; case 'SECURITY': // Form temporary protective layers, more jittery with chaos var shieldPhase = time * (1 + chaosLevel * 0.2) + self.phase; // Chaos affects pulse speed var shieldRadius = self.radius * (0.8 + Math.sin(shieldPhase) * 0.2); var shieldAngle = self.angle + Math.sin(shieldPhase * 0.5) * (0.5 + chaosLevel * 0.3); // More angle wobble with chaos x = Math.cos(shieldAngle) * shieldRadius; y = Math.sin(shieldAngle) * shieldRadius; break; default: // Default to basic movement if type is unknown self.angle += self.speed * 0.5 * (1 + chaosLevel * Math.random()); x = Math.cos(self.angle) * self.radius; y = Math.sin(self.angle) * self.radius; break; } // Add chaos movement (overall jitter) if (chaosLevel > 0) { x += (Math.random() - 0.5) * chaosLevel * 30; // Reduced intensity slightly y += (Math.random() - 0.5) * chaosLevel * 30; } // Apply final position self.x = x; self.y = y; // Slow rotation of the particle itself self.rotation = Math.sin(time + self.phase) * 0.2; // Update pulse effect if (self.pulseScale > 1) { self.pulseScale = Math.max(1, self.pulseScale - 0.05); self.scale.set(self.pulseScale); } }; self.pulse = function () { self.pulseScale = 1.5; // Keep pulse effect simple // Pulse tween is handled by ParticleGroup now, so just set the target scale }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x1e2329 }); /**** * Game Code ****/ // Game constants var MAX_DAYS = 10; var TARGET_CODE_LINES = 800; var MAX_CONTEXT_COLLAPSE = 100; var HAND_SIZE = 5; var MAX_BUGS = 10; // Particle system constants var PARTICLE_TYPES = { BASIC: { assets: ['basicparticle1', 'basicparticle2', 'basicparticle3'], color: 0x00FFFF, // Teal baseSpeed: 0.5, orbitRadius: 200, count: 30 }, UI: { assets: ['uiparticle1', 'uiparticle2', 'uiparticle3'], color: 0x4A86E8, // Blue baseSpeed: 0.7, orbitRadius: 250, count: 25 }, DATABASE: { assets: ['databaseparticle1', 'databaseparticle2', 'databaseparticle3'], color: 0x9C27B0, // Purple baseSpeed: 0.6, orbitRadius: 230, count: 25 }, API: { assets: ['apiparticle1', 'apiparticle2', 'apiparticle3'], color: 0x4CAF50, // Green baseSpeed: 0.8, orbitRadius: 220, count: 20 }, SECURITY: { assets: ['securityparticle1', 'securityparticle2', 'securityparticle3'], color: 0xFF5252, // Red baseSpeed: 0.4, orbitRadius: 210, count: 20 } }; // Game state variables var gameState = { day: 1, codeLines: 0, vibePoints: 5, contextCollapse: 0, cardsPlayed: 0, maxCardsPerDay: 3, bugs: 0, phase: 'menu', // 'menu', 'playing', 'dayEnd', 'gameOver' canPlayCard: true, features: { ui: false, database: false, api: false, security: false }, thresholdEffects: { bugChanceModifier: 0, maxCardsModifier: 0, contextMultiplier: 1, vibeCostModifier: 0 } }; // Card position constants var projectAreaY = 2732 * 0.7; // Moved down 10% from 0.6 var handY = 2732 - 400; var deckX = 200; var deckY = handY; // Card templates var cardTemplates = [ // Basic cards { type: 'basic', promptText: "Make it work like that app, you know the one", codeLines: 15, vibePoints: 1, contextImpact: 5, bugChance: 0.2 }, { type: 'basic', promptText: "Just spaghetti code it for now", codeLines: 25, vibePoints: 1, contextImpact: 15, bugChance: 0.4 }, { type: 'basic', promptText: "It should be like... clean and efficient", codeLines: 12, vibePoints: 2, contextImpact: 3, bugChance: 0.1 }, { type: 'basic', promptText: "Use that coding pattern with the factory thing", codeLines: 20, vibePoints: 2, contextImpact: 8, bugChance: 0.2 }, // UI cards { type: 'UI', promptText: "Make it look like Apple but not too much", codeLines: 30, vibePoints: 3, contextImpact: 10, bugChance: 0.2, feature: 'ui' }, { type: 'UI', promptText: "I want that Material Design vibe but more flat", codeLines: 35, vibePoints: 3, contextImpact: 12, bugChance: 0.3, feature: 'ui' }, // Database cards { type: 'Database', promptText: "Store stuff efficiently, you know?", codeLines: 40, vibePoints: 4, contextImpact: 15, bugChance: 0.3, feature: 'database' }, { type: 'Database', promptText: "Like SQL but without actual SQL", codeLines: 45, vibePoints: 4, contextImpact: 20, bugChance: 0.4, feature: 'database' }, // API cards { type: 'API', promptText: "Make endpoints that just work", codeLines: 35, vibePoints: 3, contextImpact: 12, bugChance: 0.25, feature: 'api' }, { type: 'API', promptText: "RESTful but also GraphQL-ish", codeLines: 40, vibePoints: 4, contextImpact: 15, bugChance: 0.3, feature: 'api' }, // Security cards { type: 'Security', promptText: "Make it unhackable please", codeLines: 25, vibePoints: 3, contextImpact: 10, bugChance: 0.2, feature: 'security' }, { type: 'Security', promptText: "Do that OAuth thing everyone uses", codeLines: 30, vibePoints: 3, contextImpact: 12, bugChance: 0.25, feature: 'security' }, // Special cards { type: 'refactor', promptText: "Clean up that spaghetti code, please", codeLines: 5, vibePoints: 2, contextImpact: -20, bugChance: 0.1 }, { type: 'coffee', promptText: "Need caffeine to think straight", codeLines: 0, vibePoints: 3, contextImpact: 0, bugChance: 0 }, { type: 'debug', promptText: "Find and squash all those little bugs", codeLines: -10, vibePoints: 3, contextImpact: -5, bugChance: -0.5 }]; // Current hand and deck of cards var currentHand = []; var cardDeck = []; var discardPile = []; var bugContainer; // UI Elements var statsText; var contextBar; var progressBar; var dayIndicator; var endDayButton; var deckVisual; var codebaseContainer = null; var featuresText; // Declare globally // Initialize the game function initializeGame() { gameState = { day: 1, codeLines: 0, vibePoints: 5, contextCollapse: 0, bugs: 0, cardsPlayed: 0, maxCardsPerDay: 3, phase: 'playing', canPlayCard: true, features: { ui: false, database: false, api: false, security: false }, thresholdEffects: { // Initialize here as well bugChanceModifier: 0, maxCardsModifier: 0, contextMultiplier: 1, vibeCostModifier: 0 }, cardStack: [] // Initialize empty card stack }; // Make sure effects are initialized properly updateContextThresholdEffects(); // Clear existing elements while (game.children.length > 0) { game.removeChild(game.children[0]); } // Reset card collections currentHand = []; cardDeck = []; discardPile = []; // Create background var background = LK.getAsset('background', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2 }); game.addChild(background); // Create UI elements createUI(); // Create the stack area var stackArea = createStackArea(); // Store reference to the stack area for hit testing gameState.stackArea = stackArea; // Create bug container bugContainer = new Container(); bugContainer.x = 2048 / 2; bugContainer.y = 500; game.addChild(bugContainer); // Initialize deck initializeDeck(); // Draw initial hand drawHand(); // Update stats display updateStatsDisplay(); // Play background music LK.playMusic('gameMusic'); } // New function to check and apply threshold effects function updateContextThresholdEffects() { // Reset modifiers gameState.thresholdEffects = { bugChanceModifier: 0, maxCardsModifier: 0, contextMultiplier: 1, vibeCostModifier: 0 }; var collapseRatio = gameState.contextCollapse / MAX_CONTEXT_COLLAPSE; // Apply effects based on thresholds (cumulative) if (collapseRatio >= 0.25) { gameState.thresholdEffects.bugChanceModifier += 0.1; } if (collapseRatio >= 0.5) { gameState.thresholdEffects.maxCardsModifier -= 1; } if (collapseRatio >= 0.75) { gameState.thresholdEffects.contextMultiplier = 2; } if (collapseRatio >= 0.9) { gameState.thresholdEffects.vibeCostModifier += 1; } } function showBugDetection() { // Create glitchy text effect var alertText = new Text2("BUG DETECTED!", { size: 120, fill: 0xFF0000 }); alertText.anchor.set(0.5, 0.5); alertText.x = 2048 / 2; alertText.y = 2732 / 2; game.addChild(alertText); // Add screen shake var originalX = game.x; var originalY = game.y; var shakeIntensity = 20; var shakeDuration = 500; var startTime = Date.now(); var shakeInterval = null; function updateShake() { var elapsed = Date.now() - startTime; if (elapsed < shakeDuration) { game.x = originalX + (Math.random() * 2 - 1) * shakeIntensity; game.y = originalY + (Math.random() * 2 - 1) * shakeIntensity; } else { if (shakeInterval) { LK.clearInterval(shakeInterval); shakeInterval = null; } game.x = originalX; game.y = originalY; if (alertText.parent) { // Check if alertText is still attached before removing game.removeChild(alertText); } } } // Play alarm sound LK.getSound('bugAlert').play(); // Start the shake interval shakeInterval = LK.setInterval(updateShake, 16); // Call roughly 60 times per second // Ensure the shake stops even if interval timing is slightly off LK.setTimeout(function () { if (shakeInterval) { LK.clearInterval(shakeInterval); shakeInterval = null; } game.x = originalX; game.y = originalY; if (alertText.parent) { game.removeChild(alertText); } }, shakeDuration + 50); // Add a small buffer } function createUI() { // Stats display statsText = new Text2("Code Lines: 0 / " + TARGET_CODE_LINES + "\nVibe Points: 5\nBugs: 0/" + MAX_BUGS, { size: 55, fill: 0xFFFFFF }); statsText.anchor.set(0, 0); statsText.x = 150; statsText.y = 150; game.addChild(statsText); // Project title var projectTitle = new Text2("PROJECT: VIBE CODER", { size: 75, fill: 0xFFFFFF }); projectTitle.anchor.set(0.5, 0); projectTitle.x = 2048 / 2; projectTitle.y = 50; game.addChild(projectTitle); // Context collapse bar background var contextBarBg = LK.getAsset('progressBarBg', { anchorX: 0, anchorY: 0.5, x: 224, y: 660, // Moved up by 50 pixels (from 710 to 660) height: 80 // Doubled height from 40 to 80 }); game.addChild(contextBarBg); // Context collapse bar contextBar = LK.getAsset('progressBar', { anchorX: 0, anchorY: 0.5, x: 224, y: 660, // Moved up by 50 pixels (from 710 to 660) width: 0, height: 80 // Doubled height from 40 to 80 }); game.addChild(contextBar); // Context bar label var contextLabel = new Text2("Context Collapse:", { size: 45, fill: 0xFFFFFF }); contextLabel.anchor.set(0.5, 0.5); // Center anchor contextLabel.x = 224 + 1600 / 2; // Center horizontally over the bar contextLabel.y = 660; // Moved up by 50 pixels (from 710 to 660) game.addChild(contextLabel); // Add threshold indicators var thresholds = [0.25, 0.5, 0.75, 0.9]; thresholds.forEach(function (threshold) { // Create vertical line indicator var indicator = new Text2("│", { size: 80, fill: 0xFF0000 }); indicator.anchor.set(0.5, 0.5); indicator.x = 224 + 1600 * threshold; // Position based on bar width indicator.y = 660; // Match context bar y position game.addChild(indicator); // Add percentage text var percentText = new Text2("".concat(threshold * 100, "%"), { size: 35, fill: 0xFF0000 }); percentText.anchor.set(0.5, 1); percentText.x = indicator.x; percentText.y = indicator.y - 45; // Position above the indicator line game.addChild(percentText); }); // Progress bar background var progressBarBg = LK.getAsset('progressBarBg', { anchorX: 0, anchorY: 0.5, x: 224, y: 790, // Moved down 15% (380 + 2732 * 0.15) height: 80 // Doubled height from 40 to 80 }); game.addChild(progressBarBg); // Progress bar progressBar = LK.getAsset('progressBar', { anchorX: 0, anchorY: 0.5, x: 224, y: 790, // Moved down 15% width: 0, height: 80 // Doubled height from 40 to 80 }); game.addChild(progressBar); // Progress bar label var progressLabel = new Text2("Project Progress:", { size: 45, fill: 0xFFFFFF }); progressLabel.anchor.set(0.5, 0.5); // Center anchor progressLabel.x = 224 + 1600 / 2; // Center horizontally over the bar progressLabel.y = 790; // Moved down 15% game.addChild(progressLabel); // Day indicator dayIndicator = new DayIndicator(); dayIndicator.x = 1848; dayIndicator.y = 200; game.addChild(dayIndicator); // End day button endDayButton = new MenuButton("END DAY", endDay); endDayButton.x = 1848; endDayButton.y = 400; game.addChild(endDayButton); // Project area separator var separator = new Text2("───────────────────────────────────────────────", { size: 55, fill: 0xFFFFFF }); separator.anchor.set(0.5, 0.5); separator.x = 2048 / 2; separator.y = projectAreaY; game.addChild(separator); // Project area label var projectAreaLabel = new Text2("PROJECT AREA", { size: 45, fill: 0xFFFFFF }); projectAreaLabel.anchor.set(0.5, 0); projectAreaLabel.x = 2048 / 2; projectAreaLabel.y = projectAreaY - 80; game.addChild(projectAreaLabel); // Features checklist will be added to the vibe display area // Hand area label var handLabel = new Text2("YOUR HAND", { size: 45, fill: 0xFFFFFF }); handLabel.anchor.set(0.5, 0); handLabel.x = 2048 / 2; handLabel.y = handY - 280; game.addChild(handLabel); // Codebase visualization var codebaseContainer = new Container(); codebaseContainer.x = 2048 / 2; codebaseContainer.y = projectAreaY - 200; game.addChild(codebaseContainer); // [Keep all existing UI creation code here unchanged] // Add vibe layer after all existing UI is created // Create a top-level vibe container that sits above everything else var vibeContainer = new Container(); game.addChild(vibeContainer); // This puts it on top of existing UI // Add vibe background var vibeBackground = LK.getAsset('vibebackground', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2 }); vibeContainer.addChild(vibeBackground); // Add vibe core in center var vibeCore = LK.getAsset('vibecore', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2 - 200 // Slightly above center }); vibeContainer.addChild(vibeCore); // Add core first // Add particle groups container var particleContainer = new Container(); particleContainer.x = vibeCore.x; particleContainer.y = vibeCore.y; vibeContainer.addChild(particleContainer); // Add container to hold particles // Store references gameState.vibeCore = vibeCore; gameState.particleContainer = particleContainer; gameState.particleGroups = {}; // Add initial basic particles gameState.particleGroups.BASIC = new ParticleGroup('BASIC'); particleContainer.addChild(gameState.particleGroups.BASIC); // Stylized day counter (we can make this more vibe-appropriate later) var vibeDayIndicator = new Text2("DAY " + gameState.day, { size: 75, fill: 0x00ffff // Cyan color for vibe aesthetic }); vibeDayIndicator.anchor.set(0.5, 0.5); vibeDayIndicator.x = 1848; vibeDayIndicator.y = 200; vibeContainer.addChild(vibeDayIndicator); // Stylized end day button var vibeEndDayButton = new MenuButton("END DAY", endDay); vibeEndDayButton.x = 1848; vibeEndDayButton.y = 400; vibeEndDayButton.scale.set(1.2); // Make it slightly larger vibeContainer.addChild(vibeEndDayButton); // Store the container reference in gameState gameState.vibeContainer = vibeContainer; } function pulseVibeCore() { if (gameState.vibeCore) { tween(gameState.vibeCore, { scaleX: 1.2, scaleY: 1.2 }, { duration: 150, onFinish: function onFinish() { tween(gameState.vibeCore, { scaleX: 1, scaleY: 1 }, { duration: 150 }); } }); } } function initializeDeck() { // Create a copy of all card templates cardDeck = []; // Add multiple copies of each card template to the deck cardTemplates.forEach(function (template) { // Add more basic cards var count = template.type === 'basic' ? 3 : template.type === 'refactor' || template.type === 'coffee' || template.type === 'debug' ? 1 : 2; for (var i = 0; i < count; i++) { cardDeck.push(Object.assign({}, template)); } }); // Shuffle the deck shuffleDeck(cardDeck); } function shuffleDeck(deck) { for (var i = deck.length - 1; i > 0; i--) { var j = Math.floor(Math.random() * (i + 1)); var _ref = [deck[j], deck[i]]; deck[i] = _ref[0]; deck[j] = _ref[1]; } } function drawHand() { // Only remove cards from display that aren't in the currentHand anymore for (var i = game.children.length - 1; i >= 0; i--) { var child = game.children[i]; if (child instanceof Card && currentHand.indexOf(child) === -1 && gameState.cardStack.indexOf(child) === -1 && !child.isDragging) { game.removeChild(child); } } // Check if we need to reshuffle the discard pile if (cardDeck.length < HAND_SIZE - currentHand.length && discardPile.length > 0) { // Add discard pile back to deck and shuffle cardDeck = cardDeck.concat(discardPile); discardPile = []; shuffleDeck(cardDeck); } // Draw up to hand size but don't remove current cards while (currentHand.length < HAND_SIZE && cardDeck.length > 0) { var cardTemplate = cardDeck.pop(); var card = new Card(cardTemplate.type, cardTemplate.promptText, cardTemplate.codeLines, cardTemplate.vibePoints, cardTemplate.contextImpact, cardTemplate.bugChance); // Add feature property if it exists if (cardTemplate.feature) { card.feature = cardTemplate.feature; } currentHand.push(card); game.addChild(card); } // Position cards in hand positionCardsInHand(); } function positionCardsInHand() { var cardWidth = 400; var spacing = 60; // Increased spacing further for wider hand var overlap = 200; // Keep overlap the same for now var centerIndex = Math.floor((currentHand.length - 1) / 2); var fanAngle = 0.09; // Slightly increased rotation for wider fan // Calculate positions with cards closer to center currentHand.forEach(function (card, index) { // Calculate distance from center card (0 to n) var distanceFromCenter = Math.abs(index - centerIndex); // Cards closer to edges move more towards center var compressionFactor = distanceFromCenter * 0.35; // Reduced compression strength var adjustedSpacing = spacing + overlap * compressionFactor; // Calculate x position with compression toward center var centerX = 2048 / 2; var direction = index < centerIndex ? -1 : 1; // Left or right of center if (index === centerIndex) { // Center card card.x = centerX; } else { // Side cards with compression var positionFromCenter = direction * (cardWidth / 2 + adjustedSpacing * distanceFromCenter); card.x = centerX + positionFromCenter; } card.y = handY + Math.abs(index - (currentHand.length - 1) / 2) * 20; // Arc up in middle card.rotation = (index - (currentHand.length - 1) / 2) * fanAngle; // Fan rotation // Animate to new positions with tween tween(card, { x: card.x, y: card.y, rotation: card.rotation }, { duration: 300, easing: tween.easeOutQuad }); // Update target and original positions card.targetX = card.x; card.targetY = card.y; card.originalX = card.x; card.originalY = card.y; card.originalRotation = card.rotation; card.isDragging = false; }); } function playCard(card) { if (currentHand.indexOf(card) === -1) { return; } if (gameState.cardsPlayed >= gameState.maxCardsPerDay) { card.targetX = card.originalX; card.targetY = card.originalY; return; } // Check if player has enough vibe points var vibeCost = Math.max(0, -card.vibePoints + gameState.thresholdEffects.vibeCostModifier); if (gameState.vibePoints < vibeCost) { card.targetX = card.originalX; card.targetY = card.originalY; return; } // Apply all game state changes gameState.vibePoints += card.vibePoints; gameState.vibePoints -= vibeCost; gameState.codeLines += card.codeLines; gameState.contextCollapse += card.contextImpact * gameState.thresholdEffects.contextMultiplier; gameState.contextCollapse = Math.max(0, Math.min(gameState.contextCollapse, MAX_CONTEXT_COLLAPSE)); updateContextThresholdEffects(); if (card.feature) { gameState.features[card.feature] = true; } LK.getSound('cardPlace').play(); // Remove from hand var index = currentHand.indexOf(card); if (index > -1) { currentHand.splice(index, 1); discardPile.push({ type: card.type, promptText: card.promptText, codeLines: card.codeLines, vibePoints: card.vibePoints, contextImpact: card.contextImpact, bugChance: card.bugChance, feature: card.feature }); } gameState.cardsPlayed++; // Animate card being absorbed into core tween(card, { x: gameState.stackArea.x, y: gameState.stackArea.y, scaleX: 0.2, scaleY: 0.2, alpha: 0 }, { duration: 300, onFinish: function onFinish() { pulseVibeCore(); gameState.cardStack.push(card); checkForBugs(card.bugChance); updateStatsDisplay(); positionCardsInHand(); if (currentHand.length < HAND_SIZE) { drawHand(); } checkGameState(); } }); } function updateCodebaseVisualization() { if (!codebaseContainer) { return; } // Clear existing visualization while (codebaseContainer.children.length > 0) { codebaseContainer.removeChild(codebaseContainer.children[0]); } // Calculate how many code blocks to show based on current code lines var totalBlocks = Math.min(20, Math.floor(gameState.codeLines / 50)); // Create blocks for (var i = 0; i < totalBlocks; i++) { var block = new Container(); // Create a code block shape var blockShape = new Sprite(); blockShape.width = 50; blockShape.height = 30; blockShape.color = Math.random() > 0.5 ? 0x4a86e8 : 0x34a853; block.addChild(blockShape); // Position in a grid or pattern block.x = i % 10 * 60 - 270; block.y = Math.floor(i / 10) * 40 - 20; codebaseContainer.addChild(block); } } // Create a Stack area where cards are played function createStackArea() { // Create stack container var stackContainer = new Container(); stackContainer.x = 2048 / 2; stackContainer.y = projectAreaY - 450; // Create background for the stack area using a shape asset var stackBg = LK.getAsset('card', { anchorX: 0.5, anchorY: 0.5, width: 450, height: 550, color: 0x1a1f26, // Slightly lighter than background alpha: 0 // Set to 0 to hide it }); // stackBg.alpha = 0.5; // Alpha set during creation stackContainer.addChild(stackBg); // Stack label var stackLabel = new Text2("THE STACK", { size: 45, fill: 0xFFFFFF }); stackLabel.alpha = 0; stackLabel.anchor.set(0.5, 0); stackLabel.y = -250; stackContainer.addChild(stackLabel); // Simple border using Text2 with underscores and pipes var topBorder = new Text2("┌────────────────────────────┐", { size: 30, fill: 0x4a86e8 }); topBorder.alpha = 0; topBorder.anchor.set(0.5, 0.5); topBorder.y = -260; stackContainer.addChild(topBorder); var bottomBorder = new Text2("└────────────────────────────┘", { size: 30, fill: 0x4a86e8 }); bottomBorder.alpha = 0; bottomBorder.anchor.set(0.5, 0.5); bottomBorder.y = 260; stackContainer.addChild(bottomBorder); // Side borders for (var i = -220; i <= 220; i += 40) { var leftBorder = new Text2("│", { size: 30, fill: 0x4a86e8 }); leftBorder.alpha = 0; leftBorder.anchor.set(0.5, 0.5); leftBorder.x = -225; leftBorder.y = i; stackContainer.addChild(leftBorder); var rightBorder = new Text2("│", { size: 30, fill: 0x4a86e8 }); rightBorder.alpha = 0; rightBorder.anchor.set(0.5, 0.5); rightBorder.x = 225; rightBorder.y = i; stackContainer.addChild(rightBorder); } game.addChild(stackContainer); // Add code console on left: var codeConsole = new Container(); codeConsole.alpha = 0; // Set to 0 to hide it codeConsole.x = -750 + 2048 * 0.02; // Move right by 2% of screen width codeConsole.y = -136 + 2732 * 0.02; // Move down by 2% of screen height var consoleBg = LK.getAsset('menuButton', { anchorX: 0.5, anchorY: 0.5, width: 473, // Increased by 5% (450 * 1.05) height: 688, // Increased by 10% (625 * 1.10) color: 0x000000, alpha: 0.8 }); codeConsole.addChild(consoleBg); var codeText = new Text2("", { size: 30, fill: 0x00FF00 }); codeText.x = -221; // -180 - (2048 * 0.02) codeText.y = -230; codeConsole.addChild(codeText); // Add blinking cursor var cursor = new Text2("_", { size: 30, fill: 0x00FF00 }); cursor.x = codeText.x; // Match updated codeText position cursor.y = codeText.y; codeConsole.addChild(cursor); // Blink cursor LK.setInterval(function () { cursor.visible = !cursor.visible; }, 500); stackContainer.addChild(codeConsole); // Create code generator and attach to stack area var codeGenerator = new CodeGenerator(); codeGenerator.setTextDisplay(codeText, cursor); stackContainer.codeGenerator = codeGenerator; // Add vibe points display on right, mirroring the code console position: var vibeDisplay = new Container(); vibeDisplay.alpha = 0; // Set to 0 to hide it vibeDisplay.x = 750 - 2048 * 0.02; // Mirror console's horizontal offset from center vibeDisplay.y = -136 + 2732 * 0.02; // Match console's vertical offset var vibeBg = LK.getAsset('menuButton', { anchorX: 0.5, anchorY: 0.5, width: 473, // Match console background width height: 688, // Match console background height color: 0x4a86e8, alpha: 0.2 }); vibeDisplay.addChild(vibeBg); // Add features checklist inside the vibe display featuresText = new Text2("Required Features:\n□ UI Framework\n□ Database\n□ API Integration\n□ Security", { size: 35, // Slightly smaller to fit fill: 0xFFFFFF, align: 'left', wordWrap: true, wordWrapWidth: vibeBg.width * 0.9 // Fit within the background }); featuresText.anchor.set(0, 0); // Anchor top-left featuresText.x = -vibeBg.width / 2 + 30; // Position inside the vibeBg featuresText.y = -vibeBg.height / 2 + 30; vibeDisplay.addChild(featuresText); stackContainer.addChild(vibeDisplay); return stackContainer; } function startBugFix(bug) { var gameContainer = new Container(); gameContainer.x = 2048 / 2; gameContainer.y = 2732 / 2; game.addChild(gameContainer); // Add background panel var panel = LK.getAsset('menuButton', { width: 800, height: 600, color: 0x1a1f26, anchorX: 0.5, anchorY: 0.5 }); gameContainer.addChild(panel); // Add title var title = new Text2(bug instanceof SyntaxBug ? "Fix Syntax Errors!" : "Place Debug Breakpoints!", { size: 55, fill: 0xFFFFFF }); title.anchor.set(0.5, 0.5); title.y = -250; gameContainer.addChild(title); // Add instructions var instructions = new Text2(bug instanceof SyntaxBug ? "Click on the typos in the code to fix them" : "Place exactly 3 breakpoints to catch the bug", { size: 35, fill: 0xFFFFFF }); instructions.anchor.set(0.5, 0.5); instructions.y = -180; gameContainer.addChild(instructions); if (bug instanceof SyntaxBug) { // Syntax bug mini-game with doubled sizes var codeLines = ["function brokenCode() {", " reutrn 'Hello World'", // Typo " cosole.log('Done');", // Typo "}"]; // Double the panel size panel.width = 1600; panel.height = 1200; var errorPositions = [[1, 2], [2, 2]]; // Position of errors in code var foundErrors = 0; // Progress indicator with larger font var progress = new Text2("Errors found: 0/2", { size: 70, // Doubled from 35 fill: 0xFFFFFF }); progress.anchor.set(0.5, 0.5); progress.y = 300; // Doubled from 150 gameContainer.addChild(progress); // Display code with larger font and spacing codeLines.forEach(function (line, index) { var codeLine = new Text2(line, { size: 90, // Doubled from 45 fill: 0xFFFFFF }); codeLine.anchor.set(0, 0); codeLine.x = -600; // Doubled from -300 codeLine.y = index * 100 - 200; // Doubled spacing and offset // Make the hit area for the whole line var hitArea = new Container(); // Use a simple shape for hit area, 'menuButton' asset might not be ideal if we want it truly invisible and just for area detection var hitBox = LK.getAsset('menuButton', { // Using menuButton for simplicity as requested, could be a basic shape too width: 1200, // Wide enough for the full line height: 90, // Match text height color: 0x000000, // Color doesn't matter much if alpha is low alpha: 0.01 // Nearly invisible, but still interactive }); hitArea.addChild(hitBox); hitArea.x = codeLine.x; // Align hitArea with codeLine visually hitArea.y = codeLine.y; hitArea.interactive = true; hitArea.down = function (x, y, obj) { // Calculate character position based on local x within the hit area. // 'x' is already the local coordinate relative to the hitArea. var localX = x; var charPos = Math.floor(localX / 40); // Adjusted char width estimate for size 90 font // Check if click is near an error position for the corresponding line index var isErrorClick = errorPositions.some(function (pos) { return pos[0] === index && Math.abs(pos[1] - charPos) < 2; }); if (isErrorClick && codeLine.fill !== 0x00FF00) { // Check the Text2 object's color foundErrors++; progress.setText("Errors found: ".concat(foundErrors, "/2")); codeLine.fill = 0x00FF00; // Change text color to green hitArea.interactive = false; // Disable further clicks on this line's hit area LK.getSound('cardPlace').play(); // Feedback sound if (foundErrors >= errorPositions.length) { bugFixSuccess(bug, gameContainer); } } }; gameContainer.addChild(hitArea); // Add hit area first gameContainer.addChild(codeLine); // Add text line on top }); // Adjust title and instructions size and position (modifying existing variables) title.size = 110; // Doubled from 55 title.y = -500; // Doubled from -250 instructions.size = 70; // Doubled from 35 instructions.y = -360; // Doubled from -180 // Adjust close button (modifying existing variable) // Note: 'closeButton' is defined later in the function, this modification happens *before* its definition in the original flow. // This code needs to be applied *after* closeButton is created. // Let's modify the closeButton properties right after its creation instead. // --- The modification code for closeButton will be handled in a separate change_block --- } else if (bug instanceof LogicBug) { // Logic bug mini-game var gridSize = 5; var grid = new Container(); var breakpointCount = 0; // Progress indicator var progress = new Text2("Breakpoints: 0/3", { size: 70, // Match syntax bug size fill: 0xFFFFFF }); progress.anchor.set(0.5, 0.5); progress.y = 300; // Match syntax bug position gameContainer.addChild(progress); for (var i = 0; i < gridSize; i++) { for (var j = 0; j < gridSize; j++) { var cell = LK.getAsset('menuButton', { width: 120, // Doubled from 60 height: 120, // Doubled from 60 color: 0x666666, // Lighter gray for inactive cells anchorX: 0.5, anchorY: 0.5 }); cell.x = (i - (gridSize - 1) / 2) * 140; // Doubled spacing from 70, adjusted centering cell.y = (j - (gridSize - 1) / 2) * 140; // Doubled spacing from 70, adjusted centering cell.interactive = true; cell.isBreakpoint = false; cell.down = function () { if (!this.isBreakpoint) { if (breakpointCount < 3) { // Ensure we don't exceed 3 this.color = 0xFF0000; // Changed to red for active breakpoints this.isBreakpoint = true; breakpointCount++; LK.getSound('cardPlace').play(); } } else { this.color = 0x666666; // Back to gray when deactivated this.isBreakpoint = false; breakpointCount--; } progress.setText("Breakpoints: " + breakpointCount + "/3"); if (breakpointCount === 3) { // Introduce a slight delay before success to see the last breakpoint LK.setTimeout(function () { bugFixSuccess(bug, gameContainer); }, 200); } }; grid.addChild(cell); } } // Adjust grid container position slightly if needed to center it within the doubled panel grid.y = 50; // You might need to adjust this based on visual testing with the doubled panel size gameContainer.addChild(grid); } // Add close button (Give Up) var closeButton = new MenuButton("GIVE UP", function () { // Add a fade out effect for the mini-game container tween(gameContainer, { alpha: 0 }, { duration: 300, onFinish: function onFinish() { if (gameContainer && gameContainer.parent) { gameContainer.parent.removeChild(gameContainer); gameContainer.destroy(); } } }); }); // Adjust close button scale and position conditionally for SyntaxBug if (bug instanceof SyntaxBug) { closeButton.scale.set(1.0); // Doubled from 0.5 closeButton.x = 600; // Doubled from 300 (Position relative to larger panel) closeButton.y = -500; // Doubled from -250 (Align with larger title position) } else { closeButton.scale.set(0.5); // Keep original scale for LogicBug closeButton.x = 300; // Original position closeButton.y = -250; // Original position } gameContainer.addChild(closeButton); // Animate the mini-game appearance gameContainer.alpha = 0; gameContainer.scale.set(0.8); tween(gameContainer, { alpha: 1, scaleX: 1, scaleY: 1 }, { duration: 300 }); } function checkLogicSolution(grid, bug, gameContainer) { // Count placed breakpoints var breakpoints = 0; grid.children.forEach(function (cell) { if (cell.color === 0x4A86E8) { breakpoints++; } }); // Need 3 breakpoints to solve if (breakpoints === 3) { bugFixSuccess(bug, gameContainer); } } function bugFixSuccess(bug, gameContainer) { // Remove vibe points cost gameState.vibePoints -= bug.vibePointsCost; // Remove code lines cost gameState.codeLines -= bug.codeLinesCost; // Decrement bug count gameState.bugs--; // Play success sound LK.getSound('bugFix').play(); // Remove bug with effect - check if bug still exists and has a parent if (bug && bug.parent) { tween(bug, { scaleX: 0, scaleY: 0, alpha: 0 }, { duration: 300, onFinish: function onFinish() { if (bug && bug.parent) { bug.parent.removeChild(bug); bug.destroy(); } } }); } // Remove mini-game tween(gameContainer, { alpha: 0 }, { duration: 300, onFinish: function onFinish() { if (gameContainer && gameContainer.parent) { gameContainer.parent.removeChild(gameContainer); gameContainer.destroy(); } } }); // Update stats updateStatsDisplay(); } function checkForBugs(bugChance) { // Adjust bug chance based on context collapse and threshold effect var adjustedBugChance = bugChance + gameState.contextCollapse / MAX_CONTEXT_COLLAPSE * 0.3 + gameState.thresholdEffects.bugChanceModifier; // Special case for debug card if (bugChance < 0) { // Reduce bugs by a fixed amount var bugsToRemove = Math.min(gameState.bugs, Math.abs(Math.floor(bugChance * 10))); for (var i = 0; i < bugsToRemove; i++) { if (bugContainer.children.length > 0) { var bug = bugContainer.children[bugContainer.children.length - 1]; bugContainer.removeChild(bug); bug.destroy(); } } gameState.bugs -= bugsToRemove; return; } // Roll for bug if (Math.random() < adjustedBugChance && gameState.bugs < MAX_BUGS) { // Show detection sequence first showBugDetection(); // Create either a syntax or logic bug var bug = Math.random() < 0.5 ? new SyntaxBug() : new LogicBug(); // Position randomly in the project area (within bugContainer's space) bug.x = Math.random() * 1600 - 800; // -800 to 800 (relative to bugContainer center) bug.y = Math.random() * 400 - 200; // -200 to 200 (relative to bugContainer center) bugContainer.addChild(bug); gameState.bugs++; // Apply bug's effect immediately bug.effect(); // Play bug sound LK.getSound('bugAppear').play(); // Animate bug appearance bug.scale.set(0); tween(bug, { scaleX: 1, scaleY: 1 }, { duration: 300 }); } } function updateStatsDisplay() { // Create effects text var effectsText = ""; if (gameState.thresholdEffects.bugChanceModifier > 0) { effectsText += "\nIncreased Bug Chance!"; } if (gameState.thresholdEffects.maxCardsModifier < 0) { effectsText += "\nReduced Cards Per Day!"; } if (gameState.thresholdEffects.contextMultiplier > 1) { effectsText += "\nDouble Context Impact!"; } if (gameState.thresholdEffects.vibeCostModifier > 0) { effectsText += "\nIncreased Vibe Costs!"; } // Update stats text with effects statsText.setText("Code Lines: " + gameState.codeLines + " / " + TARGET_CODE_LINES + "\nVibe Points: " + gameState.vibePoints + "\nBugs: " + gameState.bugs + "/" + MAX_BUGS + "\nCards: " + gameState.cardsPlayed + "/" + Math.max(1, gameState.maxCardsPerDay + gameState.thresholdEffects.maxCardsModifier) + (effectsText ? "\n" + effectsText : "")); // Update context bar var contextWidth = gameState.contextCollapse / MAX_CONTEXT_COLLAPSE * 1600; tween(contextBar, { width: contextWidth }, { duration: 300 }); // Update progress bar var progressWidth = Math.min(gameState.codeLines / TARGET_CODE_LINES, 1) * 1600; tween(progressBar, { width: progressWidth }, { duration: 300 }); // Update features checklist text using the global reference var featuresStatus = "Required Features:\n" + (gameState.features.ui ? "☑" : "□") + " UI Framework\n" + (gameState.features.database ? "☑" : "□") + " Database\n" + (gameState.features.api ? "☑" : "□") + " API Integration\n" + (gameState.features.security ? "☑" : "□") + " Security"; if (featuresText) { featuresText.setText(featuresStatus); } updateCodebaseVisualization(); // [Keep all existing update code] // Update vibe day indicator if it exists if (gameState.vibeContainer) { // Find the day indicator in the vibe container's children var vibeDayIndicator = gameState.vibeContainer.children.find(function (child) { // Ensure child is Text2 and its text property is a string before calling startsWith return child instanceof Text2 && typeof child.text === 'string' && child.text.startsWith("DAY"); }); if (vibeDayIndicator) { vibeDayIndicator.setText("DAY " + gameState.day); } } } function checkGameState() { // Update threshold effects first updateContextThresholdEffects(); // Check for game over conditions if (gameState.bugs >= MAX_BUGS) { showGameOver("Too many bugs! Your project crashed!"); return; } if (gameState.contextCollapse >= MAX_CONTEXT_COLLAPSE) { showGameOver("Context collapse! Your AI forgot what it was doing!"); return; } // Check if player can play any more cards *this day* // Adjust max cards per day based on threshold effect var adjustedMaxCards = gameState.maxCardsPerDay + gameState.thresholdEffects.maxCardsModifier; var canPlayMoreCardsThisDay = gameState.cardsPlayed < Math.max(1, adjustedMaxCards); // Ensure at least 1 card can be played // Update card visual states based on whether they can be played this day currentHand.forEach(function (card) { if (!canPlayMoreCardsThisDay) { // Optional: Add visual indicator that cards can't be played card.alpha = 0.7; // Dim the cards } else { card.alpha = 1.0; // Ensure cards are fully visible if playable } }); // Determine if *any* card in hand is playable currently (based on daily limit and having cards) var canPlayAnyCardCurrently = false; if (canPlayMoreCardsThisDay && currentHand.length > 0) { // If within daily limit and hand is not empty, player can potentially play a card. // (Add resource checks here if needed in the future) canPlayAnyCardCurrently = true; } gameState.canPlayCard = canPlayAnyCardCurrently; // Update the global state // Check if player needs to end their day automatically (stuck condition) // This happens if they *cannot* play any card currently AND have no way to draw more cards. if (!canPlayAnyCardCurrently && cardDeck.length === 0 && discardPile.length === 0) { endDay(); } } function endDay() { if (gameState.day >= MAX_DAYS) { // Final evaluation evaluateProject(); } else { // Advance to next day gameState.day++; dayIndicator.updateDay(gameState.day); // Play day change sound LK.getSound('dayChange').play(); // Animate stack cards flying away gameState.cardStack.forEach(function (card, index) { tween(card, { x: 2048 + 300, y: 300 + index * 30, rotation: 0.3, alpha: 0 }, { duration: 500, delay: index * 50, onFinish: function onFinish() { game.removeChild(card); card.destroy(); } }); }); // Clear the stack gameState.cardStack = []; // Discard current hand currentHand.forEach(function (card) { discardPile.push({ type: card.type, promptText: card.promptText, codeLines: card.codeLines, vibePoints: card.vibePoints, contextImpact: card.contextImpact, bugChance: card.bugChance, feature: card.feature }); game.removeChild(card); card.destroy(); }); currentHand = []; // Reset for new day gameState.cardsPlayed = 0; gameState.contextCollapse = Math.max(0, gameState.contextCollapse - 10); // Update threshold effects after reducing context collapse updateContextThresholdEffects(); // Draw new hand drawHand(); // Update stats updateStatsDisplay(); } } function evaluateProject() { var featureCount = (gameState.features.ui ? 1 : 0) + (gameState.features.database ? 1 : 0) + (gameState.features.api ? 1 : 0) + (gameState.features.security ? 1 : 0); var codeProgress = gameState.codeLines / TARGET_CODE_LINES; // Calculate score (out of 100) var score = codeProgress * 50 + featureCount * 10 + Math.max(0, 10 - gameState.bugs) * 2; score = Math.round(score); // Set the final score LK.setScore(score); if (score >= 80) { showYouWin("Project Success! Score: " + score + "/100"); } else if (score >= 50) { showGameOver("Project Submitted With Issues. Score: " + score + "/100"); } else { showGameOver("Project Failed! Score: " + score + "/100"); } } function showYouWin(message) { // Show win message var messageText = new Text2(message, { size: 75, fill: 0xFFFFFF }); messageText.anchor.set(0.5, 0.5); messageText.x = 2048 / 2; messageText.y = 2732 / 2 - 100; game.addChild(messageText); // Add some delay before showing game win LK.setTimeout(function () { LK.showYouWin(); }, 2000); } function showGameOver(message) { // Show game over message var messageText = new Text2(message, { size: 75, fill: 0xFFFFFF }); messageText.anchor.set(0.5, 0.5); messageText.x = 2048 / 2; messageText.y = 2732 / 2 - 100; game.addChild(messageText); // Add some delay before showing game over LK.setTimeout(function () { LK.showGameOver(); }, 2000); } function showMainMenu() { // Clear existing elements while (game.children.length > 0) { game.removeChild(game.children[0]); } // Create background var background = LK.getAsset('background', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2 }); game.addChild(background); // Title var titleText = new Text2("VIBE CODER", { size: 135, fill: 0xFFFFFF }); titleText.anchor.set(0.5, 0.5); titleText.x = 2048 / 2; titleText.y = 600; game.addChild(titleText); // Subtitle var subtitleText = new Text2("The AI Coding Simulator", { size: 75, fill: 0x4A86E8 }); subtitleText.anchor.set(0.5, 0.5); subtitleText.x = 2048 / 2; subtitleText.y = 700; game.addChild(subtitleText); // Description var descText = new Text2("Build a project in 10 days using vague AI prompts.\nBalance code lines, vibe points, and technical debt.\nAvoid bugs and context collapse!", { size: 55, fill: 0xFFFFFF }); descText.anchor.set(0.5, 0.5); descText.x = 2048 / 2; descText.y = 900; game.addChild(descText); // Start button var startButton = new MenuButton("START GAME", initializeGame); startButton.x = 2048 / 2; startButton.y = 1200; game.addChild(startButton); // Play music LK.playMusic('gameMusic', { fade: { start: 0, end: 0.3, duration: 1000 } }); } game.update = function () { // Skip updates if game isn't in playing state if (gameState.phase !== 'playing') { return; } // Update particles if (gameState.particleContainer) { var groups = Object.values(gameState.particleGroups); for (var i = 0; i < groups.length; i++) { groups[i].update(); } } // Update all cards for smooth movement this.children.forEach(function (child) { if (child instanceof Card && child.update) { child.update(); } }); // Can add other game updates here like: // - Animations // - Visual effects // - Game state checks }; // Game drag state var dragNode = null; var draggedCard = null; var dragOffsetX = 0; var dragOffsetY = 0; var dragStartX = 0; var dragStartY = 0; // Global move handler // Game event handlers // In the down handler, modify how the preview mode works: game.down = function (x, y, obj) { // Reset drag tracking dragStartX = x; dragStartY = y; // Find clicked card var clickedCard = null; for (var i = 0; i < currentHand.length; i++) { var card = currentHand[i]; var dx = x - card.x; var dy = y - card.y; if (Math.abs(dx) < 200 && Math.abs(dy) < 250) { clickedCard = card; break; } } if (clickedCard && gameState.phase === 'playing') { draggedCard = clickedCard; dragOffsetX = clickedCard.x - x; dragOffsetY = clickedCard.y - y; // Store original values draggedCard.originalX = draggedCard.x; draggedCard.originalY = draggedCard.y; // Set up preview timer draggedCard.holdTimer = LK.setTimeout(function () { // Only preview if we haven't moved much from start position var dx = x - dragStartX; var dy = y - dragStartY; var distance = Math.sqrt(dx * dx + dy * dy); if (!draggedCard.isDragging && distance < 10) { // Set preview mode draggedCard.previewMode = true; // Move card up by a fixed amount var previewY = draggedCard.originalY - 600; // Apply scale and move up in same tween tween(draggedCard, { scaleX: draggedCard.previewScale, scaleY: draggedCard.previewScale, y: previewY }, { duration: 300 }); // Bring to front game.setChildIndex(draggedCard, game.children.length - 1); } }, draggedCard.holdDuration); // Set initial target position draggedCard.targetX = draggedCard.x; draggedCard.targetY = draggedCard.y; // Bring to front game.setChildIndex(draggedCard, game.children.length - 1); } }; // In the move handler game.move = function (x, y, obj) { if (draggedCard) { // Calculate distance moved var dx = x - dragStartX; var dy = y - dragStartY; var distance = Math.sqrt(dx * dx + dy * dy); // If we've moved significantly, cancel preview and start drag if (distance > 40) { // Cancel preview mode and timer if (draggedCard.holdTimer) { LK.clearTimeout(draggedCard.holdTimer); draggedCard.holdTimer = null; } // If in preview mode, exit it first with a tween if (draggedCard.previewMode) { draggedCard.previewMode = false; tween(draggedCard, { scaleX: 1, scaleY: 1, y: draggedCard.originalY // Return to original Y while scaling down }, { duration: 150, onFinish: function onFinish() { // Only start dragging after scale tween completes draggedCard.isDragging = true; // Update position after scale reset draggedCard.x = x + dragOffsetX; draggedCard.y = y + dragOffsetY; draggedCard.targetX = draggedCard.x; draggedCard.targetY = draggedCard.y; } }); return; // Exit early while transitioning from preview } // Normal drag handling if not in preview mode if (!draggedCard.isDragging) { draggedCard.isDragging = true; } // Direct 1:1 movement - set actual position, not just target draggedCard.x = x + dragOffsetX; draggedCard.y = y + dragOffsetY; // Also update target position for consistency draggedCard.targetX = draggedCard.x; draggedCard.targetY = draggedCard.y; } } }; // In the up handler game.up = function (x, y, obj) { if (draggedCard) { var cardToEndInteraction = draggedCard; // Store reference locally // Clear any pending preview timer if (cardToEndInteraction.holdTimer) { LK.clearTimeout(cardToEndInteraction.holdTimer); cardToEndInteraction.holdTimer = null; } if (cardToEndInteraction.previewMode) { // End preview mode - return to original position and scale tween(cardToEndInteraction, { scaleX: 1, scaleY: 1, y: cardToEndInteraction.originalY }, { duration: 300, onFinish: function onFinish() { if (cardToEndInteraction) { cardToEndInteraction.previewMode = false; } } }); cardToEndInteraction.isDragging = false; } else if (cardToEndInteraction.isDragging) { // Handle card drop // Check if card is dropped on the stack area var stackAreaX = 2048 / 2; var stackAreaY = projectAreaY - 450; // Simple rectangular hit testing if (Math.abs(x - stackAreaX) < 225 && Math.abs(y - stackAreaY) < 275) { // Card dropped on the stack playCard(cardToEndInteraction); } else { // Return card to hand position cardToEndInteraction.targetX = cardToEndInteraction.originalX; cardToEndInteraction.targetY = cardToEndInteraction.originalY; } cardToEndInteraction.isDragging = false; } // Nullify the global reference draggedCard = null; } }; // Initialize with main menu showMainMenu();
===================================================================
--- original.js
+++ change.js
@@ -349,51 +349,101 @@
var sprite = self.attachAsset(typeConfig.assets[assetIndex], {
anchorX: 0.5,
anchorY: 0.5
});
- // Movement properties
+ // Base movement properties
self.angle = Math.PI * 2 * index / typeConfig.count;
self.speed = typeConfig.baseSpeed * (0.8 + Math.random() * 0.4);
self.radius = typeConfig.orbitRadius * (0.9 + Math.random() * 0.2);
self.verticalOffset = Math.random() * 40 - 20;
+ // Additional movement properties
+ self.phase = Math.random() * Math.PI * 2; // For oscillation
+ self.timeOffset = Math.random() * 1000; // For varied timing
// Visual state
self.pulseScale = 1;
self.update = function () {
var chaosLevel = Math.min(gameState.contextCollapse / MAX_CONTEXT_COLLAPSE, 1);
- // Update angle
- self.angle += self.speed * (1 + chaosLevel * Math.random());
- // Calculate position
- var x = Math.cos(self.angle) * self.radius;
- var y = Math.sin(self.angle) * self.radius + self.verticalOffset;
- // Add chaos movement
+ var time = Date.now() * 0.001; // Current time in seconds
+ var x, y;
+ switch (type) {
+ case 'BASIC':
+ // Gentle, slow orbital rings with slight oscillation
+ var orbitSpeed = 0.2;
+ self.angle += orbitSpeed * self.speed * (1 + chaosLevel * Math.random() * 0.5); // Add chaos to speed
+ x = Math.cos(self.angle) * self.radius;
+ y = Math.sin(self.angle) * self.radius;
+ // Add gentle vertical oscillation
+ y += Math.sin(time + self.phase) * 20;
+ break;
+ case 'UI':
+ // Slide in smooth arc paths, occasionally forming grids
+ var gridPhase = Math.floor((time + self.timeOffset) % 10);
+ if (gridPhase < 5 - chaosLevel * 2) {
+ // More chaos = less grid time
+ // Arc movement
+ self.angle += self.speed * 0.3 * (1 + chaosLevel * Math.random()); // Add chaos to speed
+ x = Math.cos(self.angle) * self.radius;
+ y = Math.sin(self.angle * 2 + self.phase) * (self.radius * 0.5); // Add phase
+ } else {
+ // Grid alignment (less stable with chaos)
+ var gridX = Math.floor(index % 5) - 2;
+ var gridY = Math.floor(index / 5) - 2;
+ var targetX = gridX * 50;
+ var targetY = gridY * 50;
+ x = targetX + (Math.random() - 0.5) * chaosLevel * 30; // Jitter grid
+ y = targetY + (Math.random() - 0.5) * chaosLevel * 30;
+ }
+ break;
+ case 'DATABASE':
+ // Flow in stream-like patterns
+ var flowSpeed = time * 0.5 * (1 + chaosLevel * 0.5) + self.phase; // Chaos affects flow speed
+ x = Math.cos(flowSpeed) * self.radius * 0.8;
+ y = Math.sin(flowSpeed * 2) * self.radius * 0.4;
+ // Add data-stream effect (more erratic with chaos)
+ y += index % 3 * 30 * Math.sin(time * (1 + chaosLevel) + self.phase);
+ break;
+ case 'API':
+ // Extend tendrils that reach outward then retract
+ var tendrilPhase = (Math.sin(time * (1 + chaosLevel * 0.3) + self.phase) + 1) * 0.5; // Chaos affects speed
+ var baseRadius = self.radius * 0.5;
+ var extendedRadius = baseRadius + self.radius * 0.8 * tendrilPhase; // Adjusted extension range
+ x = Math.cos(self.angle) * extendedRadius;
+ y = Math.sin(self.angle) * extendedRadius;
+ break;
+ case 'SECURITY':
+ // Form temporary protective layers, more jittery with chaos
+ var shieldPhase = time * (1 + chaosLevel * 0.2) + self.phase; // Chaos affects pulse speed
+ var shieldRadius = self.radius * (0.8 + Math.sin(shieldPhase) * 0.2);
+ var shieldAngle = self.angle + Math.sin(shieldPhase * 0.5) * (0.5 + chaosLevel * 0.3); // More angle wobble with chaos
+ x = Math.cos(shieldAngle) * shieldRadius;
+ y = Math.sin(shieldAngle) * shieldRadius;
+ break;
+ default:
+ // Default to basic movement if type is unknown
+ self.angle += self.speed * 0.5 * (1 + chaosLevel * Math.random());
+ x = Math.cos(self.angle) * self.radius;
+ y = Math.sin(self.angle) * self.radius;
+ break;
+ }
+ // Add chaos movement (overall jitter)
if (chaosLevel > 0) {
- x += (Math.random() - 0.5) * chaosLevel * 40;
- y += (Math.random() - 0.5) * chaosLevel * 40;
+ x += (Math.random() - 0.5) * chaosLevel * 30; // Reduced intensity slightly
+ y += (Math.random() - 0.5) * chaosLevel * 30;
}
+ // Apply final position
self.x = x;
self.y = y;
+ // Slow rotation of the particle itself
+ self.rotation = Math.sin(time + self.phase) * 0.2;
// Update pulse effect
if (self.pulseScale > 1) {
self.pulseScale = Math.max(1, self.pulseScale - 0.05);
self.scale.set(self.pulseScale);
}
};
self.pulse = function () {
- self.pulseScale = 1.5;
- tween(self.scale, {
- x: self.pulseScale,
- y: self.pulseScale
- }, {
- duration: 300,
- onFinish: function onFinish() {
- tween(self.scale, {
- x: 1,
- y: 1
- }, {
- duration: 300
- });
- }
- });
+ self.pulseScale = 1.5; // Keep pulse effect simple
+ // Pulse tween is handled by ParticleGroup now, so just set the target scale
};
return self;
});
vibebeat1
Music
vibebeat2
Music
vibebeat3
Music
vibebeat4
Music
vibebeat5
Music
vibebeat6
Music
buttonsound
Sound effect
endday
Sound effect
startsound
Sound effect
bugsquish
Sound effect
conceptbutton
Sound effect
wheelstart
Sound effect
wheelspin
Sound effect
wheelstop
Sound effect
keytype
Sound effect