User prompt
Adjust mouth tracking down by 50 pixels.
User prompt
Increase the volume threshold to change mouth alpha to 0.45
User prompt
Update with: var CALIBRATION_SAMPLES = 100; // Doubled to 100 samples
User prompt
Start mouth alpha at 0 and change to 1 when facekit volume is greater than 0.35
User prompt
Position mouth over players mouth using facekit. Initialize after Poseidon to appear on top. ↪💡 Consider importing and using the following plugins: @upit/facekit.v1
User prompt
Poseidon is not visible. Analyze.
User prompt
Adjust Poseidon scale to fit the players face.
User prompt
Reorder initialization so Poseidon appears at the lowest layer.
User prompt
Use FaceKit plugin to detect player face and place Poseidon asset on top. ↪💡 Consider importing and using the following plugins: @upit/facekit.v1
User prompt
Update with: // And in the scoring section if (facekit.volume > 0.35) { // Was 0.15 score += smoothedHeight / WAVE_HEIGHT * multiplier; multiplier += 0.001; } else { multiplier = Math.max(1, multiplier - 0.01); }
User prompt
Update with: // In WaveSystem update function, increase regular wave detection from 0.15 to 0.35 if (facekit.volume > 0.35) { // Was 0.15 var normalizedPitch = (facekit.pitch - MIN_PITCH) / (MAX_PITCH - MIN_PITCH); normalizedPitch = Math.max(0, Math.min(1, normalizedPitch)); targetPitch = normalizedPitch * 0.8 + lastPitch * 0.2; }
User prompt
Update with: // In WaveSystem class, increase calibration threshold from 0.2 to 0.4 var CALIBRATION_VOLUME_THRESHOLD = 0.4; // Was 0.2
User prompt
Update wave system with: self.update = function() { // Always calculate wave points first, regardless of calibration state var targetPitch = 0; if (facekit.volume > 0.15) { var normalizedPitch = (facekit.pitch - MIN_PITCH) / (MAX_PITCH - MIN_PITCH); normalizedPitch = Math.max(0, Math.min(1, normalizedPitch)); targetPitch = normalizedPitch * 0.8 + lastPitch * 0.2; } lastPitch += (targetPitch - lastPitch) * 0.2; var smoothedHeight = getSmoothedHeight(lastPitch * WAVE_HEIGHT); points = []; for (var i = 0; i < NUM_POINTS; i++) { var x = i / (NUM_POINTS - 1) * SCREEN_WIDTH; var distanceFromCenter = (x - SCREEN_WIDTH * 0.35) / (SCREEN_WIDTH * 0.45); var heightFactor = gaussianCurve(distanceFromCenter); var y = baseY - smoothedHeight * heightFactor; points.push({ x: x, y: y }); } // Always update water rectangles for (var i = 0; i < NUM_WATER_SECTIONS; i++) { var rect = waterRects[i]; var xPosition = i / NUM_WATER_SECTIONS * SCREEN_WIDTH; var exactPointPosition = xPosition / SCREEN_WIDTH * (NUM_POINTS - 1); var pointIndex = Math.floor(exactPointPosition); var nextPointIndex = Math.min(pointIndex + 1, NUM_POINTS - 1); var progress = exactPointPosition - pointIndex; var y1 = points[pointIndex].y; var y2 = points[nextPointIndex].y; var y = y1 + (y2 - y1) * progress; rect.x = xPosition; rect.y = y; rect.height = 2732 - y; rect.alpha = 0.3 + Math.sin(LK.ticks * 0.02 + i * 0.2) * 0.02; } self.points = points; // Handle calibration if still calibrating if (self.isCalibrating) { if (facekit.volume > CALIBRATION_VOLUME_THRESHOLD) { calibrationSamples.push(facekit.pitch); var progress = Math.min(100, Math.floor(calibrationSamples.length / CALIBRATION_SAMPLES * 100)); progressText.setText(progress + "%"); if (calibrationSamples.length >= CALIBRATION_SAMPLES) { finishCalibration(); } } if (LK.ticks - calibrationStartTime > CALIBRATION_TIMEOUT) { if (calibrationSamples.length < 10) { calibrationSamples = []; calibrationStartTime = LK.ticks; calibrationText.setText("Let's try again!\nMake some noise - hum or speak"); } else { finishCalibration(); } } } else { // Only update score when not calibrating if (facekit.volume > 0.15) { score += smoothedHeight / WAVE_HEIGHT * multiplier; multiplier += 0.001; } else { multiplier = Math.max(1, multiplier - 0.01); } } // Always update wave line segments for (var i = 0; i < lines.length; i++) { var start = points[i]; var end = points[i + 1]; var dx = end.x - start.x; var dy = end.y - start.y; var length = Math.sqrt(dx * dx + dy * dy); var angle = Math.atan2(dy, dx); lines[i].x += (start.x - lines[i].x) * 0.3; lines[i].y += (start.y - lines[i].y) * 0.3; lines[i].width += (length - lines[i].width) * 0.3; var angleDiff = angle - lines[i].rotation; if (angleDiff > Math.PI) angleDiff -= Math.PI * 2; if (angleDiff < -Math.PI) angleDiff += Math.PI * 2; lines[i].rotation += angleDiff * 0.3; } };
User prompt
Please fix the bug: 'TypeError: undefined is not an object (evaluating 'currentPoint.y')' in or related to this line: 'var targetY = currentPoint.y + (nextPoint.y - currentPoint.y) * progress + WAVE_OFFSET;' Line Number: 197
Code edit (1 edits merged)
Please save this source code
User prompt
Update wave system with: self.update = function() { if (self.isCalibrating) { if (facekit.volume > CALIBRATION_VOLUME_THRESHOLD) { calibrationSamples.push(facekit.pitch); var progress = Math.min(100, Math.floor(calibrationSamples.length / CALIBRATION_SAMPLES * 100)); progressText.setText(progress + "%"); if (calibrationSamples.length >= CALIBRATION_SAMPLES) { finishCalibration(); } } if (LK.ticks - calibrationStartTime > CALIBRATION_TIMEOUT) { if (calibrationSamples.length < 10) { calibrationSamples = []; calibrationStartTime = LK.ticks; calibrationText.setText("Let's try again!\nMake some noise - hum or speak"); } else { finishCalibration(); } } return; } var targetPitch = 0; if (facekit.volume > 0.15) { var normalizedPitch = (facekit.pitch - MIN_PITCH) / (MAX_PITCH - MIN_PITCH); normalizedPitch = Math.max(0, Math.min(1, normalizedPitch)); targetPitch = normalizedPitch * 0.8 + lastPitch * 0.2; } lastPitch += (targetPitch - lastPitch) * 0.2; var smoothedHeight = getSmoothedHeight(lastPitch * WAVE_HEIGHT); points = []; for (var i = 0; i < NUM_POINTS; i++) { var x = i / (NUM_POINTS - 1) * SCREEN_WIDTH; var distanceFromCenter = (x - SCREEN_WIDTH * 0.35) / (SCREEN_WIDTH * 0.45); var heightFactor = gaussianCurve(distanceFromCenter); var y = baseY - smoothedHeight * heightFactor; points.push({ x: x, y: y }); } // Update water rectangles for (var i = 0; i < NUM_WATER_SECTIONS; i++) { var rect = waterRects[i]; var xPosition = i / NUM_WATER_SECTIONS * SCREEN_WIDTH; var exactPointPosition = xPosition / SCREEN_WIDTH * (NUM_POINTS - 1); var pointIndex = Math.floor(exactPointPosition); var nextPointIndex = Math.min(pointIndex + 1, NUM_POINTS - 1); var progress = exactPointPosition - pointIndex; var y1 = points[pointIndex].y; var y2 = points[nextPointIndex].y; var y = y1 + (y2 - y1) * progress; rect.x = xPosition; rect.y = y; rect.height = 2732 - y; rect.alpha = 0.3 + Math.sin(LK.ticks * 0.02 + i * 0.2) * 0.02; } self.points = points; if (facekit.volume > 0.15) { score += smoothedHeight / WAVE_HEIGHT * multiplier; multiplier += 0.001; } else { multiplier = Math.max(1, multiplier - 0.01); } // Update wave line segments for (var i = 0; i < lines.length; i++) { var start = points[i]; var end = points[i + 1]; var dx = end.x - start.x; var dy = end.y - start.y; var length = Math.sqrt(dx * dx + dy * dy); var angle = Math.atan2(dy, dx); lines[i].x += (start.x - lines[i].x) * 0.3; lines[i].y += (start.y - lines[i].y) * 0.3; lines[i].width += (length - lines[i].width) * 0.3; var angleDiff = angle - lines[i].rotation; if (angleDiff > Math.PI) angleDiff -= Math.PI * 2; if (angleDiff < -Math.PI) angleDiff += Math.PI * 2; lines[i].rotation += angleDiff * 0.3; } };
User prompt
Update only as needed with: function updatePitchRange(pitch) { if (facekit.volume > CALIBRATION_VOLUME_THRESHOLD) { calibrationSamples.push(pitch); var progress = Math.min(100, Math.floor(calibrationSamples.length / CALIBRATION_SAMPLES * 100)); progressText.setText(progress + "%"); if (calibrationSamples.length >= CALIBRATION_SAMPLES) { finishCalibration(); } } if (LK.ticks - calibrationStartTime > CALIBRATION_TIMEOUT) { if (calibrationSamples.length < 10) { calibrationSamples = []; calibrationStartTime = LK.ticks; calibrationText.setText("Let's try again!\nMake some noise - hum or speak"); } else { finishCalibration(); } } }
Code edit (1 edits merged)
Please save this source code
User prompt
Update as needed with: function updatePitchRange(pitch) { if (facekit.volume > CALIBRATION_VOLUME_THRESHOLD) { calibrationSamples.push(pitch); // Update progress display var progress = Math.min(100, Math.floor((calibrationSamples.length / CALIBRATION_SAMPLES) * 100)); progressText.setText(progress + "%"); if (calibrationSamples.length >= CALIBRATION_SAMPLES) { finishCalibration(); } } } self.update = function() { if (self.isCalibrating) { updatePitchRange(facekit.pitch); } else { var targetPitch = 0; if (facekit.volume > 0.15) { var normalizedPitch = (facekit.pitch - MIN_PITCH) / (MAX_PITCH - MIN_PITCH); normalizedPitch = Math.max(0, Math.min(1, normalizedPitch)); targetPitch = normalizedPitch * 0.8 + lastPitch * 0.2; } // ... rest of original wave code } };
User prompt
Update only as needed with: var WaveSystem = Container.expand(function() { var self = Container.call(this); self.isCalibrating = true; // Save original update function FIRST, before any overrides var originalUpdate = function() { // Copy the original wave system update code here var targetPitch = 0; if (facekit.volume > 0.15) { var normalizedPitch = (facekit.pitch - MIN_PITCH) / (MAX_PITCH - MIN_PITCH); normalizedPitch = Math.max(0, Math.min(1, normalizedPitch)); targetPitch = normalizedPitch * 0.8 + lastPitch * 0.2; } // ... rest of original wave system code ... }; // Create UI elements at class level var calibrationText = new Text2("Make some noise!\nHum high and low to calibrate", { size: 60, fill: 0xFFFFFF, align: 'center' }); calibrationText.anchor.set(0.5, 0.5); LK.gui.center.addChild(calibrationText); var progressText = new Text2("0%", { size: 40, fill: 0xFFFFFF, alpha: 0.8 }); progressText.anchor.set(0.5, 0.5); progressText.y = calibrationText.y + 80; LK.gui.center.addChild(progressText); var calibrationSamples = []; var CALIBRATION_SAMPLES = 50; var CALIBRATION_VOLUME_THRESHOLD = 0.2; var calibrationStartTime = LK.ticks; var CALIBRATION_TIMEOUT = 300; // Now we can properly reference progressText in our functions function updatePitchRange(pitch) { if (facekit.volume > CALIBRATION_VOLUME_THRESHOLD) { calibrationSamples.push(pitch); var progress = Math.min(100, Math.floor((calibrationSamples.length / CALIBRATION_SAMPLES) * 100)); progressText.setText(progress + "%"); if (calibrationSamples.length >= CALIBRATION_SAMPLES) { finishCalibration(); } } // ... rest of function } // Update function with proper scoping self.update = function() { if (self.isCalibrating) { updatePitchRange(facekit.pitch); } else { originalUpdate.call(self); } }; return self; });
User prompt
Remove the pitch meter from the wave system
User prompt
Update with: var WaveSystem = Container.expand(function() { var self = Container.call(this); // Add to top of WaveSystem to expose calibration state self.isCalibrating = true; // Make this public // Keep existing variables... var calibrationSamples = []; var CALIBRATION_SAMPLES = 50; var CALIBRATION_VOLUME_THRESHOLD = 0.2; var calibrationStartTime = LK.ticks; var CALIBRATION_TIMEOUT = 300; function updatePitchRange(pitch) { if (facekit.volume > CALIBRATION_VOLUME_THRESHOLD) { calibrationSamples.push(pitch); // Update progress display var progress = Math.min(100, Math.floor((calibrationSamples.length / CALIBRATION_SAMPLES) * 100)); progressText.setText(progress + "%"); if (calibrationSamples.length >= CALIBRATION_SAMPLES) { finishCalibration(); } } // Check for timeout if (LK.ticks - calibrationStartTime > CALIBRATION_TIMEOUT) { if (calibrationSamples.length < 10) { calibrationSamples = []; calibrationStartTime = LK.ticks; calibrationText.setText("Let's try again!\nMake some noise - hum or speak"); } else { finishCalibration(); } } } function finishCalibration() { var sortedPitches = calibrationSamples.sort((a, b) => a - b); MIN_PITCH = sortedPitches[Math.floor(calibrationSamples.length * 0.1)]; MAX_PITCH = sortedPitches[Math.floor(calibrationSamples.length * 0.9)]; MIN_PITCH = Math.max(30, MIN_PITCH - 10); MAX_PITCH = MAX_PITCH + 20; self.isCalibrating = false; // Clean up UI calibrationText.setText("Ready!"); progressText.destroy(); tween(calibrationText, { alpha: 0 }, { duration: 1000, onFinish: () => calibrationText.destroy() }); console.log("Calibrated pitch range:", MIN_PITCH, "to", MAX_PITCH); } // Modify the update function var originalUpdate = self.update; self.update = function() { if (self.isCalibrating) { updatePitchRange(facekit.pitch); } else { originalUpdate.call(self); } }; return self; }); ↪💡 Consider importing and using the following plugins: @upit/facekit.v1, @upit/tween.v1
User prompt
Update as needed with: game.update = function() { var now = Date.now(); if (now - lastUpdateTime < 16) { return; } lastUpdateTime = now;
User prompt
Update with: var WaveSystem = Container.expand(function() { var self = Container.call(this); // Add to top of WaveSystem to expose calibration state self.isCalibrating = true; // Make this public var NUM_POINTS = 40; var SCREEN_WIDTH = 2048; var points = []; var baseY = 2732 * 0.85; var MIN_PITCH = 50; var MAX_PITCH = 300; var CALIBRATION_SAMPLES = 50; var CALIBRATION_VOLUME_THRESHOLD = 0.2; var calibrationSamples = []; var calibrationStartTime = LK.ticks; var CALIBRATION_TIMEOUT = 300; // Create calibration UI var calibrationText = new Text2("Make some noise!\nHum high and low to calibrate", { size: 60, fill: 0xFFFFFF, align: 'center' }); calibrationText.anchor.set(0.5, 0.5); calibrationText.x = SCREEN_WIDTH/2; calibrationText.y = 400; LK.gui.center.addChild(calibrationText); var progressText = new Text2("0%", { size: 40, fill: 0xFFFFFF, alpha: 0.8 }); progressText.anchor.set(0.5, 0.5); progressText.x = SCREEN_WIDTH/2; progressText.y = calibrationText.y + 80; LK.gui.center.addChild(progressText); // Visual pitch meter setup var pitchMeter = game.addChild(LK.getAsset('wave_line', { width: 400, height: 8, tint: 0x14ffff })); var pitchIndicator = game.addChild(LK.getAsset('orb', { width: 20, height: 20, tint: 0xd733a6 })); // Position meter pitchMeter.x = SCREEN_WIDTH/2 - 200; pitchMeter.y = progressText.y + 60; pitchIndicator.y = pitchMeter.y; var lowPitchText = new Text2("Low", { size: 30, fill: 0xFFFFFF, alpha: 0.8 }); var highPitchText = new Text2("High", { size: 30, fill: 0xFFFFFF, alpha: 0.8 }); lowPitchText.anchor.set(1, 0.5); highPitchText.anchor.set(0, 0.5); lowPitchText.x = pitchMeter.x - 10; highPitchText.x = pitchMeter.x + pitchMeter.width + 10; lowPitchText.y = pitchMeter.y; highPitchText.y = pitchMeter.y; LK.gui.center.addChild(lowPitchText); LK.gui.center.addChild(highPitchText); function updatePitchRange(pitch) { if (facekit.volume > CALIBRATION_VOLUME_THRESHOLD) { calibrationSamples.push(pitch); // Update progress display var progress = Math.min(100, Math.floor((calibrationSamples.length / CALIBRATION_SAMPLES) * 100)); progressText.setText(progress + "%"); // Update pitch indicator position var normalizedPitch = (pitch - 50) / (300 - 50); normalizedPitch = Math.max(0, Math.min(1, normalizedPitch)); pitchIndicator.x = pitchMeter.x + (pitchMeter.width * normalizedPitch); if (calibrationSamples.length >= CALIBRATION_SAMPLES) { finishCalibration(); } } else { // Reset indicator to center when not making sound pitchIndicator.x = pitchMeter.x + (pitchMeter.width * 0.5); } // Check for timeout if (LK.ticks - calibrationStartTime > CALIBRATION_TIMEOUT) { if (calibrationSamples.length < 10) { calibrationSamples = []; calibrationStartTime = LK.ticks; calibrationText.setText("Let's try again!\nMake some noise - hum or speak"); } else { finishCalibration(); } } } function finishCalibration() { var sortedPitches = calibrationSamples.sort((a, b) => a - b); MIN_PITCH = sortedPitches[Math.floor(calibrationSamples.length * 0.1)]; MAX_PITCH = sortedPitches[Math.floor(calibrationSamples.length * 0.9)]; MIN_PITCH = Math.max(30, MIN_PITCH - 10); MAX_PITCH = MAX_PITCH + 20; self.isCalibrating = false; // Clean up UI calibrationText.setText("Ready!"); progressText.destroy(); pitchMeter.destroy(); pitchIndicator.destroy(); lowPitchText.destroy(); highPitchText.destroy(); tween(calibrationText, { alpha: 0 }, { duration: 1000, onFinish: () => calibrationText.destroy() }); console.log("Calibrated pitch range:", MIN_PITCH, "to", MAX_PITCH); } // Modify the update function var originalUpdate = self.update; self.update = function() { if (self.isCalibrating) { updatePitchRange(facekit.pitch); } else { originalUpdate.call(self); } }; return self; }); ↪💡 Consider importing and using the following plugins: @upit/facekit.v1
Code edit (1 edits merged)
Please save this source code
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
var facekit = LK.import("@upit/facekit.v1");
/****
* Classes
****/
var ParticleSystem = Container.expand(function () {
var self = Container.call(this);
self.addWaterParticle = function (x, y, type) {
var particle = ParticlePool.get();
if (type === 'trail') {
// Move spawn point up and behind surfer
particle.x = x - 100; // Spawn behind (to the right of) surfer
particle.y = y + 10; // Raised up from previous +90
} else {
// Keep original splash positioning
particle.x = x + Math.random() * 130 - 40;
particle.y = y - 20;
}
particle.init(type);
self.addChild(particle);
};
self.update = function () {
for (var i = self.children.length - 1; i >= 0; i--) {
var particle = self.children[i];
if (particle.update) {
particle.update();
}
// Remove particles that have moved far off screen
if (particle.x < -500 || particle.x > 2548 || particle.y < -500 || particle.y > 3232) {
ParticlePool["return"](particle);
self.removeChild(particle);
}
}
};
return self;
});
var Rock = Container.expand(function () {
var self = Container.call(this);
var rock = self.attachAsset('island', {
anchorX: 0.5,
anchorY: 1 // Anchor to top since we're stretching upward
});
// Set scales independently
rock.scaleX = 2;
rock.scaleY = 2; // Start with a base scale
self.checkCollision = function (surfer) {
var rockWidth = self.width;
var rockHeight = self.height;
var rockTop = self.y - rockHeight;
var points = [{
x: self.x,
y: rockTop
}, {
x: self.x - rockWidth * 0.4,
y: self.y - rockHeight * 0.1
}, {
x: self.x + rockWidth * 0.4,
y: self.y - rockHeight * 0.1
}];
var surferBox = {
x: surfer.x - 30,
y: surfer.y - 30,
width: 60,
height: 60
};
return isPointInTriangle(surferBox.x, surferBox.y, points) || isPointInTriangle(surferBox.x + surferBox.width, surferBox.y, points) || isPointInTriangle(surferBox.x, surferBox.y + surferBox.height, points) || isPointInTriangle(surferBox.x + surferBox.width, surferBox.y + surferBox.height, points);
};
self.update = function () {
if (self.lastX === undefined) {
self.lastX = self.x;
} // Initialize lastX if not set
self.x -= 8;
if (self.x < -self.width) {
self.destroy();
}
self.lastX = self.x; // Update lastX
};
return self;
});
var Seagull = Container.expand(function () {
var self = Container.call(this);
var seagullGraphics = self.attachAsset('seagull', {
anchorX: 0.5,
anchorY: 0.5
});
// Circle collision data
self.radius = 35;
self.collisionX = 0;
self.collisionY = 0;
self.speed = -5 - Math.random() * 3; // Random speed variation
self.y = Math.random() * (2732 * 0.33); // Top third of screen
self.x = 2248; // Start off-screen right
// Flying animation
function flyAnimation() {
tween(self, {
y: self.y + (Math.random() * 100 - 50)
}, {
duration: 1000,
easing: tween.easeInOut,
onFinish: flyAnimation
});
// Wing flap effect
tween(seagullGraphics, {
scaleY: 0.8,
y: 5
}, {
duration: 500,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(seagullGraphics, {
scaleY: 1,
y: 0
}, {
duration: 500,
easing: tween.easeInOut
});
}
});
}
flyAnimation();
self.update = function () {
self.x += self.speed;
// Update collision circle position
self.collisionX = self.x;
self.collisionY = self.y;
// Remove if off screen
if (self.x < -100) {
self.destroy();
}
// Circle collision with surfer
var dx = self.collisionX - surfer.x;
var dy = self.collisionY - surfer.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < self.radius + 40) {
// 40 is approximate surfer radius
LK.showGameOver();
}
};
return self;
});
var Surfer = Container.expand(function () {
var self = Container.call(this);
var BASE_GRAVITY = 1.5; // Reduced for smoother acceleration
var MAX_SPEED = 40; // Increased for longer falls
var DAMPENING = 0.98; // Less dampening for smoother motion
var WAVE_OFFSET = -30;
var FIXED_X = 2048 * 0.35;
var MAX_AIR_VELOCITY = -25; // Only applies when surfer is above wave
var velocityY = 0;
var velocityRot = 0;
var activeTween = null; // Initialize activeTween variable
var lastWaveY = 2732 * 0.85; // Match WaveSystem's baseY
var initialized = false;
var surferGraphics = self.attachAsset('surfer', {
anchorX: 0.5,
anchorY: 0.8
});
self.x = FIXED_X;
self.y = lastWaveY + WAVE_OFFSET; // Start at base wave height
self.setWaveSystem = function (ws) {
waveSystem = ws;
if (!waveSystem.points) {
waveSystem.points = [];
}
initialized = true;
};
self.update = function () {
// Add tween cleanup
if (activeTween) {
tween.stop(activeTween);
}
if (!waveSystem) {
return;
}
var normalizedX = self.x / 2048;
var pointIndex = Math.floor(normalizedX * (waveSystem.points.length - 1));
var nextPointIndex = Math.min(pointIndex + 1, waveSystem.points.length - 1);
var progress = normalizedX * (waveSystem.points.length - 1) - pointIndex;
var currentPoint = waveSystem.points[pointIndex];
var nextPoint = waveSystem.points[nextPointIndex];
if (currentPoint && nextPoint) {
var targetY = currentPoint.y + (nextPoint.y - currentPoint.y) * progress + WAVE_OFFSET;
} else {
return; // Exit update if points are undefined
}
var waveRising = targetY < lastWaveY;
var aboveWave = self.y < targetY;
if (waveRising && !aboveWave) {
// Natural wave following - no limits when on the wave
velocityY = (targetY - self.y) * 0.2;
self.y += velocityY;
} else {
// In air or falling
velocityY += BASE_GRAVITY;
velocityY *= DAMPENING;
// Only cap velocity when above the wave
if (aboveWave && velocityY < MAX_AIR_VELOCITY) {
velocityY = MAX_AIR_VELOCITY;
}
self.y += velocityY;
if (self.y > targetY && velocityY > 0) {
var fallVelocity = velocityY; // Capture velocity before reset
self.y = targetY;
velocityY = 0;
if (aboveWave && fallVelocity > 15) {
// Only splash on significant falls
createSplash();
}
}
}
lastWaveY = targetY;
var baseRotation = -0.1; // Slight left tilt as base position
var waveRotation = Math.sin(LK.ticks / 30) * 0.05; // Gentle wave motion
// Calculate vertical movement speed
var verticalSpeed = self.y - lastWaveY;
// Add rotation based on vertical movement
var verticalRotation = 0;
if (verticalSpeed < -2) {
// Moving up
verticalRotation = Math.min(0.3, -verticalSpeed * 0.005); // Changed from 0.01
} else if (verticalSpeed > 2) {
// Moving down
verticalRotation = Math.max(-0.4, -verticalSpeed * 0.005); // Changed from 0.01
}
// Smoothly apply all rotations
velocityRot += (baseRotation + waveRotation + verticalRotation - self.rotation) * 0.05; // Changed from 0.1
velocityRot *= 0.9; // Changed from 0.8 for less damping
self.rotation += velocityRot;
// Create trail particles whenever touching water
if (self.y >= targetY) {
createTrail();
}
var targetAngle = Math.atan2(nextPoint.y - currentPoint.y, nextPoint.x - currentPoint.x);
// ... rest of the rotation code ...
particles.children.forEach(function (particle) {
if (particle.update) {
particle.update();
}
});
};
self.getScore = function () {
return Math.floor(score);
};
// Then in the Surfer class, replace the particle system with:
var particles = self.addChild(new ParticleSystem());
function createSplash() {
for (var i = 0; i < 50; i++) {
// Move splash up by 40 to match trail Y position
game.particles.addWaterParticle(FIXED_X, self.y + 40, 'splash');
}
}
function createTrail() {
// Create fewer particles but more frequently for trail
for (var i = 0; i < 4; i++) {
game.particles.addWaterParticle(FIXED_X, self.y, 'trail');
}
}
return self;
});
var WaterParticle = Container.expand(function () {
var self = Container.call(this);
var particleGraphics = self.attachAsset('wave_point', {
anchorX: 0.5,
anchorY: 0.5
});
var speed, angle, scale;
self.init = function (type) {
// Reset properties
scale = 1;
self.type = type;
if (type === 'trail') {
speed = Math.random() * 8 + 6;
angle = Math.PI + (Math.random() * 0.4 - 0.2);
scale = 0.7;
particleGraphics.alpha = 0.8;
} else {
speed = Math.random() * 12 + 8;
angle = -Math.PI / 2 + (Math.random() * 1.4 - 0.7);
scale = 1.2;
particleGraphics.alpha = 0.9;
}
self.scale.set(scale, scale);
};
self.update = function () {
scale -= self.type === 'splash' ? 0.04 : 0.02;
self.scale.set(scale, scale);
if (scale <= 0) {
// Instead of destroying, return to pool
if (self.parent) {
self.parent.removeChild(self);
}
ParticlePool["return"](self);
return;
}
self.x += Math.cos(angle) * speed;
self.y += Math.sin(angle) * speed;
};
return self;
});
var WaveSystem = Container.expand(function () {
var self = Container.call(this);
var NUM_POINTS = 40;
var SCREEN_WIDTH = 2048;
var points = [];
var baseY = 2732 * 0.85;
var MIN_PITCH = 50;
var MAX_PITCH = 300;
var calibrationSamples = [];
self.isCalibrating = true;
var CALIBRATION_SAMPLES = 100; // Doubled to 100 samples
var CALIBRATION_VOLUME_THRESHOLD = 0.4; // Minimum volume to count as valid input
var calibrationStartTime = LK.ticks;
var CALIBRATION_TIMEOUT = 300; // 5 seconds (60 ticks per second)
var WAVE_HEIGHT = 2000;
var lastPitch = 0;
// Create calibration message
var calibrationText = new Text2("Make some noise!\nHum high and low to calibrate", {
size: 60,
fill: 0xFFFFFF,
align: 'center'
});
calibrationText.anchor.set(0.5, 0.5);
LK.gui.center.addChild(calibrationText);
// Progress indicator
var progressText = new Text2("0%", {
size: 40,
fill: 0xFFFFFF,
alpha: 0.8
});
progressText.anchor.set(0.5, 0.5);
progressText.y = calibrationText.y + 80;
LK.gui.center.addChild(progressText);
// Removed visual pitch indicator and labels
function updatePitchRange(pitch) {
if (facekit.volume > CALIBRATION_VOLUME_THRESHOLD) {
calibrationSamples.push(pitch);
// Update progress display
var progress = Math.min(100, Math.floor(calibrationSamples.length / CALIBRATION_SAMPLES * 100));
progressText.setText(progress + "%");
// Removed pitch indicator position update as visual indicator is no longer used
if (calibrationSamples.length >= CALIBRATION_SAMPLES) {
finishCalibration();
}
}
// Check for timeout
if (LK.ticks - calibrationStartTime > CALIBRATION_TIMEOUT) {
if (calibrationSamples.length < 10) {
// Not enough samples
// Reset and extend time
calibrationSamples = [];
calibrationStartTime = LK.ticks;
calibrationText.setText("Let's try again!\nMake some noise - hum or speak");
} else {
finishCalibration(); // Use what we have
}
}
}
function finishCalibration() {
var sortedPitches = calibrationSamples.sort(function (a, b) {
return a - b;
});
MIN_PITCH = sortedPitches[Math.floor(calibrationSamples.length * 0.1)];
MAX_PITCH = sortedPitches[Math.floor(calibrationSamples.length * 0.9)];
// Add padding to range
MIN_PITCH = Math.max(30, MIN_PITCH - 10);
MAX_PITCH = MAX_PITCH + 20;
self.isCalibrating = false;
// Show completion message
calibrationText.setText("Ready!");
progressText.destroy();
// Fade out completion message
tween(calibrationText, {
alpha: 0
}, {
duration: 1000,
onFinish: function onFinish() {
return calibrationText.destroy();
}
});
// Removed pitch meter cleanup
console.log("Calibrated pitch range:", MIN_PITCH, "to", MAX_PITCH);
}
// Enhanced smoothing system
var heightBuffer = Array(15).fill(0);
var bufferIndex = 0;
var lastSmoothedHeight = 0;
// Water fill rectangles
var waterRects = [];
var NUM_WATER_SECTIONS = 80; // Reduced from 80
for (var i = 0; i < NUM_WATER_SECTIONS; i++) {
var rect = self.attachAsset('wave_line', {
anchorX: 0.5,
// Center anchor
anchorY: 0,
// Top anchor
height: 2732,
width: SCREEN_WIDTH / NUM_WATER_SECTIONS + 1,
// Tiny overlap to prevent pixel gaps
tint: 0x0066cc,
alpha: 0.3
});
waterRects.push(rect);
}
// Create wave line segments
var lines = [];
function createLines() {
// Clean up any existing lines first
lines.forEach(function (line) {
line.destroy();
self.removeChild(line);
});
lines = [];
// Create new lines
for (var i = 0; i < NUM_POINTS - 1; i++) {
var line = self.attachAsset('wave_line', {
anchorX: 0,
anchorY: 0.5,
height: 4
});
lines.push(line);
}
}
// Call initial creation
createLines();
function gaussianCurve(x) {
return Math.exp(-(x * x) / 0.8);
}
function getSmoothedHeight(newHeight) {
heightBuffer[bufferIndex] = newHeight;
bufferIndex = (bufferIndex + 1) % heightBuffer.length;
// Simplified smoothing calculation
var total = 0;
for (var i = 0; i < heightBuffer.length; i++) {
total += heightBuffer[i];
}
var smoothedHeight = total / heightBuffer.length;
lastSmoothedHeight = lastSmoothedHeight * 0.7 + smoothedHeight * 0.3;
return lastSmoothedHeight;
}
self.update = function () {
// Always calculate wave points first, regardless of calibration state
var targetPitch = 0;
if (facekit.volume > 0.35) {
var normalizedPitch = (facekit.pitch - MIN_PITCH) / (MAX_PITCH - MIN_PITCH);
normalizedPitch = Math.max(0, Math.min(1, normalizedPitch));
targetPitch = normalizedPitch * 0.8 + lastPitch * 0.2;
}
lastPitch += (targetPitch - lastPitch) * 0.2;
var smoothedHeight = getSmoothedHeight(lastPitch * WAVE_HEIGHT);
points = [];
for (var i = 0; i < NUM_POINTS; i++) {
var x = i / (NUM_POINTS - 1) * SCREEN_WIDTH;
var distanceFromCenter = (x - SCREEN_WIDTH * 0.35) / (SCREEN_WIDTH * 0.45);
var heightFactor = gaussianCurve(distanceFromCenter);
var y = baseY - smoothedHeight * heightFactor;
points.push({
x: x,
y: y
});
}
// Always update water rectangles
for (var i = 0; i < NUM_WATER_SECTIONS; i++) {
var rect = waterRects[i];
var xPosition = i / NUM_WATER_SECTIONS * SCREEN_WIDTH;
var exactPointPosition = xPosition / SCREEN_WIDTH * (NUM_POINTS - 1);
var pointIndex = Math.floor(exactPointPosition);
var nextPointIndex = Math.min(pointIndex + 1, NUM_POINTS - 1);
var progress = exactPointPosition - pointIndex;
var y1 = points[pointIndex].y;
var y2 = points[nextPointIndex].y;
var y = y1 + (y2 - y1) * progress;
rect.x = xPosition;
rect.y = y;
rect.height = 2732 - y;
rect.alpha = 0.3 + Math.sin(LK.ticks * 0.02 + i * 0.2) * 0.02;
}
self.points = points;
// Handle calibration if still calibrating
if (self.isCalibrating) {
if (facekit.volume > CALIBRATION_VOLUME_THRESHOLD) {
calibrationSamples.push(facekit.pitch);
var progress = Math.min(100, Math.floor(calibrationSamples.length / CALIBRATION_SAMPLES * 100));
progressText.setText(progress + "%");
if (calibrationSamples.length >= CALIBRATION_SAMPLES) {
finishCalibration();
}
}
if (LK.ticks - calibrationStartTime > CALIBRATION_TIMEOUT) {
if (calibrationSamples.length < 10) {
calibrationSamples = [];
calibrationStartTime = LK.ticks;
calibrationText.setText("Let's try again!\nMake some noise - hum or speak");
} else {
finishCalibration();
}
}
} else {
// Only update score when not calibrating
if (facekit.volume > 0.35) {
score += smoothedHeight / WAVE_HEIGHT * multiplier;
multiplier += 0.001;
} else {
multiplier = Math.max(1, multiplier - 0.01);
}
}
// Always update wave line segments
for (var i = 0; i < lines.length; i++) {
var start = points[i];
var end = points[i + 1];
var dx = end.x - start.x;
var dy = end.y - start.y;
var length = Math.sqrt(dx * dx + dy * dy);
var angle = Math.atan2(dy, dx);
lines[i].x += (start.x - lines[i].x) * 0.3;
lines[i].y += (start.y - lines[i].y) * 0.3;
lines[i].width += (length - lines[i].width) * 0.3;
var angleDiff = angle - lines[i].rotation;
if (angleDiff > Math.PI) {
angleDiff -= Math.PI * 2;
}
if (angleDiff < -Math.PI) {
angleDiff += Math.PI * 2;
}
lines[i].rotation += angleDiff * 0.3;
}
};
self.destroy = function () {
waterRects.forEach(function (rect) {
return rect.destroy();
});
lines.forEach(function (line) {
return line.destroy();
});
waterRects = [];
lines = [];
Container.prototype.destroy.call(this);
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000000 //Init game with black background
});
/****
* Game Code
****/
var ParticlePool = {
pool: [],
maxSize: 200,
get: function get() {
if (this.pool.length > 0) {
var particle = this.pool.pop();
particle.visible = true;
return particle;
}
return new WaterParticle();
},
"return": function _return(particle) {
if (this.pool.length < this.maxSize) {
// Reset particle properties
particle.visible = false;
particle.scale.set(1, 1);
particle.x = 0;
particle.y = 0;
particle.rotation = 0;
this.pool.push(particle);
} else {
particle.destroy();
}
}
};
function isPointInTriangle(px, py, points) {
var p0 = points[0],
p1 = points[1],
p2 = points[2];
var A = 1 / 2 * (-p1.y * p2.x + p0.y * (-p1.x + p2.x) + p0.x * (p1.y - p2.y) + p1.x * p2.y);
var sign = A < 0 ? -1 : 1;
var s = (p0.y * p2.x - p0.x * p2.y + (p2.y - p0.y) * px + (p0.x - p2.x) * py) * sign;
var t = (p0.x * p1.y - p0.y * p1.x + (p0.y - p1.y) * px + (p1.x - p0.x) * py) * sign;
return s > 0 && t > 0 && s + t < 2 * A * sign;
}
var lastScoreDisplay = -1;
var lastMultiplierDisplay = -1;
var originalSetInterval = LK.setInterval;
LK.setInterval = function () {
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
}
var timer = originalSetInterval.apply(this, args);
gameTimers.push(timer);
return timer;
};
var originalSetTimeout = LK.setTimeout;
LK.setTimeout = function () {
for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
args[_key2] = arguments[_key2];
}
var timer = originalSetTimeout.apply(this, args);
gameTimers.push(timer);
return timer;
};
var gameTimers = [];
var seagullSpawnInterval = 6000; // Spawn every 3 seconds
var lastSeagullSpawn = 0;
function spawnSeagull() {
if (Date.now() - lastSeagullSpawn > seagullSpawnInterval) {
var seagull = new Seagull();
game.addChild(seagull);
lastSeagullSpawn = Date.now();
seagullSpawnInterval = 4000 + Math.random() * 4000; // Random interval between 2-4 seconds
}
}
var rocks = [];
var lastRockTime = 0;
var score = 0; // Initialize score variable
var multiplier = 1;
var lastWaveHeight = 0;
var lastWaveUpdate = 0;
var devicePerformance = 1; // Default performance multiplier
var poseidon = LK.getAsset('poseidon', {
anchorX: 0.5,
anchorY: 0.5
});
game.addChild(poseidon);
var mouth = LK.getAsset('mouth', {
anchorX: 0.5,
// Center anchor
anchorY: 0.5,
// Center anchor
alpha: 0 // Initialize alpha to 0
});
game.addChild(mouth);
var waveSystem = game.addChild(new WaveSystem());
var particles = new ParticleSystem();
game.particles = game.addChild(new ParticleSystem());
var surfer = game.addChild(new Surfer());
surfer.setWaveSystem(waveSystem);
var scoreText = new Text2("", {
size: 100,
fill: 0xFFFFFF
});
scoreText.anchor.set(1, 0);
LK.gui.top.addChild(scoreText);
var multiplierText = new Text2("", {
size: 60,
fill: 0xFFFFFF,
alpha: 0.8
});
multiplierText.anchor.set(1, 1);
LK.gui.bottomRight.addChild(multiplierText);
// Game update function
var lastUpdateTime = 0;
game.update = function () {
var now = Date.now();
if (now - lastUpdateTime < 16) {
// Don't update faster than 60fps
return;
}
lastUpdateTime = now;
// Every 300 frames, log counts
if (LK.ticks % 600 === 0) {
console.log('Active timers:', gameTimers.length);
}
if (LK.ticks % 300 === 0) {
console.log('Particle count:', game.particles.children.length);
console.log('Wave points:', waveSystem.points.length);
console.log('Total game children:', game.children.length);
console.log('Active tweens:', tween.getActiveTweens ? tween.getActiveTweens().length : 0);
}
waveSystem.update();
surfer.update();
particles.update();
// Update Poseidon's position to follow the player's face
if (facekit.noseTip) {
poseidon.x = facekit.noseTip.x;
poseidon.y = facekit.noseTip.y;
}
// Update mouth position to follow the player's mouth
if (facekit.mouthCenter) {
mouth.x = facekit.mouthCenter.x;
mouth.y = facekit.mouthCenter.y + 50;
if (facekit.volume > 0.45) {
// Change alpha to 1 when volume is greater than 0.35
mouth.alpha = 1;
} else {
mouth.alpha = 0;
}
}
// Only spawn obstacles if not calibrating
if (!waveSystem.isCalibrating) {
// Rock spawning
if (LK.ticks - lastRockTime > 240 + Math.random() * 360) {
lastRockTime = LK.ticks;
var rock = game.addChild(new Rock());
rock.x = 2548; // Start off right side
rock.y = 2732 + 200; // Place base below screen
// Set the vertical scale independently for random height
rock.children[0].scaleY = 3 + Math.random() * 4; // Random height between 3x and 7x
rocks.push(rock);
}
// Seagull spawning
spawnSeagull();
}
// Update and check rocks
for (var i = rocks.length - 1; i >= 0; i--) {
var rock = rocks[i];
rock.update();
// Remove destroyed rocks
if (!rock.parent) {
rocks.splice(i, 1);
continue;
}
// Check collision with surfer
if (rock.checkCollision(surfer)) {
LK.showGameOver();
}
}
game.children.forEach(function (child) {
if (child instanceof Seagull && child.update) {
child.update();
}
});
var currentScore = Math.floor(score);
if (currentScore !== lastScoreDisplay) {
lastScoreDisplay = currentScore;
scoreText.setText(currentScore.toLocaleString());
}
var currentMultiplier = Math.floor(multiplier * 10) / 10; // Round to 1 decimal
if (currentMultiplier !== lastMultiplierDisplay) {
lastMultiplierDisplay = currentMultiplier;
multiplierText.setText("x" + currentMultiplier.toFixed(1));
}
}; ===================================================================
--- original.js
+++ change.js
@@ -686,9 +686,9 @@
}
// Update mouth position to follow the player's mouth
if (facekit.mouthCenter) {
mouth.x = facekit.mouthCenter.x;
- mouth.y = facekit.mouthCenter.y;
+ mouth.y = facekit.mouthCenter.y + 50;
if (facekit.volume > 0.45) {
// Change alpha to 1 when volume is greater than 0.35
mouth.alpha = 1;
} else {
A surfer standing and riding on a surfboard. Side profile. Cartoon. Full body. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
A peaked blue rock. Cartoon style.. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
Poseidon’s face. Cartoon style.. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
An opened pair of lips as if singing . Light Skin color. Cell shading vector art style. Facing forward. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
A tropical fish. Cartoon.. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows