User prompt
Remove the all the combo UI
Code edit (2 edits merged)
Please save this source code
User prompt
make the start point on where the notes start appearing 200 above the center the screen, add a variable so i can adjust that as i want aswell
User prompt
Add perspective to the game, make the notes seem as if they come from distance towards the screen and the target boxes
User prompt
Please fix the bug: 'TypeError: tween.colorTo is not a function' in or related to this line: 'tween.colorTo(game, {' Line Number: 583
User prompt
Just animate the colors of the background
User prompt
Please fix the bug: 'particles is not defined' in or related to this line: 'self.emitter = new particles.Emitter(self);' Line Number: 46
User prompt
Please fix the bug: 'particles is not defined' in or related to this line: 'self.emitter = new particles.Emitter(self);' Line Number: 46
User prompt
Please fix the bug: 'particles is not defined' in or related to this line: 'self.emitter = new particles.Emitter(self);' Line Number: 46
User prompt
Please fix the bug: 'particles is not defined' in or related to this line: 'self.emitter = new particles.Emitter(self);' Line Number: 46
User prompt
Please fix the bug: 'particles is not defined' in or related to this line: 'self.emitter = new particles.Emitter(self);' Line Number: 46
User prompt
make the background animated and react to the miss and hit
User prompt
make the background animated like the target zone, and add a variable to choose the colors
User prompt
make the tiles increasingly faster ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Now, divide half of the screen for this mechanic, but the top half add two characters, the player character on the left and an enemy character on the right, add a ground, background
User prompt
Sometimes the buttons are giving a miss when they are inside the target zone, correct that
Code edit (1 edits merged)
Please save this source code
User prompt
Change the target box size variable to be able to adjust its size im x and y
User prompt
Make an variable so i can adjust the size of the target box
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot set properties of undefined (setting 'fill')' in or related to this line: 'self.feedbackText.style.fill = color;' Line Number: 214
Code edit (1 edits merged)
Please save this source code
User prompt
Rhythm Reactor
Initial prompt
Make a simple rythm game mechanic, where buttons fall from top of the screen and you have to click in the right timing, in the bottom of the screen will have small semi transparent boxes where the buttons will fall on, and the player has to click when the button is inside the box for the right timing
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var AnimatedBackground = Container.expand(function () {
var self = Container.call(this);
self.backgroundShape = null;
self.emitter = null;
self.pulseIntensity = 0;
self.baseColor = 0x111133;
self.targetColor = self.baseColor;
self.lastTick = 0;
self.ripples = [];
self.maxRipples = 10;
self.init = function () {
// Create background
self.backgroundShape = self.attachAsset('background', {
anchorX: 0,
anchorY: 0
});
// Create particle emitter for background effects
self.emitter = new particles.Emitter(self);
self.emitter.init({
particleCount: 50,
particleSize: {
min: 5,
max: 15
},
lifetime: {
min: 2000,
max: 4000
},
speed: {
min: 0.2,
max: 0.8
},
color: [0x3366ff, 0x4477ff, 0x5588ff],
alpha: {
start: 0.1,
end: 0
},
blendMode: 'add',
enabled: true
});
// Position emitter in center
self.emitter.x = 2048 / 2;
self.emitter.y = 2732 / 2;
return self;
};
self.update = function () {
// Background color pulsing
if (self.pulseIntensity > 0) {
self.pulseIntensity *= 0.95;
// Interpolate between base color and target color based on pulse intensity
var r1 = self.baseColor >> 16 & 0xFF;
var g1 = self.baseColor >> 8 & 0xFF;
var b1 = self.baseColor & 0xFF;
var r2 = self.targetColor >> 16 & 0xFF;
var g2 = self.targetColor >> 8 & 0xFF;
var b2 = self.targetColor & 0xFF;
var r = Math.floor(r1 + (r2 - r1) * self.pulseIntensity);
var g = Math.floor(g1 + (g2 - g1) * self.pulseIntensity);
var b = Math.floor(b1 + (b2 - b1) * self.pulseIntensity);
var color = r << 16 | g << 8 | b;
self.backgroundShape.tint = color;
}
// Update particle emitter
self.emitter.update();
// Update ripples
for (var i = self.ripples.length - 1; i >= 0; i--) {
var ripple = self.ripples[i];
ripple.lifetime -= 1;
ripple.scale.x += ripple.speed;
ripple.scale.y += ripple.speed;
ripple.alpha -= 0.02;
if (ripple.lifetime <= 0 || ripple.alpha <= 0) {
self.removeChild(ripple);
self.ripples.splice(i, 1);
}
}
self.lastTick = LK.ticks;
};
self.pulse = function (color, intensity) {
self.targetColor = color;
self.pulseIntensity = intensity || 1.0;
// Adjust particle colors based on pulse
var colors = [color, 0xFFFFFF];
if (color === 0x32CD32) {
// Green for hit
colors = [0x32CD32, 0x88FF88, 0xAAFFAA];
} else if (color === 0xFF4500) {
// Orange/red for perfect
colors = [0xFF4500, 0xFF8844, 0xFFAA66];
} else if (color === 0x888888) {
// Grey for miss
colors = [0x666666, 0x888888, 0xAAAAAA];
}
self.emitter.setProperty('color', colors);
self.emitter.burst(20);
};
self.createRipple = function (x, y, color) {
// Create a ripple effect at given position
if (self.ripples.length >= self.maxRipples) {
return;
}
var ripple = LK.getAsset('targetZone', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.3,
tint: color
});
ripple.x = x;
ripple.y = y;
ripple.scale.set(0.1, 0.1);
ripple.lifetime = 30;
ripple.speed = 0.1;
self.ripples.push(ripple);
self.addChild(ripple);
};
return self;
});
var Note = Container.expand(function () {
var self = Container.call(this);
self.type = 'normal'; // normal, perfect, good
self.lane = 0; // 0-3 for different lanes
self.speed = 10; // Base speed
self.active = true; // Whether note is still active
self.scored = false; // Whether note has been scored
self.noteGraphics = null;
self.init = function (noteType, laneNum, noteSpeed) {
self.type = noteType || 'normal';
self.lane = laneNum || 0;
self.speed = noteSpeed || 10;
// Create note graphic based on type
var assetId = 'note';
if (self.type === 'perfect') {
assetId = 'perfectNote';
} else if (self.type === 'good') {
assetId = 'goodNote';
}
self.noteGraphics = self.attachAsset(assetId, {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.9
});
return self;
};
self.update = function () {
if (!self.active) {
return;
}
// Move note down
self.y += self.speed;
// Store last speed for smooth changes
self.lastSpeed = self.speed;
// Check if note is out of bounds and hasn't been scored
if (self.y > 2732 + 100 && !self.scored) {
self.miss();
}
};
self.hit = function (accuracy) {
if (!self.active || self.scored) {
return;
}
self.scored = true;
self.active = false;
// Create hit effect
LK.effects.flashObject(self, 0xFFFFFF, 300);
if (accuracy === 'perfect') {
LK.getSound('perfectSound').play();
tween(self.noteGraphics, {
alpha: 0,
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 300,
onFinish: function onFinish() {
self.destroy();
}
});
} else if (accuracy === 'good') {
LK.getSound('hitSound').play();
tween(self.noteGraphics, {
alpha: 0,
scaleX: 1.3,
scaleY: 1.3
}, {
duration: 300,
onFinish: function onFinish() {
self.destroy();
}
});
} else {
LK.getSound('hitSound').play();
tween(self.noteGraphics, {
alpha: 0
}, {
duration: 200,
onFinish: function onFinish() {
self.destroy();
}
});
}
};
self.miss = function () {
if (!self.active || self.scored) {
return;
}
self.scored = true;
self.active = false;
LK.getSound('missSound').play();
// Create miss effect in background
if (game.animatedBackground) {
game.animatedBackground.createRipple(self.x, self.y, 0x888888);
}
// Change to missed note appearance
if (self.noteGraphics) {
self.removeChild(self.noteGraphics);
}
self.noteGraphics = self.attachAsset('missedNote', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.5
});
tween(self.noteGraphics, {
alpha: 0
}, {
duration: 200,
onFinish: function onFinish() {
self.destroy();
}
});
};
return self;
});
var ScoreDisplay = Container.expand(function () {
var self = Container.call(this);
self.scoreText = null;
self.comboText = null;
self.accuracyText = null;
self.feedbackText = null;
self.init = function () {
// Create score text
self.scoreText = new Text2('Score: 0', {
size: 80,
fill: 0xFFFFFF
});
self.scoreText.anchor.set(0.5, 0);
self.addChild(self.scoreText);
// Create combo text
self.comboText = new Text2('Combo: 0', {
size: 60,
fill: 0xFFFFFF
});
self.comboText.anchor.set(0.5, 0);
self.comboText.y = 90;
self.addChild(self.comboText);
// Create accuracy text
self.accuracyText = new Text2('Accuracy: 0%', {
size: 40,
fill: 0xDDDDDD
});
self.accuracyText.anchor.set(0.5, 0);
self.accuracyText.y = 160;
self.addChild(self.accuracyText);
// Create feedback text for "Perfect!", "Good!", "Miss!"
self.feedbackText = new Text2('', {
size: 90,
fill: 0xFFFFFF
});
self.feedbackText.anchor.set(0.5, 0.5);
self.feedbackText.y = 300;
self.addChild(self.feedbackText);
return self;
};
self.updateScore = function (score) {
self.scoreText.setText('Score: ' + score);
};
self.updateCombo = function (combo) {
self.comboText.setText('Combo: ' + combo);
// Scale effect on combo update
tween.stop(self.comboText, {
scaleX: true,
scaleY: true
});
self.comboText.scale.set(1.2, 1.2);
tween(self.comboText, {
scaleX: 1,
scaleY: 1
}, {
duration: 300,
easing: tween.elasticOut
});
};
self.updateAccuracy = function (accuracy) {
self.accuracyText.setText('Accuracy: ' + accuracy + '%');
};
self.showFeedback = function (type) {
// Clear any existing animations
tween.stop(self.feedbackText, {
alpha: true,
scaleX: true,
scaleY: true
});
var color = "#FFFFFF";
var text = "";
if (type === 'perfect') {
text = "Perfect!";
color = "#FF4500";
} else if (type === 'good') {
text = "Good!";
color = "#32CD32";
} else if (type === 'miss') {
text = "Miss!";
color = "#888888";
}
self.feedbackText.setText(text);
// Set the text with the new color in the style
self.feedbackText.setText(text, {
fill: color
});
self.feedbackText.alpha = 1;
self.feedbackText.scale.set(1.3, 1.3);
tween(self.feedbackText, {
alpha: 0,
scaleX: 1,
scaleY: 1
}, {
duration: 600,
easing: tween.easeOut
});
};
return self;
});
var TargetZone = Container.expand(function () {
var self = Container.call(this);
self.lane = 0;
self.zoneGraphics = null;
self.active = false;
self.pulseTimer = 0;
self.init = function (laneNum) {
self.lane = laneNum || 0;
self.zoneGraphics = self.attachAsset('targetZone', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.4,
width: targetBoxSize.width,
// Use the target box size variable here
height: targetBoxSize.height
});
return self;
};
self.update = function () {
// Subtle pulsing effect when not active
if (!self.active) {
self.pulseTimer += 0.05;
self.zoneGraphics.alpha = 0.3 + Math.sin(self.pulseTimer) * 0.1;
}
};
self.activate = function () {
if (self.active) {
return;
}
self.active = true;
tween(self.zoneGraphics, {
alpha: 0.8,
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 100,
onFinish: function onFinish() {
self.deactivate();
}
});
};
self.deactivate = function () {
self.active = false;
tween(self.zoneGraphics, {
alpha: 0.4,
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 200
});
};
self.down = function (x, y, obj) {
self.activate();
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x111133
});
/****
* Game Code
****/
// Game configuration
// Default size, will be overridden when initialized
var laneCount = 4;
var laneWidth = 2048 / laneCount;
var targetBoxSize = {
width: 300,
height: 300
}; // Adjustable target zone dimensions
var gameSpeed = 6; // Increased base speed multiplier (was 5)
var currentLevel = 1;
var difficultyMultiplier = 1.0;
var speedIncreaseInterval = 300; // Frames between speed increases (5 seconds at 60fps)
var beatFrequency = 60; // Frames between beat patterns
var beatVariance = 10; // Random variation in beat timing
var nextBeatFrame = 20; // When to spawn the next beat
// Game state
var score = 0;
var combo = 0;
var maxCombo = 0;
var totalNotes = 0;
var hitNotes = 0;
var perfectHits = 0;
var activeNotes = [];
var targetZones = [];
var gameStarted = false;
var gameOver = false;
// UI elements
var scoreDisplay;
var startText;
var animatedBackground;
// Initialize animated background
animatedBackground = new AnimatedBackground().init();
game.addChild(animatedBackground);
// Create target zones
for (var i = 0; i < laneCount; i++) {
var zone = new TargetZone().init(i);
zone.x = laneWidth * (i + 0.5);
zone.y = 2500; // Bottom of screen
targetZones.push(zone);
game.addChild(zone);
}
// Create and position score display
scoreDisplay = new ScoreDisplay().init();
scoreDisplay.x = 2048 / 2;
scoreDisplay.y = 150;
game.addChild(scoreDisplay);
// Create start text
startText = new Text2('Tap to Start', {
size: 120,
fill: 0xFFFFFF
});
startText.anchor.set(0.5, 0.5);
startText.x = 2048 / 2;
startText.y = 2732 / 2;
game.addChild(startText);
// Calculate accuracy as a percentage
function calculateAccuracy() {
if (totalNotes === 0) {
return 100;
}
return Math.floor(hitNotes / totalNotes * 100);
}
// Spawn a new note
function spawnNote() {
var laneNum = Math.floor(Math.random() * laneCount);
var noteType = 'normal';
// 20% chance for a "perfect" note, 30% chance for a "good" note
var rand = Math.random();
if (rand < 0.2) {
noteType = 'perfect';
} else if (rand < 0.5) {
noteType = 'good';
}
var noteSpeed = gameSpeed * difficultyMultiplier;
var note = new Note().init(noteType, laneNum, noteSpeed);
note.x = laneWidth * (laneNum + 0.5);
note.y = -50; // Start above the screen
activeNotes.push(note);
game.addChild(note);
totalNotes++;
return note;
}
// Generate beat pattern
function generateBeatPattern() {
var patternLength = Math.min(4, 1 + Math.floor(currentLevel / 2));
for (var i = 0; i < patternLength; i++) {
// Stagger notes based on pattern position
LK.setTimeout(function () {
if (!gameOver && gameStarted) {
spawnNote();
}
}, i * (200 / difficultyMultiplier));
}
}
// Check if a note is in the hit zone
function checkNoteHit(laneNum) {
var hitZone = targetZones[laneNum];
var hitY = hitZone.y;
var hitFound = false;
// Find notes in this lane
for (var i = 0; i < activeNotes.length; i++) {
var note = activeNotes[i];
if (note.lane === laneNum && note.active && !note.scored) {
// Check if note is inside target zone bounds
var targetTop = hitY - targetBoxSize.height / 2;
var targetBottom = hitY + targetBoxSize.height / 2;
var isInsideTargetZone = note.y >= targetTop && note.y <= targetBottom;
if (isInsideTargetZone) {
// Calculate distance from perfect hit position as a percentage of target box height
var distance = Math.abs(note.y - hitY);
var distancePercent = distance / (targetBoxSize.height / 2);
// Different hit zones based on percentage of target box height
if (distancePercent < 0.3) {
// Perfect hit - center 30% of target zone
score += 100 * (1 + combo / 10);
combo++;
hitNotes++;
perfectHits++;
note.hit('perfect');
scoreDisplay.showFeedback('perfect');
// Trigger background effect for perfect hit
animatedBackground.pulse(0xFF4500, 0.7);
animatedBackground.createRipple(note.x, note.y, 0xFF4500);
hitFound = true;
break;
} else if (distancePercent < 0.7) {
// Good hit - middle 40% of target zone
score += 50 * (1 + combo / 20);
combo++;
hitNotes++;
note.hit('good');
scoreDisplay.showFeedback('good');
// Trigger background effect for good hit
animatedBackground.pulse(0x32CD32, 0.5);
animatedBackground.createRipple(note.x, note.y, 0x32CD32);
hitFound = true;
break;
} else {
// Within bounds but not centered - early/late hit at edges of target zone
score += 10;
combo++;
hitNotes++;
note.hit('early');
scoreDisplay.showFeedback('good');
// Trigger background effect for early/late hit
animatedBackground.pulse(0x32CD32, 0.3);
animatedBackground.createRipple(note.x, note.y, 0x32CD32);
hitFound = true;
break;
}
}
}
}
// If we didn't hit any notes, it's a miss
if (!hitFound) {
combo = 0;
scoreDisplay.showFeedback('miss');
// Trigger miss effect on background
animatedBackground.pulse(0x888888, 0.4);
}
// Update score display
scoreDisplay.updateScore(Math.floor(score));
scoreDisplay.updateCombo(combo);
maxCombo = Math.max(maxCombo, combo);
// Update accuracy
var accuracy = calculateAccuracy();
scoreDisplay.updateAccuracy(accuracy);
return hitFound;
}
// Handle tap on a lane
function handleLaneTap(laneNum) {
if (!gameStarted || gameOver) {
return;
}
targetZones[laneNum].activate();
return checkNoteHit(laneNum);
}
// Start the game
function startGame() {
if (gameStarted) {
return;
}
gameStarted = true;
game.removeChild(startText);
// Reset game state
score = 0;
combo = 0;
maxCombo = 0;
totalNotes = 0;
hitNotes = 0;
perfectHits = 0;
currentLevel = 1;
difficultyMultiplier = 1.0;
gameSpeed = 6; // Reset base speed
gameOver = false;
// Update UI
scoreDisplay.updateScore(score);
scoreDisplay.updateCombo(combo);
scoreDisplay.updateAccuracy(100);
// Initial speed up message
scoreDisplay.showFeedback("Get Ready!");
// Start music
LK.playMusic('gameMusic', {
fade: {
start: 0,
end: 1,
duration: 1000
}
});
// Create startup visual effect
animatedBackground.pulse(0x3366ff, 1.0);
for (var i = 0; i < 4; i++) {
var lane = laneWidth * (i + 0.5);
LK.setTimeout(function (laneX) {
animatedBackground.createRipple(laneX, 2732 / 2, 0x3366ff);
}, i * 200, lane);
}
// Set the first beat to spawn soon
nextBeatFrame = 60;
}
// Check if game should end (based on time or score)
function checkGameOver() {
// For demo purposes, end game after reaching level 10
if (currentLevel >= 10 && score >= 10000) {
endGame(true); // Win
}
// Player loses if accuracy drops too low
if (totalNotes > 20 && calculateAccuracy() < 40) {
endGame(false); // Lose
}
}
// End the game
function endGame(win) {
gameOver = true;
// Fade out music
LK.playMusic('gameMusic', {
fade: {
start: 1,
end: 0,
duration: 800
}
});
// Show game over or win screen based on performance
if (win) {
LK.showYouWin();
} else {
LK.showGameOver();
}
}
// Handle lane tap detection - we'll divide the screen into lanes
function getLaneFromPosition(x) {
return Math.floor(x / laneWidth);
}
// Handle touch events
game.down = function (x, y, obj) {
if (!gameStarted) {
startGame();
} else {
var lane = getLaneFromPosition(x);
if (lane >= 0 && lane < laneCount) {
handleLaneTap(lane);
}
}
};
game.update = function () {
// Always update the animated background
animatedBackground.update();
if (!gameStarted) {
return;
}
// Update all active notes
for (var i = activeNotes.length - 1; i >= 0; i--) {
var note = activeNotes[i];
// Remove notes that have been scored and faded out
if (!note.active && note.scored) {
activeNotes.splice(i, 1);
}
}
// Update target zones
for (var j = 0; j < targetZones.length; j++) {
targetZones[j].update();
}
// Generate new beat patterns at intervals
if (gameStarted && !gameOver) {
if (LK.ticks >= nextBeatFrame) {
generateBeatPattern();
// Calculate next beat timing with some variance
var interval = beatFrequency - currentLevel * 5;
interval = Math.max(interval, 30); // Don't go too fast
var variance = Math.floor(Math.random() * beatVariance) - beatVariance / 2;
nextBeatFrame = LK.ticks + interval + variance;
// Increase difficulty over time
if (LK.ticks % 600 === 0) {
// Every 10 seconds
currentLevel++;
difficultyMultiplier = 1.0 + currentLevel * 0.2; // Increased from 0.1 to 0.2 for faster speed growth
// Dynamically increase speed of existing notes
for (var i = 0; i < activeNotes.length; i++) {
var note = activeNotes[i];
if (note.active) {
// Gradually increase speed over 1 second
tween(note, {
speed: gameSpeed * difficultyMultiplier
}, {
duration: 1000,
easing: tween.easeOut
});
}
}
}
}
}
// Apply continuous speed increase
if (gameStarted && !gameOver && LK.ticks % speedIncreaseInterval === 0) {
// Small incremental speed increase every few seconds
difficultyMultiplier += 0.05;
// Visual feedback when speed increases
scoreDisplay.showFeedback("Speed Up!");
// Flash effect on target zones to indicate increased speed
for (var i = 0; i < targetZones.length; i++) {
LK.effects.flashObject(targetZones[i], 0xFF4500, 300);
}
}
// Check for game over conditions
checkGameOver();
}; ===================================================================
--- original.js
+++ change.js
@@ -8,61 +8,121 @@
* Classes
****/
var AnimatedBackground = Container.expand(function () {
var self = Container.call(this);
- self.bgGraphics = null;
- self.pulseTimer = 0;
- self.colorPrimary = 0x111133;
- self.colorSecondary = 0x222266;
- self.colorHighlight = 0x3344AA;
- self.init = function (colors) {
- if (colors) {
- self.colorPrimary = colors.primary || self.colorPrimary;
- self.colorSecondary = colors.secondary || self.colorSecondary;
- self.colorHighlight = colors.highlight || self.colorHighlight;
- }
- self.bgGraphics = self.attachAsset('background', {
+ self.backgroundShape = null;
+ self.emitter = null;
+ self.pulseIntensity = 0;
+ self.baseColor = 0x111133;
+ self.targetColor = self.baseColor;
+ self.lastTick = 0;
+ self.ripples = [];
+ self.maxRipples = 10;
+ self.init = function () {
+ // Create background
+ self.backgroundShape = self.attachAsset('background', {
anchorX: 0,
- anchorY: 0,
- width: 2048,
- height: 2732
+ anchorY: 0
});
- // Initial color
- self.bgGraphics.tint = self.colorPrimary;
+ // Create particle emitter for background effects
+ self.emitter = new particles.Emitter(self);
+ self.emitter.init({
+ particleCount: 50,
+ particleSize: {
+ min: 5,
+ max: 15
+ },
+ lifetime: {
+ min: 2000,
+ max: 4000
+ },
+ speed: {
+ min: 0.2,
+ max: 0.8
+ },
+ color: [0x3366ff, 0x4477ff, 0x5588ff],
+ alpha: {
+ start: 0.1,
+ end: 0
+ },
+ blendMode: 'add',
+ enabled: true
+ });
+ // Position emitter in center
+ self.emitter.x = 2048 / 2;
+ self.emitter.y = 2732 / 2;
return self;
};
self.update = function () {
- // Create pulsing effect similar to target zone
- self.pulseTimer += 0.02;
- // Calculate color blend between primary and secondary colors
- var ratio = (Math.sin(self.pulseTimer) + 1) / 2; // 0-1 value
- // Create a pulsing color effect
- var r1 = self.colorPrimary >> 16 & 0xFF;
- var g1 = self.colorPrimary >> 8 & 0xFF;
- var b1 = self.colorPrimary & 0xFF;
- var r2 = self.colorSecondary >> 16 & 0xFF;
- var g2 = self.colorSecondary >> 8 & 0xFF;
- var b2 = self.colorSecondary & 0xFF;
- var r = Math.floor(r1 + (r2 - r1) * ratio);
- var g = Math.floor(g1 + (g2 - g1) * ratio);
- var b = Math.floor(b1 + (b2 - b1) * ratio);
- var color = r << 16 | g << 8 | b;
- self.bgGraphics.tint = color;
+ // Background color pulsing
+ if (self.pulseIntensity > 0) {
+ self.pulseIntensity *= 0.95;
+ // Interpolate between base color and target color based on pulse intensity
+ var r1 = self.baseColor >> 16 & 0xFF;
+ var g1 = self.baseColor >> 8 & 0xFF;
+ var b1 = self.baseColor & 0xFF;
+ var r2 = self.targetColor >> 16 & 0xFF;
+ var g2 = self.targetColor >> 8 & 0xFF;
+ var b2 = self.targetColor & 0xFF;
+ var r = Math.floor(r1 + (r2 - r1) * self.pulseIntensity);
+ var g = Math.floor(g1 + (g2 - g1) * self.pulseIntensity);
+ var b = Math.floor(b1 + (b2 - b1) * self.pulseIntensity);
+ var color = r << 16 | g << 8 | b;
+ self.backgroundShape.tint = color;
+ }
+ // Update particle emitter
+ self.emitter.update();
+ // Update ripples
+ for (var i = self.ripples.length - 1; i >= 0; i--) {
+ var ripple = self.ripples[i];
+ ripple.lifetime -= 1;
+ ripple.scale.x += ripple.speed;
+ ripple.scale.y += ripple.speed;
+ ripple.alpha -= 0.02;
+ if (ripple.lifetime <= 0 || ripple.alpha <= 0) {
+ self.removeChild(ripple);
+ self.ripples.splice(i, 1);
+ }
+ }
+ self.lastTick = LK.ticks;
};
- self.flash = function () {
- // Flash the highlight color
- var originalTint = self.bgGraphics.tint;
- self.bgGraphics.tint = self.colorHighlight;
- // Revert back with a tween
- LK.setTimeout(function () {
- tween(self.bgGraphics, {
- tint: originalTint
- }, {
- duration: 400,
- easing: tween.easeOut
- });
- }, 100);
+ self.pulse = function (color, intensity) {
+ self.targetColor = color;
+ self.pulseIntensity = intensity || 1.0;
+ // Adjust particle colors based on pulse
+ var colors = [color, 0xFFFFFF];
+ if (color === 0x32CD32) {
+ // Green for hit
+ colors = [0x32CD32, 0x88FF88, 0xAAFFAA];
+ } else if (color === 0xFF4500) {
+ // Orange/red for perfect
+ colors = [0xFF4500, 0xFF8844, 0xFFAA66];
+ } else if (color === 0x888888) {
+ // Grey for miss
+ colors = [0x666666, 0x888888, 0xAAAAAA];
+ }
+ self.emitter.setProperty('color', colors);
+ self.emitter.burst(20);
};
+ self.createRipple = function (x, y, color) {
+ // Create a ripple effect at given position
+ if (self.ripples.length >= self.maxRipples) {
+ return;
+ }
+ var ripple = LK.getAsset('targetZone', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ alpha: 0.3,
+ tint: color
+ });
+ ripple.x = x;
+ ripple.y = y;
+ ripple.scale.set(0.1, 0.1);
+ ripple.lifetime = 30;
+ ripple.speed = 0.1;
+ self.ripples.push(ripple);
+ self.addChild(ripple);
+ };
return self;
});
var Note = Container.expand(function () {
var self = Container.call(this);
@@ -153,8 +213,12 @@
}
self.scored = true;
self.active = false;
LK.getSound('missSound').play();
+ // Create miss effect in background
+ if (game.animatedBackground) {
+ game.animatedBackground.createRipple(self.x, self.y, 0x888888);
+ }
// Change to missed note appearance
if (self.noteGraphics) {
self.removeChild(self.noteGraphics);
}
@@ -339,10 +403,10 @@
/****
* Game Code
****/
-// Default size, will be overridden when initialized
// Game configuration
+// Default size, will be overridden when initialized
var laneCount = 4;
var laneWidth = 2048 / laneCount;
var targetBoxSize = {
width: 300,
@@ -354,14 +418,8 @@
var speedIncreaseInterval = 300; // Frames between speed increases (5 seconds at 60fps)
var beatFrequency = 60; // Frames between beat patterns
var beatVariance = 10; // Random variation in beat timing
var nextBeatFrame = 20; // When to spawn the next beat
-// Background animation configuration
-var backgroundColors = {
- primary: 0x111133,
- secondary: 0x222266,
- highlight: 0x3344AA
-};
// Game state
var score = 0;
var combo = 0;
var maxCombo = 0;
@@ -374,13 +432,12 @@
var gameOver = false;
// UI elements
var scoreDisplay;
var startText;
-var backgroundShape;
-// Add animated background
-var animatedBackground = new AnimatedBackground().init(backgroundColors);
+var animatedBackground;
+// Initialize animated background
+animatedBackground = new AnimatedBackground().init();
game.addChild(animatedBackground);
-backgroundShape = animatedBackground.bgGraphics; // Keep reference for compatibility
// Create target zones
for (var i = 0; i < laneCount; i++) {
var zone = new TargetZone().init(i);
zone.x = laneWidth * (i + 0.5);
@@ -466,8 +523,11 @@
hitNotes++;
perfectHits++;
note.hit('perfect');
scoreDisplay.showFeedback('perfect');
+ // Trigger background effect for perfect hit
+ animatedBackground.pulse(0xFF4500, 0.7);
+ animatedBackground.createRipple(note.x, note.y, 0xFF4500);
hitFound = true;
break;
} else if (distancePercent < 0.7) {
// Good hit - middle 40% of target zone
@@ -475,8 +535,11 @@
combo++;
hitNotes++;
note.hit('good');
scoreDisplay.showFeedback('good');
+ // Trigger background effect for good hit
+ animatedBackground.pulse(0x32CD32, 0.5);
+ animatedBackground.createRipple(note.x, note.y, 0x32CD32);
hitFound = true;
break;
} else {
// Within bounds but not centered - early/late hit at edges of target zone
@@ -484,8 +547,11 @@
combo++;
hitNotes++;
note.hit('early');
scoreDisplay.showFeedback('good');
+ // Trigger background effect for early/late hit
+ animatedBackground.pulse(0x32CD32, 0.3);
+ animatedBackground.createRipple(note.x, note.y, 0x32CD32);
hitFound = true;
break;
}
}
@@ -494,8 +560,10 @@
// If we didn't hit any notes, it's a miss
if (!hitFound) {
combo = 0;
scoreDisplay.showFeedback('miss');
+ // Trigger miss effect on background
+ animatedBackground.pulse(0x888888, 0.4);
}
// Update score display
scoreDisplay.updateScore(Math.floor(score));
scoreDisplay.updateCombo(combo);
@@ -544,8 +612,16 @@
end: 1,
duration: 1000
}
});
+ // Create startup visual effect
+ animatedBackground.pulse(0x3366ff, 1.0);
+ for (var i = 0; i < 4; i++) {
+ var lane = laneWidth * (i + 0.5);
+ LK.setTimeout(function (laneX) {
+ animatedBackground.createRipple(laneX, 2732 / 2, 0x3366ff);
+ }, i * 200, lane);
+ }
// Set the first beat to spawn soon
nextBeatFrame = 60;
}
// Check if game should end (based on time or score)
@@ -592,13 +668,13 @@
}
}
};
game.update = function () {
+ // Always update the animated background
+ animatedBackground.update();
if (!gameStarted) {
return;
}
- // Update background animation
- animatedBackground.update();
// Update all active notes
for (var i = activeNotes.length - 1; i >= 0; i--) {
var note = activeNotes[i];
// Remove notes that have been scored and faded out
@@ -649,10 +725,8 @@
// Flash effect on target zones to indicate increased speed
for (var i = 0; i < targetZones.length; i++) {
LK.effects.flashObject(targetZones[i], 0xFF4500, 300);
}
- // Flash the background too
- animatedBackground.flash();
}
// Check for game over conditions
checkGameOver();
};
\ No newline at end of file