Code edit (1 edits merged)
Please save this source code
User prompt
audioOffset del nivel "tutorial" no se cambio como 0:00.00
User prompt
Haz que audioOffset: 0; de var niveles funcione como "0:00.00"
User prompt
haz que audioOffset de niveles se cuente como 0:00.00
User prompt
haz que audioOffset se cuente como 0:00.00
Code edit (1 edits merged)
Please save this source code
User prompt
Haz que audioOffset es el tiempo que tarda en empezar la música, si el tiempo es positivo se agrega segundos, negativo se resta (cuentalos como 0:00.00)
Code edit (1 edits merged)
Please save this source code
User prompt
agrega a niveles una especificacion para offset de audio y notes
User prompt
agrega a niveles un offset de audio y botones
User prompt
haz que al inicial el nivel empiece andar tanto el reloj como la musica
User prompt
Crea un mnu inicial
User prompt
Please fix the bug: 'TypeError: Cannot read properties of undefined (reading 'setText')' in or related to this line: 'timerText.setText(timeString);' Line Number: 464
User prompt
Crea un menu inicial
User prompt
Crea un menu inicial
User prompt
elimina la canción de fondo
User prompt
agrega a niveles un ID
User prompt
agrega a addnote a que nivel pertenecen asi forzar su aparición allí. addNote(nivel, time, x, y)
User prompt
crea una variable de objeto llamada niveles donde salen: Nombre, canción, puntuación max.
User prompt
agrega audio offset y noteoffset
User prompt
agrega un boton play al principio
Code edit (2 edits merged)
Please save this source code
User prompt
Agrega musica de fondo
Code edit (1 edits merged)
Please save this source code
User prompt
Asegúrate que las notas solo se puedan presionar si son 1 y que las que no son tengan un 0.8 de transparencia
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ var Note = Container.expand(function () { var self = Container.call(this); var hitZone = self.attachAsset('hit', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.6, scaleY: 1.6 }); hitZone.alpha = 0.4; var hitAccuracy = self.attachAsset('hit', { anchorX: 0.5, anchorY: 0.5, scaleX: 2.5, scaleY: 2.5 }); hitAccuracy.alpha = 0.25; var hitAccuracyTargetScale = 1.6; var hitAccuracyStartScale = 3.4; hitAccuracy.scaleX = hitAccuracyStartScale; hitAccuracy.scaleY = hitAccuracyStartScale; tween(hitAccuracy, { scaleX: hitAccuracyTargetScale, scaleY: hitAccuracyTargetScale }, { duration: 1000 / speed }); var noteAsset = self.attachAsset('note', { anchorX: 0.5, anchorY: 0.5 }); self.numberText = new Text2('1', { size: 150, fill: 0x000000 }); self.numberText.anchor.set(0.5, 0.5); self.addChild(self.numberText); self.setNumber = function (num) { self.numberText.setText(num.toString()); }; var margin = 100; self.x = margin + Math.random() * (2048 - 2 * margin); self.y = margin + Math.random() * (2732 - 2 * margin); var MARVELOUS_WINDOW = 30; var PERFECT_WINDOW = 70; var GOOD_WINDOW = 120; var BAD_WINDOW = 180; var FAIL_WINDOW = 250; self.spawnTime = Date.now(); self.hitZoneTime = self.spawnTime + 1000 / speed; function showFeedback(result, msValue) { var colorMap = { marvelous: 0x00fffc, perfect: 0x00ff00, good: 0xffff00, bad: 0xffa500, fail: 0xff0000 }; var color = colorMap[result] || 0xffffff; var msText = ""; if (typeof msValue === "number") { var msAbs = Math.abs(Math.round(msValue)); msText = " / " + (msValue > 0 ? "-" : "") + msAbs + "ms"; } var feedback = new Text2(result.toUpperCase() + msText, { size: 120, fill: "#" + ("000000" + color.toString(16)).slice(-6) }); feedback.anchor.set(0.5, 0); feedback.x = 2048 / 2; feedback.y = 120; game.addChild(feedback); tween(feedback, { alpha: 0, y: feedback.y - 60 }, { duration: 500 }); LK.setTimeout(function () { feedback.destroy(); }, 500); } self.down = function (x, y, obj) { // Only allow if this note is the first in activeNotes if (activeNotes.length === 0 || activeNotes[0] !== self) { // Not the first note, ignore press return; } var now = Date.now(); var msDiff = now - self.hitZoneTime; var absMs = Math.abs(msDiff); var result = "fail"; if (absMs <= MARVELOUS_WINDOW) { result = "marvelous"; marvelousCount++; } else if (absMs <= PERFECT_WINDOW) { result = "perfect"; perfectCount++; } else if (absMs <= GOOD_WINDOW) { result = "good"; goodCount++; } else if (absMs <= BAD_WINDOW) { result = "bad"; badCount++; } else if (absMs <= FAIL_WINDOW) { result = "fail"; failCount++; } if (now < self.spawnTime + 0.2 * (self.hitZoneTime - self.spawnTime)) { result = "fail"; failCount++; } updateAccuracyDisplay(); LK.getSound('hitSound').play(); showFeedback(result, msDiff); removeNoteFromActive(self); self.destroy(); }; self.update = function () { var now = Date.now(); if (now - self.hitZoneTime > FAIL_WINDOW) { failCount++; updateAccuracyDisplay(); showFeedback("fail", undefined); removeNoteFromActive(self); self.destroy(); } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x000000 }); /**** * Game Code ****/ // Niveles: lista de niveles con id, nombre, canción y puntuación máxima var niveles = [{ id: 0, nombre: "Tutorial", cancion: "Tutorial", puntuacionMax: 0 } // Puedes agregar más niveles aquí ]; var ms; var time = 0; var gameStartTime; var gameStart; var timerText; var speed = 1.3; var note; var life = 100; var combo = 0; var score = 0; var marvelousCount = 0; var perfectCount = 0; var goodCount = 0; var badCount = 0; var failCount = 0; var noteCounter = 0; var activeNotes = []; // === Audio and Note Offsets === var audioOffset = 0; // in milliseconds, positive delays music, negative advances var noteOffset = 0; // in milliseconds, positive delays notes, negative advances var accuracyDisplayConfig = [{ label: 'Marvelous', color: 0x00FFFC, yOffset: -300, type: 'marvelous' }, { label: 'Perfect', color: 0x00FF00, yOffset: -240, type: 'perfect' }, { label: 'Good', color: 0xFFFF00, yOffset: -180, type: 'good' }, { label: 'Bad', color: 0xFFA500, yOffset: -120, type: 'bad' }, { label: 'Fail', color: 0xFF0000, yOffset: -60, type: 'fail' }]; var accuracyTexts = {}; function createAccuracyText(label, color, yOffset) { var txt = new Text2(label + ': 0', { size: 40, fill: color }); txt.anchor.set(1, 0); txt.x = -20; txt.y = yOffset; LK.gui.bottomRight.addChild(txt); return txt; } // Reusable function to create notes at specific times var scheduledNotes = []; function addNote(nivel, timeString, x, y) { // Convert time string format "M:SS.CC" or "MM:SS.CC" to milliseconds var parts = timeString.split(':'); var minutes = parseInt(parts[0]); var secondsParts = parts[1].split('.'); var seconds = parseInt(secondsParts[0]); var centiseconds = parseInt(secondsParts[1]); var totalMs = minutes * 60 * 1000 + seconds * 1000 + centiseconds * 10; scheduledNotes.push({ nivel: nivel, time: totalMs, created: false, x: x, y: y }); } function createNoteAtPosition(x, y) { var newNote = new Note(); // Use random position if x is undefined, null, or 0 if (x === undefined || x === null || x === 0) { newNote.x = 100 + Math.random() * (2048 - 200); } else { newNote.x = x; } // Use random position if y is undefined, null, or 0 if (y === undefined || y === null || y === 0) { newNote.y = 100 + Math.random() * (2732 - 200); } else { newNote.y = y; } noteCounter++; newNote.orderNumber = noteCounter; newNote.setNumber(activeNotes.length + 1); activeNotes.push(newNote); // Set alpha and interactivity: only first note is fully opaque and interactive if (activeNotes.length === 1) { newNote.alpha = 1; newNote.interactive = true; } else { newNote.alpha = 0.8; newNote.interactive = false; } game.addChild(newNote); return newNote; } function updateNoteNumbers() { for (var i = 0; i < activeNotes.length; i++) { activeNotes[i].setNumber(i + 1); // Only the first note is fully opaque and interactive if (i === 0) { activeNotes[i].alpha = 1; activeNotes[i].interactive = true; } else { activeNotes[i].alpha = 0.8; activeNotes[i].interactive = false; } } } function removeNoteFromActive(note) { var index = activeNotes.indexOf(note); if (index > -1) { activeNotes.splice(index, 1); updateNoteNumbers(); } } accuracyDisplayConfig.forEach(function (cfg) { accuracyTexts[cfg.type] = createAccuracyText(cfg.label, cfg.color, cfg.yOffset); }); function updateAccuracyDisplay() { accuracyTexts.marvelous.setText('Marvelous: ' + marvelousCount); accuracyTexts.perfect.setText('Perfect: ' + perfectCount); accuracyTexts.good.setText('Good: ' + goodCount); accuracyTexts.bad.setText('Bad: ' + badCount); accuracyTexts.fail.setText('Fail: ' + failCount); } /* * Initializations */ // --- MENU STATE --- var menuContainer = new Container(); var menuTitle = new Text2("RHYTHM GAME", { size: 120, fill: 0xFFFFFF }); menuTitle.anchor.set(0.5, 0); menuTitle.x = 2048 / 2; menuTitle.y = 200; menuContainer.addChild(menuTitle); var levelButtons = []; var buttonStartY = 500; var buttonSpacing = 180; for (var i = 0; i < niveles.length; i++) { (function (idx) { var nivel = niveles[idx]; var btn = LK.getAsset('button', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: buttonStartY + idx * buttonSpacing, scaleX: 2.5, scaleY: 2.5 }); var btnText = new Text2(nivel.nombre, { size: 60, fill: 0x000000 }); btnText.anchor.set(0.5, 0.5); btnText.x = btn.x; btnText.y = btn.y; btn.interactive = true; btn.down = function (x, y, obj) { startGameWithLevel(idx); }; menuContainer.addChild(btn); menuContainer.addChild(btnText); levelButtons.push(btn); })(i); } game.addChild(menuContainer); // --- GAME STATE --- var gameStarted = false; function startGameWithLevel(levelIdx) { // Hide menu menuContainer.visible = false; gameStarted = true; // Reset state gameStartTime = Date.now(); marvelousCount = 0; perfectCount = 0; goodCount = 0; badCount = 0; failCount = 0; noteCounter = 0; activeNotes = []; score = 0; combo = 0; for (var k = 0; k < scheduledNotes.length; k++) { scheduledNotes[k].created = false; } updateAccuracyDisplay(); // Show timer timerText.visible = true; } // Timer text (hidden until game starts) timerText = new Text2('0:00.00', { size: 60, fill: 0xFFFFFF }); timerText.anchor.set(0.5, 0); timerText.x = 0; timerText.y = 50; LK.gui.top.addChild(timerText); timerText.visible = false; // Add notes for Tutorial (nivel 0) as example addNote(0, "0:01.75", 0, 0); addNote(0, "0:03.75", 0, 0); addNote(0, "0:05.75", 0, 0); addNote(0, "0:07.75", 0, 0); addNote(0, "0:09.75", 0, 0); addNote(0, "0:11.75", 0, 0); addNote(0, "0:13.75", 0, 0); addNote(0, "0:15.75", 0, 0); game.update = function () { if (!gameStarted) { // Menu is active, do not run game logic return; } var currentTime = Date.now(); var elapsedMs = currentTime - gameStartTime; // Apply noteOffset to note timing var adjustedElapsedMs = elapsedMs + noteOffset; var totalSeconds = Math.floor(elapsedMs / 1000); var minutes = Math.floor(totalSeconds / 60); var seconds = totalSeconds % 60; var centiseconds = Math.floor(elapsedMs % 1000 / 10); var timeString = minutes + ':' + (seconds < 10 ? '0' : '') + seconds + '.' + (centiseconds < 10 ? '0' : '') + centiseconds; timerText.setText(timeString); // Check scheduled notes for (var i = 0; i < scheduledNotes.length; i++) { var scheduled = scheduledNotes[i]; if (!scheduled.created && adjustedElapsedMs >= scheduled.time) { createNoteAtPosition(scheduled.x, scheduled.y); scheduled.created = true; } } };
===================================================================
--- original.js
+++ change.js
@@ -158,18 +158,9 @@
var ms;
var time = 0;
var gameStartTime;
var gameStart;
-// Initialize timerText as a global Text2 object and add to GUI
-var timerText = new Text2("0:00.00", {
- size: 90,
- fill: 0xFFFFFF
-});
-timerText.anchor.set(1, 0);
-timerText.x = -20;
-timerText.y = -20;
-LK.gui.topRight.addChild(timerText);
-timerText.visible = false;
+var timerText;
var speed = 1.3;
var note;
var life = 100;
var combo = 0;
@@ -303,134 +294,82 @@
* Initializations
*/
// --- MENU STATE ---
var menuContainer = new Container();
-var menuBg = LK.getAsset('note', {
- anchorX: 0.5,
- anchorY: 0.5
-});
-menuBg.width = 900;
-menuBg.height = 1200;
-menuBg.x = 2048 / 2;
-menuBg.y = 2732 / 2;
-menuBg.alpha = 0.15;
-menuContainer.addChild(menuBg);
-var titleText = new Text2("RHYTHM GAME", {
+var menuTitle = new Text2("RHYTHM GAME", {
size: 120,
- fill: 0x00FFFC
+ fill: 0xFFFFFF
});
-titleText.anchor.set(0.5, 0);
-titleText.x = 2048 / 2;
-titleText.y = 350;
-menuContainer.addChild(titleText);
+menuTitle.anchor.set(0.5, 0);
+menuTitle.x = 2048 / 2;
+menuTitle.y = 200;
+menuContainer.addChild(menuTitle);
var levelButtons = [];
-var selectedLevel = 0;
-var buttonStartY = 600;
+var buttonStartY = 500;
var buttonSpacing = 180;
for (var i = 0; i < niveles.length; i++) {
(function (idx) {
- var lvl = niveles[idx];
+ var nivel = niveles[idx];
var btn = LK.getAsset('button', {
anchorX: 0.5,
- anchorY: 0.5
+ anchorY: 0.5,
+ x: 2048 / 2,
+ y: buttonStartY + idx * buttonSpacing,
+ scaleX: 2.5,
+ scaleY: 2.5
});
- btn.x = 2048 / 2;
- btn.y = buttonStartY + idx * buttonSpacing;
+ var btnText = new Text2(nivel.nombre, {
+ size: 60,
+ fill: 0x000000
+ });
+ btnText.anchor.set(0.5, 0.5);
+ btnText.x = btn.x;
+ btnText.y = btn.y;
btn.interactive = true;
- btn.levelId = lvl.id;
- btn.levelIdx = idx;
- btn.alpha = 0.85;
btn.down = function (x, y, obj) {
- // Highlight selected
- for (var j = 0; j < levelButtons.length; j++) {
- levelButtons[j].alpha = 0.85;
- }
- btn.alpha = 1;
- selectedLevel = btn.levelIdx;
- for (var j = 0; j < levelButtons.length; j++) {
- levelButtons[j].levelNameText.fill = "#000000";
- }
- btn.levelNameText.fill = "#00FFFC";
+ startGameWithLevel(idx);
};
- // Level name
- var nameText = new Text2(lvl.nombre, {
- size: 60,
- fill: idx === 0 ? "#00FFFC" : "#000000"
- });
- nameText.anchor.set(0.5, 0.5);
- nameText.x = btn.x;
- nameText.y = btn.y;
- btn.levelNameText = nameText;
menuContainer.addChild(btn);
- menuContainer.addChild(nameText);
+ menuContainer.addChild(btnText);
levelButtons.push(btn);
})(i);
}
-// Play button
-var playBtn = LK.getAsset('button', {
- anchorX: 0.5,
- anchorY: 0.5
-});
-playBtn.x = 2048 / 2;
-playBtn.y = buttonStartY + niveles.length * buttonSpacing + 100;
-playBtn.interactive = true;
-menuContainer.addChild(playBtn);
-var playText = new Text2("JUGAR", {
- size: 70,
- fill: 0x000000
-});
-playText.anchor.set(0.5, 0.5);
-playText.x = playBtn.x;
-playText.y = playBtn.y;
-menuContainer.addChild(playText);
-// Add menu to game
game.addChild(menuContainer);
-// Hide gameplay UI until game starts
-if (typeof timerText !== "undefined") timerText.visible = false;
-for (var key in accuracyTexts) {
- if (accuracyTexts[key]) accuracyTexts[key].visible = false;
-}
-// Start game function
-function startGameFromMenu() {
+// --- GAME STATE ---
+var gameStarted = false;
+function startGameWithLevel(levelIdx) {
// Hide menu
menuContainer.visible = false;
- // Show gameplay UI
- if (typeof timerText !== "undefined") timerText.visible = true;
- for (var key in accuracyTexts) {
- if (accuracyTexts[key]) accuracyTexts[key].visible = true;
- }
+ gameStarted = true;
// Reset state
gameStartTime = Date.now();
- noteCounter = 0;
- activeNotes = [];
marvelousCount = 0;
perfectCount = 0;
goodCount = 0;
badCount = 0;
failCount = 0;
- updateAccuracyDisplay();
- // Remove all notes from previous game
- for (var i = game.children.length - 1; i >= 0; i--) {
- var ch = game.children[i];
- if (ch && ch instanceof Container && ch !== menuContainer) {
- if (typeof ch.setNumber === "function") {
- ch.destroy();
- }
- }
+ noteCounter = 0;
+ activeNotes = [];
+ score = 0;
+ combo = 0;
+ for (var k = 0; k < scheduledNotes.length; k++) {
+ scheduledNotes[k].created = false;
}
- // Reset scheduled notes
- for (var i = 0; i < scheduledNotes.length; i++) {
- scheduledNotes[i].created = false;
- }
+ updateAccuracyDisplay();
+ // Show timer
+ timerText.visible = true;
}
-// Play button event
-playBtn.down = function (x, y, obj) {
- startGameFromMenu();
-};
-// --- END MENU STATE ---
-// Only add notes for the selected level when game starts
-// Example usage: addNote(nivel, "0:01.00") will create a note at 1 second for the given nivel
-// Add 5 random notes for nivel 0 (Tutorial)
+// Timer text (hidden until game starts)
+timerText = new Text2('0:00.00', {
+ size: 60,
+ fill: 0xFFFFFF
+});
+timerText.anchor.set(0.5, 0);
+timerText.x = 0;
+timerText.y = 50;
+LK.gui.top.addChild(timerText);
+timerText.visible = false;
+// Add notes for Tutorial (nivel 0) as example
addNote(0, "0:01.75", 0, 0);
addNote(0, "0:03.75", 0, 0);
addNote(0, "0:05.75", 0, 0);
addNote(0, "0:07.75", 0, 0);
@@ -438,10 +377,12 @@
addNote(0, "0:11.75", 0, 0);
addNote(0, "0:13.75", 0, 0);
addNote(0, "0:15.75", 0, 0);
game.update = function () {
- // If menu is visible, do not run gameplay
- if (menuContainer.visible) return;
+ if (!gameStarted) {
+ // Menu is active, do not run game logic
+ return;
+ }
var currentTime = Date.now();
var elapsedMs = currentTime - gameStartTime;
// Apply noteOffset to note timing
var adjustedElapsedMs = elapsedMs + noteOffset;
@@ -450,12 +391,11 @@
var seconds = totalSeconds % 60;
var centiseconds = Math.floor(elapsedMs % 1000 / 10);
var timeString = minutes + ':' + (seconds < 10 ? '0' : '') + seconds + '.' + (centiseconds < 10 ? '0' : '') + centiseconds;
timerText.setText(timeString);
- // Check scheduled notes for selected level only
+ // Check scheduled notes
for (var i = 0; i < scheduledNotes.length; i++) {
var scheduled = scheduledNotes[i];
- if (scheduled.nivel !== niveles[selectedLevel].id) continue;
if (!scheduled.created && adjustedElapsedMs >= scheduled.time) {
createNoteAtPosition(scheduled.x, scheduled.y);
scheduled.created = true;
}