User prompt
could we also add a booster block along with the others for the player to collect which will increase the players speed and increase the tempo of the music. βͺπ‘ Consider importing and using the following plugins: @upit/tween.v1
User prompt
make it so!
User prompt
make it so!
User prompt
sounds good make it so!
User prompt
sick! make it so please!
User prompt
can you move the 2 buttons a little higher
User prompt
make it so!
User prompt
cool! love this! make it so! βͺπ‘ Consider importing and using the following plugins: @upit/facekit.v1
User prompt
try again βͺπ‘ Consider importing and using the following plugins: @upit/facekit.v1
User prompt
For the background image can you Add a moving neon grid or subtle scrolling starfield for synthwave effect Use a linear gradient (top to bottom) in dark purples/blues βͺπ‘ Consider importing and using the following plugins: @upit/tween.v1
User prompt
make it so!
User prompt
cool sounds good make it so !
Code edit (1 edits merged)
Please save this source code
User prompt
Sound Surfer
Initial prompt
Create a simple rhythm game called "Sound Surfer" with the following features: A main menu that will be within a black and neon box with two options: option 1 will include use of the facekit which will use the mic for recording the music and beats that the player decides to use. Option 2 will NOT use the facekit and mic for beats/music and instead will use a randomly generated beat/music that you will create for the player. The game has three vertical lanes: left, center, and right. The player is a small glowing cool looking ship like from F-zero games at the bottom of the screen that can switch between lanes by clicking. Clicking on the left half of the screen moves the player one lane to the left. Clicking on the right half of the screen moves the player one lane to the right. The player cannot move outside the 3 lanes. Colored blocks spawn at the top of the screen in a random lane and fall down at a constant speed. When a block reaches the playerβs lane and collides with the player, the block disappears, and: +10 points are added to the score. A combo counter increases. If the block passes the player without a collision, the combo resets. Display the current "score" and "combo" in the top corner of the screen. Use a minimal neon/synthwave visual style: Dark background Bright glowing blocks and player Simple grid or lines to separate the lanes Use simple logic for now: Spawn a block every 1 second using a timer.
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
var facekit = LK.import("@upit/facekit.v1");
/****
* Classes
****/
var BackgroundGrid = Container.expand(function () {
var self = Container.call(this);
// Create horizontal grid lines
self.horizontalLines = [];
for (var i = 0; i < 15; i++) {
var line = self.attachAsset('gridLine', {
anchorX: 0,
anchorY: 0.5,
alpha: 0.3
});
line.y = i * 200 - 400;
self.horizontalLines.push(line);
}
// Create vertical grid lines
self.verticalLines = [];
for (var j = 0; j < 8; j++) {
var vLine = self.attachAsset('gridLineVertical', {
anchorX: 0.5,
anchorY: 0,
alpha: 0.2
});
vLine.x = j * 300;
self.verticalLines.push(vLine);
}
self.update = function () {
// Move horizontal lines down
for (var i = 0; i < self.horizontalLines.length; i++) {
var line = self.horizontalLines[i];
line.y += 2;
// Reset line position when it goes off screen
if (line.y > 2800) {
line.y = -100;
}
// Fade effect based on distance from center
var distanceFromCenter = Math.abs(line.y - 1366);
var maxDistance = 1366;
line.alpha = 0.3 * (1 - distanceFromCenter / maxDistance);
}
};
return self;
});
var Block = Container.expand(function () {
var self = Container.call(this);
var blockGraphics = self.attachAsset('block', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
scaleY: 0.8
});
self.speed = 8;
self.lane = 0;
self.caught = false;
// Random neon colors
var colors = [0xff00ff, 0x00ffff, 0xffff00, 0xff0066, 0x66ff00];
blockGraphics.tint = colors[Math.floor(Math.random() * colors.length)];
self.update = function () {
self.y += self.speed;
};
return self;
});
var Ship = Container.expand(function () {
var self = Container.call(this);
var shipGraphics = self.attachAsset('ship', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 1.5
});
// Add glow effect
shipGraphics.filters = [];
self.currentLane = 1; // 0 = left, 1 = center, 2 = right
self.targetX = 1024; // center position
self.update = function () {
// Smooth movement to target lane
var diff = self.targetX - self.x;
if (Math.abs(diff) > 2) {
self.x += diff * 0.15;
} else {
self.x = self.targetX;
}
};
self.moveToLane = function (lane) {
self.currentLane = lane;
if (lane === 0) {
self.targetX = 341; // left lane
} else if (lane === 1) {
self.targetX = 1024; // center lane
} else if (lane === 2) {
self.targetX = 1707; // right lane
}
// Add movement animation
tween(shipGraphics, {
scaleX: 1.2,
scaleY: 0.8
}, {
duration: 100,
onFinish: function onFinish() {
tween(shipGraphics, {
scaleX: 1,
scaleY: 1
}, {
duration: 100
});
}
});
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x0a0a0a
});
/****
* Game Code
****/
// Create synthwave background with gradient effect
game.setBackgroundColor(0x1a0033);
// Create moving background grid
var backgroundGrid = game.addChild(new BackgroundGrid());
// Game state
var gameMode = 'menu'; // 'menu', 'classic', 'microphone'
var ship;
var blocks = [];
var score = 0;
var combo = 0;
var bestCombo = 0;
var lastSpawnTime = 0;
var spawnInterval = 1000; // 1 second
// Beat detection variables
var audioBuffer = [];
var beatThreshold = 0.4;
var lastBeatTime = 0;
var minBeatInterval = 200; // Minimum ms between beats
var volumeHistory = [];
var bufferSize = 10;
var beatSensitivity = 1.5;
// Lane positions - equal width lanes
var lanePositions = [341, 1024, 1707];
// UI Elements
var scoreTxt = new Text2('Score: 0', {
size: 60,
fill: 0x00FFFF
});
scoreTxt.anchor.set(0, 0);
scoreTxt.x = 50;
scoreTxt.y = 50;
LK.gui.topLeft.addChild(scoreTxt);
var comboTxt = new Text2('Combo: 0', {
size: 50,
fill: 0xFF00FF
});
comboTxt.anchor.set(0, 0);
comboTxt.x = 50;
comboTxt.y = 120;
LK.gui.topLeft.addChild(comboTxt);
// Create mode selection buttons with neon glow outline
var classicButton = new Text2('1. CLASSIC MODE\nBuilt-in synthwave music', {
size: 60,
fill: 0x00FFFF,
stroke: 0x00FFFF,
strokeThickness: 3
});
classicButton.anchor.set(0.5, 0.5);
classicButton.x = 0;
classicButton.y = -150;
LK.gui.center.addChild(classicButton);
var micButton = new Text2('2. MICROPHONE MODE\nSync with your music', {
size: 60,
fill: 0xFF00FF,
stroke: 0xFF00FF,
strokeThickness: 3
});
micButton.anchor.set(0.5, 0.5);
micButton.x = 0;
micButton.y = 50;
LK.gui.center.addChild(micButton);
var instructionTxt = new Text2('TAP A BUTTON TO SELECT MODE', {
size: 50,
fill: 0xFFFFFF
});
instructionTxt.anchor.set(0.5, 0.5);
instructionTxt.y = 100;
LK.gui.center.addChild(instructionTxt);
// Create lane dividers
var lane1 = game.addChild(LK.getAsset('lane1', {
x: 682,
y: 0
}));
var lane2 = game.addChild(LK.getAsset('lane2', {
x: 1366,
y: 0
}));
// Create ship
ship = game.addChild(new Ship());
ship.x = 1024;
ship.y = 2400;
function startGame(mode) {
gameMode = mode;
score = 0;
combo = 0;
bestCombo = 0;
blocks = [];
lastSpawnTime = 0;
// Reset beat detection variables
audioBuffer = [];
volumeHistory = [];
lastBeatTime = 0;
// Hide menu elements
classicButton.visible = false;
micButton.visible = false;
instructionTxt.visible = false;
// Start background music only in classic mode
if (mode === 'classic') {
LK.playMusic('synthwave');
} else {
// Stop background music in microphone mode to focus on external audio
LK.stopMusic();
}
updateUI();
}
function spawnBlock() {
var block = new Block();
var lane;
if (gameMode === 'microphone') {
// Create more musical patterns based on audio intensity
var intensity = facekit.volume;
if (intensity > 0.8) {
// High intensity - spawn in multiple lanes or center
lane = Math.random() > 0.5 ? 1 : Math.floor(Math.random() * 3);
} else if (intensity > 0.5) {
// Medium intensity - prefer outer lanes
lane = Math.random() > 0.5 ? 0 : 2;
} else {
// Low intensity - single random lane
lane = Math.floor(Math.random() * 3);
}
} else {
// Classic mode - random lane
lane = Math.floor(Math.random() * 3);
}
block.lane = lane;
block.x = lanePositions[lane];
block.y = -50;
blocks.push(block);
game.addChild(block);
}
function updateUI() {
scoreTxt.setText('Score: ' + score);
comboTxt.setText('Combo: ' + combo + ' (Best: ' + bestCombo + ')');
}
function checkCollisions() {
for (var i = blocks.length - 1; i >= 0; i--) {
var block = blocks[i];
// Check if block is in ship's catch zone
if (!block.caught && block.y >= ship.y - 100 && block.y <= ship.y + 100) {
if (block.lane === ship.currentLane) {
// Block caught!
block.caught = true;
score += 10 + combo * 2;
combo++;
if (combo > bestCombo) {
bestCombo = combo;
}
// Visual feedback
LK.effects.flashObject(block, 0xffffff, 200);
tween(block, {
scaleX: 1.5,
scaleY: 1.5,
alpha: 0
}, {
duration: 200
});
LK.getSound('catch').play();
updateUI();
// Remove block
block.destroy();
blocks.splice(i, 1);
continue;
}
}
// Check if block missed (passed ship)
if (!block.caught && block.y > ship.y + 150) {
if (block.lane === ship.currentLane) {
// Block missed - reset combo
combo = 0;
LK.effects.flashScreen(0xff0000, 300);
LK.getSound('miss').play();
updateUI();
}
block.caught = true; // Mark as processed
}
// Remove blocks that are off screen
if (block.y > 2800) {
block.destroy();
blocks.splice(i, 1);
}
}
}
function detectBeat() {
var currentVolume = facekit.volume;
var currentTime = Date.now();
// Add current volume to history buffer
volumeHistory.push(currentVolume);
if (volumeHistory.length > bufferSize) {
volumeHistory.shift();
}
// Calculate average volume from buffer
var avgVolume = 0;
for (var i = 0; i < volumeHistory.length; i++) {
avgVolume += volumeHistory[i];
}
avgVolume = avgVolume / volumeHistory.length;
// Detect beat: current volume significantly higher than average
var volumeSpike = currentVolume > avgVolume * beatSensitivity;
var timeSinceLastBeat = currentTime - lastBeatTime;
var beatDetected = volumeSpike && currentVolume > beatThreshold && timeSinceLastBeat > minBeatInterval;
if (beatDetected) {
lastBeatTime = currentTime;
// Add visual feedback for beat detection
LK.effects.flashScreen(0x440088, 100);
return true;
}
return false;
}
function shouldSpawnBlock() {
if (gameMode === 'microphone') {
// Spawn based on beat detection from microphone input
return detectBeat();
} else {
// Classic mode - spawn every second
return LK.ticks - lastSpawnTime >= spawnInterval / (1000 / 60);
}
}
// Button event handlers
classicButton.down = function (x, y, obj) {
if (gameMode === 'menu') {
// Add button press animation
tween(classicButton, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 100,
onFinish: function onFinish() {
tween(classicButton, {
scaleX: 1,
scaleY: 1
}, {
duration: 100
});
}
});
startGame('classic');
}
};
micButton.down = function (x, y, obj) {
if (gameMode === 'menu') {
// Add button press animation
tween(micButton, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 100,
onFinish: function onFinish() {
tween(micButton, {
scaleX: 1,
scaleY: 1
}, {
duration: 100
});
}
});
startGame('microphone');
}
};
// Touch controls for lane switching during gameplay
game.down = function (x, y, obj) {
if (gameMode === 'menu') {
return;
}
// Lane switching
if (x < 1024) {
// Left side tapped - move left
if (ship.currentLane > 0) {
ship.moveToLane(ship.currentLane - 1);
}
} else {
// Right side tapped - move right
if (ship.currentLane < 2) {
ship.moveToLane(ship.currentLane + 1);
}
}
};
// Main game update
game.update = function () {
if (gameMode === 'menu') {
return;
}
// Spawn blocks
if (shouldSpawnBlock()) {
spawnBlock();
lastSpawnTime = LK.ticks;
}
// Check collisions
checkCollisions();
// Game over condition (optional - can be removed for endless play)
if (score >= 500) {
LK.showYouWin();
}
}; ===================================================================
--- original.js
+++ change.js
@@ -166,24 +166,28 @@
comboTxt.anchor.set(0, 0);
comboTxt.x = 50;
comboTxt.y = 120;
LK.gui.topLeft.addChild(comboTxt);
-// Create mode selection buttons
+// Create mode selection buttons with neon glow outline
var classicButton = new Text2('1. CLASSIC MODE\nBuilt-in synthwave music', {
size: 60,
- fill: 0x00FFFF
+ fill: 0x00FFFF,
+ stroke: 0x00FFFF,
+ strokeThickness: 3
});
classicButton.anchor.set(0.5, 0.5);
-classicButton.x = -300;
-classicButton.y = -100;
+classicButton.x = 0;
+classicButton.y = -150;
LK.gui.center.addChild(classicButton);
var micButton = new Text2('2. MICROPHONE MODE\nSync with your music', {
size: 60,
- fill: 0xFF00FF
+ fill: 0xFF00FF,
+ stroke: 0xFF00FF,
+ strokeThickness: 3
});
micButton.anchor.set(0.5, 0.5);
-micButton.x = 300;
-micButton.y = -100;
+micButton.x = 0;
+micButton.y = 50;
LK.gui.center.addChild(micButton);
var instructionTxt = new Text2('TAP A BUTTON TO SELECT MODE', {
size: 50,
fill: 0xFFFFFF
synthwave neon glow audiosurf or f-zero like ship. In-Game asset. 2d. High contrast. No shadows
faint glowing outlines with a shimmer effect retro synthwave style. In-Game asset. 2d. High contrast. No shadows
a musical note thats bright and neon thats also really cool looking. In-Game asset. 2d. High contrast. No shadows
synthwave bright neon glow audiosurf or f-zero like ship In-Game asset. 2d. High contrast. No shadows
synthwave bright neon glow audiosurf or f-zero like ship In-Game asset. 2d. High contrast. No shadows. facing upright vertical
a musical note thats bright and neon thats also really cool looking. In-Game asset. 2d. High contrast. No shadows
- Shape: a glowing neon **circle or hexagon** - Color: bright **red or magenta** - Inner symbol: a small white or yellow **skull**, **explosion**, or **β οΈ warning icon** in the center - Glow: apply a soft outer glow that pulses slightly - Visual style: match the **synthwave aesthetic** (think neon, arcade, retro-futuristic) - Size: same as the existing note blocks - Animation: gently pulsate or shimmer while falling. In-Game asset. 2d. High contrast. No shadows
a bright laser vertical line retro style. In-Game asset. 2d. High contrast. No shadows. In-Game asset. 2d. High contrast. No shadows
a line that is set to the theme of this game that looks like lightsabre. In-Game asset. 2d. High contrast. No shadows
synthwave bright neon glow audiosurf or f-zero like ship In-Game asset. 2d. High contrast. No shadows. facing upright vertical 3d like