/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1"); var facekit = LK.import("@upit/facekit.v1"); /**** * Classes ****/ var Collectible = Container.expand(function () { var self = Container.call(this); var collectibleGraphics = self.attachAsset('collectible', { anchorX: 0.5, anchorY: 0.5 }); self.collected = false; self.collect = function () { if (!self.collected) { self.collected = true; LK.getSound('collect').play(); tween(self, { alpha: 0, scaleX: 1.5, scaleY: 1.5 }, { duration: 300, onFinish: function onFinish() { self.visible = false; } }); return true; } return false; }; self.update = function () { if (!self.collected) { self.rotation += 0.02; } }; return self; }); var Goal = Container.expand(function () { var self = Container.call(this); var goalGraphics = self.attachAsset('goal', { anchorX: 0.5, anchorY: 0.5 }); self.reached = false; self.reach = function () { if (!self.reached) { self.reached = true; LK.getSound('win').play(); tween(self, { alpha: 0.5, scaleX: 1.5, scaleY: 1.5 }, { duration: 500, onFinish: function onFinish() { LK.showYouWin(); } }); return true; } return false; }; self.update = function () { // Animate the goal if needed self.rotation += 0.01; }; return self; }); var Obstacle = Container.expand(function () { var self = Container.call(this); var obstacleGraphics = self.attachAsset('obstacle', { anchorX: 0.5, anchorY: 0.5 }); self.detectsStealth = false; self.update = function () { // If this is a patrolling obstacle, add movement logic here }; return self; }); var Platform = Container.expand(function () { var self = Container.call(this); var platformGraphics = self.attachAsset('platform', { anchorX: 0.5, anchorY: 0.5 }); self.width = platformGraphics.width; self.height = platformGraphics.height; return self; }); var Player = Container.expand(function () { var self = Container.call(this); var playerGraphics = self.attachAsset('player', { anchorX: 0.5, anchorY: 0.5 }); var stealthMode = self.attachAsset('stealthIndicator', { anchorX: 0.5, anchorY: 0.5, alpha: 0 }); self.vx = 0; self.vy = 0; self.speed = 5; self.jumpStrength = -15; self.gravity = 0.6; self.grounded = false; self.inStealth = false; self.breathLevel = 0; self.dead = false; self.toggleStealth = function (value) { if (self.inStealth !== value) { self.inStealth = value; if (value) { tween(stealthMode, { alpha: 0.5 }, { duration: 300 }); tween(playerGraphics, { alpha: 0.6 }, { duration: 300 }); } else { tween(stealthMode, { alpha: 0 }, { duration: 300 }); tween(playerGraphics, { alpha: 1 }, { duration: 300 }); } } }; self.jump = function () { if (self.grounded && !self.dead) { self.vy = self.jumpStrength; self.grounded = false; LK.getSound('jump').play(); } }; self.die = function () { if (!self.dead) { self.dead = true; LK.getSound('death').play(); LK.effects.flashObject(self, 0xff0000, 1000); LK.setTimeout(function () { LK.showGameOver(); }, 1000); } }; self.update = function () { if (self.dead) { return; } // Apply gravity self.vy += self.gravity; // Apply movement self.x += self.vx; self.y += self.vy; // Check boundaries if (self.y > 2732 - 100) { self.die(); } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x87CEEB // Sky blue background }); /**** * Game Code ****/ // Game variables var player; var platforms = []; var obstacles = []; var collectibles = []; var goal; var camera = { x: 0, y: 0 }; var currentLevel = storage.currentLevel || 1; var score = 0; var breathIndicator; var breathText; var holdingBreath = false; var breathHoldStartTime = 0; var breathAnalysisBuffer = []; var breathBufferSize = 10; // Game world container var world = new Container(); game.addChild(world); // Setup UI function setupUI() { // Score display var scoreText = new Text2('Score: 0', { size: 50, fill: 0xFFFFFF }); scoreText.anchor.set(1, 0); LK.gui.topRight.addChild(scoreText); // Breath indicator background breathIndicator = LK.getAsset('platform', { width: 300, height: 30, anchorX: 0, anchorY: 0.5, tint: 0x444444 }); // Breath level fill var breathLevel = LK.getAsset('platform', { width: 0, height: 20, anchorX: 0, anchorY: 0.5, tint: 0x3498db }); breathIndicator.addChild(breathLevel); // Label for breath indicator breathText = new Text2('Breath', { size: 40, fill: 0xFFFFFF }); breathText.anchor.set(0, 0.5); breathText.x = 10; // Add UI elements to the GUI overlay LK.gui.right.addChild(breathIndicator); breathIndicator.addChild(breathText); // Update functions game.updateScore = function (newScore) { score = newScore; scoreText.setText('Score: ' + score); }; game.updateBreathIndicator = function (level) { breathLevel.width = Math.min(1, level) * 290; if (holdingBreath) { breathText.setText('STEALTH'); } else if (level > 0.6) { breathText.setText('RUNNING'); } else if (level > 0.1) { breathText.setText('WALKING'); } else { breathText.setText('Breath'); } }; } // Create level function createLevel(levelNumber) { // Clear existing level objects clearLevel(); // Create player player = new Player(); player.x = 200; player.y = 2000; world.addChild(player); // Level design based on levelNumber switch (levelNumber) { case 1: createLevelOne(); break; case 2: createLevelTwo(); break; default: createLevelOne(); // Default to level 1 } // Store current level storage.currentLevel = levelNumber; } function clearLevel() { platforms = []; obstacles = []; collectibles = []; // Remove all children from the world container while (world.children.length > 0) { world.removeChildAt(0); } } function createLevelOne() { // Starting platform createPlatform(200, 2200, 400, 50); // Basic platforms createPlatform(700, 2100, 300, 50); createPlatform(1200, 2000, 300, 50); createPlatform(1700, 2100, 300, 50); // Add some obstacles var obstacle1 = new Obstacle(); obstacle1.x = 1200; obstacle1.y = 1900; obstacles.push(obstacle1); world.addChild(obstacle1); // Add collectibles for (var i = 0; i < 3; i++) { var collectible = new Collectible(); collectible.x = 700 + i * 500; collectible.y = 1950; collectibles.push(collectible); world.addChild(collectible); } // Create goal goal = new Goal(); goal.x = 1900; goal.y = 2000; world.addChild(goal); } function createLevelTwo() { // More complex platform arrangement createPlatform(200, 2200, 400, 50); createPlatform(700, 2100, 200, 50); createPlatform(1100, 2000, 200, 50); createPlatform(1500, 2100, 200, 50); createPlatform(1900, 2000, 200, 50); // Add more obstacles var obstacle1 = new Obstacle(); obstacle1.x = 1100; obstacle1.y = 1900; obstacle1.detectsStealth = true; obstacles.push(obstacle1); world.addChild(obstacle1); var obstacle2 = new Obstacle(); obstacle2.x = 1500; obstacle2.y = 2000; obstacles.push(obstacle2); world.addChild(obstacle2); // Add collectibles for (var i = 0; i < 5; i++) { var collectible = new Collectible(); collectible.x = 500 + i * 400; collectible.y = 1900; collectibles.push(collectible); world.addChild(collectible); } // Create goal goal = new Goal(); goal.x = 1900; goal.y = 1900; world.addChild(goal); } function createPlatform(x, y, width, height) { var platform = new Platform(); platform.x = x; platform.y = y; // If we want to resize platforms if (width && width !== 300) { platform.scale.x = width / 300; } if (height && height !== 50) { platform.scale.y = height / 50; } platforms.push(platform); world.addChild(platform); return platform; } // Breath analysis function analyzeBreath() { var currentVolume = facekit.volume; // Add current breath to buffer breathAnalysisBuffer.push(currentVolume); if (breathAnalysisBuffer.length > breathBufferSize) { breathAnalysisBuffer.shift(); } // Calculate average breath level var sum = 0; for (var i = 0; i < breathAnalysisBuffer.length; i++) { sum += breathAnalysisBuffer[i]; } var avgBreath = sum / breathAnalysisBuffer.length; // Detect if holding breath (very low volume for a sustained period) var currentTime = Date.now(); if (currentVolume < 0.1) { if (!holdingBreath) { breathHoldStartTime = currentTime; holdingBreath = true; } else if (currentTime - breathHoldStartTime > 1000) { // Been holding breath for over a second, activate stealth player.toggleStealth(true); } } else { holdingBreath = false; player.toggleStealth(false); } // Update player speed based on breath intensity if (!holdingBreath) { if (avgBreath > 0.6) { // Running player.speed = 10; } else if (avgBreath > 0.1) { // Walking player.speed = 5; } else { // Standing still (very light breathing) player.speed = 0; } } else { // Stealth mode - slower movement player.speed = 1; } return avgBreath; } // Check collisions between player and platforms function checkPlatformCollisions() { player.grounded = false; for (var i = 0; i < platforms.length; i++) { var platform = platforms[i]; if (player.intersects(platform)) { // Calculate the sides of both objects var playerBottom = player.y + 75; var playerTop = player.y - 75; var platformTop = platform.y - platform.height * platform.scale.y / 2; // Check if landing on top of platform if (player.vy > 0 && playerBottom >= platformTop && playerTop < platformTop) { player.y = platformTop - 75; player.vy = 0; player.grounded = true; } // Could add side collision handling here if needed } } } // Check collisions with obstacles function checkObstacleCollisions() { for (var i = 0; i < obstacles.length; i++) { var obstacle = obstacles[i]; if (player.intersects(obstacle)) { // Check if player is in stealth mode and if the obstacle can detect stealth if (player.inStealth && !obstacle.detectsStealth) { // Successfully sneaking past continue; } player.die(); return; } } } // Check collectibles function checkCollectibles() { for (var i = 0; i < collectibles.length; i++) { var collectible = collectibles[i]; if (!collectible.collected && player.intersects(collectible)) { if (collectible.collect()) { game.updateScore(score + 10); } } } } // Check if player reached the goal function checkGoal() { if (goal && player.intersects(goal)) { goal.reach(); } } // Initialize game function initGame() { setupUI(); createLevel(currentLevel); LK.playMusic('bgMusic', { fade: { start: 0, end: 0.3, duration: 1000 } }); } // Main update function game.update = function () { if (!player || player.dead) { return; } // Analyze breathing var breathLevel = analyzeBreath(); game.updateBreathIndicator(breathLevel); // Apply movement based on breath if (player.speed > 0) { player.vx = player.speed; } else { player.vx = 0; } // Update player physics player.update(); // Check collisions checkPlatformCollisions(); checkObstacleCollisions(); checkCollectibles(); checkGoal(); // Update all game objects for (var i = 0; i < obstacles.length; i++) { obstacles[i].update(); } for (var i = 0; i < collectibles.length; i++) { collectibles[i].update(); } if (goal) { goal.update(); } // Update camera to follow player (simple version) if (player.x > 1024) { world.x = Math.min(0, 1024 - player.x); } }; // Initialize the game initGame();
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
var facekit = LK.import("@upit/facekit.v1");
/****
* Classes
****/
var Collectible = Container.expand(function () {
var self = Container.call(this);
var collectibleGraphics = self.attachAsset('collectible', {
anchorX: 0.5,
anchorY: 0.5
});
self.collected = false;
self.collect = function () {
if (!self.collected) {
self.collected = true;
LK.getSound('collect').play();
tween(self, {
alpha: 0,
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 300,
onFinish: function onFinish() {
self.visible = false;
}
});
return true;
}
return false;
};
self.update = function () {
if (!self.collected) {
self.rotation += 0.02;
}
};
return self;
});
var Goal = Container.expand(function () {
var self = Container.call(this);
var goalGraphics = self.attachAsset('goal', {
anchorX: 0.5,
anchorY: 0.5
});
self.reached = false;
self.reach = function () {
if (!self.reached) {
self.reached = true;
LK.getSound('win').play();
tween(self, {
alpha: 0.5,
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 500,
onFinish: function onFinish() {
LK.showYouWin();
}
});
return true;
}
return false;
};
self.update = function () {
// Animate the goal if needed
self.rotation += 0.01;
};
return self;
});
var Obstacle = Container.expand(function () {
var self = Container.call(this);
var obstacleGraphics = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.5
});
self.detectsStealth = false;
self.update = function () {
// If this is a patrolling obstacle, add movement logic here
};
return self;
});
var Platform = Container.expand(function () {
var self = Container.call(this);
var platformGraphics = self.attachAsset('platform', {
anchorX: 0.5,
anchorY: 0.5
});
self.width = platformGraphics.width;
self.height = platformGraphics.height;
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
var playerGraphics = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5
});
var stealthMode = self.attachAsset('stealthIndicator', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0
});
self.vx = 0;
self.vy = 0;
self.speed = 5;
self.jumpStrength = -15;
self.gravity = 0.6;
self.grounded = false;
self.inStealth = false;
self.breathLevel = 0;
self.dead = false;
self.toggleStealth = function (value) {
if (self.inStealth !== value) {
self.inStealth = value;
if (value) {
tween(stealthMode, {
alpha: 0.5
}, {
duration: 300
});
tween(playerGraphics, {
alpha: 0.6
}, {
duration: 300
});
} else {
tween(stealthMode, {
alpha: 0
}, {
duration: 300
});
tween(playerGraphics, {
alpha: 1
}, {
duration: 300
});
}
}
};
self.jump = function () {
if (self.grounded && !self.dead) {
self.vy = self.jumpStrength;
self.grounded = false;
LK.getSound('jump').play();
}
};
self.die = function () {
if (!self.dead) {
self.dead = true;
LK.getSound('death').play();
LK.effects.flashObject(self, 0xff0000, 1000);
LK.setTimeout(function () {
LK.showGameOver();
}, 1000);
}
};
self.update = function () {
if (self.dead) {
return;
}
// Apply gravity
self.vy += self.gravity;
// Apply movement
self.x += self.vx;
self.y += self.vy;
// Check boundaries
if (self.y > 2732 - 100) {
self.die();
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87CEEB // Sky blue background
});
/****
* Game Code
****/
// Game variables
var player;
var platforms = [];
var obstacles = [];
var collectibles = [];
var goal;
var camera = {
x: 0,
y: 0
};
var currentLevel = storage.currentLevel || 1;
var score = 0;
var breathIndicator;
var breathText;
var holdingBreath = false;
var breathHoldStartTime = 0;
var breathAnalysisBuffer = [];
var breathBufferSize = 10;
// Game world container
var world = new Container();
game.addChild(world);
// Setup UI
function setupUI() {
// Score display
var scoreText = new Text2('Score: 0', {
size: 50,
fill: 0xFFFFFF
});
scoreText.anchor.set(1, 0);
LK.gui.topRight.addChild(scoreText);
// Breath indicator background
breathIndicator = LK.getAsset('platform', {
width: 300,
height: 30,
anchorX: 0,
anchorY: 0.5,
tint: 0x444444
});
// Breath level fill
var breathLevel = LK.getAsset('platform', {
width: 0,
height: 20,
anchorX: 0,
anchorY: 0.5,
tint: 0x3498db
});
breathIndicator.addChild(breathLevel);
// Label for breath indicator
breathText = new Text2('Breath', {
size: 40,
fill: 0xFFFFFF
});
breathText.anchor.set(0, 0.5);
breathText.x = 10;
// Add UI elements to the GUI overlay
LK.gui.right.addChild(breathIndicator);
breathIndicator.addChild(breathText);
// Update functions
game.updateScore = function (newScore) {
score = newScore;
scoreText.setText('Score: ' + score);
};
game.updateBreathIndicator = function (level) {
breathLevel.width = Math.min(1, level) * 290;
if (holdingBreath) {
breathText.setText('STEALTH');
} else if (level > 0.6) {
breathText.setText('RUNNING');
} else if (level > 0.1) {
breathText.setText('WALKING');
} else {
breathText.setText('Breath');
}
};
}
// Create level
function createLevel(levelNumber) {
// Clear existing level objects
clearLevel();
// Create player
player = new Player();
player.x = 200;
player.y = 2000;
world.addChild(player);
// Level design based on levelNumber
switch (levelNumber) {
case 1:
createLevelOne();
break;
case 2:
createLevelTwo();
break;
default:
createLevelOne();
// Default to level 1
}
// Store current level
storage.currentLevel = levelNumber;
}
function clearLevel() {
platforms = [];
obstacles = [];
collectibles = [];
// Remove all children from the world container
while (world.children.length > 0) {
world.removeChildAt(0);
}
}
function createLevelOne() {
// Starting platform
createPlatform(200, 2200, 400, 50);
// Basic platforms
createPlatform(700, 2100, 300, 50);
createPlatform(1200, 2000, 300, 50);
createPlatform(1700, 2100, 300, 50);
// Add some obstacles
var obstacle1 = new Obstacle();
obstacle1.x = 1200;
obstacle1.y = 1900;
obstacles.push(obstacle1);
world.addChild(obstacle1);
// Add collectibles
for (var i = 0; i < 3; i++) {
var collectible = new Collectible();
collectible.x = 700 + i * 500;
collectible.y = 1950;
collectibles.push(collectible);
world.addChild(collectible);
}
// Create goal
goal = new Goal();
goal.x = 1900;
goal.y = 2000;
world.addChild(goal);
}
function createLevelTwo() {
// More complex platform arrangement
createPlatform(200, 2200, 400, 50);
createPlatform(700, 2100, 200, 50);
createPlatform(1100, 2000, 200, 50);
createPlatform(1500, 2100, 200, 50);
createPlatform(1900, 2000, 200, 50);
// Add more obstacles
var obstacle1 = new Obstacle();
obstacle1.x = 1100;
obstacle1.y = 1900;
obstacle1.detectsStealth = true;
obstacles.push(obstacle1);
world.addChild(obstacle1);
var obstacle2 = new Obstacle();
obstacle2.x = 1500;
obstacle2.y = 2000;
obstacles.push(obstacle2);
world.addChild(obstacle2);
// Add collectibles
for (var i = 0; i < 5; i++) {
var collectible = new Collectible();
collectible.x = 500 + i * 400;
collectible.y = 1900;
collectibles.push(collectible);
world.addChild(collectible);
}
// Create goal
goal = new Goal();
goal.x = 1900;
goal.y = 1900;
world.addChild(goal);
}
function createPlatform(x, y, width, height) {
var platform = new Platform();
platform.x = x;
platform.y = y;
// If we want to resize platforms
if (width && width !== 300) {
platform.scale.x = width / 300;
}
if (height && height !== 50) {
platform.scale.y = height / 50;
}
platforms.push(platform);
world.addChild(platform);
return platform;
}
// Breath analysis
function analyzeBreath() {
var currentVolume = facekit.volume;
// Add current breath to buffer
breathAnalysisBuffer.push(currentVolume);
if (breathAnalysisBuffer.length > breathBufferSize) {
breathAnalysisBuffer.shift();
}
// Calculate average breath level
var sum = 0;
for (var i = 0; i < breathAnalysisBuffer.length; i++) {
sum += breathAnalysisBuffer[i];
}
var avgBreath = sum / breathAnalysisBuffer.length;
// Detect if holding breath (very low volume for a sustained period)
var currentTime = Date.now();
if (currentVolume < 0.1) {
if (!holdingBreath) {
breathHoldStartTime = currentTime;
holdingBreath = true;
} else if (currentTime - breathHoldStartTime > 1000) {
// Been holding breath for over a second, activate stealth
player.toggleStealth(true);
}
} else {
holdingBreath = false;
player.toggleStealth(false);
}
// Update player speed based on breath intensity
if (!holdingBreath) {
if (avgBreath > 0.6) {
// Running
player.speed = 10;
} else if (avgBreath > 0.1) {
// Walking
player.speed = 5;
} else {
// Standing still (very light breathing)
player.speed = 0;
}
} else {
// Stealth mode - slower movement
player.speed = 1;
}
return avgBreath;
}
// Check collisions between player and platforms
function checkPlatformCollisions() {
player.grounded = false;
for (var i = 0; i < platforms.length; i++) {
var platform = platforms[i];
if (player.intersects(platform)) {
// Calculate the sides of both objects
var playerBottom = player.y + 75;
var playerTop = player.y - 75;
var platformTop = platform.y - platform.height * platform.scale.y / 2;
// Check if landing on top of platform
if (player.vy > 0 && playerBottom >= platformTop && playerTop < platformTop) {
player.y = platformTop - 75;
player.vy = 0;
player.grounded = true;
}
// Could add side collision handling here if needed
}
}
}
// Check collisions with obstacles
function checkObstacleCollisions() {
for (var i = 0; i < obstacles.length; i++) {
var obstacle = obstacles[i];
if (player.intersects(obstacle)) {
// Check if player is in stealth mode and if the obstacle can detect stealth
if (player.inStealth && !obstacle.detectsStealth) {
// Successfully sneaking past
continue;
}
player.die();
return;
}
}
}
// Check collectibles
function checkCollectibles() {
for (var i = 0; i < collectibles.length; i++) {
var collectible = collectibles[i];
if (!collectible.collected && player.intersects(collectible)) {
if (collectible.collect()) {
game.updateScore(score + 10);
}
}
}
}
// Check if player reached the goal
function checkGoal() {
if (goal && player.intersects(goal)) {
goal.reach();
}
}
// Initialize game
function initGame() {
setupUI();
createLevel(currentLevel);
LK.playMusic('bgMusic', {
fade: {
start: 0,
end: 0.3,
duration: 1000
}
});
}
// Main update function
game.update = function () {
if (!player || player.dead) {
return;
}
// Analyze breathing
var breathLevel = analyzeBreath();
game.updateBreathIndicator(breathLevel);
// Apply movement based on breath
if (player.speed > 0) {
player.vx = player.speed;
} else {
player.vx = 0;
}
// Update player physics
player.update();
// Check collisions
checkPlatformCollisions();
checkObstacleCollisions();
checkCollectibles();
checkGoal();
// Update all game objects
for (var i = 0; i < obstacles.length; i++) {
obstacles[i].update();
}
for (var i = 0; i < collectibles.length; i++) {
collectibles[i].update();
}
if (goal) {
goal.update();
}
// Update camera to follow player (simple version)
if (player.x > 1024) {
world.x = Math.min(0, 1024 - player.x);
}
};
// Initialize the game
initGame();