User prompt
Increase all mode difficulties.
User prompt
Change the maximum number of notes that can appear on screen at the same time between modes.
User prompt
Prevent getting points when the end screen appears.
User prompt
Prevent buttons that appear at the bottom from appearing in the start menu when the game restarts. Set the duration to 60 seconds.
User prompt
Add the text "Easy mode selected" in red.
User prompt
Add the text Easy mode selected. Also, there should be clear differences between the modes, such as the speed of the notes. The duration should be the same in all of them.
User prompt
Move the difficulty selection buttons below the "select difficulty" text. Indicate this when difficulty is selected. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Move "Select difficulty" text to bottom. Prevent game from starting without difficulty selected.
User prompt
Edit the mode selector keys. Move them down a bit and show them as text only.
User prompt
Edit and animate the difficulty selection screen. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Add the game 4 different difficulty modes.
User prompt
When the end screen comes out, hit all the notes
User prompt
Increases the maximum number of notes visible at once to 5.
User prompt
Remove line effect ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Add a timer feature in the start menu, just below and slightly to the right of the "start" button.
User prompt
Add a time setting to the bottom and right side of the "Start" button on the start screen.
User prompt
Create a time setting in the start menu. ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
Show combo counter under score when game over.
User prompt
Add combo and explosion effect ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Add explosion effects ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Remove flash animation ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Add more effects. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Speed up the notes a little bit
User prompt
The animation should be a different color each time. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
The animation should spread out smoothly and slowly across the entire screen. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Button = Container.expand(function (lane) {
var self = Container.call(this);
self.lane = lane;
self.isPressed = false;
self.buttonGraphics = self.attachAsset('button', {
anchorX: 0.5,
anchorY: 0.5
});
// Position at bottom of lane
self.x = lane * (2048 / 3) + 2048 / 6;
self.y = 2732 - 200;
self.down = function (x, y, obj) {
self.press();
};
self.press = function () {
if (self.isPressed) return;
self.isPressed = true;
self.buttonGraphics.alpha = 0.7;
// Check for notes in this lane
var hitNote = null;
var bestDistance = Infinity;
for (var i = 0; i < notes.length; i++) {
var note = notes[i];
if (note.lane === self.lane && !note.hasBeenHit && note.y >= timingLineY) {
var distance = Math.abs(note.y - self.y);
if (distance < bestDistance) {
bestDistance = distance;
hitNote = note;
}
}
}
if (hitNote) {
hitNote.hasBeenHit = true;
// Calculate points based on timing
var points = 0;
var feedbackText = '';
if (bestDistance <= 150) {
// Perfect hit - note is on button
points = 100;
feedbackText = 'PERFECT';
} else if (bestDistance <= 250) {
// Great hit - note is between timing line and button
points = 50;
feedbackText = 'GREAT';
}
if (points > 0) {
LK.setScore(LK.getScore() + points);
scoreTxt.setText(LK.getScore());
LK.getSound('hit').play();
// Update combo (hit)
updateCombo(true);
// Visual feedback
LK.effects.flashObject(hitNote, 0xffffff, 200);
// Create explosion effect at note position
var explosionColor = feedbackText === 'PERFECT' ? 0xFFD700 : 0x00FFFF;
createExplosion(hitNote.x, hitNote.y, explosionColor);
// Show feedback text
feedbackTxt.setText(feedbackText);
feedbackTxt.alpha = 1;
tween(feedbackTxt, {
alpha: 0
}, {
duration: 800
});
// Create floating score animation
var scoreText = new Text2('+' + points, {
size: 50,
fill: explosionColor
});
scoreText.anchor.set(0.5, 0.5);
scoreText.x = hitNote.x;
scoreText.y = hitNote.y;
scoreText.alpha = 1;
game.addChild(scoreText);
// Animate floating score
tween(scoreText, {
y: scoreText.y - 150,
alpha: 0,
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 1000,
easing: tween.easeOut,
onFinish: function onFinish() {
if (scoreText && scoreText.parent) {
scoreText.destroy();
}
}
});
// Special animations for GREAT and PERFECT
if (feedbackText === 'PERFECT') {
// Perfect animation: scale up and spin with color change
var originalScale = self.buttonGraphics.scaleX;
var originalTint = self.buttonGraphics.tint;
self.buttonGraphics.tint = 0xFFD700; // Gold color
tween(self.buttonGraphics, {
scaleX: originalScale * 1.5,
scaleY: originalScale * 1.5,
rotation: Math.PI * 2
}, {
duration: 600,
easing: tween.elasticOut,
onFinish: function onFinish() {
tween(self.buttonGraphics, {
scaleX: originalScale,
scaleY: originalScale,
rotation: 0,
tint: originalTint
}, {
duration: 200
});
}
});
// Create perfect ring animation around button
var perfectRing = game.addChild(LK.getAsset('button', {
anchorX: 0.5,
anchorY: 0.5
}));
perfectRing.x = self.x;
perfectRing.y = self.y;
perfectRing.tint = 0xFFD700;
perfectRing.alpha = 0.8;
perfectRing.scaleX = 0.5;
perfectRing.scaleY = 0.5;
// Animate ring expanding outward while fading
tween(perfectRing, {
scaleX: 3.0,
scaleY: 3.0,
alpha: 0
}, {
duration: 800,
easing: tween.easeOut,
onFinish: function onFinish() {
if (perfectRing && perfectRing.parent) {
perfectRing.destroy();
}
}
});
} else if (feedbackText === 'GREAT') {
// Great animation: pulse and glow effect
var originalScale = self.buttonGraphics.scaleX;
var originalTint = self.buttonGraphics.tint;
self.buttonGraphics.tint = 0x00FFFF; // Cyan color
tween(self.buttonGraphics, {
scaleX: originalScale * 1.3,
scaleY: originalScale * 1.3
}, {
duration: 300,
easing: tween.bounceOut,
onFinish: function onFinish() {
tween(self.buttonGraphics, {
scaleX: originalScale,
scaleY: originalScale,
tint: originalTint
}, {
duration: 300,
easing: tween.easeOut
});
}
});
}
// Remove the note immediately
hitNote.destroy();
var noteIndex = notes.indexOf(hitNote);
if (noteIndex !== -1) {
notes.splice(noteIndex, 1);
}
}
}
// Reset button after short delay
LK.setTimeout(function () {
self.isPressed = false;
self.buttonGraphics.alpha = 1.0;
}, 100);
};
return self;
});
var Note = Container.expand(function (lane, type) {
var self = Container.call(this);
self.lane = lane;
self.type = type;
self.hasBeenHit = false;
// Get speed multiplier from current difficulty
var speedMultiplier = currentDifficulty !== -1 ? difficulties[currentDifficulty].noteSpeedMultiplier : 1.0;
// Set speed and asset based on type
if (type === 'slow') {
self.speed = 8 * speedMultiplier;
self.noteGraphics = self.attachAsset('slowNote', {
anchorX: 0.5,
anchorY: 0.5
});
} else if (type === 'medium') {
self.speed = 12 * speedMultiplier;
self.noteGraphics = self.attachAsset('mediumNote', {
anchorX: 0.5,
anchorY: 0.5
});
} else if (type === 'fast') {
self.speed = 16 * speedMultiplier;
self.noteGraphics = self.attachAsset('fastNote', {
anchorX: 0.5,
anchorY: 0.5
});
}
// Position in lane
self.x = lane * (2048 / 3) + 2048 / 6;
self.y = 0;
self.update = function () {
self.y += self.speed;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000000
});
/****
* Game Code
****/
// Game state management
var gameState = 'menu'; // 'menu', 'playing', or 'gameOver'
var startButton;
var gameOverButton;
var difficultyButtons = [];
var currentDifficulty = -1; // -1=None selected, 0=Easy, 1=Medium, 2=Hard, 3=Expert
var difficultySelected = false;
var difficulties = [{
name: 'EASY',
spawnInterval: 180,
maxNotes: 2,
timeLimit: 60,
noteSpeedMultiplier: 0.6,
color: 0x00FF00
}, {
name: 'MEDIUM',
spawnInterval: 135,
maxNotes: 3,
timeLimit: 60,
noteSpeedMultiplier: 0.8,
color: 0xFFFF00
}, {
name: 'HARD',
spawnInterval: 90,
maxNotes: 4,
timeLimit: 60,
noteSpeedMultiplier: 1.0,
color: 0xFF8800
}, {
name: 'EXPERT',
spawnInterval: 60,
maxNotes: 5,
timeLimit: 60,
noteSpeedMultiplier: 1.3,
color: 0xFF0000
}];
// Game variables
var notes = [];
var buttons = [];
var maxNotes = 5;
var spawnTimer = 0;
var spawnInterval = 120; // frames between spawns
var timingLineY = 2732 - 500;
var bottomLineY = 2732 - 2; // Position miss line at bottom edge of screen
// Create lane separators
var lane1 = game.addChild(LK.getAsset('lane', {
anchorX: 0.5,
anchorY: 0
}));
lane1.x = 2048 / 3;
lane1.y = 0;
lane1.visible = false; // Hide initially
var lane2 = game.addChild(LK.getAsset('lane', {
anchorX: 0.5,
anchorY: 0
}));
lane2.x = 2048 / 3 * 2;
lane2.y = 0;
lane2.visible = false; // Hide initially
// Create timing line
var timingLine = game.addChild(LK.getAsset('timingLine', {
anchorX: 0,
anchorY: 0.5
}));
timingLine.x = 0;
timingLine.y = timingLineY;
timingLine.visible = false; // Hide initially
// Create bottom line
var bottomLine = game.addChild(LK.getAsset('bottomLine', {
anchorX: 0,
anchorY: 0.5
}));
bottomLine.x = 0;
bottomLine.y = bottomLineY;
bottomLine.visible = false; // Hide initially
// Create start menu elements
var titleTxt = new Text2('RHYTHM GAME', {
size: 120,
fill: 0xFFFFFF
});
titleTxt.anchor.set(0.5, 0.5);
titleTxt.x = 2048 / 2;
titleTxt.y = 2732 / 2 - 200;
titleTxt.alpha = 0;
titleTxt.scaleX = 0.5;
titleTxt.scaleY = 0.5;
game.addChild(titleTxt);
// Animate title appearing
tween(titleTxt, {
alpha: 1,
scaleX: 1,
scaleY: 1
}, {
duration: 1000,
easing: tween.elasticOut
});
// Add continuous floating animation
function animateTitleFloat() {
tween(titleTxt, {
y: titleTxt.y - 20
}, {
duration: 2000,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(titleTxt, {
y: titleTxt.y + 20
}, {
duration: 2000,
easing: tween.easeInOut,
onFinish: animateTitleFloat
});
}
});
}
LK.setTimeout(animateTitleFloat, 1500);
var startButtonShape = game.addChild(LK.getAsset('button', {
anchorX: 0.5,
anchorY: 0.5
}));
startButtonShape.x = 2048 / 2;
startButtonShape.y = 2732 / 2 + 100;
startButtonShape.tint = 0x00AA00;
startButtonShape.alpha = 0;
startButtonShape.scaleX = 0;
startButtonShape.scaleY = 0;
// Animate start button appearing
tween(startButtonShape, {
alpha: 1,
scaleX: 1,
scaleY: 1
}, {
duration: 800,
easing: tween.bounceOut,
delay: 1200
});
// Add pulsing glow effect to start button
function animateStartButtonPulse() {
tween(startButtonShape, {
scaleX: 1.1,
scaleY: 1.1,
tint: 0x00FF00
}, {
duration: 1500,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(startButtonShape, {
scaleX: 1,
scaleY: 1,
tint: 0x00AA00
}, {
duration: 1500,
easing: tween.easeInOut,
onFinish: animateStartButtonPulse
});
}
});
}
LK.setTimeout(animateStartButtonPulse, 2000);
var startButtonTxt = new Text2('START', {
size: 60,
fill: 0xFFFFFF
});
startButtonTxt.anchor.set(0.5, 0.5);
startButtonTxt.x = 2048 / 2 + 300;
startButtonTxt.y = 2732 / 2 + 100;
startButtonTxt.alpha = 0;
game.addChild(startButtonTxt);
// Animate start button text sliding in
tween(startButtonTxt, {
x: 2048 / 2,
alpha: 1
}, {
duration: 600,
easing: tween.easeOut,
delay: 1400
});
// Create difficulty selection text
var difficultyTitleTxt = new Text2('SELECT DIFFICULTY', {
size: 80,
fill: 0xFFFFFF
});
difficultyTitleTxt.anchor.set(0.5, 0.5);
difficultyTitleTxt.x = 2048 / 2;
difficultyTitleTxt.y = 2732 / 2 + 300;
game.addChild(difficultyTitleTxt);
// Create difficulty selection indicator text
var difficultyIndicatorTxt = new Text2('None selected', {
size: 60,
fill: 0xFF0000
});
difficultyIndicatorTxt.anchor.set(0.5, 0.5);
difficultyIndicatorTxt.x = 2048 / 2;
difficultyIndicatorTxt.y = 2732 / 2 + 500;
difficultyIndicatorTxt.alpha = 0;
game.addChild(difficultyIndicatorTxt);
// Create difficulty buttons
for (var d = 0; d < difficulties.length; d++) {
var diffButton = {
index: d,
text: new Text2(difficulties[d].name, {
size: 50,
fill: difficulties[d].color
})
};
diffButton.text.anchor.set(0.5, 0.5);
diffButton.text.x = d * 400 + 424; // Spread across screen
diffButton.text.y = 2732 / 2 + 400; // Below the "select difficulty" text
diffButton.text.scaleX = 0;
diffButton.text.scaleY = 0;
diffButton.text.alpha = 0;
game.addChild(diffButton.text);
difficultyButtons.push(diffButton);
// Animate text appearing with staggered timing
tween(diffButton.text, {
scaleX: 1,
scaleY: 1,
alpha: 1
}, {
duration: 600,
easing: tween.elasticOut,
delay: d * 150
});
}
// Animate difficulty title appearing
difficultyTitleTxt.alpha = 0;
difficultyTitleTxt.scaleY = 0;
tween(difficultyTitleTxt, {
alpha: 1,
scaleY: 1
}, {
duration: 800,
easing: tween.bounceOut,
delay: 200
});
// Animate difficulty indicator appearing
tween(difficultyIndicatorTxt, {
alpha: 1,
scaleY: 1
}, {
duration: 800,
easing: tween.bounceOut,
delay: 800
});
// No initial difficulty highlighting since none is selected
// Create start button handler
startButton = {
shape: startButtonShape,
text: startButtonTxt,
down: function down(x, y, obj) {
this.startGame();
},
startGame: function startGame() {
// Check if difficulty is selected
if (currentDifficulty === -1) {
// Flash difficulty title to indicate selection is required
tween(difficultyTitleTxt, {
scaleX: 1.2,
scaleY: 1.2,
tint: 0xFF0000
}, {
duration: 200,
easing: tween.bounceOut,
onFinish: function onFinish() {
tween(difficultyTitleTxt, {
scaleX: 1.0,
scaleY: 1.0,
tint: 0xFFFFFF
}, {
duration: 200
});
}
});
return; // Don't start the game
}
// Hide menu elements
titleTxt.visible = false;
this.shape.visible = false;
this.text.visible = false;
// Show game elements
timerTxt.visible = true;
scoreTxt.visible = true;
timingLine.visible = true;
bottomLine.visible = true;
lane1.visible = true;
lane2.visible = true;
// Create game buttons
for (var i = 0; i < 3; i++) {
var button = new Button(i);
buttons.push(button);
game.addChild(button);
}
// Hide difficulty selection
difficultyTitleTxt.visible = false;
difficultyIndicatorTxt.visible = false;
for (var d = 0; d < difficultyButtons.length; d++) {
difficultyButtons[d].text.visible = false;
}
// Apply difficulty settings
var difficulty = difficulties[currentDifficulty];
maxNotes = difficulty.maxNotes;
spawnInterval = difficulty.spawnInterval;
timeRemaining = difficulty.timeLimit;
// Start the game
gameState = 'playing';
LK.setScore(0);
scoreTxt.setText('0');
timerTxt.setText(timeRemaining.toString());
}
};
// Initially hide game elements
var gameElements = [];
// Create countdown timer
var timeRemaining = 60;
// Create timer display above score
var timerTxt = new Text2('60', {
size: 80,
fill: 0xFFFFFF
});
timerTxt.anchor.set(0.5, 0.5);
timerTxt.x = 2048 / 2;
timerTxt.y = 2732 / 2 - 300;
timerTxt.visible = false; // Hide initially
game.addChild(timerTxt);
// Create score display in center of game area
var scoreTxt = new Text2('0', {
size: 100,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0.5);
scoreTxt.x = 2048 / 2;
scoreTxt.y = 2732 / 2 - 200;
scoreTxt.visible = false; // Hide initially
game.addChild(scoreTxt);
// Create feedback text display
var feedbackTxt = new Text2('', {
size: 80,
fill: 0xFFFFFF
});
feedbackTxt.anchor.set(0.5, 0.5);
LK.gui.center.addChild(feedbackTxt);
feedbackTxt.alpha = 0;
// Create game over menu elements
var gameOverTxt = new Text2('GAME OVER', {
size: 120,
fill: 0xFF0000
});
gameOverTxt.anchor.set(0.5, 0.5);
gameOverTxt.x = 2048 / 2;
gameOverTxt.y = 2732 / 2 - 300;
gameOverTxt.visible = false;
game.addChild(gameOverTxt);
var finalScoreTxt = new Text2('', {
size: 80,
fill: 0xFFFFFF
});
finalScoreTxt.anchor.set(0.5, 0.5);
finalScoreTxt.x = 2048 / 2;
finalScoreTxt.y = 2732 / 2 - 150;
finalScoreTxt.visible = false;
game.addChild(finalScoreTxt);
var restartButtonShape = game.addChild(LK.getAsset('button', {
anchorX: 0.5,
anchorY: 0.5
}));
restartButtonShape.x = 2048 / 2;
restartButtonShape.y = 2732 / 2 + 100;
restartButtonShape.tint = 0x0066CC;
restartButtonShape.visible = false;
var restartButtonTxt = new Text2('RESTART', {
size: 60,
fill: 0xFFFFFF
});
restartButtonTxt.anchor.set(0.5, 0.5);
restartButtonTxt.x = 2048 / 2;
restartButtonTxt.y = 2732 / 2 + 100;
restartButtonTxt.visible = false;
game.addChild(restartButtonTxt);
// Create restart button handler
gameOverButton = {
shape: restartButtonShape,
text: restartButtonTxt,
down: function down(x, y, obj) {
this.restartGame();
},
restartGame: function restartGame() {
// Hide game over elements
gameOverTxt.visible = false;
finalScoreTxt.visible = false;
this.shape.visible = false;
this.text.visible = false;
// Clear existing notes and buttons
for (var i = notes.length - 1; i >= 0; i--) {
notes[i].destroy();
notes.splice(i, 1);
}
for (var i = buttons.length - 1; i >= 0; i--) {
buttons[i].destroy();
buttons.splice(i, 1);
}
// Show menu elements
titleTxt.visible = true;
startButton.shape.visible = true;
startButton.text.visible = true;
difficultyTitleTxt.visible = true;
difficultyIndicatorTxt.visible = true;
for (var d = 0; d < difficultyButtons.length; d++) {
difficultyButtons[d].text.visible = true;
}
// Hide game elements
timerTxt.visible = false;
scoreTxt.visible = false;
timingLine.visible = false;
bottomLine.visible = false;
lane1.visible = false;
lane2.visible = false;
// Reset game state to menu
gameState = 'menu';
spawnTimer = 0;
LK.setScore(0);
}
};
// Create explosion animation function
function createExplosion(x, y, color) {
var particleCount = 8;
var particles = [];
for (var i = 0; i < particleCount; i++) {
// Create particle using small ellipse shape
var particle = game.addChild(LK.getAsset('fastNote', {
anchorX: 0.5,
anchorY: 0.5
}));
particle.x = x;
particle.y = y;
particle.tint = color || 0xFFFFFF;
particle.scaleX = 0.3;
particle.scaleY = 0.3;
particles.push(particle);
// Calculate random direction for each particle
var angle = i / particleCount * Math.PI * 2 + (Math.random() - 0.5) * 0.5;
var distance = 100 + Math.random() * 50;
var targetX = x + Math.cos(angle) * distance;
var targetY = y + Math.sin(angle) * distance;
// Animate particle outward and fade out
tween(particle, {
x: targetX,
y: targetY,
scaleX: 0,
scaleY: 0,
alpha: 0
}, {
duration: 600 + Math.random() * 400,
easing: tween.easeOut,
onFinish: function onFinish() {
if (particle && particle.parent) {
particle.destroy();
}
}
});
}
}
// Create screen shake effect
function shakeScreen(intensity, duration) {
var originalX = game.x;
var originalY = game.y;
var shakeStartTime = LK.ticks;
var shakeDuration = duration || 300;
var shakeIntensity = intensity || 20;
// Create shake animation
function shakeUpdate() {
var elapsed = LK.ticks - shakeStartTime;
if (elapsed < shakeDuration) {
var progress = elapsed / shakeDuration;
var currentIntensity = shakeIntensity * (1 - progress);
game.x = originalX + (Math.random() - 0.5) * currentIntensity * 2;
game.y = originalY + (Math.random() - 0.5) * currentIntensity * 2;
LK.setTimeout(shakeUpdate, 16); // ~60fps
} else {
game.x = originalX;
game.y = originalY;
}
}
shakeUpdate();
}
// Create combo streak effects
var comboCount = 0;
var lastHitTime = 0;
function updateCombo(isHit) {
if (isHit) {
var currentTime = LK.ticks;
if (currentTime - lastHitTime < 180) {
// Within 3 seconds
comboCount++;
} else {
comboCount = 1;
}
lastHitTime = currentTime;
// Show combo effects for streaks
if (comboCount >= 5 && comboCount % 5 === 0) {
// Create combo text
var comboText = new Text2('COMBO x' + comboCount, {
size: 60,
fill: 0xFFD700
});
comboText.anchor.set(0.5, 0.5);
comboText.x = 2048 / 2;
comboText.y = 2732 / 2 + 100;
comboText.alpha = 0;
game.addChild(comboText);
// Animate combo text
tween(comboText, {
alpha: 1,
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 300,
easing: tween.bounceOut,
onFinish: function onFinish() {
tween(comboText, {
alpha: 0,
y: comboText.y - 100
}, {
duration: 500,
onFinish: function onFinish() {
if (comboText && comboText.parent) {
comboText.destroy();
}
}
});
}
});
}
} else {
comboCount = 0;
}
}
// Spawn note function
function spawnNote() {
if (notes.length >= maxNotes) return;
var lane = Math.floor(Math.random() * 3);
var noteTypes = ['slow', 'medium', 'fast'];
var type = noteTypes[Math.floor(Math.random() * noteTypes.length)];
var note = new Note(lane, type);
notes.push(note);
game.addChild(note);
}
// Handle clicks for start button
game.down = function (x, y, obj) {
if (gameState === 'menu') {
// Check if click is on start button
var dx = x - startButton.shape.x;
var dy = y - startButton.shape.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= 150) {
// Button radius
startButton.down(x, y, obj);
}
// Check if click is on difficulty buttons
for (var d = 0; d < difficultyButtons.length; d++) {
var diffButton = difficultyButtons[d];
var ddx = x - diffButton.text.x;
var ddy = y - diffButton.text.y;
var ddistance = Math.sqrt(ddx * ddx + ddy * ddy);
if (ddistance <= 100) {
// Text button hit area
// Reset previous selection if any
if (currentDifficulty !== -1) {
difficultyButtons[currentDifficulty].text.scaleX = 1.0;
difficultyButtons[currentDifficulty].text.scaleY = 1.0;
}
// Set new selection
currentDifficulty = d;
difficultySelected = true;
diffButton.text.scaleX = 1.0;
diffButton.text.scaleY = 1.0;
// Update indicator text to show selected difficulty
if (d === 0) {
// Easy mode - show in red
difficultyIndicatorTxt.setText('Easy mode selected');
difficultyIndicatorTxt.fill = 0xFF0000;
difficultyIndicatorTxt.tint = 0xFF0000;
} else {
difficultyIndicatorTxt.setText(difficulties[d].name.toLowerCase() + ' mode selected');
difficultyIndicatorTxt.fill = difficulties[d].color;
difficultyIndicatorTxt.tint = difficulties[d].color;
}
// Add selection effect
tween(diffButton.text, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 200,
easing: tween.bounceOut,
onFinish: function onFinish() {
tween(diffButton.text, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 200
});
}
});
// Animate the indicator text to show selection
tween(difficultyIndicatorTxt, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 300,
easing: tween.bounceOut,
onFinish: function onFinish() {
tween(difficultyIndicatorTxt, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 200
});
}
});
break;
}
}
} else if (gameState === 'gameOver') {
// Check if click is on restart button
var dx = x - gameOverButton.shape.x;
var dy = y - gameOverButton.shape.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= 150) {
// Button radius
gameOverButton.down(x, y, obj);
}
}
};
game.update = function () {
// Only update game logic when playing
if (gameState !== 'playing') {
return;
}
// Timing line is now static
if (timingLine.visible) {
timingLine.scaleY = 1;
timingLine.alpha = 1;
}
// Add subtle glow effect to buttons
for (var b = 0; b < buttons.length; b++) {
if (buttons[b] && buttons[b].buttonGraphics) {
var glow = Math.sin(LK.ticks * 0.08 + b) * 0.1 + 0.9;
buttons[b].buttonGraphics.alpha = buttons[b].isPressed ? 0.7 : glow;
}
}
// Update timer - countdown every second (60 frames)
if (LK.ticks % 60 === 0 && timeRemaining > 0) {
timeRemaining--;
timerTxt.setText(timeRemaining.toString());
}
// Check for game over when timer reaches 0
if (timeRemaining <= 0 && gameState === 'playing') {
gameState = 'gameOver';
// Auto-hit all remaining notes
for (var n = notes.length - 1; n >= 0; n--) {
var note = notes[n];
if (!note.hasBeenHit) {
note.hasBeenHit = true;
// Award points for each note
var points = 100; // Give perfect score for all auto-hit notes
LK.setScore(LK.getScore() + points);
// Create visual effects for auto-hit notes
LK.effects.flashObject(note, 0xFFD700, 200);
createExplosion(note.x, note.y, 0xFFD700);
// Create floating score animation
var scoreText = new Text2('+' + points, {
size: 50,
fill: 0xFFD700
});
scoreText.anchor.set(0.5, 0.5);
scoreText.x = note.x;
scoreText.y = note.y;
scoreText.alpha = 1;
game.addChild(scoreText);
// Animate floating score
tween(scoreText, {
y: scoreText.y - 150,
alpha: 0,
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 1000,
easing: tween.easeOut,
onFinish: function onFinish() {
if (scoreText && scoreText.parent) {
scoreText.destroy();
}
}
});
// Remove the note
note.destroy();
notes.splice(n, 1);
}
}
// Update final score display
scoreTxt.setText(LK.getScore());
// Hide game elements
timerTxt.visible = false;
scoreTxt.visible = false;
timingLine.visible = false;
bottomLine.visible = false;
lane1.visible = false;
lane2.visible = false;
// Hide buttons
for (var i = 0; i < buttons.length; i++) {
buttons[i].visible = false;
}
// Show game over menu
gameOverTxt.visible = true;
finalScoreTxt.setText('Final Score: ' + LK.getScore() + '\nDifficulty: ' + difficulties[currentDifficulty].name);
finalScoreTxt.visible = true;
gameOverButton.shape.visible = true;
gameOverButton.text.visible = true;
}
// Spawn notes
spawnTimer++;
if (spawnTimer >= spawnInterval) {
spawnNote();
spawnTimer = 0;
// Gradually increase spawn rate
if (spawnInterval > 60) {
spawnInterval = Math.max(60, spawnInterval - 1);
}
}
// Update and check notes
for (var i = notes.length - 1; i >= 0; i--) {
var note = notes[i];
// Add subtle pulsing effect to notes as they approach timing line
var distanceToTimingLine = Math.abs(note.y - timingLineY);
if (distanceToTimingLine < 300) {
var pulseIntensity = 1 + (300 - distanceToTimingLine) / 300 * 0.3;
note.noteGraphics.scaleX = pulseIntensity;
note.noteGraphics.scaleY = pulseIntensity;
}
// Check if note reached bottom line (missed)
if (note.y >= bottomLineY && !note.hasBeenHit) {
LK.getSound('miss').play();
// Create red explosion effect for missed notes
createExplosion(note.x, note.y, 0xFF0000);
// Add screen shake for missed notes
shakeScreen(15, 200);
// Update combo (miss)
updateCombo(false);
// Show missed feedback text
feedbackTxt.setText('MISSED');
feedbackTxt.alpha = 1;
tween(feedbackTxt, {
alpha: 0
}, {
duration: 800
});
note.destroy();
notes.splice(i, 1);
continue;
}
// Remove notes that went off screen or were hit
if (note.y > 2732 + 100 || note.hasBeenHit) {
if (note.hasBeenHit) {
// Small delay before removing hit notes for visual feedback
LK.setTimeout(function (noteToRemove, index) {
return function () {
if (noteToRemove && noteToRemove.parent) {
noteToRemove.destroy();
}
var noteIndex = notes.indexOf(noteToRemove);
if (noteIndex !== -1) {
notes.splice(noteIndex, 1);
}
};
}(note, i), 200);
} else {
note.destroy();
notes.splice(i, 1);
}
}
}
}; ===================================================================
--- original.js
+++ change.js
@@ -239,30 +239,30 @@
var difficulties = [{
name: 'EASY',
spawnInterval: 180,
maxNotes: 2,
- timeLimit: 90,
+ timeLimit: 60,
noteSpeedMultiplier: 0.6,
color: 0x00FF00
}, {
name: 'MEDIUM',
spawnInterval: 135,
maxNotes: 3,
- timeLimit: 90,
+ timeLimit: 60,
noteSpeedMultiplier: 0.8,
color: 0xFFFF00
}, {
name: 'HARD',
spawnInterval: 90,
maxNotes: 4,
- timeLimit: 90,
+ timeLimit: 60,
noteSpeedMultiplier: 1.0,
color: 0xFF8800
}, {
name: 'EXPERT',
spawnInterval: 60,
maxNotes: 5,
- timeLimit: 90,
+ timeLimit: 60,
noteSpeedMultiplier: 1.3,
color: 0xFF0000
}];
// Game variables
@@ -627,21 +627,8 @@
for (var i = buttons.length - 1; i >= 0; i--) {
buttons[i].destroy();
buttons.splice(i, 1);
}
- // Show game elements
- timerTxt.visible = true;
- scoreTxt.visible = true;
- timingLine.visible = true;
- bottomLine.visible = true;
- lane1.visible = true;
- lane2.visible = true;
- // Create game buttons
- for (var i = 0; i < 3; i++) {
- var button = new Button(i);
- buttons.push(button);
- game.addChild(button);
- }
// Show menu elements
titleTxt.visible = true;
startButton.shape.visible = true;
startButton.text.visible = true;