/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Berry = Container.expand(function () {
var self = Container.call(this);
var berryGraphics = self.attachAsset('berry', {
anchorX: 0.5,
anchorY: 0.5
});
self.collected = false;
return self;
});
var Creature = Container.expand(function () {
var self = Container.call(this);
var creatureGraphics = self.attachAsset('creature', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 1;
self.direction = Math.random() * Math.PI * 2;
self.changeDirectionTimer = 0;
self.update = function () {
self.changeDirectionTimer++;
if (self.changeDirectionTimer > 120) {
self.direction = Math.random() * Math.PI * 2;
self.changeDirectionTimer = 0;
}
self.x += Math.cos(self.direction) * self.speed;
self.y += Math.sin(self.direction) * self.speed;
// Keep creatures in bounds
if (self.x < 50 || self.x > 1998) {
self.direction = Math.PI - self.direction;
}
if (self.y < 50 || self.y > 2682) {
self.direction = -self.direction;
}
};
return self;
});
var Crystal = Container.expand(function () {
var self = Container.call(this);
var crystalGraphics = self.attachAsset('crystal', {
anchorX: 0.5,
anchorY: 0.5
});
self.collected = false;
self.glowDirection = 1;
self.update = function () {
if (!self.collected) {
crystalGraphics.alpha += 0.02 * self.glowDirection;
if (crystalGraphics.alpha >= 1) {
self.glowDirection = -1;
} else if (crystalGraphics.alpha <= 0.3) {
self.glowDirection = 1;
}
}
};
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
var playerGraphics = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 4;
self.targetX = null;
self.targetY = null;
self.isMoving = false;
self.moveTo = function (x, y) {
self.targetX = x;
self.targetY = y;
self.isMoving = true;
};
self.update = function () {
if (self.isMoving && self.targetX !== null && self.targetY !== null) {
var dx = self.targetX - self.x;
var dy = self.targetY - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < self.speed) {
self.x = self.targetX;
self.y = self.targetY;
self.isMoving = false;
} else {
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
}
}
};
return self;
});
var Thorn = Container.expand(function () {
var self = Container.call(this);
var thornGraphics = self.attachAsset('thorn', {
anchorX: 0.5,
anchorY: 0.5
});
return self;
});
var Tree = Container.expand(function () {
var self = Container.call(this);
var treeGraphics = self.attachAsset('tree', {
anchorX: 0.5,
anchorY: 1.0
});
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x2d5016
});
/****
* Game Code
****/
// Game variables
var player;
var crystals = [];
var berries = [];
var trees = [];
var thorns = [];
var creatures = [];
var areasDiscovered = 0;
var itemsCollected = 0;
// UI Elements
var scoreTxt = new Text2('Score: 0', {
size: 80,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0, 0);
LK.gui.topRight.addChild(scoreTxt);
var itemsTxt = new Text2('Items: 0', {
size: 60,
fill: 0xFFFFFF
});
itemsTxt.anchor.set(0, 0);
itemsTxt.y = 100;
LK.gui.topRight.addChild(itemsTxt);
// Inventory button
var inventoryBtn = new Text2('BAG', {
size: 60,
fill: 0xFFFFFF
});
inventoryBtn.anchor.set(0, 0);
inventoryBtn.x = 120;
inventoryBtn.y = 20;
LK.gui.topLeft.addChild(inventoryBtn);
// Map button
var mapBtn = new Text2('MAP', {
size: 60,
fill: 0xFFFFFF
});
mapBtn.anchor.set(0, 0);
mapBtn.x = 120;
mapBtn.y = 90;
LK.gui.topLeft.addChild(mapBtn);
// Inventory state
var inventoryOpen = false;
var inventoryPanel = null;
// Map state
var mapOpen = false;
var mapPanel = null;
// Create ground
var ground = game.addChild(LK.getAsset('ground', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0
}));
// Create player
player = game.addChild(new Player());
player.x = 1024;
player.y = 1366;
// Generate forest elements
function generateForestElements() {
// Create trees
for (var i = 0; i < 15; i++) {
var tree = new Tree();
tree.x = Math.random() * 1900 + 100;
tree.y = Math.random() * 2500 + 200;
trees.push(tree);
game.addChild(tree);
}
// Create crystals
for (var i = 0; i < 8; i++) {
var crystal = new Crystal();
crystal.x = Math.random() * 1800 + 200;
crystal.y = Math.random() * 2400 + 200;
crystals.push(crystal);
game.addChild(crystal);
}
// Create berries
for (var i = 0; i < 12; i++) {
var berry = new Berry();
berry.x = Math.random() * 1800 + 200;
berry.y = Math.random() * 2400 + 200;
berries.push(berry);
game.addChild(berry);
}
// Create thorns
for (var i = 0; i < 6; i++) {
var thorn = new Thorn();
thorn.x = Math.random() * 1800 + 200;
thorn.y = Math.random() * 2400 + 200;
thorns.push(thorn);
game.addChild(thorn);
}
// Create creatures
for (var i = 0; i < 4; i++) {
var creature = new Creature();
creature.x = Math.random() * 1600 + 300;
creature.y = Math.random() * 2200 + 300;
creatures.push(creature);
game.addChild(creature);
}
}
generateForestElements();
// Touch controls
game.down = function (x, y, obj) {
player.moveTo(x, y);
};
// Inventory button click handler
inventoryBtn.down = function (x, y, obj) {
if (!inventoryOpen) {
// Create inventory panel
inventoryPanel = game.addChild(LK.getAsset('ground', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1366,
scaleX: 0.8,
scaleY: 0.6
}));
inventoryPanel.tint = 0x654321;
inventoryPanel.alpha = 0.9;
// Add inventory title
var invTitle = new Text2('INVENTORY', {
size: 80,
fill: 0xFFFFFF
});
invTitle.anchor.set(0.5, 0);
invTitle.x = 1024;
invTitle.y = 900;
game.addChild(invTitle);
inventoryPanel.titleText = invTitle;
// Add close button
var closeBtn = new Text2('CLOSE', {
size: 60,
fill: 0xFF4444
});
closeBtn.anchor.set(0.5, 0.5);
closeBtn.x = 1024;
closeBtn.y = 1800;
closeBtn.down = function () {
inventoryPanel.destroy();
inventoryPanel.titleText.destroy();
this.destroy();
inventoryOpen = false;
inventoryPanel = null;
};
game.addChild(closeBtn);
inventoryPanel.closeBtn = closeBtn;
inventoryOpen = true;
} else {
// Close inventory
if (inventoryPanel) {
inventoryPanel.destroy();
inventoryPanel.titleText.destroy();
inventoryPanel.closeBtn.destroy();
inventoryOpen = false;
inventoryPanel = null;
}
}
};
// Map button click handler
mapBtn.down = function (x, y, obj) {
if (!mapOpen) {
// Create map panel
mapPanel = game.addChild(LK.getAsset('ground', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1366,
scaleX: 0.9,
scaleY: 0.8
}));
mapPanel.tint = 0x8B4513;
mapPanel.alpha = 0.95;
// Add map title
var mapTitle = new Text2('FOREST MAP', {
size: 80,
fill: 0xFFFFFF
});
mapTitle.anchor.set(0.5, 0);
mapTitle.x = 1024;
mapTitle.y = 800;
game.addChild(mapTitle);
mapPanel.titleText = mapTitle;
// Add player position indicator
var playerDot = game.addChild(LK.getAsset('crystal', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024 + (player.x - 1024) * 0.4,
y: 1366 + (player.y - 1366) * 0.3,
scaleX: 0.8,
scaleY: 0.8
}));
playerDot.tint = 0x00FF00;
mapPanel.playerDot = playerDot;
// Add close button
var closeMapBtn = new Text2('CLOSE', {
size: 60,
fill: 0xFF4444
});
closeMapBtn.anchor.set(0.5, 0.5);
closeMapBtn.x = 1024;
closeMapBtn.y = 1900;
closeMapBtn.down = function () {
mapPanel.destroy();
mapPanel.titleText.destroy();
mapPanel.playerDot.destroy();
this.destroy();
mapOpen = false;
mapPanel = null;
};
game.addChild(closeMapBtn);
mapPanel.closeBtn = closeMapBtn;
mapOpen = true;
} else {
// Close map
if (mapPanel) {
mapPanel.destroy();
mapPanel.titleText.destroy();
mapPanel.playerDot.destroy();
mapPanel.closeBtn.destroy();
mapOpen = false;
mapPanel = null;
}
}
};
// Update score display
function updateScore() {
scoreTxt.setText('Score: ' + LK.getScore());
itemsTxt.setText('Items: ' + itemsCollected);
}
// Check collisions and interactions
game.update = function () {
// Check crystal collection
for (var i = crystals.length - 1; i >= 0; i--) {
var crystal = crystals[i];
if (!crystal.collected && player.intersects(crystal)) {
crystal.collected = true;
crystal.alpha = 0;
itemsCollected++;
LK.setScore(LK.getScore() + 10);
updateScore();
LK.getSound('collect').play();
crystals.splice(i, 1);
crystal.destroy();
}
}
// Check berry collection
for (var i = berries.length - 1; i >= 0; i--) {
var berry = berries[i];
if (!berry.collected && player.intersects(berry)) {
berry.collected = true;
berry.alpha = 0;
itemsCollected++;
LK.setScore(LK.getScore() + 5);
updateScore();
LK.getSound('collect').play();
berries.splice(i, 1);
berry.destroy();
}
}
// Check thorn collisions
for (var i = 0; i < thorns.length; i++) {
var thorn = thorns[i];
if (player.intersects(thorn)) {
// Push player away from thorn
var dx = player.x - thorn.x;
var dy = player.y - thorn.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
player.x = thorn.x + dx / distance * 60;
player.y = thorn.y + dy / distance * 60;
}
player.isMoving = false;
LK.effects.flashObject(player, 0xff0000, 500);
LK.getSound('danger').play();
}
}
// Check creature encounters
for (var i = 0; i < creatures.length; i++) {
var creature = creatures[i];
if (player.intersects(creature)) {
// Push player away from creature
var dx = player.x - creature.x;
var dy = player.y - creature.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
player.x = creature.x + dx / distance * 70;
player.y = creature.y + dy / distance * 70;
}
player.isMoving = false;
LK.effects.flashObject(player, 0x8b4513, 500);
LK.setScore(Math.max(0, LK.getScore() - 2));
updateScore();
LK.getSound('danger').play();
}
}
// Check tree collisions (blocking)
for (var i = 0; i < trees.length; i++) {
var tree = trees[i];
if (player.intersects(tree)) {
// Push player away from tree (account for tree anchor being at bottom center)
var dx = player.x - tree.x;
var dy = player.y - (tree.y - tree.height / 2); // Adjust for tree anchor point
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
// Increase push distance to ensure player stays outside tree bounds
player.x = tree.x + dx / distance * (tree.width / 2 + 35);
player.y = tree.y - tree.height / 2 + dy / distance * (tree.height / 2 + 35);
}
player.isMoving = false;
}
}
// Keep player in bounds
if (player.x < 30) player.x = 30;
if (player.x > 2018) player.x = 2018;
if (player.y < 30) player.y = 30;
if (player.y > 2702) player.y = 2702;
// Check win condition
if (itemsCollected >= 15) {
LK.showYouWin();
}
};
// Play ambient forest music
LK.playMusic('forestAmbient');
// Initialize score display
updateScore(); /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Berry = Container.expand(function () {
var self = Container.call(this);
var berryGraphics = self.attachAsset('berry', {
anchorX: 0.5,
anchorY: 0.5
});
self.collected = false;
return self;
});
var Creature = Container.expand(function () {
var self = Container.call(this);
var creatureGraphics = self.attachAsset('creature', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 1;
self.direction = Math.random() * Math.PI * 2;
self.changeDirectionTimer = 0;
self.update = function () {
self.changeDirectionTimer++;
if (self.changeDirectionTimer > 120) {
self.direction = Math.random() * Math.PI * 2;
self.changeDirectionTimer = 0;
}
self.x += Math.cos(self.direction) * self.speed;
self.y += Math.sin(self.direction) * self.speed;
// Keep creatures in bounds
if (self.x < 50 || self.x > 1998) {
self.direction = Math.PI - self.direction;
}
if (self.y < 50 || self.y > 2682) {
self.direction = -self.direction;
}
};
return self;
});
var Crystal = Container.expand(function () {
var self = Container.call(this);
var crystalGraphics = self.attachAsset('crystal', {
anchorX: 0.5,
anchorY: 0.5
});
self.collected = false;
self.glowDirection = 1;
self.update = function () {
if (!self.collected) {
crystalGraphics.alpha += 0.02 * self.glowDirection;
if (crystalGraphics.alpha >= 1) {
self.glowDirection = -1;
} else if (crystalGraphics.alpha <= 0.3) {
self.glowDirection = 1;
}
}
};
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
var playerGraphics = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 4;
self.targetX = null;
self.targetY = null;
self.isMoving = false;
self.moveTo = function (x, y) {
self.targetX = x;
self.targetY = y;
self.isMoving = true;
};
self.update = function () {
if (self.isMoving && self.targetX !== null && self.targetY !== null) {
var dx = self.targetX - self.x;
var dy = self.targetY - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < self.speed) {
self.x = self.targetX;
self.y = self.targetY;
self.isMoving = false;
} else {
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
}
}
};
return self;
});
var Thorn = Container.expand(function () {
var self = Container.call(this);
var thornGraphics = self.attachAsset('thorn', {
anchorX: 0.5,
anchorY: 0.5
});
return self;
});
var Tree = Container.expand(function () {
var self = Container.call(this);
var treeGraphics = self.attachAsset('tree', {
anchorX: 0.5,
anchorY: 1.0
});
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x2d5016
});
/****
* Game Code
****/
// Game variables
var player;
var crystals = [];
var berries = [];
var trees = [];
var thorns = [];
var creatures = [];
var areasDiscovered = 0;
var itemsCollected = 0;
// UI Elements
var scoreTxt = new Text2('Score: 0', {
size: 80,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0, 0);
LK.gui.topRight.addChild(scoreTxt);
var itemsTxt = new Text2('Items: 0', {
size: 60,
fill: 0xFFFFFF
});
itemsTxt.anchor.set(0, 0);
itemsTxt.y = 100;
LK.gui.topRight.addChild(itemsTxt);
// Inventory button
var inventoryBtn = new Text2('BAG', {
size: 60,
fill: 0xFFFFFF
});
inventoryBtn.anchor.set(0, 0);
inventoryBtn.x = 120;
inventoryBtn.y = 20;
LK.gui.topLeft.addChild(inventoryBtn);
// Map button
var mapBtn = new Text2('MAP', {
size: 60,
fill: 0xFFFFFF
});
mapBtn.anchor.set(0, 0);
mapBtn.x = 120;
mapBtn.y = 90;
LK.gui.topLeft.addChild(mapBtn);
// Inventory state
var inventoryOpen = false;
var inventoryPanel = null;
// Map state
var mapOpen = false;
var mapPanel = null;
// Create ground
var ground = game.addChild(LK.getAsset('ground', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0
}));
// Create player
player = game.addChild(new Player());
player.x = 1024;
player.y = 1366;
// Generate forest elements
function generateForestElements() {
// Create trees
for (var i = 0; i < 15; i++) {
var tree = new Tree();
tree.x = Math.random() * 1900 + 100;
tree.y = Math.random() * 2500 + 200;
trees.push(tree);
game.addChild(tree);
}
// Create crystals
for (var i = 0; i < 8; i++) {
var crystal = new Crystal();
crystal.x = Math.random() * 1800 + 200;
crystal.y = Math.random() * 2400 + 200;
crystals.push(crystal);
game.addChild(crystal);
}
// Create berries
for (var i = 0; i < 12; i++) {
var berry = new Berry();
berry.x = Math.random() * 1800 + 200;
berry.y = Math.random() * 2400 + 200;
berries.push(berry);
game.addChild(berry);
}
// Create thorns
for (var i = 0; i < 6; i++) {
var thorn = new Thorn();
thorn.x = Math.random() * 1800 + 200;
thorn.y = Math.random() * 2400 + 200;
thorns.push(thorn);
game.addChild(thorn);
}
// Create creatures
for (var i = 0; i < 4; i++) {
var creature = new Creature();
creature.x = Math.random() * 1600 + 300;
creature.y = Math.random() * 2200 + 300;
creatures.push(creature);
game.addChild(creature);
}
}
generateForestElements();
// Touch controls
game.down = function (x, y, obj) {
player.moveTo(x, y);
};
// Inventory button click handler
inventoryBtn.down = function (x, y, obj) {
if (!inventoryOpen) {
// Create inventory panel
inventoryPanel = game.addChild(LK.getAsset('ground', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1366,
scaleX: 0.8,
scaleY: 0.6
}));
inventoryPanel.tint = 0x654321;
inventoryPanel.alpha = 0.9;
// Add inventory title
var invTitle = new Text2('INVENTORY', {
size: 80,
fill: 0xFFFFFF
});
invTitle.anchor.set(0.5, 0);
invTitle.x = 1024;
invTitle.y = 900;
game.addChild(invTitle);
inventoryPanel.titleText = invTitle;
// Add close button
var closeBtn = new Text2('CLOSE', {
size: 60,
fill: 0xFF4444
});
closeBtn.anchor.set(0.5, 0.5);
closeBtn.x = 1024;
closeBtn.y = 1800;
closeBtn.down = function () {
inventoryPanel.destroy();
inventoryPanel.titleText.destroy();
this.destroy();
inventoryOpen = false;
inventoryPanel = null;
};
game.addChild(closeBtn);
inventoryPanel.closeBtn = closeBtn;
inventoryOpen = true;
} else {
// Close inventory
if (inventoryPanel) {
inventoryPanel.destroy();
inventoryPanel.titleText.destroy();
inventoryPanel.closeBtn.destroy();
inventoryOpen = false;
inventoryPanel = null;
}
}
};
// Map button click handler
mapBtn.down = function (x, y, obj) {
if (!mapOpen) {
// Create map panel
mapPanel = game.addChild(LK.getAsset('ground', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1366,
scaleX: 0.9,
scaleY: 0.8
}));
mapPanel.tint = 0x8B4513;
mapPanel.alpha = 0.95;
// Add map title
var mapTitle = new Text2('FOREST MAP', {
size: 80,
fill: 0xFFFFFF
});
mapTitle.anchor.set(0.5, 0);
mapTitle.x = 1024;
mapTitle.y = 800;
game.addChild(mapTitle);
mapPanel.titleText = mapTitle;
// Add player position indicator
var playerDot = game.addChild(LK.getAsset('crystal', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024 + (player.x - 1024) * 0.4,
y: 1366 + (player.y - 1366) * 0.3,
scaleX: 0.8,
scaleY: 0.8
}));
playerDot.tint = 0x00FF00;
mapPanel.playerDot = playerDot;
// Add close button
var closeMapBtn = new Text2('CLOSE', {
size: 60,
fill: 0xFF4444
});
closeMapBtn.anchor.set(0.5, 0.5);
closeMapBtn.x = 1024;
closeMapBtn.y = 1900;
closeMapBtn.down = function () {
mapPanel.destroy();
mapPanel.titleText.destroy();
mapPanel.playerDot.destroy();
this.destroy();
mapOpen = false;
mapPanel = null;
};
game.addChild(closeMapBtn);
mapPanel.closeBtn = closeMapBtn;
mapOpen = true;
} else {
// Close map
if (mapPanel) {
mapPanel.destroy();
mapPanel.titleText.destroy();
mapPanel.playerDot.destroy();
mapPanel.closeBtn.destroy();
mapOpen = false;
mapPanel = null;
}
}
};
// Update score display
function updateScore() {
scoreTxt.setText('Score: ' + LK.getScore());
itemsTxt.setText('Items: ' + itemsCollected);
}
// Check collisions and interactions
game.update = function () {
// Check crystal collection
for (var i = crystals.length - 1; i >= 0; i--) {
var crystal = crystals[i];
if (!crystal.collected && player.intersects(crystal)) {
crystal.collected = true;
crystal.alpha = 0;
itemsCollected++;
LK.setScore(LK.getScore() + 10);
updateScore();
LK.getSound('collect').play();
crystals.splice(i, 1);
crystal.destroy();
}
}
// Check berry collection
for (var i = berries.length - 1; i >= 0; i--) {
var berry = berries[i];
if (!berry.collected && player.intersects(berry)) {
berry.collected = true;
berry.alpha = 0;
itemsCollected++;
LK.setScore(LK.getScore() + 5);
updateScore();
LK.getSound('collect').play();
berries.splice(i, 1);
berry.destroy();
}
}
// Check thorn collisions
for (var i = 0; i < thorns.length; i++) {
var thorn = thorns[i];
if (player.intersects(thorn)) {
// Push player away from thorn
var dx = player.x - thorn.x;
var dy = player.y - thorn.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
player.x = thorn.x + dx / distance * 60;
player.y = thorn.y + dy / distance * 60;
}
player.isMoving = false;
LK.effects.flashObject(player, 0xff0000, 500);
LK.getSound('danger').play();
}
}
// Check creature encounters
for (var i = 0; i < creatures.length; i++) {
var creature = creatures[i];
if (player.intersects(creature)) {
// Push player away from creature
var dx = player.x - creature.x;
var dy = player.y - creature.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
player.x = creature.x + dx / distance * 70;
player.y = creature.y + dy / distance * 70;
}
player.isMoving = false;
LK.effects.flashObject(player, 0x8b4513, 500);
LK.setScore(Math.max(0, LK.getScore() - 2));
updateScore();
LK.getSound('danger').play();
}
}
// Check tree collisions (blocking)
for (var i = 0; i < trees.length; i++) {
var tree = trees[i];
if (player.intersects(tree)) {
// Push player away from tree (account for tree anchor being at bottom center)
var dx = player.x - tree.x;
var dy = player.y - (tree.y - tree.height / 2); // Adjust for tree anchor point
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
// Increase push distance to ensure player stays outside tree bounds
player.x = tree.x + dx / distance * (tree.width / 2 + 35);
player.y = tree.y - tree.height / 2 + dy / distance * (tree.height / 2 + 35);
}
player.isMoving = false;
}
}
// Keep player in bounds
if (player.x < 30) player.x = 30;
if (player.x > 2018) player.x = 2018;
if (player.y < 30) player.y = 30;
if (player.y > 2702) player.y = 2702;
// Check win condition
if (itemsCollected >= 15) {
LK.showYouWin();
}
};
// Play ambient forest music
LK.playMusic('forestAmbient');
// Initialize score display
updateScore();