Code edit (1 edits merged)
Please save this source code
User prompt
SoundRise Challenge
Initial prompt
In my new game I want to : The louder the sound you make, the louder you will rise. There are obstacles and pitfalls. You pass levels with each passing level. Also, each time you pass a level, it becomes different and more difficult than the previous one. There are 30 levels in the game.
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
currentLevel: 1,
highestLevel: 1
});
var facekit = LK.import("@upit/facekit.v1");
/****
* Classes
****/
var Goal = Container.expand(function () {
var self = Container.call(this);
var goalGraphics = self.attachAsset('goal', {
anchorX: 0.5,
anchorY: 0.5
});
// Speed at which the goal moves
self.speed = -5;
// Pulsating animation effect
self.pulse = function () {
tween(goalGraphics, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 500,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(goalGraphics, {
scaleX: 1,
scaleY: 1
}, {
duration: 500,
easing: tween.easeInOut,
onFinish: self.pulse
});
}
});
};
self.pulse();
self.update = function () {
self.x += self.speed;
// Check if off-screen
if (self.x < -100) {
self.destroy();
return true; // Signal this goal was destroyed
}
return false;
};
return self;
});
var LevelIndicator = Container.expand(function () {
var self = Container.call(this);
var indicatorGraphics = self.attachAsset('levelIndicator', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.7
});
var levelText = new Text2('1', {
size: 24,
fill: 0x000000
});
levelText.anchor.set(0.5, 0.5);
self.addChild(levelText);
self.setLevel = function (level) {
levelText.setText(level);
// Flash the indicator when level changes
indicatorGraphics.alpha = 1;
tween(indicatorGraphics, {
alpha: 0.7
}, {
duration: 500,
easing: tween.easeOut
});
};
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
var playerGraphics = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5
});
// The player's vertical velocity
self.velocity = 0;
self.gravity = 0.5;
// Base downward movement
self.baseDownForce = 3;
// Multiplier for volume-based ascension
self.liftMultiplier = 15;
// Whether the player is allowed to move (for intro/outro animations)
self.canMove = true;
self.update = function () {
if (!self.canMove) {
return;
}
// Apply volume-based lift force
if (facekit.volume > 0.05) {
self.velocity = -facekit.volume * self.liftMultiplier;
// Visualize volume with a tint (blue to red)
var intensity = Math.min(facekit.volume * 2, 1);
var color = tween.linear(intensity, 0x3498db, 0xe74c3c);
playerGraphics.tint = color;
} else {
// Reset tint when quiet
playerGraphics.tint = 0x3498db;
// Apply gravity
self.velocity += self.gravity;
}
// Apply constant downward force
self.velocity += self.baseDownForce;
// Limit max velocity
self.velocity = Math.max(Math.min(self.velocity, 25), -25);
// Update position
self.y += self.velocity;
// Constrain to screen
if (self.y < 80) {
self.y = 80;
self.velocity = 0;
}
if (self.y > 2732 - 80) {
self.y = 2732 - 80;
self.velocity = 0;
}
};
// Reset player state
self.reset = function (startX, startY) {
self.x = startX;
self.y = startY;
self.velocity = 0;
self.canMove = true;
playerGraphics.alpha = 1;
playerGraphics.tint = 0x3498db;
};
return self;
});
var Wall = Container.expand(function () {
var self = Container.call(this);
var wallGraphics = self.attachAsset('wall', {
anchorX: 0.5,
anchorY: 0.5
});
// Speed at which the wall moves
self.speed = -5;
self.update = function () {
self.x += self.speed;
// Remove if off-screen
if (self.x < -100) {
self.destroy();
return true; // Signal this wall was destroyed
}
return false;
};
// Method to change the wall's appearance
self.setProperties = function (width, height, color) {
wallGraphics.width = width;
wallGraphics.height = height;
wallGraphics.tint = color;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87CEEB
});
/****
* Game Code
****/
// Game state variables
var currentLevel = storage.currentLevel || 1;
var highestLevel = storage.highestLevel || 1;
var walls = [];
var player;
var goal;
var levelIndicator;
var gameActive = false;
var levelCompleted = false;
var volumeIndicator;
var totalLevels = 30;
var volumeHistory = [];
// Level generation parameters
var obstaclePatterns = [
// Level 1-5: Simple patterns
function () {
return [{
x: 2048,
y: 1400,
width: 500,
height: 30
}];
}, function () {
return [{
x: 2048,
y: 800,
width: 500,
height: 30
}, {
x: 2048,
y: 1800,
width: 500,
height: 30
}];
}, function () {
return [{
x: 2048,
y: 1366,
width: 700,
height: 30
}];
}, function () {
return [{
x: 2048,
y: 600,
width: 400,
height: 30
}, {
x: 2048,
y: 2100,
width: 400,
height: 30
}];
}, function () {
return [{
x: 2048,
y: 900,
width: 300,
height: 30
}, {
x: 2048,
y: 1800,
width: 300,
height: 30
}];
},
// Level 6-10: Moving gaps
function () {
return [{
x: 2048,
y: 700,
width: 800,
height: 30
}, {
x: 2048,
y: 1900,
width: 800,
height: 30
}];
}, function () {
return [{
x: 2048,
y: 500,
width: 600,
height: 30
}, {
x: 2048,
y: 1200,
width: 600,
height: 30
}, {
x: 2048,
y: 1900,
width: 600,
height: 30
}];
}, function () {
return [{
x: 2048,
y: 800,
width: 400,
height: 30
}, {
x: 2048,
y: 1500,
width: 400,
height: 30
}, {
x: 2048,
y: 2200,
width: 400,
height: 30
}];
}, function () {
return [{
x: 2048,
y: 600,
width: 350,
height: 30
}, {
x: 2048,
y: 1366,
width: 900,
height: 30
}, {
x: 2048,
y: 2100,
width: 350,
height: 30
}];
}, function () {
return [{
x: 2048,
y: 400,
width: 300,
height: 30
}, {
x: 2048,
y: 900,
width: 300,
height: 30
}, {
x: 2048,
y: 1400,
width: 300,
height: 30
}, {
x: 2048,
y: 1900,
width: 300,
height: 30
}, {
x: 2048,
y: 2400,
width: 300,
height: 30
}];
},
// Level 11-15: Complex patterns
function () {
var obstacles = [];
for (var i = 0; i < 8; i++) {
obstacles.push({
x: 2048 + i * 250,
y: 700 + i % 2 * 1200,
width: 150,
height: 30
});
}
return obstacles;
}, function () {
var obstacles = [];
for (var i = 0; i < 6; i++) {
obstacles.push({
x: 2048 + i * 300,
y: 600 + i % 3 * 700,
width: 200,
height: 30
});
}
return obstacles;
}, function () {
var obstacles = [];
for (var i = 0; i < 5; i++) {
obstacles.push({
x: 2048 + i * 350,
y: 700 + Math.sin(i * 0.7) * 900,
width: 250,
height: 30
});
}
return obstacles;
}, function () {
var obstacles = [];
var baseY = 1366;
for (var i = 0; i < 7; i++) {
var offset = i % 2 === 0 ? 700 : -700;
obstacles.push({
x: 2048 + i * 300,
y: baseY + offset,
width: 180,
height: 30
});
}
return obstacles;
}, function () {
var obstacles = [];
for (var i = 0; i < 10; i++) {
obstacles.push({
x: 2048 + i * 250,
y: 800 + i % 4 * 400,
width: 150,
height: 30
});
}
return obstacles;
},
// Level 16-20: Increasing difficulty
function () {
var obstacles = [];
var positions = [500, 900, 1300, 1700, 2100];
for (var i = 0; i < 8; i++) {
var yPos = positions[Math.floor(Math.random() * positions.length)];
obstacles.push({
x: 2048 + i * 300,
y: yPos,
width: 180,
height: 30
});
}
return obstacles;
}, function () {
var obstacles = [];
for (var i = 0; i < 6; i++) {
obstacles.push({
x: 2048 + i * 400,
y: 700 + Math.cos(i * 0.9) * 900,
width: 300,
height: 30
});
}
return obstacles;
}, function () {
var obstacles = [];
for (var i = 0; i < 15; i++) {
if (i % 3 !== 0) {
// Skip every third to create gaps
obstacles.push({
x: 2048 + i * 200,
y: 500 + i % 5 * 400,
width: 150,
height: 30
});
}
}
return obstacles;
}, function () {
var obstacles = [];
var zigzag = true;
for (var i = 0; i < 12; i++) {
var yPos = zigzag ? 600 + i % 3 * 700 : 2100 - i % 3 * 700;
obstacles.push({
x: 2048 + i * 230,
y: yPos,
width: 150,
height: 30
});
if (i % 3 === 2) {
zigzag = !zigzag;
}
}
return obstacles;
}, function () {
var obstacles = [];
for (var i = 0; i < 20; i++) {
// Create a spiral pattern
var angle = i * 0.3;
var radius = 500 + i * 30;
var yPos = 1366 + Math.sin(angle) * (radius / 3);
obstacles.push({
x: 2048 + i * 200,
y: yPos,
width: 120,
height: 30
});
}
return obstacles;
},
// Level 21-25: Advanced patterns
function () {
var obstacles = [];
// Create a wave pattern
for (var i = 0; i < 15; i++) {
obstacles.push({
x: 2048 + i * 180,
y: 1366 + Math.sin(i * 0.5) * 800,
width: 100,
height: 30
});
}
return obstacles;
}, function () {
var obstacles = [];
// Create a double helix pattern
for (var i = 0; i < 20; i++) {
obstacles.push({
x: 2048 + i * 150,
y: 1366 + Math.sin(i * 0.4) * 700,
width: 90,
height: 30
});
obstacles.push({
x: 2048 + i * 150,
y: 1366 + Math.sin(i * 0.4 + Math.PI) * 700,
width: 90,
height: 30
});
}
return obstacles;
}, function () {
var obstacles = [];
// Create random clusters
for (var i = 0; i < 5; i++) {
var clusterX = 2048 + i * 500;
for (var j = 0; j < 4; j++) {
obstacles.push({
x: clusterX + (Math.random() * 200 - 100),
y: 600 + j * 500 + (Math.random() * 200 - 100),
width: 120,
height: 30
});
}
}
return obstacles;
}, function () {
var obstacles = [];
// Create a pulsating pattern
for (var i = 0; i < 15; i++) {
var width = 100 + Math.sin(i * 0.4) * 50;
obstacles.push({
x: 2048 + i * 200,
y: 600 + i % 4 * 500,
width: width,
height: 30
});
}
return obstacles;
}, function () {
var obstacles = [];
// Create a moving wall with small openings
for (var i = 0; i < 30; i++) {
if (i % 5 !== 2) {
// Create openings
obstacles.push({
x: 2048 + Math.floor(i / 5) * 400,
y: 300 + i * 80,
width: 200,
height: 30
});
}
}
return obstacles;
},
// Level 26-30: Expert challenges
function () {
var obstacles = [];
// Create a tight slalom
for (var i = 0; i < 12; i++) {
var yOffset = i % 2 === 0 ? 1000 : -1000;
obstacles.push({
x: 2048 + i * 250,
y: 1366 + yOffset,
width: 1500,
height: 30
});
}
return obstacles;
}, function () {
var obstacles = [];
// Create a tunnel that gets progressively narrower
var tunnelWidth = 1000;
for (var i = 0; i < 10; i++) {
tunnelWidth = Math.max(300, tunnelWidth - 70);
var halfTunnel = tunnelWidth / 2;
obstacles.push({
x: 2048 + i * 300,
y: 1366 - halfTunnel - 30,
width: 200,
height: 30
});
obstacles.push({
x: 2048 + i * 300,
y: 1366 + halfTunnel,
width: 200,
height: 30
});
}
return obstacles;
}, function () {
var obstacles = [];
// Create moving blocks that require precise timing
for (var i = 0; i < 8; i++) {
for (var j = 0; j < 5; j++) {
if ((i + j) % 2 === 0) {
obstacles.push({
x: 2048 + i * 350,
y: 400 + j * 500,
width: 150,
height: 30
});
}
}
}
return obstacles;
}, function () {
var obstacles = [];
// Create a complex maze-like pattern
var positions = [[0, 1, 1, 0, 1], [1, 0, 1, 0, 1], [1, 0, 0, 0, 1], [1, 0, 1, 1, 1], [1, 0, 0, 0, 0], [1, 1, 1, 1, 0]];
for (var i = 0; i < positions.length; i++) {
for (var j = 0; j < positions[i].length; j++) {
if (positions[i][j] === 1) {
obstacles.push({
x: 2048 + i * 300,
y: 500 + j * 400,
width: 220,
height: 30
});
}
}
}
return obstacles;
}, function () {
var obstacles = [];
// The final challenge - all techniques combined
// Wave pattern
for (var i = 0; i < 5; i++) {
obstacles.push({
x: 2048 + i * 300,
y: 1366 + Math.sin(i * 0.8) * 600,
width: 180,
height: 30
});
}
// Tight slalom
for (var i = 0; i < 3; i++) {
var yOffset = i % 2 === 0 ? 800 : -800;
obstacles.push({
x: 2048 + 1500 + i * 250,
y: 1366 + yOffset,
width: 1200,
height: 30
});
}
// Final gauntlet
for (var i = 0; i < 5; i++) {
if (i !== 2) {
// Gap in the middle
obstacles.push({
x: 2048 + 2500,
y: 400 + i * 500,
width: 100,
height: 30
});
}
}
return obstacles;
}];
// Initialize UI elements
var scoreTxt = new Text2('Level: 1/' + totalLevels, {
size: 80,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
var instructionsTxt = new Text2('Make noise to rise\nStay quiet to fall', {
size: 60,
fill: 0xFFFFFF
});
instructionsTxt.anchor.set(0.5, 0);
instructionsTxt.y = 100;
LK.gui.top.addChild(instructionsTxt);
// Volume indicator
volumeIndicator = new Container();
var volumeBarBg = LK.getAsset('wall', {
anchorX: 0,
anchorY: 0.5,
width: 50,
height: 400,
tint: 0x000000,
alpha: 0.3
});
volumeIndicator.addChild(volumeBarBg);
var volumeBar = LK.getAsset('wall', {
anchorX: 0,
anchorY: 1,
width: 50,
height: 0,
tint: 0x3498db
});
volumeIndicator.addChild(volumeBar);
volumeIndicator.x = 150;
volumeIndicator.y = 1366; // Center of screen height
LK.gui.addChild(volumeIndicator);
// Level indicator
levelIndicator = new LevelIndicator();
levelIndicator.x = 120;
levelIndicator.y = 120;
LK.gui.addChild(levelIndicator);
levelIndicator.setLevel(currentLevel);
// Initialize the player
player = new Player();
player.x = 400;
player.y = 1366; // Center of screen height
game.addChild(player);
// Set up the first level
setupLevel(currentLevel);
// Play background music
LK.playMusic('bgMusic', {
fade: {
start: 0,
end: 0.3,
duration: 1000
}
});
// Main update function
game.update = function () {
// Update volume history for smoother response
volumeHistory.push(facekit.volume);
if (volumeHistory.length > 5) {
volumeHistory.shift();
}
// Calculate average volume
var avgVolume = 0;
for (var i = 0; i < volumeHistory.length; i++) {
avgVolume += volumeHistory[i];
}
avgVolume /= volumeHistory.length;
// Update volume indicator
volumeBar.height = avgVolume * 400;
volumeBar.tint = avgVolume < 0.3 ? 0x3498db : avgVolume < 0.7 ? 0xf39c12 : 0xe74c3c;
// Only update gameplay if the game is active
if (gameActive && !levelCompleted) {
// Update all walls
for (var i = walls.length - 1; i >= 0; i--) {
var removed = walls[i].update();
if (removed) {
walls.splice(i, 1);
}
}
// Check if goal is reached or destroyed
if (goal) {
var goalRemoved = goal.update();
if (goalRemoved) {
goal = null;
} else if (player.intersects(goal)) {
levelCompleted = true;
completeLevel();
}
}
// Check collisions with walls
var collision = false;
for (var i = 0; i < walls.length; i++) {
if (player.intersects(walls[i])) {
collision = true;
break;
}
}
if (collision) {
gameOver();
}
// Calculate spawn timing based on level
if (LK.ticks % Math.max(120 - currentLevel * 2, 30) === 0 && walls.length < 40) {
spawnObstacles();
}
// Spawn goal after certain time
if (LK.ticks % 600 === 0 && !goal) {
spawnGoal();
}
}
// Hide instructions after 3 seconds
if (LK.ticks === 180) {
tween(instructionsTxt, {
alpha: 0
}, {
duration: 1000,
easing: tween.easeOut
});
}
};
// Setup a new level
function setupLevel(level) {
// Ensure level is in bounds
level = Math.max(1, Math.min(level, totalLevels));
currentLevel = level;
// Update storage
storage.currentLevel = currentLevel;
if (currentLevel > highestLevel) {
highestLevel = currentLevel;
storage.highestLevel = highestLevel;
}
// Update score text
scoreTxt.setText('Level: ' + currentLevel + '/' + totalLevels);
// Update level indicator
levelIndicator.setLevel(currentLevel);
// Reset game state
walls = [];
if (goal) {
goal.destroy();
goal = null;
}
levelCompleted = false;
// Reset player position
player.reset(400, 1366);
// Set wall speed based on level
Wall.prototype.speed = -5 - currentLevel * 0.2;
if (goal) {
goal.speed = Wall.prototype.speed;
}
// Start game after a short delay
LK.setTimeout(function () {
gameActive = true;
}, 1000);
}
// Spawn obstacles based on the current level
function spawnObstacles() {
// Get the appropriate pattern generator for the current level
var patternIndex = Math.min(currentLevel - 1, obstaclePatterns.length - 1);
var obstacles = obstaclePatterns[patternIndex]();
// Create wall objects
for (var i = 0; i < obstacles.length; i++) {
var wall = new Wall();
wall.x = obstacles[i].x;
wall.y = obstacles[i].y;
wall.setProperties(obstacles[i].width, obstacles[i].height, 0xe74c3c);
walls.push(wall);
game.addChild(wall);
}
}
// Spawn the level goal
function spawnGoal() {
goal = new Goal();
goal.x = 2048 + 200; // Start off screen
goal.y = 1366; // Center of screen height
goal.speed = Wall.prototype.speed; // Match wall speed
game.addChild(goal);
}
// Handle level completion
function completeLevel() {
gameActive = false;
// Play sound
LK.getSound('levelComplete').play();
// Animate player
tween(player, {
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 500,
easing: tween.bounceOut,
onFinish: function onFinish() {
tween(player, {
scaleX: 1,
scaleY: 1
}, {
duration: 500,
easing: tween.easeIn
});
}
});
// Show level complete message
var levelCompleteTxt = new Text2('Level ' + currentLevel + ' Complete!', {
size: 120,
fill: 0xFFFFFF
});
levelCompleteTxt.anchor.set(0.5, 0.5);
levelCompleteTxt.x = 1024;
levelCompleteTxt.y = 1366;
levelCompleteTxt.alpha = 0;
LK.gui.addChild(levelCompleteTxt);
tween(levelCompleteTxt, {
alpha: 1,
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 500,
easing: tween.bounceOut,
onFinish: function onFinish() {
tween(levelCompleteTxt, {
alpha: 0
}, {
duration: 1000,
easing: tween.easeIn,
onFinish: function onFinish() {
levelCompleteTxt.destroy();
// Check if the player has completed all levels
if (currentLevel === totalLevels) {
// Game completed!
var gameCompleteTxt = new Text2('Congratulations!\nYou completed all levels!', {
size: 100,
fill: 0xFFFFFF
});
gameCompleteTxt.anchor.set(0.5, 0.5);
gameCompleteTxt.x = 1024;
gameCompleteTxt.y = 1366;
LK.gui.addChild(gameCompleteTxt);
LK.setTimeout(function () {
gameCompleteTxt.destroy();
currentLevel = 1;
setupLevel(currentLevel);
}, 3000);
} else {
// Next level
setupLevel(currentLevel + 1);
}
}
});
}
});
}
// Handle game over
function gameOver() {
gameActive = false;
// Play sound
LK.getSound('gameOver').play();
// Animate player
player.canMove = false;
tween(player, {
alpha: 0.3
}, {
duration: 500,
easing: tween.easeOut
});
// Show game over message
var gameOverTxt = new Text2('Level Failed', {
size: 120,
fill: 0xFFFFFF
});
gameOverTxt.anchor.set(0.5, 0.5);
gameOverTxt.x = 1024;
gameOverTxt.y = 1366;
gameOverTxt.alpha = 0;
LK.gui.addChild(gameOverTxt);
tween(gameOverTxt, {
alpha: 1
}, {
duration: 500,
easing: tween.easeOut,
onFinish: function onFinish() {
LK.setTimeout(function () {
tween(gameOverTxt, {
alpha: 0
}, {
duration: 500,
easing: tween.easeIn,
onFinish: function onFinish() {
gameOverTxt.destroy();
setupLevel(currentLevel);
}
});
}, 1500);
}
});
// Screen flash
LK.effects.flashScreen(0xe74c3c, 500);
} ===================================================================
--- original.js
+++ change.js
@@ -1,6 +1,938 @@
-/****
+/****
+* Plugins
+****/
+var tween = LK.import("@upit/tween.v1");
+var storage = LK.import("@upit/storage.v1", {
+ currentLevel: 1,
+ highestLevel: 1
+});
+var facekit = LK.import("@upit/facekit.v1");
+
+/****
+* Classes
+****/
+var Goal = Container.expand(function () {
+ var self = Container.call(this);
+ var goalGraphics = self.attachAsset('goal', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ // Speed at which the goal moves
+ self.speed = -5;
+ // Pulsating animation effect
+ self.pulse = function () {
+ tween(goalGraphics, {
+ scaleX: 1.1,
+ scaleY: 1.1
+ }, {
+ duration: 500,
+ easing: tween.easeInOut,
+ onFinish: function onFinish() {
+ tween(goalGraphics, {
+ scaleX: 1,
+ scaleY: 1
+ }, {
+ duration: 500,
+ easing: tween.easeInOut,
+ onFinish: self.pulse
+ });
+ }
+ });
+ };
+ self.pulse();
+ self.update = function () {
+ self.x += self.speed;
+ // Check if off-screen
+ if (self.x < -100) {
+ self.destroy();
+ return true; // Signal this goal was destroyed
+ }
+ return false;
+ };
+ return self;
+});
+var LevelIndicator = Container.expand(function () {
+ var self = Container.call(this);
+ var indicatorGraphics = self.attachAsset('levelIndicator', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ alpha: 0.7
+ });
+ var levelText = new Text2('1', {
+ size: 24,
+ fill: 0x000000
+ });
+ levelText.anchor.set(0.5, 0.5);
+ self.addChild(levelText);
+ self.setLevel = function (level) {
+ levelText.setText(level);
+ // Flash the indicator when level changes
+ indicatorGraphics.alpha = 1;
+ tween(indicatorGraphics, {
+ alpha: 0.7
+ }, {
+ duration: 500,
+ easing: tween.easeOut
+ });
+ };
+ return self;
+});
+var Player = Container.expand(function () {
+ var self = Container.call(this);
+ var playerGraphics = self.attachAsset('player', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ // The player's vertical velocity
+ self.velocity = 0;
+ self.gravity = 0.5;
+ // Base downward movement
+ self.baseDownForce = 3;
+ // Multiplier for volume-based ascension
+ self.liftMultiplier = 15;
+ // Whether the player is allowed to move (for intro/outro animations)
+ self.canMove = true;
+ self.update = function () {
+ if (!self.canMove) {
+ return;
+ }
+ // Apply volume-based lift force
+ if (facekit.volume > 0.05) {
+ self.velocity = -facekit.volume * self.liftMultiplier;
+ // Visualize volume with a tint (blue to red)
+ var intensity = Math.min(facekit.volume * 2, 1);
+ var color = tween.linear(intensity, 0x3498db, 0xe74c3c);
+ playerGraphics.tint = color;
+ } else {
+ // Reset tint when quiet
+ playerGraphics.tint = 0x3498db;
+ // Apply gravity
+ self.velocity += self.gravity;
+ }
+ // Apply constant downward force
+ self.velocity += self.baseDownForce;
+ // Limit max velocity
+ self.velocity = Math.max(Math.min(self.velocity, 25), -25);
+ // Update position
+ self.y += self.velocity;
+ // Constrain to screen
+ if (self.y < 80) {
+ self.y = 80;
+ self.velocity = 0;
+ }
+ if (self.y > 2732 - 80) {
+ self.y = 2732 - 80;
+ self.velocity = 0;
+ }
+ };
+ // Reset player state
+ self.reset = function (startX, startY) {
+ self.x = startX;
+ self.y = startY;
+ self.velocity = 0;
+ self.canMove = true;
+ playerGraphics.alpha = 1;
+ playerGraphics.tint = 0x3498db;
+ };
+ return self;
+});
+var Wall = Container.expand(function () {
+ var self = Container.call(this);
+ var wallGraphics = self.attachAsset('wall', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ // Speed at which the wall moves
+ self.speed = -5;
+ self.update = function () {
+ self.x += self.speed;
+ // Remove if off-screen
+ if (self.x < -100) {
+ self.destroy();
+ return true; // Signal this wall was destroyed
+ }
+ return false;
+ };
+ // Method to change the wall's appearance
+ self.setProperties = function (width, height, color) {
+ wallGraphics.width = width;
+ wallGraphics.height = height;
+ wallGraphics.tint = color;
+ };
+ return self;
+});
+
+/****
* Initialize Game
-****/
+****/
var game = new LK.Game({
- backgroundColor: 0x000000
-});
\ No newline at end of file
+ backgroundColor: 0x87CEEB
+});
+
+/****
+* Game Code
+****/
+// Game state variables
+var currentLevel = storage.currentLevel || 1;
+var highestLevel = storage.highestLevel || 1;
+var walls = [];
+var player;
+var goal;
+var levelIndicator;
+var gameActive = false;
+var levelCompleted = false;
+var volumeIndicator;
+var totalLevels = 30;
+var volumeHistory = [];
+// Level generation parameters
+var obstaclePatterns = [
+// Level 1-5: Simple patterns
+function () {
+ return [{
+ x: 2048,
+ y: 1400,
+ width: 500,
+ height: 30
+ }];
+}, function () {
+ return [{
+ x: 2048,
+ y: 800,
+ width: 500,
+ height: 30
+ }, {
+ x: 2048,
+ y: 1800,
+ width: 500,
+ height: 30
+ }];
+}, function () {
+ return [{
+ x: 2048,
+ y: 1366,
+ width: 700,
+ height: 30
+ }];
+}, function () {
+ return [{
+ x: 2048,
+ y: 600,
+ width: 400,
+ height: 30
+ }, {
+ x: 2048,
+ y: 2100,
+ width: 400,
+ height: 30
+ }];
+}, function () {
+ return [{
+ x: 2048,
+ y: 900,
+ width: 300,
+ height: 30
+ }, {
+ x: 2048,
+ y: 1800,
+ width: 300,
+ height: 30
+ }];
+},
+// Level 6-10: Moving gaps
+function () {
+ return [{
+ x: 2048,
+ y: 700,
+ width: 800,
+ height: 30
+ }, {
+ x: 2048,
+ y: 1900,
+ width: 800,
+ height: 30
+ }];
+}, function () {
+ return [{
+ x: 2048,
+ y: 500,
+ width: 600,
+ height: 30
+ }, {
+ x: 2048,
+ y: 1200,
+ width: 600,
+ height: 30
+ }, {
+ x: 2048,
+ y: 1900,
+ width: 600,
+ height: 30
+ }];
+}, function () {
+ return [{
+ x: 2048,
+ y: 800,
+ width: 400,
+ height: 30
+ }, {
+ x: 2048,
+ y: 1500,
+ width: 400,
+ height: 30
+ }, {
+ x: 2048,
+ y: 2200,
+ width: 400,
+ height: 30
+ }];
+}, function () {
+ return [{
+ x: 2048,
+ y: 600,
+ width: 350,
+ height: 30
+ }, {
+ x: 2048,
+ y: 1366,
+ width: 900,
+ height: 30
+ }, {
+ x: 2048,
+ y: 2100,
+ width: 350,
+ height: 30
+ }];
+}, function () {
+ return [{
+ x: 2048,
+ y: 400,
+ width: 300,
+ height: 30
+ }, {
+ x: 2048,
+ y: 900,
+ width: 300,
+ height: 30
+ }, {
+ x: 2048,
+ y: 1400,
+ width: 300,
+ height: 30
+ }, {
+ x: 2048,
+ y: 1900,
+ width: 300,
+ height: 30
+ }, {
+ x: 2048,
+ y: 2400,
+ width: 300,
+ height: 30
+ }];
+},
+// Level 11-15: Complex patterns
+function () {
+ var obstacles = [];
+ for (var i = 0; i < 8; i++) {
+ obstacles.push({
+ x: 2048 + i * 250,
+ y: 700 + i % 2 * 1200,
+ width: 150,
+ height: 30
+ });
+ }
+ return obstacles;
+}, function () {
+ var obstacles = [];
+ for (var i = 0; i < 6; i++) {
+ obstacles.push({
+ x: 2048 + i * 300,
+ y: 600 + i % 3 * 700,
+ width: 200,
+ height: 30
+ });
+ }
+ return obstacles;
+}, function () {
+ var obstacles = [];
+ for (var i = 0; i < 5; i++) {
+ obstacles.push({
+ x: 2048 + i * 350,
+ y: 700 + Math.sin(i * 0.7) * 900,
+ width: 250,
+ height: 30
+ });
+ }
+ return obstacles;
+}, function () {
+ var obstacles = [];
+ var baseY = 1366;
+ for (var i = 0; i < 7; i++) {
+ var offset = i % 2 === 0 ? 700 : -700;
+ obstacles.push({
+ x: 2048 + i * 300,
+ y: baseY + offset,
+ width: 180,
+ height: 30
+ });
+ }
+ return obstacles;
+}, function () {
+ var obstacles = [];
+ for (var i = 0; i < 10; i++) {
+ obstacles.push({
+ x: 2048 + i * 250,
+ y: 800 + i % 4 * 400,
+ width: 150,
+ height: 30
+ });
+ }
+ return obstacles;
+},
+// Level 16-20: Increasing difficulty
+function () {
+ var obstacles = [];
+ var positions = [500, 900, 1300, 1700, 2100];
+ for (var i = 0; i < 8; i++) {
+ var yPos = positions[Math.floor(Math.random() * positions.length)];
+ obstacles.push({
+ x: 2048 + i * 300,
+ y: yPos,
+ width: 180,
+ height: 30
+ });
+ }
+ return obstacles;
+}, function () {
+ var obstacles = [];
+ for (var i = 0; i < 6; i++) {
+ obstacles.push({
+ x: 2048 + i * 400,
+ y: 700 + Math.cos(i * 0.9) * 900,
+ width: 300,
+ height: 30
+ });
+ }
+ return obstacles;
+}, function () {
+ var obstacles = [];
+ for (var i = 0; i < 15; i++) {
+ if (i % 3 !== 0) {
+ // Skip every third to create gaps
+ obstacles.push({
+ x: 2048 + i * 200,
+ y: 500 + i % 5 * 400,
+ width: 150,
+ height: 30
+ });
+ }
+ }
+ return obstacles;
+}, function () {
+ var obstacles = [];
+ var zigzag = true;
+ for (var i = 0; i < 12; i++) {
+ var yPos = zigzag ? 600 + i % 3 * 700 : 2100 - i % 3 * 700;
+ obstacles.push({
+ x: 2048 + i * 230,
+ y: yPos,
+ width: 150,
+ height: 30
+ });
+ if (i % 3 === 2) {
+ zigzag = !zigzag;
+ }
+ }
+ return obstacles;
+}, function () {
+ var obstacles = [];
+ for (var i = 0; i < 20; i++) {
+ // Create a spiral pattern
+ var angle = i * 0.3;
+ var radius = 500 + i * 30;
+ var yPos = 1366 + Math.sin(angle) * (radius / 3);
+ obstacles.push({
+ x: 2048 + i * 200,
+ y: yPos,
+ width: 120,
+ height: 30
+ });
+ }
+ return obstacles;
+},
+// Level 21-25: Advanced patterns
+function () {
+ var obstacles = [];
+ // Create a wave pattern
+ for (var i = 0; i < 15; i++) {
+ obstacles.push({
+ x: 2048 + i * 180,
+ y: 1366 + Math.sin(i * 0.5) * 800,
+ width: 100,
+ height: 30
+ });
+ }
+ return obstacles;
+}, function () {
+ var obstacles = [];
+ // Create a double helix pattern
+ for (var i = 0; i < 20; i++) {
+ obstacles.push({
+ x: 2048 + i * 150,
+ y: 1366 + Math.sin(i * 0.4) * 700,
+ width: 90,
+ height: 30
+ });
+ obstacles.push({
+ x: 2048 + i * 150,
+ y: 1366 + Math.sin(i * 0.4 + Math.PI) * 700,
+ width: 90,
+ height: 30
+ });
+ }
+ return obstacles;
+}, function () {
+ var obstacles = [];
+ // Create random clusters
+ for (var i = 0; i < 5; i++) {
+ var clusterX = 2048 + i * 500;
+ for (var j = 0; j < 4; j++) {
+ obstacles.push({
+ x: clusterX + (Math.random() * 200 - 100),
+ y: 600 + j * 500 + (Math.random() * 200 - 100),
+ width: 120,
+ height: 30
+ });
+ }
+ }
+ return obstacles;
+}, function () {
+ var obstacles = [];
+ // Create a pulsating pattern
+ for (var i = 0; i < 15; i++) {
+ var width = 100 + Math.sin(i * 0.4) * 50;
+ obstacles.push({
+ x: 2048 + i * 200,
+ y: 600 + i % 4 * 500,
+ width: width,
+ height: 30
+ });
+ }
+ return obstacles;
+}, function () {
+ var obstacles = [];
+ // Create a moving wall with small openings
+ for (var i = 0; i < 30; i++) {
+ if (i % 5 !== 2) {
+ // Create openings
+ obstacles.push({
+ x: 2048 + Math.floor(i / 5) * 400,
+ y: 300 + i * 80,
+ width: 200,
+ height: 30
+ });
+ }
+ }
+ return obstacles;
+},
+// Level 26-30: Expert challenges
+function () {
+ var obstacles = [];
+ // Create a tight slalom
+ for (var i = 0; i < 12; i++) {
+ var yOffset = i % 2 === 0 ? 1000 : -1000;
+ obstacles.push({
+ x: 2048 + i * 250,
+ y: 1366 + yOffset,
+ width: 1500,
+ height: 30
+ });
+ }
+ return obstacles;
+}, function () {
+ var obstacles = [];
+ // Create a tunnel that gets progressively narrower
+ var tunnelWidth = 1000;
+ for (var i = 0; i < 10; i++) {
+ tunnelWidth = Math.max(300, tunnelWidth - 70);
+ var halfTunnel = tunnelWidth / 2;
+ obstacles.push({
+ x: 2048 + i * 300,
+ y: 1366 - halfTunnel - 30,
+ width: 200,
+ height: 30
+ });
+ obstacles.push({
+ x: 2048 + i * 300,
+ y: 1366 + halfTunnel,
+ width: 200,
+ height: 30
+ });
+ }
+ return obstacles;
+}, function () {
+ var obstacles = [];
+ // Create moving blocks that require precise timing
+ for (var i = 0; i < 8; i++) {
+ for (var j = 0; j < 5; j++) {
+ if ((i + j) % 2 === 0) {
+ obstacles.push({
+ x: 2048 + i * 350,
+ y: 400 + j * 500,
+ width: 150,
+ height: 30
+ });
+ }
+ }
+ }
+ return obstacles;
+}, function () {
+ var obstacles = [];
+ // Create a complex maze-like pattern
+ var positions = [[0, 1, 1, 0, 1], [1, 0, 1, 0, 1], [1, 0, 0, 0, 1], [1, 0, 1, 1, 1], [1, 0, 0, 0, 0], [1, 1, 1, 1, 0]];
+ for (var i = 0; i < positions.length; i++) {
+ for (var j = 0; j < positions[i].length; j++) {
+ if (positions[i][j] === 1) {
+ obstacles.push({
+ x: 2048 + i * 300,
+ y: 500 + j * 400,
+ width: 220,
+ height: 30
+ });
+ }
+ }
+ }
+ return obstacles;
+}, function () {
+ var obstacles = [];
+ // The final challenge - all techniques combined
+ // Wave pattern
+ for (var i = 0; i < 5; i++) {
+ obstacles.push({
+ x: 2048 + i * 300,
+ y: 1366 + Math.sin(i * 0.8) * 600,
+ width: 180,
+ height: 30
+ });
+ }
+ // Tight slalom
+ for (var i = 0; i < 3; i++) {
+ var yOffset = i % 2 === 0 ? 800 : -800;
+ obstacles.push({
+ x: 2048 + 1500 + i * 250,
+ y: 1366 + yOffset,
+ width: 1200,
+ height: 30
+ });
+ }
+ // Final gauntlet
+ for (var i = 0; i < 5; i++) {
+ if (i !== 2) {
+ // Gap in the middle
+ obstacles.push({
+ x: 2048 + 2500,
+ y: 400 + i * 500,
+ width: 100,
+ height: 30
+ });
+ }
+ }
+ return obstacles;
+}];
+// Initialize UI elements
+var scoreTxt = new Text2('Level: 1/' + totalLevels, {
+ size: 80,
+ fill: 0xFFFFFF
+});
+scoreTxt.anchor.set(0.5, 0);
+LK.gui.top.addChild(scoreTxt);
+var instructionsTxt = new Text2('Make noise to rise\nStay quiet to fall', {
+ size: 60,
+ fill: 0xFFFFFF
+});
+instructionsTxt.anchor.set(0.5, 0);
+instructionsTxt.y = 100;
+LK.gui.top.addChild(instructionsTxt);
+// Volume indicator
+volumeIndicator = new Container();
+var volumeBarBg = LK.getAsset('wall', {
+ anchorX: 0,
+ anchorY: 0.5,
+ width: 50,
+ height: 400,
+ tint: 0x000000,
+ alpha: 0.3
+});
+volumeIndicator.addChild(volumeBarBg);
+var volumeBar = LK.getAsset('wall', {
+ anchorX: 0,
+ anchorY: 1,
+ width: 50,
+ height: 0,
+ tint: 0x3498db
+});
+volumeIndicator.addChild(volumeBar);
+volumeIndicator.x = 150;
+volumeIndicator.y = 1366; // Center of screen height
+LK.gui.addChild(volumeIndicator);
+// Level indicator
+levelIndicator = new LevelIndicator();
+levelIndicator.x = 120;
+levelIndicator.y = 120;
+LK.gui.addChild(levelIndicator);
+levelIndicator.setLevel(currentLevel);
+// Initialize the player
+player = new Player();
+player.x = 400;
+player.y = 1366; // Center of screen height
+game.addChild(player);
+// Set up the first level
+setupLevel(currentLevel);
+// Play background music
+LK.playMusic('bgMusic', {
+ fade: {
+ start: 0,
+ end: 0.3,
+ duration: 1000
+ }
+});
+// Main update function
+game.update = function () {
+ // Update volume history for smoother response
+ volumeHistory.push(facekit.volume);
+ if (volumeHistory.length > 5) {
+ volumeHistory.shift();
+ }
+ // Calculate average volume
+ var avgVolume = 0;
+ for (var i = 0; i < volumeHistory.length; i++) {
+ avgVolume += volumeHistory[i];
+ }
+ avgVolume /= volumeHistory.length;
+ // Update volume indicator
+ volumeBar.height = avgVolume * 400;
+ volumeBar.tint = avgVolume < 0.3 ? 0x3498db : avgVolume < 0.7 ? 0xf39c12 : 0xe74c3c;
+ // Only update gameplay if the game is active
+ if (gameActive && !levelCompleted) {
+ // Update all walls
+ for (var i = walls.length - 1; i >= 0; i--) {
+ var removed = walls[i].update();
+ if (removed) {
+ walls.splice(i, 1);
+ }
+ }
+ // Check if goal is reached or destroyed
+ if (goal) {
+ var goalRemoved = goal.update();
+ if (goalRemoved) {
+ goal = null;
+ } else if (player.intersects(goal)) {
+ levelCompleted = true;
+ completeLevel();
+ }
+ }
+ // Check collisions with walls
+ var collision = false;
+ for (var i = 0; i < walls.length; i++) {
+ if (player.intersects(walls[i])) {
+ collision = true;
+ break;
+ }
+ }
+ if (collision) {
+ gameOver();
+ }
+ // Calculate spawn timing based on level
+ if (LK.ticks % Math.max(120 - currentLevel * 2, 30) === 0 && walls.length < 40) {
+ spawnObstacles();
+ }
+ // Spawn goal after certain time
+ if (LK.ticks % 600 === 0 && !goal) {
+ spawnGoal();
+ }
+ }
+ // Hide instructions after 3 seconds
+ if (LK.ticks === 180) {
+ tween(instructionsTxt, {
+ alpha: 0
+ }, {
+ duration: 1000,
+ easing: tween.easeOut
+ });
+ }
+};
+// Setup a new level
+function setupLevel(level) {
+ // Ensure level is in bounds
+ level = Math.max(1, Math.min(level, totalLevels));
+ currentLevel = level;
+ // Update storage
+ storage.currentLevel = currentLevel;
+ if (currentLevel > highestLevel) {
+ highestLevel = currentLevel;
+ storage.highestLevel = highestLevel;
+ }
+ // Update score text
+ scoreTxt.setText('Level: ' + currentLevel + '/' + totalLevels);
+ // Update level indicator
+ levelIndicator.setLevel(currentLevel);
+ // Reset game state
+ walls = [];
+ if (goal) {
+ goal.destroy();
+ goal = null;
+ }
+ levelCompleted = false;
+ // Reset player position
+ player.reset(400, 1366);
+ // Set wall speed based on level
+ Wall.prototype.speed = -5 - currentLevel * 0.2;
+ if (goal) {
+ goal.speed = Wall.prototype.speed;
+ }
+ // Start game after a short delay
+ LK.setTimeout(function () {
+ gameActive = true;
+ }, 1000);
+}
+// Spawn obstacles based on the current level
+function spawnObstacles() {
+ // Get the appropriate pattern generator for the current level
+ var patternIndex = Math.min(currentLevel - 1, obstaclePatterns.length - 1);
+ var obstacles = obstaclePatterns[patternIndex]();
+ // Create wall objects
+ for (var i = 0; i < obstacles.length; i++) {
+ var wall = new Wall();
+ wall.x = obstacles[i].x;
+ wall.y = obstacles[i].y;
+ wall.setProperties(obstacles[i].width, obstacles[i].height, 0xe74c3c);
+ walls.push(wall);
+ game.addChild(wall);
+ }
+}
+// Spawn the level goal
+function spawnGoal() {
+ goal = new Goal();
+ goal.x = 2048 + 200; // Start off screen
+ goal.y = 1366; // Center of screen height
+ goal.speed = Wall.prototype.speed; // Match wall speed
+ game.addChild(goal);
+}
+// Handle level completion
+function completeLevel() {
+ gameActive = false;
+ // Play sound
+ LK.getSound('levelComplete').play();
+ // Animate player
+ tween(player, {
+ scaleX: 1.5,
+ scaleY: 1.5
+ }, {
+ duration: 500,
+ easing: tween.bounceOut,
+ onFinish: function onFinish() {
+ tween(player, {
+ scaleX: 1,
+ scaleY: 1
+ }, {
+ duration: 500,
+ easing: tween.easeIn
+ });
+ }
+ });
+ // Show level complete message
+ var levelCompleteTxt = new Text2('Level ' + currentLevel + ' Complete!', {
+ size: 120,
+ fill: 0xFFFFFF
+ });
+ levelCompleteTxt.anchor.set(0.5, 0.5);
+ levelCompleteTxt.x = 1024;
+ levelCompleteTxt.y = 1366;
+ levelCompleteTxt.alpha = 0;
+ LK.gui.addChild(levelCompleteTxt);
+ tween(levelCompleteTxt, {
+ alpha: 1,
+ scaleX: 1.2,
+ scaleY: 1.2
+ }, {
+ duration: 500,
+ easing: tween.bounceOut,
+ onFinish: function onFinish() {
+ tween(levelCompleteTxt, {
+ alpha: 0
+ }, {
+ duration: 1000,
+ easing: tween.easeIn,
+ onFinish: function onFinish() {
+ levelCompleteTxt.destroy();
+ // Check if the player has completed all levels
+ if (currentLevel === totalLevels) {
+ // Game completed!
+ var gameCompleteTxt = new Text2('Congratulations!\nYou completed all levels!', {
+ size: 100,
+ fill: 0xFFFFFF
+ });
+ gameCompleteTxt.anchor.set(0.5, 0.5);
+ gameCompleteTxt.x = 1024;
+ gameCompleteTxt.y = 1366;
+ LK.gui.addChild(gameCompleteTxt);
+ LK.setTimeout(function () {
+ gameCompleteTxt.destroy();
+ currentLevel = 1;
+ setupLevel(currentLevel);
+ }, 3000);
+ } else {
+ // Next level
+ setupLevel(currentLevel + 1);
+ }
+ }
+ });
+ }
+ });
+}
+// Handle game over
+function gameOver() {
+ gameActive = false;
+ // Play sound
+ LK.getSound('gameOver').play();
+ // Animate player
+ player.canMove = false;
+ tween(player, {
+ alpha: 0.3
+ }, {
+ duration: 500,
+ easing: tween.easeOut
+ });
+ // Show game over message
+ var gameOverTxt = new Text2('Level Failed', {
+ size: 120,
+ fill: 0xFFFFFF
+ });
+ gameOverTxt.anchor.set(0.5, 0.5);
+ gameOverTxt.x = 1024;
+ gameOverTxt.y = 1366;
+ gameOverTxt.alpha = 0;
+ LK.gui.addChild(gameOverTxt);
+ tween(gameOverTxt, {
+ alpha: 1
+ }, {
+ duration: 500,
+ easing: tween.easeOut,
+ onFinish: function onFinish() {
+ LK.setTimeout(function () {
+ tween(gameOverTxt, {
+ alpha: 0
+ }, {
+ duration: 500,
+ easing: tween.easeIn,
+ onFinish: function onFinish() {
+ gameOverTxt.destroy();
+ setupLevel(currentLevel);
+ }
+ });
+ }, 1500);
+ }
+ });
+ // Screen flash
+ LK.effects.flashScreen(0xe74c3c, 500);
+}
\ No newline at end of file