-
Notifications
You must be signed in to change notification settings - Fork 0
Feature/may bug fixes #70
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,88 @@ | ||||||
| import * as THREE from 'three'; | ||||||
|
|
||||||
| interface StaticEntity { | ||||||
| id: string; | ||||||
| name: string; | ||||||
| position: THREE.Vector3; | ||||||
| rotation: THREE.Euler; | ||||||
| } | ||||||
|
|
||||||
| export class StaticEntityManager { | ||||||
| private scene: THREE.Scene; | ||||||
| private staticEntities: Map<string, THREE.Mesh> = new Map(); | ||||||
|
|
||||||
| constructor(scene: THREE.Scene) { | ||||||
| this.scene = scene; | ||||||
| } | ||||||
|
|
||||||
| public async addStaticEntity(entity: StaticEntity): Promise<void> { | ||||||
| if (this.staticEntities.has(entity.id)) { | ||||||
| console.warn(`Static entity with ID ${entity.id} already exists`); | ||||||
| return; | ||||||
| } | ||||||
|
|
||||||
| const geometry = new THREE.BoxGeometry(1, 1, 1); | ||||||
| const material = new THREE.MeshBasicMaterial({ color: 0x808080 }); | ||||||
| const mesh = new THREE.Mesh(geometry, material); | ||||||
| mesh.position.copy(entity.position); | ||||||
| mesh.rotation.copy(entity.rotation); | ||||||
| mesh.userData = { | ||||||
| type: 'staticEntity', | ||||||
| id: entity.id, | ||||||
| name: entity.name | ||||||
| }; | ||||||
|
|
||||||
| this.staticEntities.set(entity.id, mesh); | ||||||
| this.scene.add(mesh); | ||||||
| } | ||||||
|
|
||||||
| public createPortal(position: THREE.Vector3, destinationMap: string): THREE.Mesh { | ||||||
| const geometry = new THREE.BoxGeometry(2, 2, 2); | ||||||
| const material = new THREE.MeshBasicMaterial({ | ||||||
| color: 0x00ff00, | ||||||
| transparent: true, | ||||||
| opacity: 0.5 | ||||||
| }); | ||||||
| const portal = new THREE.Mesh(geometry, material); | ||||||
| portal.position.copy(position); | ||||||
| portal.userData = { | ||||||
| type: 'portal', | ||||||
| destinationMap: destinationMap | ||||||
| }; | ||||||
| this.scene.add(portal); | ||||||
| return portal; | ||||||
| } | ||||||
|
|
||||||
| public updateStaticEntityPosition(id: string, position: THREE.Vector3): void { | ||||||
| const entity = this.staticEntities.get(id); | ||||||
| if (entity) { | ||||||
| entity.position.copy(position); | ||||||
| } | ||||||
| } | ||||||
|
|
||||||
| public removeStaticEntity(id: string): void { | ||||||
| const entity = this.staticEntities.get(id); | ||||||
| if (entity) { | ||||||
| this.scene.remove(entity); | ||||||
| this.staticEntities.delete(id); | ||||||
| } | ||||||
| } | ||||||
|
|
||||||
| public async removeAllStaticEntities(): Promise<void> { | ||||||
|
||||||
| public async removeAllStaticEntities(): Promise<void> { | |
| public removeAllStaticEntities(): void { |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -15,6 +15,7 @@ import { PlayerData } from '../models/player/PlayerData'; | |
| import { AlienManager } from './AlienManager'; | ||
| import { PlayerManager } from './PlayerManager'; | ||
| import { CSS2DRenderer } from 'three/addons/renderers/CSS2DRenderer.js'; | ||
| import { StaticEntityManager } from './StaticEntityManager'; | ||
|
|
||
| @Component({ | ||
| selector: 'app-game', | ||
|
|
@@ -29,6 +30,7 @@ export class GameComponent implements OnInit, OnDestroy { | |
| public entities: Map<string, PlayerDto> = new Map(); | ||
| public alienManager?: AlienManager; | ||
| public playerManager?: PlayerManager; | ||
| public staticEntityManager?: StaticEntityManager; | ||
| public stats?: Stats; | ||
| public currentMapName?: string; | ||
| public playerData: PlayerData | undefined; | ||
|
|
@@ -43,7 +45,7 @@ export class GameComponent implements OnInit, OnDestroy { | |
| constructor( | ||
| private hubService: HubService, | ||
| private route: ActivatedRoute, | ||
| private keyboardService: KeyboardService | ||
| public keyboardService: KeyboardService | ||
| ) {} | ||
|
|
||
| ngOnInit(): void { | ||
|
|
@@ -64,6 +66,9 @@ export class GameComponent implements OnInit, OnDestroy { | |
| this.camera.aspect = window.innerWidth / window.innerHeight; | ||
| this.camera.updateProjectionMatrix(); | ||
| this.renderer.setSize(window.innerWidth, window.innerHeight); | ||
| if (this.labelRenderer) { | ||
| this.labelRenderer.setSize(window.innerWidth, window.innerHeight); | ||
| } | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -76,6 +81,14 @@ export class GameComponent implements OnInit, OnDestroy { | |
| console.warn('HubMessage: Received error:', error); | ||
| }); | ||
|
|
||
| hubService.on('teleportSuccessful', (message: string) => { | ||
| console.log('Teleportation successful:', message); | ||
| }); | ||
|
|
||
| hubService.on('teleportFailed', (error: string) => { | ||
|
||
| console.error('Teleportation failed:', error); | ||
| }); | ||
|
|
||
| hubService.on('loginSuccessful', (response: PlayerData) => { | ||
| console.log('HubMessage: Login successful:', response); | ||
| this.playerData = response; | ||
|
|
@@ -149,6 +162,7 @@ export class GameComponent implements OnInit, OnDestroy { | |
| await initializeThreeJs(this); | ||
| this.playerManager = new PlayerManager(this.scene!); | ||
| this.alienManager = new AlienManager(this.scene!); | ||
| this.staticEntityManager = new StaticEntityManager(this.scene!); | ||
| this.setupPerformanceMeters(); | ||
| this.animate(); | ||
| } | ||
|
|
@@ -172,6 +186,16 @@ export class GameComponent implements OnInit, OnDestroy { | |
| this.alienManager.animate(); | ||
| } | ||
|
|
||
| // Update player position for portal detection | ||
| if (this.playerData && this.playerManager) { | ||
| const playerPosition = this.playerManager.getPlayerPosition( | ||
| this.playerData.id | ||
| ); | ||
| if (playerPosition) { | ||
| this.keyboardService.setPlayerPosition(playerPosition); | ||
| } | ||
| } | ||
|
|
||
| // Update orbit controls to follow player if available | ||
| if (this.playerData && this.playerManager && this.controls) { | ||
| const playerPosition = this.playerManager.getPlayerPosition( | ||
|
|
@@ -232,6 +256,10 @@ export class GameComponent implements OnInit, OnDestroy { | |
| if (this.scene) { | ||
| this.scene.clear(); | ||
| } | ||
| this.keyboardService.clearPortals(); | ||
| if (this.staticEntityManager) { | ||
| this.staticEntityManager.removeAllStaticEntities(); | ||
| } | ||
| } | ||
|
|
||
| // Public method to handle player movement | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,7 +1,12 @@ | ||||||||||||
| import * as THREE from 'three'; | ||||||||||||
| import { OrbitControls } from 'three/addons/controls/OrbitControls.js'; | ||||||||||||
| import { CSS2DRenderer } from 'three/addons/renderers/CSS2DRenderer.js'; | ||||||||||||
| import { PlayerDto, SpaceMapData, AlienDto } from './types/SpaceMapData'; | ||||||||||||
| import { | ||||||||||||
| PlayerDto, | ||||||||||||
| SpaceMapData, | ||||||||||||
| AlienDto, | ||||||||||||
| StaticEntityDto, | ||||||||||||
| } from './types/SpaceMapData'; | ||||||||||||
| import { GameComponent } from './game.component'; | ||||||||||||
|
|
||||||||||||
| // Define layers | ||||||||||||
|
|
@@ -124,20 +129,20 @@ export async function loadNewSpacemap( | |||||||||||
| spaceMapData: SpaceMapData | ||||||||||||
| ): Promise<void> { | ||||||||||||
| if (component.isLoadingSpacemap) { | ||||||||||||
| console.log('Skipping spacemap update - still loading previous map'); | ||||||||||||
| return; | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| try { | ||||||||||||
| component.isLoadingSpacemap = true; | ||||||||||||
| console.log('Loading new space map: ', spaceMapData); | ||||||||||||
| console.log('Loading new spacemap: ', spaceMapData); | ||||||||||||
| component.currentMapName = spaceMapData.mapName; | ||||||||||||
| await clearScene(component); | ||||||||||||
| await loadMapEnvironment(component, spaceMapData); | ||||||||||||
|
|
||||||||||||
| // Load players and aliens for the new map | ||||||||||||
| // Load players, aliens, and static entities for the new map | ||||||||||||
|
||||||||||||
| await loadPlayers(spaceMapData.mapObject.players, component); | ||||||||||||
| await loadAliens(spaceMapData.mapObject.aliens, component); | ||||||||||||
| await loadStaticEntities(spaceMapData.mapObject.staticEntities, component); | ||||||||||||
|
||||||||||||
| await loadStaticEntities(spaceMapData.mapObject.staticEntities, component); | |
| const filteredStaticEntities = spaceMapData.mapObject.staticEntities.filter( | |
| (entity): entity is StaticEntityDto => 'staticEntitySpecificProperty' in entity | |
| ); | |
| await loadStaticEntities(filteredStaticEntities, component); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Portals created here are not tracked in
staticEntities, soremoveAllStaticEntitiesorremoveStaticEntitywon't remove them. You may want to store portal meshes in the manager or provide a separate cleanup method.