User prompt
But that time I can't grab and drag figure. Pls give that function back. And pls fix that bug "some figures stuck on the way and can't get to the ground" ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Super. Pls pls slow the speed a little bit. And increase a little bit sensitivity of screen that allow to grab a figure. But it's not bad yet. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Delete cursor asset but enhance the sensitivity of the screen that when player puts finger on figure that means player can control and drag that figure immediately. And add different shapes ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Cursor & Drag System (English for Developer) 1. Cursor (Pointer) System Display a visible arrow/cursor on the screen. The player can hover the cursor over a shape and then click-drag to move it. 2. Precise Drag Targeting Only the shape directly under the cursor should be draggable. Ensure smooth transition between selecting one shape and another. 3. Natural Falling All shapes should continue falling until they touch the ground or another block. Gravity should handle the fall completely, without interruption. 4. Drag Behavior Once the player releases a shape, they should be able to immediately drag another one without delay. Dragging should feel responsive and fluid, with no input lag or blocking ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
🔧 Updated Fixes & Rules (Technical English) 1. Touch-Based Movement Only A shape should only move if the user is directly touching and dragging it. No shape should move indirectly (e.g., when another shape is touched). 2. Collision Rule Shapes must not pass through each other. Implement solid collision detection to prevent overlap during movement and stacking. 3. Bomb Shape Design The bomb block must visually resemble a bomb (e.g., circular with a fuse or explosion symbol). It should be clearly different from regular blocks in shape and appearance. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Grid & Match Rules (For Developer) 1. Grid Size The game grid is 24 columns (left to right) and 24 rows (top to bottom). 2. Same-Color Match Rule If 4 or more blocks of the same color align horizontally, they should explode and give points. 3. Two-Color Match Rule If 8 or more blocks are aligned horizontally but consist of exactly two colors, they should also explode. 4. Three-Color Full Line Rule If a full row (24 blocks) contains three or more different colors, the entire row should explode and give bonus points. --- 🛠 Bug Fix Command (Touch Control Issue) Fix Touch Targeting: When dragging a shape, only the selected shape should move. Prevent cases where dragging one figure moves a different one. Ensure correct input mapping between touch position and selected object. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Please fix the bug: 'TypeError: setTimeout is not a function' in or related to this line: 'setTimeout(function () {' Line Number: 391
User prompt
🔧 Additional Gameplay Instructions (2D) 1. Continuous Side Movement On touch/drag, the shape moves continuously left or right across the screen, not just one cell per tap. 2. Increase Drag Speed Make the swipe/drag movement faster and smoother. 3. Random Spawn Positions Shapes should spawn not only from the top center, but also randomly from different horizontal positions at the top. --- 🧩 2D Tetris Shapes (Reference) I-shape: #### O-shape: ## ## T-shape: ### # L-shape: # # ## J-shape: # # ## S-shape: ## ## Z-shape: ## ## ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Please fix the bug: 'stability is not defined' in or related to this line: 'stabilityText.setText('Stability: ' + Math.round(stability) + '%');' Line Number: 248
User prompt
🧱 Core Mechanics (Short Version) 1. Shape Types: Not only squares – use Tetris-style shapes (L, T, Z, I, etc.). 2. Stacking: Shapes fall from the top and stack when they land on others or the ground. 3. No Mid-Fall Control: Once falling, shapes can't be moved or rotated. 4. Row Clearing: Full horizontal rows disappear and give points. 5. Speed Variations: Some shapes fall faster for challenge. 6. Special Blocks: 🎁 Gift = Bonus points 💣 Bomb = Destroys nearby blocks 🔄 Wildcard = Fills nearest gap ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
But I think you can add that function that allows player to grab and drag figures. And increase different figures. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Pls add that skills that . Player can move figures with finger tap and add more complex figures. And then when blocks and figures fall down they don't disappear. A Player with his hands can move, flip to right, left, forward and backward and etc.
Code edit (1 edits merged)
Please save this source code
User prompt
ShapeStack 3D
Initial prompt
🧱 Game Concept: ShapeStack 3D Genre: 3D Physics-Based Construction Game --- 🌟 Overview: ShapeStack 3D is a creative 3D construction game where geometric figures (blocks) fall slowly from the sky. The player must catch and place them to build larger structures. The more symmetrical, balanced, and space-efficient the structure is, the more stable it becomes — unlocking the ability to build higher, stronger, and more complex objects. --- 🧩 Core Gameplay: Falling Shapes: Random 3D Lego-like shapes (cubes, pyramids, L-blocks, etc.) slowly fall from the sky. Catch and Place: The player collects the falling shapes before they hit the ground. Build Freely: The player can stack shapes on top of each other to construct buildings, sculptures, machines, or any object. Stability Score: The game analyzes how well-aligned, symmetrical, and dense the structure is. More balanced structures = higher stability More stability = more build layers unlocked --- 🎯 Objective: Build the tallest and most stable structure possible. Unlock new building materials and tools. Earn bonus points for symmetry, creative use of space, and aesthetic design. --- 🧠 Strategy Mechanics: Gameplay Element Effect Symmetry Increases stability and score Gaps/Holes Reduces structural integrity Perfect Fit Bonus points and glowing effects Tilting/Unstable build Can cause collapse unless reinforced Advanced tools Unlock after score thresholds (e.g., glue, rotation tool) --- 🖥️ User Interface: Left Panel: Current Score and Stability Meter Right Panel: Inventory of caught shapes Bottom: Controls (Rotate, Move, Place) Top: Height indicator / Build progress --- ⚙️ Technical Notes (for development): Engine: Unity (preferred for 3D and physics) Language: C# Camera: Free orbit or third-person top-down view Physics: Realistic gravity and collision (Rigidbody, colliders) Build Grid: Optional snap-to-grid feature for clean construction Save System: Ability to save and reload structures --- 🔓 Bonus Features (optional): Sandbox mode: Unlimited shapes and no time limit Challenge mode: Build within specific time or block limits Multiplayer mode: Co-build or compete for stability Creative gallery: Share your best creations online
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ var FallingShape = Container.expand(function (shapeType) { var self = Container.call(this); self.shapeType = shapeType; self.fallSpeed = 2; self.caught = false; self.placed = false; var shapeGraphic = self.attachAsset(shapeType, { anchorX: 0.5, anchorY: 0.5 }); // Add slight rotation for 3D effect shapeGraphic.rotation = Math.random() * 0.2 - 0.1; self.update = function () { if (!self.caught && !self.placed) { self.y += self.fallSpeed; // Check if hit ground if (self.y > groundY - 40) { self.destroy(); var index = fallingShapes.indexOf(self); if (index > -1) { fallingShapes.splice(index, 1); } } } }; self["catch"] = function () { if (!self.caught) { self.caught = true; LK.getSound('catch').play(); inventory.push(self); self.parent.removeChild(self); updateInventoryDisplay(); } }; return self; }); var PlacedShape = Container.expand(function (shapeType) { var self = Container.call(this); self.shapeType = shapeType; self.isStable = true; var shapeGraphic = self.attachAsset(shapeType, { anchorX: 0.5, anchorY: 0.5 }); return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x87CEEB }); /**** * Game Code ****/ var fallingShapes = []; var placedShapes = []; var inventory = []; var selectedShape = null; var isDragging = false; var dragOffset = { x: 0, y: 0 }; var score = 0; var stability = 100; var maxHeight = 0; var groundY = 2400; var shapeTypes = ['cube', 'pyramid', 'lblock']; var nextShapeTimer = 0; var shapeSpawnDelay = 120; // 2 seconds at 60fps // Create ground var ground = game.addChild(LK.getAsset('ground', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: groundY })); // Create UI elements var scoreText = new Text2('Score: 0', { size: 40, fill: 0xFFFFFF }); scoreText.anchor.set(0, 0); scoreText.x = 120; scoreText.y = 120; LK.gui.topLeft.addChild(scoreText); var stabilityText = new Text2('Stability: 100%', { size: 40, fill: 0xFFFFFF }); stabilityText.anchor.set(0, 0); stabilityText.x = 120; stabilityText.y = 180; LK.gui.topLeft.addChild(stabilityText); // Stability bar background var stabilityBarBg = LK.getAsset('stabilityBarBg', { anchorX: 0, anchorY: 0, x: 120, y: 220 }); LK.gui.topLeft.addChild(stabilityBarBg); // Stability bar var stabilityBar = LK.getAsset('stabilityBar', { anchorX: 0, anchorY: 0, x: 120, y: 220 }); LK.gui.topLeft.addChild(stabilityBar); var inventoryText = new Text2('Inventory: 0', { size: 40, fill: 0xFFFFFF }); inventoryText.anchor.set(1, 0); LK.gui.topRight.addChild(inventoryText); var heightText = new Text2('Height: 0', { size: 40, fill: 0xFFFFFF }); heightText.anchor.set(0, 0); heightText.x = 120; heightText.y = 260; LK.gui.topLeft.addChild(heightText); function spawnShape() { var shapeType = shapeTypes[Math.floor(Math.random() * shapeTypes.length)]; var shape = new FallingShape(shapeType); shape.x = Math.random() * 1800 + 124; // Keep away from edges shape.y = -80; fallingShapes.push(shape); game.addChild(shape); } function updateInventoryDisplay() { inventoryText.setText('Inventory: ' + inventory.length); } function updateScore() { scoreText.setText('Score: ' + score); } function updateStability() { stabilityText.setText('Stability: ' + Math.round(stability) + '%'); var stabilityPercent = Math.max(0, Math.min(1, stability / 100)); stabilityBar.width = 300 * stabilityPercent; // Color based on stability if (stability > 70) { stabilityBar.tint = 0x00FF00; // Green } else if (stability > 30) { stabilityBar.tint = 0xFFFF00; // Yellow } else { stabilityBar.tint = 0xFF0000; // Red } } function updateHeight() { var currentHeight = 0; for (var i = 0; i < placedShapes.length; i++) { var shapeBottom = placedShapes[i].y + 40; var heightFromGround = groundY - shapeBottom; if (heightFromGround > currentHeight) { currentHeight = heightFromGround; } } maxHeight = Math.max(maxHeight, currentHeight); heightText.setText('Height: ' + Math.round(maxHeight / 80)); } function calculateStability() { if (placedShapes.length === 0) { stability = 100; return; } var totalStability = 0; var centerX = 1024; for (var i = 0; i < placedShapes.length; i++) { var shape = placedShapes[i]; var distanceFromCenter = Math.abs(shape.x - centerX); var heightFactor = (groundY - shape.y) / 80; // Shapes closer to center and lower are more stable var shapeStability = 100 - distanceFromCenter / 10 - heightFactor * 2; totalStability += Math.max(0, shapeStability); } stability = Math.max(0, Math.min(100, totalStability / placedShapes.length)); // Check for collapse if (stability < 20 && placedShapes.length > 3) { triggerCollapse(); } } function triggerCollapse() { LK.getSound('collapse').play(); // Remove unstable shapes for (var i = placedShapes.length - 1; i >= 0; i--) { if (Math.random() < 0.3) { // 30% chance each shape collapses var shape = placedShapes[i]; tween(shape, { alpha: 0, y: shape.y + 100 }, { duration: 500, onFinish: function onFinish() { shape.destroy(); } }); placedShapes.splice(i, 1); } } score = Math.max(0, score - 50); updateScore(); } function placeShape(shape, x, y) { if (inventory.length === 0) return; var inventoryShape = inventory.shift(); var placedShape = new PlacedShape(inventoryShape.shapeType); placedShape.x = x; placedShape.y = y; placedShapes.push(placedShape); game.addChild(placedShape); LK.getSound('place').play(); score += 10; // Bonus for good placement var centerX = 1024; var distanceFromCenter = Math.abs(x - centerX); if (distanceFromCenter < 100) { score += 5; // Bonus for center placement } updateScore(); updateInventoryDisplay(); calculateStability(); updateHeight(); inventoryShape.destroy(); } // Event handlers game.down = function (x, y, obj) { // Check if clicking on falling shape for (var i = 0; i < fallingShapes.length; i++) { var shape = fallingShapes[i]; if (shape.intersects({ x: x, y: y, width: 1, height: 1 })) { shape["catch"](); fallingShapes.splice(i, 1); break; } } // Check if placing from inventory if (inventory.length > 0 && y > groundY - 200) { placeShape(null, x, Math.max(groundY - 40, y)); } }; game.update = function () { // Spawn new shapes nextShapeTimer++; if (nextShapeTimer >= shapeSpawnDelay) { spawnShape(); nextShapeTimer = 0; // Gradually increase spawn rate if (shapeSpawnDelay > 60) { shapeSpawnDelay -= 0.5; } } // Update stability periodically if (LK.ticks % 30 === 0) { calculateStability(); updateStability(); } // Check win condition if (maxHeight > 800) { // About 10 blocks high LK.showYouWin(); } // Check game over condition if (stability < 10 && placedShapes.length > 0) { LK.showGameOver(); } }; // Initialize display updateScore(); updateStability(); updateInventoryDisplay(); updateHeight();
===================================================================
--- original.js
+++ change.js
@@ -1,6 +1,291 @@
-/****
+/****
+* Plugins
+****/
+var tween = LK.import("@upit/tween.v1");
+
+/****
+* Classes
+****/
+var FallingShape = Container.expand(function (shapeType) {
+ var self = Container.call(this);
+ self.shapeType = shapeType;
+ self.fallSpeed = 2;
+ self.caught = false;
+ self.placed = false;
+ var shapeGraphic = self.attachAsset(shapeType, {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ // Add slight rotation for 3D effect
+ shapeGraphic.rotation = Math.random() * 0.2 - 0.1;
+ self.update = function () {
+ if (!self.caught && !self.placed) {
+ self.y += self.fallSpeed;
+ // Check if hit ground
+ if (self.y > groundY - 40) {
+ self.destroy();
+ var index = fallingShapes.indexOf(self);
+ if (index > -1) {
+ fallingShapes.splice(index, 1);
+ }
+ }
+ }
+ };
+ self["catch"] = function () {
+ if (!self.caught) {
+ self.caught = true;
+ LK.getSound('catch').play();
+ inventory.push(self);
+ self.parent.removeChild(self);
+ updateInventoryDisplay();
+ }
+ };
+ return self;
+});
+var PlacedShape = Container.expand(function (shapeType) {
+ var self = Container.call(this);
+ self.shapeType = shapeType;
+ self.isStable = true;
+ var shapeGraphic = self.attachAsset(shapeType, {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ return self;
+});
+
+/****
* Initialize Game
-****/
+****/
var game = new LK.Game({
- backgroundColor: 0x000000
-});
\ No newline at end of file
+ backgroundColor: 0x87CEEB
+});
+
+/****
+* Game Code
+****/
+var fallingShapes = [];
+var placedShapes = [];
+var inventory = [];
+var selectedShape = null;
+var isDragging = false;
+var dragOffset = {
+ x: 0,
+ y: 0
+};
+var score = 0;
+var stability = 100;
+var maxHeight = 0;
+var groundY = 2400;
+var shapeTypes = ['cube', 'pyramid', 'lblock'];
+var nextShapeTimer = 0;
+var shapeSpawnDelay = 120; // 2 seconds at 60fps
+// Create ground
+var ground = game.addChild(LK.getAsset('ground', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ x: 1024,
+ y: groundY
+}));
+// Create UI elements
+var scoreText = new Text2('Score: 0', {
+ size: 40,
+ fill: 0xFFFFFF
+});
+scoreText.anchor.set(0, 0);
+scoreText.x = 120;
+scoreText.y = 120;
+LK.gui.topLeft.addChild(scoreText);
+var stabilityText = new Text2('Stability: 100%', {
+ size: 40,
+ fill: 0xFFFFFF
+});
+stabilityText.anchor.set(0, 0);
+stabilityText.x = 120;
+stabilityText.y = 180;
+LK.gui.topLeft.addChild(stabilityText);
+// Stability bar background
+var stabilityBarBg = LK.getAsset('stabilityBarBg', {
+ anchorX: 0,
+ anchorY: 0,
+ x: 120,
+ y: 220
+});
+LK.gui.topLeft.addChild(stabilityBarBg);
+// Stability bar
+var stabilityBar = LK.getAsset('stabilityBar', {
+ anchorX: 0,
+ anchorY: 0,
+ x: 120,
+ y: 220
+});
+LK.gui.topLeft.addChild(stabilityBar);
+var inventoryText = new Text2('Inventory: 0', {
+ size: 40,
+ fill: 0xFFFFFF
+});
+inventoryText.anchor.set(1, 0);
+LK.gui.topRight.addChild(inventoryText);
+var heightText = new Text2('Height: 0', {
+ size: 40,
+ fill: 0xFFFFFF
+});
+heightText.anchor.set(0, 0);
+heightText.x = 120;
+heightText.y = 260;
+LK.gui.topLeft.addChild(heightText);
+function spawnShape() {
+ var shapeType = shapeTypes[Math.floor(Math.random() * shapeTypes.length)];
+ var shape = new FallingShape(shapeType);
+ shape.x = Math.random() * 1800 + 124; // Keep away from edges
+ shape.y = -80;
+ fallingShapes.push(shape);
+ game.addChild(shape);
+}
+function updateInventoryDisplay() {
+ inventoryText.setText('Inventory: ' + inventory.length);
+}
+function updateScore() {
+ scoreText.setText('Score: ' + score);
+}
+function updateStability() {
+ stabilityText.setText('Stability: ' + Math.round(stability) + '%');
+ var stabilityPercent = Math.max(0, Math.min(1, stability / 100));
+ stabilityBar.width = 300 * stabilityPercent;
+ // Color based on stability
+ if (stability > 70) {
+ stabilityBar.tint = 0x00FF00; // Green
+ } else if (stability > 30) {
+ stabilityBar.tint = 0xFFFF00; // Yellow
+ } else {
+ stabilityBar.tint = 0xFF0000; // Red
+ }
+}
+function updateHeight() {
+ var currentHeight = 0;
+ for (var i = 0; i < placedShapes.length; i++) {
+ var shapeBottom = placedShapes[i].y + 40;
+ var heightFromGround = groundY - shapeBottom;
+ if (heightFromGround > currentHeight) {
+ currentHeight = heightFromGround;
+ }
+ }
+ maxHeight = Math.max(maxHeight, currentHeight);
+ heightText.setText('Height: ' + Math.round(maxHeight / 80));
+}
+function calculateStability() {
+ if (placedShapes.length === 0) {
+ stability = 100;
+ return;
+ }
+ var totalStability = 0;
+ var centerX = 1024;
+ for (var i = 0; i < placedShapes.length; i++) {
+ var shape = placedShapes[i];
+ var distanceFromCenter = Math.abs(shape.x - centerX);
+ var heightFactor = (groundY - shape.y) / 80;
+ // Shapes closer to center and lower are more stable
+ var shapeStability = 100 - distanceFromCenter / 10 - heightFactor * 2;
+ totalStability += Math.max(0, shapeStability);
+ }
+ stability = Math.max(0, Math.min(100, totalStability / placedShapes.length));
+ // Check for collapse
+ if (stability < 20 && placedShapes.length > 3) {
+ triggerCollapse();
+ }
+}
+function triggerCollapse() {
+ LK.getSound('collapse').play();
+ // Remove unstable shapes
+ for (var i = placedShapes.length - 1; i >= 0; i--) {
+ if (Math.random() < 0.3) {
+ // 30% chance each shape collapses
+ var shape = placedShapes[i];
+ tween(shape, {
+ alpha: 0,
+ y: shape.y + 100
+ }, {
+ duration: 500,
+ onFinish: function onFinish() {
+ shape.destroy();
+ }
+ });
+ placedShapes.splice(i, 1);
+ }
+ }
+ score = Math.max(0, score - 50);
+ updateScore();
+}
+function placeShape(shape, x, y) {
+ if (inventory.length === 0) return;
+ var inventoryShape = inventory.shift();
+ var placedShape = new PlacedShape(inventoryShape.shapeType);
+ placedShape.x = x;
+ placedShape.y = y;
+ placedShapes.push(placedShape);
+ game.addChild(placedShape);
+ LK.getSound('place').play();
+ score += 10;
+ // Bonus for good placement
+ var centerX = 1024;
+ var distanceFromCenter = Math.abs(x - centerX);
+ if (distanceFromCenter < 100) {
+ score += 5; // Bonus for center placement
+ }
+ updateScore();
+ updateInventoryDisplay();
+ calculateStability();
+ updateHeight();
+ inventoryShape.destroy();
+}
+// Event handlers
+game.down = function (x, y, obj) {
+ // Check if clicking on falling shape
+ for (var i = 0; i < fallingShapes.length; i++) {
+ var shape = fallingShapes[i];
+ if (shape.intersects({
+ x: x,
+ y: y,
+ width: 1,
+ height: 1
+ })) {
+ shape["catch"]();
+ fallingShapes.splice(i, 1);
+ break;
+ }
+ }
+ // Check if placing from inventory
+ if (inventory.length > 0 && y > groundY - 200) {
+ placeShape(null, x, Math.max(groundY - 40, y));
+ }
+};
+game.update = function () {
+ // Spawn new shapes
+ nextShapeTimer++;
+ if (nextShapeTimer >= shapeSpawnDelay) {
+ spawnShape();
+ nextShapeTimer = 0;
+ // Gradually increase spawn rate
+ if (shapeSpawnDelay > 60) {
+ shapeSpawnDelay -= 0.5;
+ }
+ }
+ // Update stability periodically
+ if (LK.ticks % 30 === 0) {
+ calculateStability();
+ updateStability();
+ }
+ // Check win condition
+ if (maxHeight > 800) {
+ // About 10 blocks high
+ LK.showYouWin();
+ }
+ // Check game over condition
+ if (stability < 10 && placedShapes.length > 0) {
+ LK.showGameOver();
+ }
+};
+// Initialize display
+updateScore();
+updateStability();
+updateInventoryDisplay();
+updateHeight();
\ No newline at end of file