Advertisement
nrzmalik

Game JavaScript Code

Jun 22nd, 2025 (edited)
275
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
JavaScript 14.02 KB | Source Code | 0 0
  1. //Game Class - Reusable for Multiple Slides
  2. class Game {
  3.     constructor(playerObjectId, enemy1ObjectId, enemy2ObjectId, overlayObjectId) {
  4.         // Get object references
  5.         this.question_Bot = object(playerObjectId);
  6.         this.enemy_1 = object(enemy1ObjectId);
  7.         this.enemy_2 = object(enemy2ObjectId);
  8.         this.overlay = object(overlayObjectId); // Movement boundary overlay
  9.        
  10.         // Game settings
  11.         this.MOVE_SPEED = 8; // pixels per frame
  12.         this.COLLISION_THRESHOLD = 35; // collision detection distance (reduced for better precision)
  13.        
  14.         // Track key states (only left and right)
  15.         this.keys = {
  16.             left: false,
  17.             right: false
  18.         };
  19.        
  20.         // Track collision states to prevent multiple triggers
  21.         this.collisionStates = {
  22.             enemy_1: false,
  23.             enemy_2: false
  24.         };
  25.        
  26.         // Game state
  27.         this.gameComplete = false;
  28.         this.gameStarted = false;
  29.         this.initializationComplete = false;
  30.        
  31.         // Store object IDs for variable names
  32.         this.enemy1ObjectId = enemy1ObjectId;
  33.         this.enemy2ObjectId = enemy2ObjectId;
  34.        
  35.         // Track initial positions to prevent startup collisions
  36.         this.initialPositions = {
  37.             player: null,
  38.             enemy_1: null,
  39.             enemy_2: null
  40.         };
  41.     }
  42.    
  43.     // Calculate distance between two objects (with fallback for dimensions)
  44.     getDistance(obj1, obj2) {
  45.         // Use fallback dimensions if width/height not available
  46.         const obj1Width = obj1.width || 50;
  47.         const obj1Height = obj1.height || 50;
  48.         const obj2Width = obj2.width || 50;
  49.         const obj2Height = obj2.height || 50;
  50.        
  51.         const dx = (obj1.x + obj1Width / 2) - (obj2.x + obj2Width / 2);
  52.         const dy = (obj1.y + obj1Height / 2) - (obj2.y + obj2Height / 2);
  53.         return Math.sqrt(dx * dx + dy * dy);
  54.     }
  55.    
  56.     // More precise collision detection using smaller collision boxes
  57.     checkBoundingBoxCollision(obj1, obj2) {
  58.         const obj1Width = obj1.width || 50;
  59.         const obj1Height = obj1.height || 50;
  60.         const obj2Width = obj2.width || 50;
  61.         const obj2Height = obj2.height || 50;
  62.        
  63.         // Use smaller collision boxes (80% of actual size) for more precise detection
  64.         const collisionMargin = 0.2; // 20% margin
  65.         const obj1CollisionWidth = obj1Width * (1 - collisionMargin);
  66.         const obj1CollisionHeight = obj1Height * (1 - collisionMargin);
  67.         const obj2CollisionWidth = obj2Width * (1 - collisionMargin);
  68.         const obj2CollisionHeight = obj2Height * (1 - collisionMargin);
  69.        
  70.         // Center the collision boxes
  71.         const obj1CollisionX = obj1.x + (obj1Width - obj1CollisionWidth) / 2;
  72.         const obj1CollisionY = obj1.y + (obj1Height - obj1CollisionHeight) / 2;
  73.         const obj2CollisionX = obj2.x + (obj2Width - obj2CollisionWidth) / 2;
  74.         const obj2CollisionY = obj2.y + (obj2Height - obj2CollisionHeight) / 2;
  75.        
  76.         return obj1CollisionX < obj2CollisionX + obj2CollisionWidth &&
  77.                obj1CollisionX + obj1CollisionWidth > obj2CollisionX &&
  78.                obj1CollisionY < obj2CollisionY + obj2CollisionHeight &&
  79.                obj1CollisionY + obj1CollisionHeight > obj2CollisionY;
  80.     }
  81.    
  82.     // Animate and hide enemy when hit
  83.     animateAndHideEnemy(enemy, enemyName, variableName) {
  84.        
  85.         // Add hit animation using Storyline's animate function
  86.        /* addToTimeline(
  87.             enemy.animate(
  88.                 [
  89.                     { transform: 'scale(1) rotate(0deg)', opacity: '1' },
  90.                     { transform: 'scale(1.5) rotate(180deg)', opacity: '0.5' },
  91.                     { transform: 'scale(0.1) rotate(360deg)', opacity: '0' }
  92.                 ],
  93.                 {
  94.                     duration: 800, // Animation duration in milliseconds
  95.                     easing: 'ease-in-out',
  96.                     fill: 'forwards' // Keep the final state after animation
  97.                 }
  98.             )
  99.         );*/
  100.        
  101.         // Set variable after animation completes
  102.         setTimeout(() => {
  103.             // Set the Storyline variable to true after animation
  104.             setVar(variableName, true);
  105.         }, 100);
  106.     }
  107.    
  108.     // Hide all remaining enemies
  109.     hideAllEnemies() {
  110.         const enemies = [
  111.             { obj: this.enemy_1, name: 'enemy_1' },
  112.             { obj: this.enemy_2, name: 'enemy_2' }
  113.         ];
  114.        
  115.         enemies.forEach(enemy => {
  116.             // Add fade out animation for remaining enemies
  117.             addToTimeline(
  118.                 enemy.obj.animate(
  119.                     [
  120.                         { opacity: '1' },
  121.                         { opacity: '0' }
  122.                     ],
  123.                     {
  124.                         duration: 10,
  125.                         easing: 'ease-out',
  126.                         fill: 'forwards'
  127.                     }
  128.                 )
  129.             );
  130.            
  131.             // Animation complete - objects can be manually hidden via Storyline
  132.             // No automatic hiding - let Storyline handle visibility
  133.         });
  134.        
  135.         console.log("Game Complete! All enemies eliminated!");
  136.     }
  137.    
  138.     // Store initial positions and check for overlaps
  139.     storeInitialPositions() {
  140.         this.initialPositions.player = { x: this.question_Bot.x, y: this.question_Bot.y };
  141.         this.initialPositions.enemy_1 = { x: this.enemy_1.x, y: this.enemy_1.y };
  142.         this.initialPositions.enemy_2 = { x: this.enemy_2.x, y: this.enemy_2.y };
  143.        
  144.         // Check if any objects are overlapping at start
  145.         const startupCollision1 = this.getDistance(this.question_Bot, this.enemy_1) < this.COLLISION_THRESHOLD;
  146.         const startupCollision2 = this.getDistance(this.question_Bot, this.enemy_2) < this.COLLISION_THRESHOLD;
  147.        
  148.         if (startupCollision1 || startupCollision2) {
  149.             console.warn("Warning: Objects are overlapping at startup! Consider repositioning them.");
  150.             console.log("Player position:", this.question_Bot.x, this.question_Bot.y);
  151.             console.log("Enemy positions:",
  152.                        "E1:", this.enemy_1.x, this.enemy_1.y,
  153.                        "E2:", this.enemy_2.x, this.enemy_2.y);
  154.         }
  155.     }
  156.    
  157.     // Check if player has moved significantly from start position
  158.     hasPlayerMoved() {
  159.         if (!this.initialPositions.player) return false;
  160.        
  161.         const moveThreshold = 10; // pixels
  162.         const dx = Math.abs(this.question_Bot.x - this.initialPositions.player.x);
  163.         const dy = Math.abs(this.question_Bot.y - this.initialPositions.player.y);
  164.        
  165.         return (dx > moveThreshold || dy > moveThreshold);
  166.     }
  167.    
  168.     // Check collision between question_Bot and enemies
  169.     checkCollisions() {
  170.         // Skip collision detection if game is complete or not started
  171.         if (this.gameComplete || !this.gameStarted) return;
  172.        
  173.         // Only enable collision detection after player has moved or after a delay
  174.         if (!this.initializationComplete && !this.hasPlayerMoved()) return;
  175.        
  176.         // Check collision with enemy_1 using both methods
  177.         const distance1 = this.getDistance(this.question_Bot, this.enemy_1);
  178.         const boxCollision1 = this.checkBoundingBoxCollision(this.question_Bot, this.enemy_1);
  179.        
  180.         if (distance1 < this.COLLISION_THRESHOLD || boxCollision1) {
  181.             if (!this.collisionStates.enemy_1) {
  182.                 this.collisionStates.enemy_1 = true;
  183.                 console.log("Collision with enemy_1! Distance:", distance1, "Box collision:", boxCollision1);
  184.                
  185.                 // Animate and hide the hit enemy, set variable after animation
  186.                 this.animateAndHideEnemy(this.enemy_1, "enemy_1", "enemy_1");
  187.                
  188.                 // Set game complete - no automatic hiding of other enemies
  189.                 this.gameComplete = true;
  190.             }
  191.         } else {
  192.             this.collisionStates.enemy_1 = false;
  193.         }
  194.        
  195.         // Check collision with enemy_2 using both methods
  196.         const distance2 = this.getDistance(this.question_Bot, this.enemy_2);
  197.         const boxCollision2 = this.checkBoundingBoxCollision(this.question_Bot, this.enemy_2);
  198.        
  199.         if (distance2 < this.COLLISION_THRESHOLD || boxCollision2) {
  200.             if (!this.collisionStates.enemy_2) {
  201.                 this.collisionStates.enemy_2 = true;
  202.                 console.log("Collision with enemy_2! Distance:", distance2, "Box collision:", boxCollision2);
  203.                
  204.                 // Animate and hide the hit enemy, set variable after animation
  205.                 this.animateAndHideEnemy(this.enemy_2, "enemy_2", "enemy_2");
  206.                
  207.                 // Set game complete - no automatic hiding of other enemies
  208.                 this.gameComplete = true;
  209.             }
  210.         } else {
  211.             this.collisionStates.enemy_2 = false;
  212.         }
  213.     }
  214.    
  215.     // Update player position based on key states (only left and right movement)
  216.     updatePlayerMovement() {
  217.         // Stop movement if game is complete
  218.         if (this.gameComplete) return;
  219.        
  220.         let newX = this.question_Bot.x;
  221.        
  222.         // Calculate new position based on key states (only horizontal movement)
  223.         if (this.keys.left) {
  224.             newX -= this.MOVE_SPEED;
  225.         }
  226.         if (this.keys.right) {
  227.             newX += this.MOVE_SPEED;
  228.         }
  229.        
  230.         // Constrain movement within overlay boundaries
  231.         const antWidth = this.question_Bot.width || 50;
  232.         const overlayLeft = this.overlay.x;
  233.         const overlayRight = this.overlay.x + (this.overlay.width || 400);
  234.         const minX = overlayLeft;
  235.         const maxX = overlayRight - antWidth;
  236.        
  237.         // Apply constraints
  238.         newX = Math.max(minX, Math.min(maxX, newX));
  239.        
  240.         // Update position (only X coordinate changes)
  241.         this.question_Bot.x = newX;
  242.     }
  243.    
  244.     // Keyboard event handlers (only left and right keys)
  245.     handleKeyDown(event) {
  246.         switch(event.code) {
  247.             case 'ArrowLeft':
  248.                 this.keys.left = true;
  249.                 event.preventDefault();
  250.                 break;
  251.             case 'ArrowRight':
  252.                 this.keys.right = true;
  253.                 event.preventDefault();
  254.                 break;
  255.         }
  256.     }
  257.    
  258.     handleKeyUp(event) {
  259.         switch(event.code) {
  260.             case 'ArrowLeft':
  261.                 this.keys.left = false;
  262.                 event.preventDefault();
  263.                 break;
  264.             case 'ArrowRight':
  265.                 this.keys.right = false;
  266.                 event.preventDefault();
  267.                 break;
  268.         }
  269.     }
  270.    
  271.     // Touch Screen Button Functions (only left and right)
  272.     keyLeftStart() {
  273.         if (this.gameComplete) return;
  274.        
  275.         let newX = this.question_Bot.x - this.MOVE_SPEED;
  276.         const antWidth = this.question_Bot.width || 50;
  277.         const overlayLeft = this.overlay.x;
  278.         const minX = overlayLeft;
  279.        
  280.         // Apply boundary constraint
  281.         newX = Math.max(minX, newX);
  282.         this.question_Bot.x = newX;
  283.        
  284.         console.log("Moved left a little");
  285.     }
  286.    
  287.     keyRightStart() {
  288.         if (this.gameComplete) return;
  289.        
  290.         let newX = this.question_Bot.x + this.MOVE_SPEED;
  291.         const antWidth = this.question_Bot.width || 50;
  292.         const overlayRight = this.overlay.x + (this.overlay.width || 400);
  293.         const maxX = overlayRight - antWidth;
  294.        
  295.         // Apply boundary constraint
  296.         newX = Math.min(maxX, newX);
  297.         this.question_Bot.x = newX;
  298.        
  299.         console.log("Moved right a little");
  300.     }
  301.    
  302.     // Initialize the game
  303.     initializeGame() {
  304.         // Initialize collision variables to false
  305.         setVar("enemy_1", false);
  306.         setVar("enemy_2", false);
  307.        
  308.         // Store initial positions and check for overlaps
  309.         this.storeInitialPositions();
  310.        
  311.         // Add keyboard event listeners with bound context
  312.         document.addEventListener('keydown', (event) => this.handleKeyDown(event));
  313.         document.addEventListener('keyup', (event) => this.handleKeyUp(event));
  314.        
  315.         // Start the game with a small delay to ensure proper initialization
  316.         setTimeout(() => {
  317.             this.gameStarted = true;
  318.             console.log("Game collision detection enabled!");
  319.         }, 500); // Half second delay
  320.        
  321.         // Enable collision detection after 2 seconds regardless of movement
  322.         setTimeout(() => {
  323.             this.initializationComplete = true;
  324.             console.log("Initialization period complete - full collision detection active!");
  325.         }, 2000);
  326.        
  327.         // Start the game loop
  328.         update(() => {
  329.             this.updatePlayerMovement();
  330.             this.checkCollisions();
  331.         });
  332.        
  333.         console.log("Game initialized! Use left/right arrow keys to move the player within the overlay.");
  334.         console.log("Collision detection will start after player moves or 2-second delay.");
  335.         return this; // Return instance for method chaining
  336.     }
  337. }
  338.  
  339. // Global game instance reference
  340. let currentGame = null;
  341.  
  342. // Global functions for touch buttons (call these from Storyline)
  343. // These work with the currently active game instance (only left and right)
  344. function keyLeftStart() {
  345.     if (currentGame) {
  346.         currentGame.keyLeftStart();
  347.     } else {
  348.         console.warn("No game instance active. Please initialize a game first.");
  349.     }
  350. }
  351.  
  352. function keyRightStart() {
  353.     if (currentGame) {
  354.         currentGame.keyRightStart();
  355.     } else {
  356.         console.warn("No game instance active. Please initialize a game first.");
  357.     }
  358. }
  359.  
  360.  
  361. /* How to initialize Game in Storyline
  362. currentGame = new Game('playerObjectId', 'enemy1ObjectId', 'enemy2ObjectId', 'overlayObjectId')
  363. currentGame.initializeGame();
  364.  
  365. */
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement