User prompt
Cada 1 - 3 beats debe aparecer un enemigo al azar
User prompt
Al presionar el botón play, si está seleccionada "idol", que carguen sus assets dentro del juego. Si está seleccionada "idolKasumin", deben cargar los assets de "idolKasumin"
User prompt
Haz que ambas idols tengan el mismo tamaño, 160x200
User prompt
Baja las idols y el botón de play un poco más
User prompt
Si selecciono una idol, el asset "menuSelectionCharacter" debe desaparecer de la otra, y solo mostrarse en la que está seleccionada ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Usa el asset "menuSelectionCharacter" para remarcar a la idol seleccionada en el menú, y que el asset parpadea cada segundo con una animación smooth ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
En el menú, coloca al asset "idol" y "idolKasumin" una al lado de otra, en el centro de la pantalla, y mueve el botón de "play" un poco más abajo de ellas. Ambas idols podrán seleccionarse, apareciendo un recuadro que indique cuál esté seleccionada
User prompt
Haz que se tarden 4 segundos ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Cambia la velocidad de todos los enemigos, a qué tarden 5 segundos en llegar al recuadro de su color ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Después de un movimiento, cuando la idol vuelve al centro desaparece por un momento y aparece en su posición inicial, quiero que no desaparezca en ningún momento, y que cuando vuelva al centro esté en su posición original ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Replica el funcionamiento del asset "idolAttackDown" con el asset "idolAttackUp" cuando se mueve hacia arriba ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Replica el funcionamiento del asset "idolAttackRight" con el asset "idolAttackLeft" cuando se mueve hacia la izquierda ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Replica el funcionamiento del asset "idolAttackDown" con el asset "idolAttackRight" cuando se mueve hacia la derecha ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Aún no se muestra el asset "idolAttackDown"
User prompt
Haz que el asset "idolAttackDown" se muestre cuando la idol se mueva hacia el recuadro verde, y cuando vuelva al centro se coloque el asset original ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Haz que el asset "idolAttackDown" se muestre cuando la idol ataca hacia abajo ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Please fix the bug: 'Cannot read properties of undefined (reading 'texture')' in or related to this line: 'var originalIdolTexture = idolGraphics.texture;' Line Number: 287
User prompt
Agrega una animación para cuando la idol se mueve en su ataque, con un asset diferente para cada posición ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Haz que la idol también haga una pequeña animación cuando suena el BPM, al igual que los enemigos ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Si el enemigo llega al recuadro rojo y no es golpeado, debe seguir su dirección al centro hasta golpear a la idol ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Haz que cada enemigo se tarde 5 segundos en llegar a su recuadro respectivo. Ejemplo, el enemigo azul debe tardar 5 segundos en llegar al recuadro azul, y eso replica a los demás colores ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Cada vez que se llegue a un combo múltiplo de 25, se obtiene una vida adicional
User prompt
El asset "menuSong" solo debe sonar una vez
User prompt
Cuando inicie la aplicación, en el menú, debe ser el asset "menuSong". Cuando se presione el botón "play", debe sonar el asset "bgmusic"
User prompt
En el menú, solo debe sonar el assets "menuSong"
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var ActionButton = Container.expand(function (color, direction, keyText) {
var self = Container.call(this);
var assetName = color + 'Button';
var buttonGraphics = self.attachAsset(assetName, {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.3,
scaleY: 1.3
});
// Add invisible larger hitbox
var hitbox = LK.getAsset('beatIndicator', {
anchorX: 0.5,
anchorY: 0.5,
width: 320,
height: 230
});
hitbox.alpha = 0; // Make completely invisible
hitbox.tint = 0x000000; // Ensure it's invisible
self.addChild(hitbox);
// Key text removed - button functions without text display
self.color = color;
self.direction = direction;
self.isPressed = false;
self.activate = function () {
self.isPressed = true;
buttonGraphics.scaleX = 1.17; // 0.9 * 1.3 to maintain same press effect
buttonGraphics.scaleY = 1.17;
tween(buttonGraphics, {
scaleX: 1.3,
scaleY: 1.3
}, {
duration: 150
});
// Button activation visual feedback only - enemy destruction handled in processInput
self.isPressed = false;
};
self.isEnemyInHitZone = function (enemy) {
var hitZoneSize = 200;
var centerX = 1024;
var centerY = 1366;
if (enemy.direction === 'up' && enemy.y > centerY - hitZoneSize && enemy.y < centerY + hitZoneSize) {
return true;
} else if (enemy.direction === 'down' && enemy.y > centerY - hitZoneSize && enemy.y < centerY + hitZoneSize) {
return true;
} else if (enemy.direction === 'left' && enemy.x > centerX - hitZoneSize && enemy.x < centerX + hitZoneSize) {
return true;
} else if (enemy.direction === 'right' && enemy.x > centerX - hitZoneSize && enemy.x < centerX + hitZoneSize) {
return true;
}
return false;
};
self.down = function (x, y, obj) {
self.activate();
processInput(self.direction);
updateUI();
};
return self;
});
var BeatIndicator = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('beatIndicator', {
anchorX: 0.5,
anchorY: 0.5
});
self.pulse = function () {
graphics.scaleX = 1.5;
graphics.scaleY = 1.5;
tween(graphics, {
scaleX: 1,
scaleY: 1
}, {
duration: 200
});
};
return self;
});
var Enemy = Container.expand(function (color, direction) {
var self = Container.call(this);
var enemyAsset = color + 'Enemy';
var graphics = self.attachAsset(enemyAsset, {
anchorX: 0.5,
anchorY: 0.5
});
self.color = color;
self.direction = direction;
self.health = 3;
self.maxHealth = 3;
self.speed = 8.4; // Speed calculated to reach center in 5 seconds
self.baseSpeed = 8.4;
self.rhythmMultiplier = 1;
self.targetX = 1024; // Center X
self.targetY = 1200; // Center Y (matching idol position)
self.lastY = self.y;
self.lastX = self.x;
self.pulseWithBeat = function () {
tween(graphics, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: beatInterval / 4,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(graphics, {
scaleX: 1,
scaleY: 1
}, {
duration: beatInterval / 4,
easing: tween.easeIn
});
}
});
};
self.takeDamage = function () {
self.health--;
graphics.alpha = 0.5 + self.health / self.maxHealth * 0.5;
if (self.health <= 0) {
LK.effects.flashObject(self, 0xffffff, 300);
return true; // Enemy defeated
}
return false;
};
self.update = function () {
// Calculate rhythm-based speed - enemies move in sync with beat
var currentTime = Date.now();
var timeSinceLastBeat = (currentTime - lastBeatTime) % beatInterval;
var beatProgress = timeSinceLastBeat / beatInterval;
// Create pulsing movement that syncs with beat (faster on beat, slower between beats)
var beatSyncMultiplier = 0.5 + 0.8 * Math.abs(Math.sin(beatProgress * 2 * Math.PI));
self.rhythmMultiplier = beatSyncMultiplier;
var currentSpeed = self.baseSpeed * self.rhythmMultiplier;
// Move toward center based on direction
if (self.direction === 'up') {
self.y += currentSpeed; // Moving down from top
} else if (self.direction === 'down') {
self.y -= currentSpeed; // Moving up from bottom
} else if (self.direction === 'left') {
self.x += currentSpeed; // Moving right from left
} else if (self.direction === 'right') {
self.x -= currentSpeed; // Moving left from right
}
};
return self;
});
var InputZone = Container.expand(function (color, direction, keyText) {
var self = Container.call(this);
var assetName = color + 'Outline';
var background = self.attachAsset(assetName, {
anchorX: 0.5,
anchorY: 0.5
});
// Make background transparent to show only the outline
background.alpha = 0.3;
// Key text removed - zone functions without text display
self.color = color;
self.direction = direction;
self.active = false;
self.activate = function () {
self.active = true;
background.alpha = 0.8;
tween(background, {
alpha: 0.3
}, {
duration: 300
});
};
self.getColorValue = function () {
if (self.color === 'blue') {
return 0x0066ff;
}
if (self.color === 'yellow') {
return 0xffff00;
}
if (self.color === 'red') {
return 0xff0000;
}
if (self.color === 'green') {
return 0x00ff00;
}
return 0x0066ff;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x1a0d33
});
/****
* Game Code
****/
// Game state variables
var gameState = 'menu'; // menu, playing, gameOver
var lives = 3;
var score = 0;
var combo = 0;
var bpm = 120;
var beatInterval = 60 / bpm * 1000; // milliseconds per beat (500ms at 120 BPM)
var lastBeatTime = 0;
var beatTolerance = 100; // ms tolerance for timing - tighter for rhythm gameplay
var menuSongPlaying = false; // Flag to track if menuSong is currently playing
// Game objects
var idol;
var enemies = [];
var beatIndicator;
var inputZones = [];
var actionButtons = [];
var hearts = [];
var nextBeatTime = 0;
var beatCounter = 0; // Counter to track beats for enemy spawning
// Enemy configuration - blue, yellow, red and green
var enemyColors = ['blue', 'yellow', 'red', 'green'];
var enemyDirections = ['left', 'right', 'up', 'down'];
var colorDirectionMap = {
'blue': 'left',
// Blue enemies come from left
'yellow': 'right',
// Yellow enemies come from right
'red': 'up',
// Red enemies come from up
'green': 'down' // Green enemies come from down
};
var keyMappings = {
'left': 'A',
'right': 'D',
'up': 'W',
'down': 'S'
};
// Initialize background
var background = game.attachAsset('background', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0
});
// Initialize idol character
idol = game.addChild(LK.getAsset('idol', {
anchorX: 0.5,
anchorY: 0.5
}));
idol.x = 1024; // Center horizontally
idol.y = 1200; // Slightly above center vertically
// Add pulse animation method to idol
idol.pulseWithBeat = function () {
tween(idol, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: beatInterval / 4,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(idol, {
scaleX: 1,
scaleY: 1
}, {
duration: beatInterval / 4,
easing: tween.easeIn
});
}
});
};
// Initialize beat indicator
beatIndicator = game.addChild(new BeatIndicator());
beatIndicator.x = 1024;
beatIndicator.y = 150;
// Initialize input zones - blue on left, yellow on right, red on top, green on bottom
var zonePositions = [{
x: 824,
y: 1200
}, {
x: 1224,
y: 1200
}, {
x: 1024,
y: 1000
}, {
x: 1024,
y: 1400
}];
for (var i = 0; i < 4; i++) {
var zone = game.addChild(new InputZone(enemyColors[i], enemyDirections[i], keyMappings[enemyDirections[i]]));
zone.x = zonePositions[i].x;
zone.y = zonePositions[i].y;
inputZones.push(zone);
}
// Initialize action buttons at bottom of screen - blue, yellow, red and green buttons
var buttonPositions = [{
x: 824,
y: 2400
}, {
x: 1224,
y: 2400
}, {
x: 1024,
y: 2200
}, {
x: 1024,
y: 2600
}];
for (var i = 0; i < 4; i++) {
var button = game.addChild(new ActionButton(enemyColors[i], enemyDirections[i], keyMappings[enemyDirections[i]]));
button.x = buttonPositions[i].x;
button.y = buttonPositions[i].y;
actionButtons.push(button);
}
// Initialize UI
var scoreTitle = new Text2('Score', {
size: 36,
fill: 0xFFFFFF
});
scoreTitle.anchor.set(1, 0);
scoreTitle.x = -20; // Offset from right edge
scoreTitle.y = 10;
LK.gui.topRight.addChild(scoreTitle); // Hidden on menu
var scoreText = new Text2('0', {
size: 48,
fill: 0xFFFFFF
});
scoreText.anchor.set(1, 0);
scoreText.x = -20; // Offset from right edge
scoreText.y = 50; // Below the title
LK.gui.topRight.addChild(scoreText); // Hidden on menu
var comboText = new Text2('Combo: 0', {
size: 36,
fill: 0xFFFF00
});
comboText.anchor.set(0.5, 0);
LK.gui.top.addChild(comboText); // Hidden on menu
var livesText = new Text2('Lives: ' + lives, {
size: 36,
fill: 0xFFFFFF
});
livesText.anchor.set(0, 0);
livesText.x = 20; // Offset from left edge
livesText.y = 10;
// Initialize hearts display
for (var h = 0; h < lives; h++) {
var heart = LK.getAsset('heart', {
anchorX: 0.5,
anchorY: 0.5
});
heart.x = 1800 + h * 80; // Position hearts horizontally with spacing in top right
heart.y = 250; // Moved further down to avoid overlapping with score
game.addChild(heart);
hearts.push(heart);
}
// Menu elements
var menuContainer = game.addChild(new Container());
menuContainer.addChild(titleGraphic);
var playButton = menuContainer.addChild(new InputZone('green', 'down', 'PLAY')); // Using InputZone for rounded button
// Replace the background asset with the startButton asset
playButton.removeChild(playButton.children[0]); // Remove the default outline asset
playButton.attachAsset('startButton', {
// Add the startButton asset
anchorX: 0.5,
anchorY: 0.5,
scaleX: 3,
scaleY: 2
});
var playButtonText = new Text2('▶ PLAY', {
size: 60,
fill: 0xFFFFFF
});
playButtonText.anchor.set(0.5, 0.5);
playButton.addChild(playButtonText);
playButton.x = 1024;
playButton.y = 1400;
playButton.down = function (x, y, obj) {
gameState = 'playing';
menuContainer.visible = false;
// Stop menu music and start background music when game begins
LK.stopMusic();
menuSongPlaying = false;
LK.playMusic('bgmusic');
// Initialize beat timing
nextBeatTime = Date.now() + beatInterval;
lastBeatTime = Date.now();
beatCounter = 0;
// Reset game state
lives = 3;
score = 0;
combo = 0;
// Clear any existing enemies
for (var i = enemies.length - 1; i >= 0; i--) {
enemies[i].destroy();
enemies.splice(i, 1);
}
// Update visibility to show game elements
updateVisibility();
// Update UI to reflect reset state
updateUI();
};
// Initially hide game elements and show menu
function updateVisibility() {
var showGame = gameState === 'playing';
var showMenu = gameState === 'menu';
menuContainer.visible = showMenu;
idol.visible = showGame;
beatIndicator.visible = showGame;
for (var i = 0; i < inputZones.length; i++) {
inputZones[i].visible = showGame;
}
for (var i = 0; i < actionButtons.length; i++) {
actionButtons[i].visible = showGame;
}
for (var i = 0; i < hearts.length; i++) {
hearts[i].visible = showGame;
}
livesText.visible = showGame;
scoreTitle.visible = showGame;
scoreText.visible = showGame;
comboText.visible = showGame;
// Handle menu music
if (showMenu && !menuSongPlaying) {
LK.stopMusic(); // Stop any currently playing music first
LK.playMusic('menuSong');
menuSongPlaying = true;
} else if (showGame) {
// Stop menu music when transitioning to game
LK.stopMusic();
menuSongPlaying = false;
}
}
updateVisibility();
// Start menu music when application loads
if (!menuSongPlaying) {
LK.playMusic('menuSong');
menuSongPlaying = true;
}
// Input handling
var pressedKeys = {};
var inputBuffer = [];
function processInput(direction) {
// Check if input is on beat for bonus scoring
var currentTime = Date.now();
var timeToBeat = Math.abs((currentTime - lastBeatTime) % beatInterval - beatInterval / 2);
var isOnBeat = timeToBeat < beatTolerance;
var beatMultiplier = isOnBeat ? 2 : 1; // Double points for on-beat hits
// Find enemies of matching color that are in their corresponding color zones
var hitEnemy = null;
var minDistance = Infinity;
var hitZoneSize = 100; // Size of the color zone around center
var blueZoneX = 824; // Left zone X position
var yellowZoneX = 1224; // Right zone X position
var zoneY = 1200; // Zone Y position
for (var i = 0; i < enemies.length; i++) {
var enemy = enemies[i];
// Check if enemy color matches the button direction and enemy is coming from correct direction
var colorMatch = false;
if (direction === 'left' && enemy.color === 'blue' && enemy.direction === 'left') {
colorMatch = true;
}
if (direction === 'right' && enemy.color === 'yellow' && enemy.direction === 'right') {
colorMatch = true;
}
if (direction === 'up' && enemy.color === 'red' && enemy.direction === 'up') {
colorMatch = true;
}
if (direction === 'down' && enemy.color === 'green' && enemy.direction === 'down') {
colorMatch = true;
}
if (colorMatch) {
// Check if enemy is within the correct color zone boundaries
var zoneX = enemy.color === 'blue' ? blueZoneX : enemy.color === 'yellow' ? yellowZoneX : 1024;
var checkZoneY = enemy.color === 'red' ? 1000 : enemy.color === 'green' ? 1400 : zoneY;
var distanceCheck = enemy.color === 'red' || enemy.color === 'green' ? Math.abs(enemy.x - zoneX) < hitZoneSize && Math.abs(enemy.y - checkZoneY) < hitZoneSize : Math.abs(enemy.x - zoneX) < hitZoneSize && Math.abs(enemy.y - zoneY) < hitZoneSize;
if (distanceCheck) {
var distance = Math.sqrt(Math.pow(enemy.x - zoneX, 2) + Math.pow(enemy.y - checkZoneY, 2));
if (distance < minDistance) {
minDistance = distance;
hitEnemy = enemy;
}
}
}
}
if (hitEnemy) {
// Animate idol movement towards enemy direction
var originalX = idol.x;
var originalY = idol.y;
var moveDistance = 50;
var targetX = originalX;
var targetY = originalY;
// Calculate movement direction based on enemy direction
if (hitEnemy.direction === 'left') {
targetX = originalX - moveDistance;
} else if (hitEnemy.direction === 'right') {
targetX = originalX + moveDistance;
} else if (hitEnemy.direction === 'up') {
targetY = originalY - moveDistance;
} else if (hitEnemy.direction === 'down') {
targetY = originalY + moveDistance;
}
// Move idol towards enemy direction
tween(idol, {
x: targetX,
y: targetY
}, {
duration: 150,
easing: tween.easeOut,
onFinish: function onFinish() {
// Always return idol to center position (1024, 1200)
tween(idol, {
x: 1024,
y: 1200
}, {
duration: 200,
easing: tween.easeInOut
});
}
});
// Destroy enemy immediately on hit
var index = enemies.indexOf(hitEnemy);
if (index > -1) {
hitEnemy.destroy();
enemies.splice(index, 1);
// Calculate score: fixed 10 points per enemy
var enemyScore = 10;
score += enemyScore * beatMultiplier;
combo++;
// Check if combo reached a multiple of 25 for extra life
if (combo % 25 === 0 && combo > 0) {
lives++;
// Visual feedback for gaining a life
LK.effects.flashObject(idol, 0x00ff00, 500); // Green flash for extra life
LK.effects.flashScreen(0x00ff00, 300); // Green screen flash
// Update hearts display immediately
if (lives <= hearts.length) {
hearts[lives - 1].alpha = 1; // Show the new heart
}
}
// Visual feedback for on-beat hits
if (isOnBeat) {
LK.effects.flashObject(idol, 0xffff00, 200); // Golden flash for perfect timing
}
}
LK.getSound('hit').play();
} else {
// No matching enemy found in color zone
combo = 0;
LK.getSound('error').play();
}
// Find matching input zone and activate
for (var j = 0; j < inputZones.length; j++) {
var zone = inputZones[j];
var shouldActivate = false;
// Map button directions to color zones correctly
if (direction === 'left' && zone.color === 'blue') {
shouldActivate = true;
} // Blue button activates blue zone
else if (direction === 'right' && zone.color === 'yellow') {
shouldActivate = true;
} // Yellow button activates yellow zone
else if (direction === 'up' && zone.color === 'red') {
shouldActivate = true;
} // Red button activates red zone
else if (direction === 'down' && zone.color === 'green') {
shouldActivate = true;
} // Green button activates green zone
if (shouldActivate) {
zone.activate();
break;
}
}
// Also activate corresponding action button
for (var k = 0; k < actionButtons.length; k++) {
if (actionButtons[k].direction === direction) {
actionButtons[k].activate();
break;
}
}
updateUI();
}
function updateUI() {
scoreText.setText(score.toString());
livesText.setText('Lives: ' + lives);
comboText.setText('Combo: ' + combo);
// Update hearts display
for (var h = 0; h < hearts.length; h++) {
if (h < lives) {
hearts[h].alpha = 1; // Show heart
} else {
hearts[h].alpha = 0.3; // Dim lost hearts
}
}
}
function spawnEnemy() {
var colorIndex = Math.floor(Math.random() * enemyColors.length);
var color = enemyColors[colorIndex];
var direction = colorDirectionMap[color];
var enemy = game.addChild(new Enemy(color, direction));
// Position enemy at center of each edge based on direction
if (direction === 'up') {
enemy.x = 1024; // Center X of top edge
enemy.y = -100; // Above screen
} else if (direction === 'down') {
enemy.x = 1024; // Center X of bottom edge
enemy.y = 2832; // Below screen
} else if (direction === 'left') {
enemy.x = -100; // Left of screen
enemy.y = 1200; // Center Y of left edge
} else if (direction === 'right') {
enemy.x = 2148; // Right of screen
enemy.y = 1200; // Center Y of right edge
}
enemy.lastY = enemy.y;
enemy.lastX = enemy.x;
enemies.push(enemy);
}
// Touch controls removed - buttons now only activate when directly touched
game.down = function (x, y, obj) {
// Game down handler - buttons handle their own touch events
};
// Main game loop
game.update = function () {
if (gameState === 'menu') {
updateVisibility();
return;
}
if (gameState !== 'playing') {
return;
}
var currentTime = Date.now();
// Beat tracking
if (currentTime >= nextBeatTime) {
lastBeatTime = currentTime;
nextBeatTime = currentTime + beatInterval;
beatCounter++; // Increment beat counter
beatIndicator.pulse();
// Make all enemies pulse with the beat
for (var j = 0; j < enemies.length; j++) {
enemies[j].pulseWithBeat();
}
// Make idol pulse with the beat
idol.pulseWithBeat();
// Enemy spawning - spawn one enemy every 2 beats
if (beatCounter % 2 === 0) {
spawnEnemy();
}
}
// Update enemies
for (var i = enemies.length - 1; i >= 0; i--) {
var enemy = enemies[i];
// Check if enemy reached center (idol position)
var reachedCenter = false;
if (enemy.direction === 'up' && enemy.lastY < 1200 && enemy.y >= 1200) {
reachedCenter = true;
} else if (enemy.direction === 'down' && enemy.lastY > 1200 && enemy.y <= 1200) {
reachedCenter = true;
} else if (enemy.direction === 'left' && enemy.lastX < 1024 && enemy.x >= 1024) {
reachedCenter = true;
} else if (enemy.direction === 'right' && enemy.lastX > 1024 && enemy.x <= 1024) {
reachedCenter = true;
}
if (reachedCenter) {
lives--;
enemy.destroy();
enemies.splice(i, 1);
combo = 0;
LK.getSound('miss').play();
if (lives <= 0) {
gameState = 'gameOver';
LK.showGameOver();
return;
}
updateUI();
LK.effects.flashScreen(0xff0000, 500);
}
enemy.lastY = enemy.y;
enemy.lastX = enemy.x;
}
};
// Touch controls are already implemented above in game.down event handler
// No keyboard input needed for mobile-optimized game
;
var titleGraphic = LK.getAsset('titleGame', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 800,
width: 900,
height: 900
});
menuContainer.addChild(titleGraphic);
var idolGraphic = LK.getAsset('idol', {
anchorX: 0.5,
anchorY: 0.5,
width: 300,
height: 300
});
// Position the idol relative to the titleGraphic's top-left corner
idolGraphic.x = titleGraphic.x - titleGraphic.width / 2 + idolGraphic.width / 2 - 70; // Moved a bit left
idolGraphic.y = titleGraphic.y - titleGraphic.height / 2 + idolGraphic.height / 2 + 30; // Moved down slightly and up a little more
menuContainer.addChild(idolGraphic);
; ===================================================================
--- original.js
+++ change.js
@@ -127,10 +127,26 @@
}
return false;
};
self.update = function () {
- // Update last known positions for collision detection
- // Movement is now handled by tween animation in spawnEnemy function
+ // Calculate rhythm-based speed - enemies move in sync with beat
+ var currentTime = Date.now();
+ var timeSinceLastBeat = (currentTime - lastBeatTime) % beatInterval;
+ var beatProgress = timeSinceLastBeat / beatInterval;
+ // Create pulsing movement that syncs with beat (faster on beat, slower between beats)
+ var beatSyncMultiplier = 0.5 + 0.8 * Math.abs(Math.sin(beatProgress * 2 * Math.PI));
+ self.rhythmMultiplier = beatSyncMultiplier;
+ var currentSpeed = self.baseSpeed * self.rhythmMultiplier;
+ // Move toward center based on direction
+ if (self.direction === 'up') {
+ self.y += currentSpeed; // Moving down from top
+ } else if (self.direction === 'down') {
+ self.y -= currentSpeed; // Moving up from bottom
+ } else if (self.direction === 'left') {
+ self.x += currentSpeed; // Moving right from left
+ } else if (self.direction === 'right') {
+ self.x -= currentSpeed; // Moving left from right
+ }
};
return self;
});
var InputZone = Container.expand(function (color, direction, keyText) {
@@ -233,8 +249,27 @@
anchorY: 0.5
}));
idol.x = 1024; // Center horizontally
idol.y = 1200; // Slightly above center vertically
+// Add pulse animation method to idol
+idol.pulseWithBeat = function () {
+ tween(idol, {
+ scaleX: 1.1,
+ scaleY: 1.1
+ }, {
+ duration: beatInterval / 4,
+ easing: tween.easeOut,
+ onFinish: function onFinish() {
+ tween(idol, {
+ scaleX: 1,
+ scaleY: 1
+ }, {
+ duration: beatInterval / 4,
+ easing: tween.easeIn
+ });
+ }
+ });
+};
// Initialize beat indicator
beatIndicator = game.addChild(new BeatIndicator());
beatIndicator.x = 1024;
beatIndicator.y = 150;
@@ -562,30 +597,8 @@
var colorIndex = Math.floor(Math.random() * enemyColors.length);
var color = enemyColors[colorIndex];
var direction = colorDirectionMap[color];
var enemy = game.addChild(new Enemy(color, direction));
- // Define target positions for each color's zone
- var targetPositions = {
- 'blue': {
- x: 824,
- y: 1200
- },
- // Left zone (blue)
- 'yellow': {
- x: 1224,
- y: 1200
- },
- // Right zone (yellow)
- 'red': {
- x: 1024,
- y: 1000
- },
- // Top zone (red)
- 'green': {
- x: 1024,
- y: 1400
- } // Bottom zone (green)
- };
// Position enemy at center of each edge based on direction
if (direction === 'up') {
enemy.x = 1024; // Center X of top edge
enemy.y = -100; // Above screen
@@ -598,22 +611,10 @@
} else if (direction === 'right') {
enemy.x = 2148; // Right of screen
enemy.y = 1200; // Center Y of right edge
}
- // Store initial position for tracking
enemy.lastY = enemy.y;
enemy.lastX = enemy.x;
- // Get target position for this enemy's color
- var targetPos = targetPositions[color];
- // Use tween to move enemy to its target zone over 5 seconds
- tween(enemy, {
- x: targetPos.x,
- y: targetPos.y
- }, {
- duration: 5000,
- // 5 seconds
- easing: tween.linear
- });
enemies.push(enemy);
}
// Touch controls removed - buttons now only activate when directly touched
game.down = function (x, y, obj) {
@@ -638,40 +639,18 @@
// Make all enemies pulse with the beat
for (var j = 0; j < enemies.length; j++) {
enemies[j].pulseWithBeat();
}
+ // Make idol pulse with the beat
+ idol.pulseWithBeat();
// Enemy spawning - spawn one enemy every 2 beats
if (beatCounter % 2 === 0) {
spawnEnemy();
}
}
// Update enemies
for (var i = enemies.length - 1; i >= 0; i--) {
var enemy = enemies[i];
- // Check if red enemy reached its red zone and needs to continue to center
- var reachedRedZone = false;
- if (enemy.color === 'red' && enemy.direction === 'up' && !enemy.continuingToCenter) {
- if (enemy.lastY > 1000 && enemy.y <= 1000) {
- reachedRedZone = true;
- }
- }
- if (reachedRedZone) {
- // Red enemy reached red zone, now continue to center (idol position)
- enemy.continuingToCenter = true;
- tween.stop(enemy, {
- x: true,
- y: true
- }); // Stop current tween
- tween(enemy, {
- x: 1024,
- // Center X (idol position)
- y: 1200 // Center Y (idol position)
- }, {
- duration: 2000,
- // 2 seconds to reach center from red zone
- easing: tween.linear
- });
- }
// Check if enemy reached center (idol position)
var reachedCenter = false;
if (enemy.direction === 'up' && enemy.lastY < 1200 && enemy.y >= 1200) {
reachedCenter = true;
Flecha verde apuntando hacia abajo. In-Game asset. 2d. High contrast. No shadows
Flecha azul apuntando a la izquierda. In-Game asset. 2d. High contrast. No shadows
Flecha roja apuntando hacia arriba, con borde negro. In-Game asset. 2d. High contrast. No shadows
Flecha amarilla apuntando a la derecha. In-Game asset. 2d. High contrast. No shadows
Una mazmorra rocosa, sin contorno y de fondo se vean piedras algo difuminadas y una entrada a una mazmorra. In-Game asset. 2d. High contrast. No shadows. In-Game asset. 2d. High contrast. No shadows
Un panel cuadrado con contornos redondos, de color violeta. In-Game asset. 2d. High contrast. No shadows
Letras de color blanco, que digan "IDOL DUNGEON BEAT", que tengan un WordArt animado. En alta resolución para poner en una imagen 100 X 150 In-Game asset. 2d. High contrast. No shadows
espada dorada brillante, que da un toque de guerrera mágica o heroína valiente.. In-Game asset. 2d. High contrast. No shadows
Un recuadro blanco sin relleno interlineado. In-Game asset. 2d. High contrast. No shadows
Micrófono chibi, con un lazo rosado y una estrella como moño en el mango del micrófono. In-Game asset. 2d. High contrast. No shadows
Haz una animación en la que solo se vea su cara recortada, un aura de energía rosada rodeándola, y que aparezca como una viñeta que demuestre que está a punto de hacer su acción definitiva
Haz una animación en la que solo se vea su cara recortada, un aura de energía rosada rodeándola, y que aparezca como una viñeta que demuestre que está a punto de hacer su acción definitiva. Que escriba la palabra TWINKLE! abajo a la derecha. La imagen debe tener un fondo color blanco
Pintarlo de color verde
Recuadro de madera, parecido a un tablón de anuncios, animado. In-Game asset. 2d. High contrast. No shadows
Agrégale detalles en los ojos
Haz una animación simulando que ataca hacia la derecha con su escudo, y su mano y cuerpo debe seguir el movimiento del lanzamiento
Haz una animación simulando que ataca hacia abajo con su escudo, y su mano y cuerpo debe seguir el movimiento del golpe
Haz una animación en la que solo se vea su cara recortada, un aura de energía roja rodeándola, y que aparezca como una viñeta que demuestre que está a punto de hacer su acción definitiva. Que escriba la palabra SMILE! abajo a la derecha. La imagen debe tener un fondo color gris
hit
Sound effect
miss
Sound effect
error
Sound effect
bgmusic
Music
menuSong
Music
kasuminbgmusic
Music
ultimate
Sound effect
kasuminUltimate
Sound effect
IdolSelected
Sound effect
IdolKasuminSelected
Sound effect
maplebgmusic
Music
IdolMapleSelected
Sound effect
IdolMapleUltimate
Sound effect
hitKasumin
Sound effect
hitMaple
Sound effect