User prompt
Add the music
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot set properties of undefined (setting 'fill')' in or related to this line: 'self.text.style.fill = color;' Line Number: 330
Code edit (1 edits merged)
Please save this source code
User prompt
Rhythm Battle: Beat Masters
Initial prompt
Friday night funkin
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1"); /**** * Classes ****/ var Arrow = Container.expand(function (direction, speed, holdDuration) { var self = Container.call(this); self.direction = direction || 'up'; self.speed = speed || 10; self.holdDuration = holdDuration || 0; self.isHold = self.holdDuration > 0; self.isActive = true; self.wasHit = false; self.holdActive = false; self.holdTime = 0; // Get arrow asset based on direction var arrowAsset = 'arrow_' + self.direction; var arrow = self.attachAsset(arrowAsset, { anchorX: 0.5, anchorY: 0.5 }); // Rotate arrow based on direction if (self.direction === 'up') { arrow.rotation = 0; } else if (self.direction === 'down') { arrow.rotation = Math.PI; } else if (self.direction === 'left') { arrow.rotation = -Math.PI / 2; } else if (self.direction === 'right') { arrow.rotation = Math.PI / 2; } // If it's a hold note, create an extension if (self.isHold) { self.holdExtension = self.addChild(LK.getAsset(arrowAsset, { anchorX: 0.5, anchorY: 0, y: arrow.height / 2, scaleY: self.holdDuration / 100, // Scale based on duration alpha: 0.5 })); // Rotate the hold extension if (self.direction === 'up') { self.holdExtension.rotation = 0; } else if (self.direction === 'down') { self.holdExtension.rotation = Math.PI; self.holdExtension.y = -arrow.height / 2; self.holdExtension.anchorY = 1; } else if (self.direction === 'left') { self.holdExtension.rotation = -Math.PI / 2; self.holdExtension.x = -arrow.height / 2; self.holdExtension.y = 0; self.holdExtension.anchorX = 1; self.holdExtension.anchorY = 0.5; } else if (self.direction === 'right') { self.holdExtension.rotation = Math.PI / 2; self.holdExtension.x = arrow.height / 2; self.holdExtension.y = 0; self.holdExtension.anchorX = 0; self.holdExtension.anchorY = 0.5; } } self.update = function () { // Move arrow upward self.y -= self.speed; // Check if the arrow is off screen and should be removed if (self.y < -300 && self.isActive) { if (!self.wasHit) { // Player missed the arrow game.handleMiss(); } self.isActive = false; LK.setTimeout(function () { self.destroy(); var index = arrows.indexOf(self); if (index > -1) { arrows.splice(index, 1); } }, 100); } }; self.hit = function (rating) { if (self.isActive && !self.wasHit) { self.wasHit = true; if (self.isHold) { self.holdActive = true; return 'hold_start'; } else { tween(self, { alpha: 0 }, { duration: 200 }); LK.setTimeout(function () { self.isActive = false; }, 200); return rating; } } return null; }; self.updateHold = function (holdActive) { if (self.isHold && self.wasHit) { self.holdTime += 1; if (holdActive) { // Player is holding correctly self.holdExtension.alpha = 0.8; // Check if hold is complete if (self.holdTime >= self.holdDuration) { self.isActive = false; tween(self, { alpha: 0 }, { duration: 200 }); return 'hold_complete'; } return 'holding'; } else { // Player released too early self.holdExtension.alpha = 0.3; self.isActive = false; tween(self, { alpha: 0 }, { duration: 200 }); return 'hold_break'; } } return null; }; return self; }); var Character = Container.expand(function (isPlayer) { var self = Container.call(this); self.isPlayer = isPlayer; var sprite = self.attachAsset(isPlayer ? 'player' : 'opponent', { anchorX: 0.5, anchorY: 1 }); self.setIdle = function () { tween(sprite, { scaleY: 1 }, { duration: 200 }); }; self.setAction = function () { tween(sprite, { scaleY: 1.05 }, { duration: 100, onFinish: function onFinish() { tween(sprite, { scaleY: 1 }, { duration: 200 }); } }); }; return self; }); var HealthBar = Container.expand(function (isPlayer) { var self = Container.call(this); self.health = 100; self.isPlayer = isPlayer; // Background bar var barBg = self.attachAsset('healthBar', { anchorX: 0, anchorY: 0.5 }); // Health fill var fillAsset = isPlayer ? 'healthFill' : 'opponentHealthFill'; self.fillBar = self.attachAsset(fillAsset, { anchorX: 0, anchorY: 0.5, x: 2, scaleX: 796 // Width - 4 for padding }); // Label self.label = new Text2(isPlayer ? "YOU" : "CPU", { size: 40, fill: 0xFFFFFF }); self.label.anchor.set(0.5); self.label.x = barBg.width / 2; self.label.y = 0; self.addChild(self.label); self.updateHealth = function (amount) { self.health = Math.max(0, Math.min(100, self.health + amount)); tween(self.fillBar, { scaleX: 796 * (self.health / 100) }, { duration: 300, easing: tween.easeOut }); if (self.health <= 0) { return true; // Health depleted } return false; }; return self; }); var HitArea = Container.expand(function (direction) { var self = Container.call(this); self.direction = direction; self.isPressed = false; var hitBox = self.attachAsset('hitArea', { anchorX: 0.5, anchorY: 0.5, alpha: 0.3 }); var arrow = self.attachAsset('arrow_' + direction, { anchorX: 0.5, anchorY: 0.5, alpha: 0.7 }); // Rotate arrow based on direction if (direction === 'up') { arrow.rotation = 0; } else if (direction === 'down') { arrow.rotation = Math.PI; } else if (direction === 'left') { arrow.rotation = -Math.PI / 2; } else if (direction === 'right') { arrow.rotation = Math.PI / 2; } self.down = function (x, y, obj) { self.isPressed = true; hitBox.alpha = 0.7; game.handleInput(self.direction); }; self.up = function (x, y, obj) { self.isPressed = false; hitBox.alpha = 0.3; game.handleInputRelease(self.direction); }; self.setHighlight = function (highlight) { if (highlight) { tween(hitBox, { alpha: 0.7 }, { duration: 100 }); tween(arrow, { alpha: 1 }, { duration: 100 }); } else { tween(hitBox, { alpha: 0.3 }, { duration: 100 }); tween(arrow, { alpha: 0.7 }, { duration: 100 }); } }; return self; }); var RatingDisplay = Container.expand(function () { var self = Container.call(this); self.text = new Text2('', { size: 80, fill: 0xFFFFFF }); self.text.anchor.set(0.5); self.addChild(self.text); self.show = function (rating, score) { var ratingText = ''; var color = "#FFFFFF"; switch (rating) { case 'perfect': ratingText = 'PERFECT!'; color = "#00FFFF"; break; case 'good': ratingText = 'GOOD'; color = "#00FF00"; break; case 'okay': ratingText = 'OKAY'; color = "#FFFF00"; break; case 'miss': ratingText = 'MISS'; color = "#FF0000"; break; case 'hold_complete': ratingText = 'HOLD BONUS!'; color = "#FF00FF"; break; case 'hold_break': ratingText = 'HOLD BROKEN!'; color = "#FF8800"; break; } if (score && rating !== 'miss' && rating !== 'hold_break') { ratingText += '\n+' + score; } self.text.setText(ratingText); if (self.text.style) { self.text.style.fill = color; } else { self.text.setStyle({ fill: color }); } self.alpha = 1; self.scale.set(1.2); tween(self, { alpha: 0, y: self.y - 50 }, { duration: 800, easing: tween.easeOut }); tween(self.scale, { x: 1, y: 1 }, { duration: 300, easing: tween.elasticOut }); }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x222222 }); /**** * Game Code ****/ // Game variables var arrows = []; var hitAreas = {}; var activeHoldNotes = {}; var gameStarted = false; var score = 0; var combo = 0; var currentSong = 'song1'; var songBPM = 120; var noteSpeed = 10; var currentDifficulty = 1; var beatTimer = 0; var nextNoteTime = 0; var lastBeat = 0; var beatInterval = 60 / songBPM * 60; // Convert to frames var arrowTypes = ['up', 'down', 'left', 'right']; // Create game elements var playerCharacter, opponentCharacter; var playerHealth, opponentHealth; var ratingDisplay; var scoreText, comboText; var gameTimingBar; // Initialize game function initGame() { // Create UI elements scoreText = new Text2('SCORE: 0', { size: 60, fill: 0xFFFFFF }); scoreText.anchor.set(0.5, 0); scoreText.x = 2048 / 2; scoreText.y = 50; LK.gui.top.addChild(scoreText); comboText = new Text2('', { size: 50, fill: 0xFFFFFF }); comboText.anchor.set(0.5, 0); comboText.x = 2048 / 2; comboText.y = 120; LK.gui.top.addChild(comboText); // Create health bars playerHealth = new HealthBar(true); playerHealth.x = 150; playerHealth.y = 100; game.addChild(playerHealth); opponentHealth = new HealthBar(false); opponentHealth.x = 2048 - 950; opponentHealth.y = 100; game.addChild(opponentHealth); // Create characters playerCharacter = new Character(true); playerCharacter.x = 600; playerCharacter.y = 2732 - 100; game.addChild(playerCharacter); opponentCharacter = new Character(false); opponentCharacter.x = 2048 - 600; opponentCharacter.y = 2732 - 100; game.addChild(opponentCharacter); // Create hit areas var hitAreaY = 2732 - 300; var hitAreaSpacing = 220; var centerX = 2048 / 2; hitAreas.left = new HitArea('left'); hitAreas.left.x = centerX - hitAreaSpacing - hitAreaSpacing / 2; hitAreas.left.y = hitAreaY; game.addChild(hitAreas.left); hitAreas.down = new HitArea('down'); hitAreas.down.x = centerX - hitAreaSpacing / 2; hitAreas.down.y = hitAreaY; game.addChild(hitAreas.down); hitAreas.up = new HitArea('up'); hitAreas.up.x = centerX + hitAreaSpacing / 2; hitAreas.up.y = hitAreaY; game.addChild(hitAreas.up); hitAreas.right = new HitArea('right'); hitAreas.right.x = centerX + hitAreaSpacing + hitAreaSpacing / 2; hitAreas.right.y = hitAreaY; game.addChild(hitAreas.right); // Create rating display ratingDisplay = new RatingDisplay(); ratingDisplay.x = 2048 / 2; ratingDisplay.y = hitAreaY - 300; game.addChild(ratingDisplay); // Reset game state resetGameState(); // Start game startGame(); } function resetGameState() { score = 0; combo = 0; arrows = []; activeHoldNotes = {}; beatTimer = 0; nextNoteTime = 60; // Start with a small delay lastBeat = 0; updateScore(); updateCombo(); playerHealth.updateHealth(100 - playerHealth.health); opponentHealth.updateHealth(100 - opponentHealth.health); } function startGame() { gameStarted = true; LK.playMusic('Banger'); } // Arrow spawn pattern generators function generateRandomPattern() { var pattern = []; var numNotes = 1 + Math.floor(Math.random() * 2); // 1-2 notes at once // Add some randomness based on difficulty if (currentDifficulty > 1 && Math.random() < 0.3) { numNotes += 1; } // Occasionally add hold notes var shouldAddHold = currentDifficulty > 1 && Math.random() < 0.2; // Select random directions var usedDirections = {}; for (var i = 0; i < numNotes; i++) { var direction; do { direction = arrowTypes[Math.floor(Math.random() * arrowTypes.length)]; } while (usedDirections[direction]); usedDirections[direction] = true; var holdDuration = 0; if (shouldAddHold && i === 0) { // Only make one note a hold note at most holdDuration = 20 + Math.floor(Math.random() * 40); // Hold for 20-60 frames } pattern.push({ direction: direction, holdDuration: holdDuration }); } return pattern; } // Game input handlers game.handleInput = function (direction) { if (!gameStarted) return; var hitAreaY = hitAreas[direction].y; var closestArrow = null; var closestDistance = Infinity; // Find the closest arrow of the correct direction for (var i = 0; i < arrows.length; i++) { var arrow = arrows[i]; if (arrow.direction === direction && arrow.isActive && !arrow.wasHit) { var distance = Math.abs(arrow.y - hitAreaY); if (distance < closestDistance) { closestDistance = distance; closestArrow = arrow; } } } // Check if any arrow is close enough to hit if (closestArrow && closestDistance < 100) { // Determine rating based on distance var rating; var points = 0; if (closestDistance < 20) { rating = 'perfect'; points = 100; LK.getSound('perfect').play(); } else if (closestDistance < 50) { rating = 'good'; points = 50; LK.getSound('hit').play(); } else { rating = 'okay'; points = 25; LK.getSound('hit').play(); } // Apply combo bonus if (combo > 10) { points = Math.floor(points * (1 + combo / 100)); } // Hit the arrow var result = closestArrow.hit(rating); // Handle the result if (result === 'hold_start') { // Start tracking the hold note activeHoldNotes[direction] = closestArrow; hitAreas[direction].setHighlight(true); } else { // Regular note hit handleRating(result, points); } // Show player animation playerCharacter.setAction(); } else { // Check if we're re-pressing a hold note that was active if (activeHoldNotes[direction]) { activeHoldNotes[direction].holdActive = true; hitAreas[direction].setHighlight(true); } else { // Miss if no arrows to hit handleRating('miss', 0); LK.getSound('miss').play(); } } }; game.handleInputRelease = function (direction) { if (!gameStarted) return; hitAreas[direction].setHighlight(false); // Check if we're releasing a hold note if (activeHoldNotes[direction]) { activeHoldNotes[direction].holdActive = false; } }; game.handleMiss = function () { handleRating('miss', 0); LK.getSound('miss').play(); }; function handleRating(rating, points) { if (rating === 'miss' || rating === 'hold_break') { // Break combo on miss combo = 0; // Damage player health var gameOver = playerHealth.updateHealth(-5); if (gameOver) { endGame(false); } } else { // Increase combo combo++; // Add score score += points; // Damage opponent health var playerWon = opponentHealth.updateHealth(-5); if (playerWon) { endGame(true); } } // Show rating ratingDisplay.show(rating, points); // Update UI updateScore(); updateCombo(); } function updateScore() { scoreText.setText('SCORE: ' + score); } function updateCombo() { if (combo > 1) { comboText.setText('COMBO: ' + combo + 'x'); } else { comboText.setText(''); } } function spawnArrow(direction, holdDuration) { var hitAreaY = hitAreas[direction].y; var hitAreaX = hitAreas[direction].x; var arrow = new Arrow(direction, noteSpeed, holdDuration); arrow.x = hitAreaX; arrow.y = hitAreaY + 1000; // Start below screen game.addChild(arrow); arrows.push(arrow); } function endGame(playerWon) { gameStarted = false; LK.stopMusic(); if (playerWon) { LK.showYouWin(); } else { LK.showGameOver(); } } // Game update loop game.update = function () { if (!gameStarted) { return; } // Update beat timer beatTimer++; // Check if it's time to spawn a new set of arrows if (beatTimer >= nextNoteTime) { // Generate a pattern based on the current beat var pattern = generateRandomPattern(); // Spawn the arrows for (var i = 0; i < pattern.length; i++) { spawnArrow(pattern[i].direction, pattern[i].holdDuration); } // Opponent animation when they "hit" notes opponentCharacter.setAction(); // Set time for next note var beatMultiplier = 1; // Vary the timing for more complexity if (Math.random() < 0.3) { beatMultiplier = 0.5; // Eighth note } else if (Math.random() < 0.2) { beatMultiplier = 0.25; // Sixteenth note } else if (Math.random() < 0.1) { beatMultiplier = 2; // Half note } nextNoteTime += beatInterval * beatMultiplier; lastBeat = beatTimer; } // Update hold notes for (var direction in activeHoldNotes) { var holdNote = activeHoldNotes[direction]; if (holdNote) { var result = holdNote.updateHold(hitAreas[direction].isPressed); if (result === 'hold_complete') { // Hold was completed successfully handleRating('hold_complete', 150); activeHoldNotes[direction] = null; hitAreas[direction].setHighlight(false); } else if (result === 'hold_break') { // Hold was broken early handleRating('hold_break', 0); activeHoldNotes[direction] = null; hitAreas[direction].setHighlight(false); } } } // Update arrows for (var a = arrows.length - 1; a >= 0; a--) { var arrow = arrows[a]; if (!arrow.isActive) { arrows.splice(a, 1); arrow.destroy(); } } }; // Initialize the game on start initGame();
===================================================================
--- original.js
+++ change.js
@@ -449,9 +449,9 @@
opponentHealth.updateHealth(100 - opponentHealth.health);
}
function startGame() {
gameStarted = true;
- LK.playMusic(currentSong);
+ LK.playMusic('Banger');
}
// Arrow spawn pattern generators
function generateRandomPattern() {
var pattern = [];