Back to home page

EIC code displayed by LXR

 
 

    


Warning, /firebird/firebird-ng/src/app/services/game-controller.service.ts is written in an unsupported language. File is not indexed.

0001 import { Injectable } from '@angular/core';
0002 import * as THREE from "three";
0003 import {BehaviorSubject, Observable, Subject} from "rxjs";
0004 import {ThreeService} from "./three.service";
0005 import {LocalStorageService} from "./local-storage.service";
0006 
0007 
0008 export enum GamepadButtonIndexes {
0009   ButtonA = 0,
0010   ButtonB = 1,
0011   ButtonX = 2,
0012   ButtonY = 3,
0013   ButtonLB = 4,
0014   ButtonRB = 5,
0015   ButtonLT = 6,
0016   ButtonRT = 7,
0017   Select = 8,
0018   Start = 9,
0019 }
0020 
0021 export class GamepadObservableButton {
0022   private onPressSubject = new Subject<boolean>();
0023   public onPress = this.onPressSubject.asObservable();
0024   public state: GamepadButton = {pressed: false, touched: false, value: 0};
0025 
0026   constructor(public index: GamepadButtonIndexes) {
0027   }
0028 
0029   updateState(newState: GamepadButton) {
0030     if(this.onPressSubject.observed) {
0031       if(newState.pressed != this.state.pressed) {
0032         this.onPressSubject.next(newState.pressed);
0033       }
0034     }
0035     this.state = newState;
0036   }
0037 
0038   updateFromGamepadState(gamepad: Gamepad) {
0039     this.updateState(gamepad.buttons[this.index]);
0040   }
0041 }
0042 
0043 @Injectable({
0044   providedIn: 'root'
0045 })
0046 export class GameControllerService {
0047 
0048   private xAxisSubject = new BehaviorSubject<number>(0);
0049   public xAxisChanged = this.xAxisSubject.asObservable();
0050   public xAxis = 0;
0051 
0052   private yAxisSubject = new BehaviorSubject<number>(0);
0053   private yAxisChanged = this.yAxisSubject.asObservable();
0054   public yAxis: number = 0;
0055   public buttons: GamepadButton[] = [];
0056   public prevButtons: GamepadButton[] = [];
0057 
0058 
0059   public buttonA: GamepadObservableButton = new GamepadObservableButton(GamepadButtonIndexes.ButtonA);
0060   public buttonB: GamepadObservableButton = new GamepadObservableButton(GamepadButtonIndexes.ButtonB);
0061   public buttonX: GamepadObservableButton = new GamepadObservableButton(GamepadButtonIndexes.ButtonX);
0062   public buttonY: GamepadObservableButton = new GamepadObservableButton(GamepadButtonIndexes.ButtonY);
0063   public buttonLB: GamepadObservableButton = new GamepadObservableButton(GamepadButtonIndexes.ButtonLB);
0064   public buttonRB: GamepadObservableButton = new GamepadObservableButton(GamepadButtonIndexes.ButtonRB);
0065   public buttonLT: GamepadObservableButton = new GamepadObservableButton(GamepadButtonIndexes.ButtonLT);
0066   public buttonRT: GamepadObservableButton = new GamepadObservableButton(GamepadButtonIndexes.ButtonRT);
0067   public buttonStart: GamepadObservableButton = new GamepadObservableButton(GamepadButtonIndexes.Start);
0068   public buttonSelect: GamepadObservableButton = new GamepadObservableButton(GamepadButtonIndexes.Select);
0069 
0070   public activeGamepad: Gamepad|null = null;
0071   private frameCallbackRef: (() => void) | null = null;
0072   private isControllerEnabled: boolean = false;
0073 
0074   animationLoopHandler () {
0075     // Only process if controller is enabled
0076     if (!this.isControllerEnabled) {
0077       return;
0078     }
0079 
0080     const epsilon = 0.01;
0081     const gamepads = navigator.getGamepads();
0082     for (const gamepad of gamepads) {
0083       if (gamepad) {
0084 
0085         this.activeGamepad = gamepad;
0086         // Example: Using left joystick to control OrbitControls
0087         // Axis 0: Left joystick horizontal (left/right)
0088         // Axis 1: Left joystick vertical (up/down)
0089         this.xAxis = gamepad.axes[0];
0090         this.yAxis = gamepad.axes[1];
0091 
0092         if(Math.abs(this.xAxis - this.xAxisSubject.value) > epsilon) {
0093           this.xAxisSubject.next(this.xAxis);
0094         }
0095 
0096         if(Math.abs(this.yAxis - this.yAxisSubject.value) > epsilon) {
0097           this.yAxisSubject.next(this.yAxis);
0098         }
0099 
0100         const xAxis = gamepad.axes[0];
0101         const yAxis = gamepad.axes[1];
0102 
0103         if (Math.abs(xAxis) > 0.1 || Math.abs(yAxis) > 0.1) {
0104           this.rotateCamera(xAxis, yAxis);
0105         }
0106 
0107         // Zooming using buttons (X and A)
0108         const zoomInButton = gamepad.buttons[2]; // X button
0109         const zoomOutButton = gamepad.buttons[0]; // A button
0110 
0111         if (zoomInButton.pressed) {
0112           this.zoom(0.99);
0113         }
0114 
0115         if (zoomOutButton.pressed) {
0116           this.zoom(1.01);
0117         }
0118 
0119         // Strafe functionality
0120         // B button for strafe left
0121         if (this.buttonB.state.pressed) {
0122           this.strafe(-0.5);
0123         }
0124 
0125         // RT button for strafe right  
0126         if (this.buttonRT.state.pressed) {
0127           this.strafe(0.5);
0128         }
0129 
0130         // Default view on LT button press
0131         if (this.buttonLT.state.pressed) {
0132           this.resetToDefaultView();
0133         }
0134 
0135         this.buttonSelect.updateFromGamepadState(gamepad);
0136         this.buttonStart.updateFromGamepadState(gamepad);
0137 
0138         this.buttonA.updateFromGamepadState(gamepad);
0139         this.buttonB.updateFromGamepadState(gamepad);
0140         this.buttonY.updateFromGamepadState(gamepad);
0141         this.buttonX.updateFromGamepadState(gamepad);
0142 
0143         this.buttonLB.updateFromGamepadState(gamepad);
0144         this.buttonRB.updateFromGamepadState(gamepad);
0145         this.buttonLT.updateFromGamepadState(gamepad);
0146         this.buttonRT.updateFromGamepadState(gamepad);
0147 
0148         break; // Only use the first connected gamepad
0149       }
0150     }
0151   };
0152 
0153 
0154   rotateCamera(xAxisChange: number, yAxisChange: number) {
0155     let orbitControls = this.three.controls;
0156     let camera = this.three.camera;
0157 
0158     const offset = new THREE.Vector3(); // Offset of the camera from the target
0159     const quat = new THREE.Quaternion().setFromUnitVectors(camera.up, new THREE.Vector3(0, 1, 0));
0160     const quatInverse = quat.clone().invert();
0161 
0162     const currentPosition = camera.position.clone().sub(orbitControls.target);
0163     currentPosition.applyQuaternion(quat); // Apply the quaternion
0164 
0165     // Spherical coordinates
0166     const spherical = new THREE.Spherical().setFromVector3(currentPosition);
0167 
0168     // Adjusting spherical coordinates
0169     spherical.theta -= xAxisChange * 0.023; // Azimuth angle change
0170     spherical.phi += yAxisChange * 0.023; // Polar angle change, for rotating up/down
0171 
0172     // Ensure phi is within bounds to avoid flipping
0173     spherical.phi = Math.max(0.1, Math.min(Math.PI - 0.1, spherical.phi));
0174 
0175     // Convert back to Cartesian coordinates
0176     const newPostion = new THREE.Vector3().setFromSpherical(spherical);
0177     newPostion.applyQuaternion(quatInverse);
0178 
0179     camera.position.copy(newPostion.add(orbitControls.target));
0180     camera.lookAt(orbitControls.target);
0181     orbitControls.update();
0182   }
0183 
0184   zoom(factor: number) {
0185     let orbitControls = this.three.controls;
0186     let camera = this.three.camera;
0187     orbitControls.object.position.subVectors(camera.position, orbitControls.target).multiplyScalar(factor).add(orbitControls.target);
0188     orbitControls.update();
0189   }
0190 
0191   strafe(amount: number) {
0192     const camera = this.three.camera;
0193     const controls = this.three.controls;
0194     
0195     // Move along Z axis (right = positive Z, left = negative Z)
0196     const offset = new THREE.Vector3(0, 0, amount * 10); // Scale for reasonable movement
0197     
0198     // Move camera and target together
0199     camera.position.add(offset);
0200     controls.target.add(offset);
0201     controls.update();
0202   }
0203 
0204   resetToDefaultView() {
0205     const camera = this.three.camera;
0206     const controls = this.three.controls;
0207     
0208     // Reset camera to default position
0209     camera.position.set(-7000, 0, 0);
0210     controls.target.set(0, 0, 0);
0211     
0212     // Update controls
0213     controls.update();
0214     
0215     console.log('[GameController] Camera reset to default view');
0216   }
0217 
0218   constructor(
0219     private three: ThreeService,
0220     private localStorageService: LocalStorageService
0221   ) {
0222     // Check if controller should be enabled on initialization
0223     this.isControllerEnabled = this.localStorageService.useController?.value ?? false;
0224     
0225     // Create the callback reference
0226     this.frameCallbackRef = () => { this.animationLoopHandler(); };
0227     
0228     // Only attach handler if controller is enabled
0229     if (this.isControllerEnabled) {
0230       this.three.addFrameCallback(this.frameCallbackRef);
0231       console.log('[GameController] Controller enabled on initialization');
0232     }
0233     
0234     // Subscribe to changes in the use controller setting
0235     this.localStorageService.useController?.changes$.subscribe((enabled) => {
0236       this.setControllerEnabled(enabled);
0237     });
0238     
0239     this.xAxisChanged.subscribe((data)=>{
0240       if (this.isControllerEnabled) {
0241         console.log(`[joystick] x: ${data}`);
0242       }
0243     });
0244     this.yAxisChanged.subscribe((data)=>{
0245       if (this.isControllerEnabled) {
0246         console.log(`[joystick] y: ${data}`);
0247       }
0248     });
0249   }
0250 
0251   private setControllerEnabled(enabled: boolean) {
0252     if (this.isControllerEnabled === enabled) {
0253       return;
0254     }
0255     
0256     this.isControllerEnabled = enabled;
0257     
0258     if (enabled) {
0259       // Attach the frame callback
0260       if (this.frameCallbackRef) {
0261         this.three.addFrameCallback(this.frameCallbackRef);
0262         console.log('[GameController] Controller enabled');
0263       }
0264     } else {
0265       // Remove the frame callback
0266       if (this.frameCallbackRef) {
0267         this.three.removeFrameCallback(this.frameCallbackRef);
0268         console.log('[GameController] Controller disabled');
0269       }
0270     }
0271   }
0272 }