User prompt
add a button that opens the inventory and add a button that opens a new map
User prompt
fix the bug where if the player touches the tree he would go inside it
Code edit (1 edits merged)
Please save this source code
User prompt
Forest Explorer
Initial prompt
make me a 2D explorer game that takes place in the forest
/**** * 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();
===================================================================
--- original.js
+++ change.js
@@ -143,8 +143,32 @@
});
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,
@@ -202,8 +226,127 @@
// 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);