/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
//<Write imports for supported plugins here>
// ForestSpirit class representing the main character
var ForestSpirit = Container.expand(function () {
var self = Container.call(this);
var spiritGraphics = self.attachAsset('forestSpirit', {
anchorX: 0.5,
anchorY: 0.5
// Apply watercolor effect
});
self.move = function (x, y, obj) {
var game_position = game.toLocal(obj.global);
self.x = game_position.x;
self.y = game_position.y;
};
self.controlWind = function (direction, strength) {
console.log("Controlling wind: ".concat(direction, " with strength: ").concat(strength));
// Logic to move platforms or sway branches based on wind direction and strength
};
self.manipulateFoliage = function (action, target) {
console.log("Manipulating foliage: ".concat(action, " on target: ").concat(target));
// Logic to grow vines, shrink/enlarge trees, or create stepping stones
};
self.controlShadows = function (action, target) {
console.log("Controlling shadows: ".concat(action, " on target: ").concat(target));
// Logic to create platforms, distract enemies, or mimic the child's movements
};
});
// HumanChild class representing the lost child
var HumanChild = Container.expand(function () {
var self = Container.call(this);
var childGraphics = self.attachAsset('humanChild', {
anchorX: 0.5,
anchorY: 0.5
// Apply watercolor effect
});
self.follow = function (target) {
// Simple follow logic
self.x += (target.x - self.x) * 0.05;
self.y += (target.y - self.y) * 0.05;
};
});
// Item class representing a collectible item
var Item = Container.expand(function () {
var self = Container.call(this);
var itemGraphics = self.attachAsset('scatteredToys', {
anchorX: 0.5,
anchorY: 0.5
});
self.follow = function (target) {
// Make the item follow the target (HumanChild) with a slight offset
self.x = target.x;
self.y = target.y - 50; // Offset to position the item above the target
};
});
// PuzzleElement class for interactive elements
var PuzzleElement = Container.expand(function () {
var self = Container.call(this);
var elementGraphics = self.attachAsset('puzzleElement', {
anchorX: 0.5,
anchorY: 0.5
// Apply watercolor effect
});
self.interact = function () {
// Define interaction logic
console.log("PuzzleElement interacted with by ForestSpirit!");
// Additional interaction logic can be added here
};
});
// Sword class representing a collectible item
var Sword = Container.expand(function () {
var self = Container.call(this);
var swordGraphics = self.attachAsset('sword', {
anchorX: 0.5,
anchorY: 0.5
});
self.collect = function () {
console.log("Sword collected!");
// Logic for what happens when the sword is collected
self.destroy(); // Remove the sword from the game
};
});
// Tree class representing an obstacle
var Tree = Container.expand(function () {
var self = Container.call(this);
var treeGraphics = self.attachAsset('tree', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 1.0
});
// Prevent movement through the tree
self.intersects = function (character) {
return character.intersects(treeGraphics);
};
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x8FBC8F
// Init game with a soft blue-green background to mimic watercolor style
});
/****
* Game Code
****/
// Initialize collectible items and add them to the game
var items = [];
for (var i = 0; i < 3; i++) {
var item = new Item();
item.x = Math.random() * 2048; // Random X position
item.y = Math.random() * 2732; // Random Y position
items.push(item);
game.addChild(item);
}
var footstepsCooldown = false;
// Initialize sword and add it to the game
var sword = new Sword();
sword.x = Math.random() * 2048; // Random X position
sword.y = Math.random() * 2732; // Random Y position
game.addChild(sword);
// Update game logic to handle sword collection
game.update = function () {
atmosphericEffects.update(); // Update atmospheric effects each frame
// Check for collisions with trees
for (var i = 0; i < trees.length; i++) {
if (forestSpirit.intersects(trees[i])) {
forestSpirit.x = forestSpirit.lastX;
forestSpirit.y = forestSpirit.lastY;
} else {
forestSpirit.lastX = forestSpirit.x;
forestSpirit.lastY = forestSpirit.y;
}
}
// Check if ForestSpirit collects the sword
if (forestSpirit.intersects(sword)) {
console.log("ForestSpirit finds sword, hinting at its great appearance.");
showNarrative("The ForestSpirit discovers a mystical sword, \nits blade shimmering with ancient power.");
}
// Check if HumanChild collects any items
for (var i = items.length - 1; i >= 0; i--) {
if (humanChild.intersects(items[i])) {
items[i].follow(humanChild);
}
}
// Existing update logic...
if (humanChild.initialFear) {
humanChild.x += (Math.random() - 0.5) * 5;
humanChild.y += (Math.random() - 0.5) * 5;
humanChild.trustLevel += 0.005;
if (humanChild.trustLevel > 1) {
humanChild.initialFear = false;
}
} else {
if (!humanChild.initialFear) {
humanChild.follow(forestSpirit);
}
}
if (forestSpirit.lastX === undefined) {
forestSpirit.lastX = forestSpirit.x;
}
if (forestSpirit.lastY === undefined) {
forestSpirit.lastY = forestSpirit.y;
}
forestSpirit.lastX = forestSpirit.x;
forestSpirit.lastY = forestSpirit.y;
};
// Initialize trees and add them to the game
var puzzleElements = [];
var trees = [];
var forestSpirit = new ForestSpirit();
var humanChild = new HumanChild();
var scatteredToys = [];
var animalFootprints = [];
for (var i = 0; i < 6; i++) {
var tree = new Tree();
do {
tree.x = Math.random() * 2048;
tree.y = Math.random() * 2732;
} while (trees.some(function (existingTree) {
return Math.abs(existingTree.x - tree.x) < 500 && Math.abs(existingTree.y - tree.y) < 500;
}) || Math.abs(tree.x - forestSpirit.x) < 500 && Math.abs(tree.y - forestSpirit.y) < 500 || Math.abs(tree.x - humanChild.x) < 500 && Math.abs(tree.y - humanChild.y) < 500 || puzzleElements.some(function (puzzleElement) {
return Math.abs(puzzleElement.x - tree.x) < 500 && Math.abs(puzzleElement.y - tree.y) < 500;
}) || scatteredToys.some(function (toy) {
return Math.abs(toy.x - tree.x) < 500 && Math.abs(toy.y - tree.y) < 500;
}) || animalFootprints.some(function (footprint) {
return Math.abs(footprint.x - tree.x) < 500 && Math.abs(footprint.y - tree.y) < 500;
})); // Ensure distance from all objects
trees.push(tree);
game.addChild(tree);
}
// Update game logic to handle tree collisions
game.update = function () {
atmosphericEffects.update(); // Update atmospheric effects each frame
// Check for collisions with trees
for (var i = 0; i < trees.length; i++) {
if (forestSpirit.intersects(trees[i])) {
forestSpirit.x = forestSpirit.lastX;
forestSpirit.y = forestSpirit.lastY;
} else {
// Ensure last positions are updated only when not intersecting
forestSpirit.lastX = forestSpirit.x;
forestSpirit.lastY = forestSpirit.y;
}
}
// Disable functionality for objects outside the frame
if (forestSpirit.x < 0 || forestSpirit.x > 2048 || forestSpirit.y < 0 || forestSpirit.y > 2732) {
// Disable or limit functionality for forestSpirit
forestSpirit.controlWind = function () {};
forestSpirit.manipulateFoliage = function () {};
forestSpirit.controlShadows = function () {};
}
if (humanChild.x < 0 || humanChild.x > 2048 || humanChild.y < 0 || humanChild.y > 2732) {
// Disable or limit functionality for humanChild
humanChild.follow = function () {};
}
// Existing update logic...
if (humanChild.initialFear) {
humanChild.x += (Math.random() - 0.5) * 5;
humanChild.y += (Math.random() - 0.5) * 5;
humanChild.trustLevel += 0.005;
if (humanChild.trustLevel > 1) {
humanChild.initialFear = false;
}
} else {
if (!humanChild.initialFear) {
humanChild.follow(forestSpirit);
}
}
if (forestSpirit.lastX === undefined) {
forestSpirit.lastX = forestSpirit.x;
}
if (forestSpirit.lastY === undefined) {
forestSpirit.lastY = forestSpirit.y;
}
forestSpirit.lastX = forestSpirit.x;
forestSpirit.lastY = forestSpirit.y;
// Existing coordinate checks...
};
//<Write imports for supported plugins here>
// Initialize background image
// Add background image to the game
var narrativeCooldown = false;
function showNarrative(text) {
if (narrativeCooldown) {
return;
}
narrativeCooldown = true;
console.log("Narrative: " + text);
// Additional logic to display narrative text on the screen can be added here
// For example, you could create a Text2 object to display the narrative
var narrativeText = new Text2(text, {
size: 50,
fill: 0xFFFFFF,
align: "center"
});
narrativeText.anchor.set(0.5, 0.5);
narrativeText.x = Math.min(2048 / 16, 2048 - narrativeText.width);
narrativeText.y = Math.min(2732 / 4, 2732 - narrativeText.height / 2) + LK.gui.center.children.length * narrativeText.height;
LK.gui.center.addChild(narrativeText);
// Animate the narrative text to fade out and then remove it
tween(narrativeText, {
alpha: 0
}, {
duration: 2000,
easing: tween.easeOut,
onFinish: function onFinish() {
LK.gui.center.removeChild(narrativeText);
LK.setTimeout(function () {
narrativeCooldown = false;
}, 1500); // Cooldown period of 1.5 seconds
}
});
}
/** Assets
**/
function transitionToNextLevel() {
console.log("Transitioning to the next level...");
// Check if ForestSpirit reached a specific X and Y coordinate (e.g., 1500, 1000)
if (forestSpirit.lastY <= 900 && forestSpirit.y > 900 && forestSpirit.lastX <= 1300 && forestSpirit.x > 1300) {
console.log("ForestSpirit and HumanChild share a moment of connection.");
// Trigger a narrative event to show the bond between ForestSpirit and HumanChild
showNarrative("In a serene clearing, the ForestSpirit and the lost child find solace in each other's presence.");
// Additional logic for this narrative event can be added here
}
if (forestSpirit.lastX <= 1200 && forestSpirit.x > 1200) {
console.log("ForestSpirit and HumanChild share a moment of connection.");
// Trigger a narrative event to show the bond between ForestSpirit and HumanChild
showNarrative("The ForestSpirit whispers words of comfort to the lost child, their journey intertwined.");
// Additional logic for this narrative event can be added here
}
if (forestSpirit.lastY <= 800 && forestSpirit.y > 800) {
console.log("ForestSpirit and HumanChild share a moment of connection.");
// Trigger a narrative event to show the bond between ForestSpirit and HumanChild
showNarrative("The ForestSpirit gently guides the lost child, their bond growing stronger with each step.");
// Additional logic for this narrative event can be added here
}
for (var i = 0; i < puzzleElements.length; i++) {
puzzleElements[i].destroy();
}
puzzleElements = [];
// Logic to set up the next level with unique features
var levelType = Math.floor(Math.random() * 3); // Randomly select a level type
for (var i = 0; i < 5; i++) {
var puzzleElement = new PuzzleElement();
puzzleElement.x = Math.random() * 2048;
puzzleElement.y = Math.random() * 2732;
puzzleElements.push(puzzleElement);
game.addChild(puzzleElement);
// Add unique features based on level type
if (levelType === 0) {
// Level with more foliage challenges
forestSpirit.manipulateFoliage('grow', 'vines');
forestSpirit.manipulateFoliage('enlarge', 'tree');
} else if (levelType === 1) {
// Level with more wind challenges
forestSpirit.controlWind('left', 4);
forestSpirit.controlWind('right', 3);
} else if (levelType === 2) {
// Level with more shadow challenges
forestSpirit.controlShadows('mimic', 'child');
forestSpirit.controlShadows('create', 'platform');
}
}
// Reset ForestSpirit and HumanChild positions
forestSpirit.x = 1024;
forestSpirit.y = 1366;
humanChild.x = 800;
humanChild.y = 1500;
}
// Initialize game elements
var forestSpirit = new ForestSpirit();
forestSpirit.lastX = 1024; // Center horizontally
forestSpirit.lastY = 1366; // Center vertically
forestSpirit.x = forestSpirit.lastX;
forestSpirit.y = forestSpirit.lastY;
game.addChild(forestSpirit);
var humanChild = game.addChild(new HumanChild());
humanChild.x = 800; // Initial position
humanChild.y = 1500; // Initial position
humanChild.initialFear = true; // Start with fear
humanChild.trustLevel = 0; // Initial trust level
var puzzleElements = [];
// Add visual storytelling elements
var scatteredToys = LK.getAsset('scatteredToys', {
anchorX: 0.5,
anchorY: 0.5
});
scatteredToys.x = Math.min(500, 2048 - scatteredToys.width / 2);
scatteredToys.y = Math.min(1200, 2732 - scatteredToys.height / 2);
game.addChild(scatteredToys);
// Initialize lastX and lastY for scatteredToys if not already set
if (scatteredToys.lastX === undefined) {
scatteredToys.lastX = scatteredToys.x;
}
if (scatteredToys.lastY === undefined) {
scatteredToys.lastY = scatteredToys.y;
}
// Update lastX and lastY for scatteredToys
scatteredToys.lastX = scatteredToys.x;
scatteredToys.lastY = scatteredToys.y;
var animalFootprints = LK.getAsset('animalFootprints', {
anchorX: 0.5,
anchorY: 0.5
});
animalFootprints.x = Math.min(1500, 2048 - animalFootprints.width / 2);
animalFootprints.y = Math.min(800, 2732 - animalFootprints.height / 2);
game.addChild(animalFootprints);
// Initialize lastX and lastY for animalFootprints if not already set
if (animalFootprints.lastX === undefined) {
animalFootprints.lastX = animalFootprints.x;
}
if (animalFootprints.lastY === undefined) {
animalFootprints.lastY = animalFootprints.y;
}
// Update lastX and lastY for animalFootprints
animalFootprints.lastX = animalFootprints.x;
animalFootprints.lastY = animalFootprints.y;
var initialLevelType = Math.floor(Math.random() * 3); // Randomly select initial level type
for (var i = 0; i < 5; i++) {
var puzzleElement = new PuzzleElement();
puzzleElement.x = Math.random() * 2048;
puzzleElement.y = Math.random() * 2732;
puzzleElements.push(puzzleElement);
game.addChild(puzzleElement);
// Add unique features based on initial level type
if (initialLevelType === 0) {
forestSpirit.manipulateFoliage('grow', 'vines');
forestSpirit.manipulateFoliage('enlarge', 'tree');
} else if (initialLevelType === 1) {
forestSpirit.controlWind('left', 4);
forestSpirit.controlWind('right', 3);
} else if (initialLevelType === 2) {
forestSpirit.controlShadows('mimic', 'child');
forestSpirit.controlShadows('create', 'platform');
}
}
// Initialize atmospheric effects
var atmosphericEffects = {
fogDensity: 0.5,
lightIntensity: 0.8,
update: function update() {
// Custom logic to update atmospheric effects each frame
console.log("Updating atmospheric effects with fogDensity:", this.fogDensity, "and lightIntensity:", this.lightIntensity);
}
};
// Game update logic
game.update = function () {
atmosphericEffects.update(); // Update atmospheric effects each frame
if (humanChild.initialFear) {
humanChild.lastX = humanChild.x; // Track last X position
humanChild.lastY = humanChild.y; // Track last Y position
// HumanChild hesitates and moves erratically
humanChild.x += (Math.random() - 0.5) * 5; // Reduced movement range for smoother transition
humanChild.y += (Math.random() - 0.5) * 5; // Reduced movement range for smoother transition
// Gradually increase trust level
humanChild.trustLevel += 0.005; // Slower trust increase for more gradual transition
humanChild.lastX = humanChild.x; // Track last X position
humanChild.lastY = humanChild.y; // Track last Y position
if (humanChild.trustLevel > 1) {
humanChild.initialFear = false; // Overcome fear
}
} else {
// HumanChild follows ForestSpirit smoothly
// Ensure HumanChild follows ForestSpirit smoothly after overcoming initial fear
if (!humanChild.initialFear) {
humanChild.lastX = humanChild.x; // Track last X position
humanChild.lastY = humanChild.y; // Track last Y position
humanChild.follow(forestSpirit);
}
}
// Initialize lastX and lastY if not already set
if (forestSpirit.lastX === undefined) {
forestSpirit.lastX = forestSpirit.x;
}
if (forestSpirit.lastY === undefined) {
forestSpirit.lastY = forestSpirit.y;
}
// Update lastX and lastY for ForestSpirit
forestSpirit.lastX = forestSpirit.x;
forestSpirit.lastY = forestSpirit.y;
// Check if ForestSpirit reached a specific Y coordinate (e.g., 1000)
if (forestSpirit.lastY <= 1000 && forestSpirit.y > 1000) {
console.log("ForestSpirit reached Y coordinate 1000!");
// Trigger foliage manipulation ability
// forestSpirit.manipulateFoliage('grow', 'vines'); // Ability disabled for the first level
// Additional logic for reaching this coordinate can be added here
// Example: Unlock a new path or reveal a hidden area
// Trigger wind control ability
// forestSpirit.controlWind('up', 3); // Ability disabled for the first level
// Discover a secret area
console.log("A secret area is discovered!");
// Logic to discover a secret area
// Transition to next level
transitionToNextLevel();
// Trigger a narrative event to show the bond between ForestSpirit and HumanChild
showNarrative("The ForestSpirit gently guides the lost child,\ntheir bond growing stronger with each step.");
}
// Check if ForestSpirit reached a specific X coordinate (e.g., 1500)
if (forestSpirit.lastX <= 1500 && forestSpirit.x > 1500) {
console.log("ForestSpirit reached X coordinate 1500!");
// Trigger wind control ability
forestSpirit.controlWind('right', 5);
// Additional logic for reaching this coordinate can be added here
// Example: Move a platform or clear an obstacle
// Trigger shadow control ability
// forestSpirit.controlShadows('distract', 'enemy'); // Ability disabled for the first level
// Reveal a hidden path
console.log("A hidden path is revealed!");
// Logic to reveal a hidden path or secret area
}
// Check if ForestSpirit reached a specific X and Y coordinate (e.g., 1500, 1000)
if (forestSpirit.lastY <= 1000 && forestSpirit.y > 1000 && forestSpirit.lastX <= 1500 && forestSpirit.x > 1500) {
console.log("ForestSpirit reached X and Y coordinates 1500, 1000!");
// Trigger shadow control ability
forestSpirit.controlShadows('create', 'platform');
// Additional logic for reaching this coordinate can be added here
// Example: Create a temporary platform or open a secret passage
// Trigger foliage manipulation ability
// forestSpirit.manipulateFoliage('shrink', 'tree'); // Ability disabled for the first level
// Reveal a hidden path
console.log("A hidden path is revealed!");
// Logic to reveal a hidden path or secret area
}
// Check interactions with puzzle elements
for (var i = 0; i < puzzleElements.length; i++) {
if (forestSpirit.intersects(puzzleElements[i])) {
puzzleElements[i].interact();
// Example: Solve a puzzle or activate a mechanism
}
}
// Check interaction with scattered toys for storytelling
if (forestSpirit.intersects(scatteredToys)) {
console.log("ForestSpirit finds scattered toys, hinting at the child's past.");
showNarrative("The scattered toys tell a story of a child's playful past,\nnow lost in the woods.");
}
// Check interaction with animal footprints for storytelling
if (forestSpirit.intersects(animalFootprints)) {
console.log("ForestSpirit discovers animal footprints, hinting at the presence of wildlife.");
showNarrative("The animal footprints reveal the presence of unseen wildlife,\nguiding the way.");
}
// Check if ForestSpirit reached a specific X coordinate (e.g., 1500)
if (forestSpirit.lastX <= 1500 && forestSpirit.x > 1500) {
console.log("ForestSpirit reached X coordinate 1500!");
// Trigger wind control ability
forestSpirit.controlWind('right', 5);
// Additional logic for reaching this coordinate can be added here
// Example: Move a platform or clear an obstacle
// Trigger shadow control ability
forestSpirit.controlShadows('distract', 'enemy');
// Reveal a hidden path
console.log("A hidden path is revealed!");
// Logic to reveal a hidden path or secret area
// Trigger a narrative event to show the bond between ForestSpirit and HumanChild
showNarrative("The ForestSpirit whispers words of comfort to the lost child,\ntheir journey intertwined.");
}
// Check if ForestSpirit reached a specific X and Y coordinate (e.g., 1500, 1000)
if (forestSpirit.lastY <= 1000 && forestSpirit.y > 1000 && forestSpirit.lastX <= 1500 && forestSpirit.x > 1500) {
console.log("ForestSpirit reached X and Y coordinates 1500, 1000!");
// Trigger shadow control ability
forestSpirit.controlShadows('create', 'platform');
// Additional logic for reaching this coordinate can be added here
// Example: Create a temporary platform or open a secret passage
// Trigger foliage manipulation ability
forestSpirit.manipulateFoliage('shrink', 'tree');
// Reveal a hidden path
console.log("A hidden path is revealed!");
// Logic to reveal a hidden path or secret area
// Trigger a narrative event to show the bond between ForestSpirit and HumanChild
showNarrative("In a serene clearing, the ForestSpirit and the lost child\nfind solace in each other's presence.");
}
};
// Handle touch/mouse events
game.down = function (x, y, obj) {
forestSpirit.move(x, y, obj);
// Additional logic for platform-specific adjustments can be added here
};
game.move = function (x, y, obj) {
forestSpirit.move(x, y, obj);
// Additional logic for platform-specific adjustments can be added here
};
game.up = function (x, y, obj) {
// Optional: Add logic for when touch/mouse is released
};