diff --git a/back/src/ecs/system/VehicleSystem.ts b/back/src/ecs/system/VehicleSystem.ts index d1c6a08..c0c99be 100644 --- a/back/src/ecs/system/VehicleSystem.ts +++ b/back/src/ecs/system/VehicleSystem.ts @@ -24,7 +24,7 @@ export class VehicleSystem { */ this.vehicleCreationSystem.update(entities, world) /** - * Vehicle movement + * Vehicle movement based on player input */ this.vehicleMovementSystem.update(entities, dt) /** @@ -37,6 +37,8 @@ export class VehicleSystem { this.handlePlayerExitVehicle(entities) /** * Update vehicle controller raycast + * To optimize this : Only update the raycast if a player is inside the vehicle + * But since wheels can be non physical, idle vehicles will have their chassis on the ground */ for (const entity of entities) { const vehicleRayCastComponent = entity.getComponent(VehicleRayCastComponent) @@ -213,9 +215,16 @@ export class VehicleSystem { } } private updateText(textComponent: TextComponent, vehicleComponent: VehicleComponent) { - textComponent.text = `🚗 Driver: ${ - vehicleComponent.driverEntityId ? 'Yes' : 'No' - } | 🧑‍🤝‍🧑 Passengers: ${vehicleComponent.passengerEntityIds.length}` + const hasDriver = !!vehicleComponent.driverEntityId + const passengerCount = vehicleComponent.passengerEntityIds.length + + textComponent.text = [ + hasDriver ? '' : '🚗 Car', + passengerCount > 0 ? `👥 ${passengerCount} passenger${passengerCount > 1 ? 's' : ''}` : '', + ] + .filter(Boolean) + .join(' ') + textComponent.updated = true } } diff --git a/back/src/scripts/carScript.js b/back/src/scripts/carScript.js deleted file mode 100644 index 595ee75..0000000 --- a/back/src/scripts/carScript.js +++ /dev/null @@ -1,235 +0,0 @@ -function randomHexColor() { - const hex = Math.floor(Math.random() * 16777215).toString(16) - return '#' + '0'.repeat(6 - hex.length) + hex -} - -// Load the game world -// Can also be hosted on a gittblox-Assets + https://rawcdn.githack.comhub repo : https://github.com/iErcann/No -new MapWorld('http://localhost:4001/FlatMap.glb') - -let i = 0 -// Spawn cars in a loop -setInterval(() => { - new Car({ - position: { - x: 10, - y: 10, - z: 10 + i++, - }, - meshUrl: 'http://localhost:4001/EzCar.glb', - }) -}, 5000) -// new Car({ -// position: { -// x: 40, -// y: 10, -// z: 10, -// }, -// }) - -// new Car({ -// position: { -// x: -40, -// y: 10, -// z: 10, -// }, -// }) - -// new Car({ -// position: { -// x: 100, -// y: 5, -// z: 10, -// }, -// meshUrl: 'http://localhost:4001/EzCar.glb', -// }) - -15 - 8 - 25 -new Mesh({ - position: { - x: 0, - y: 100, - z: 0, - }, - physicsProperties: { - mass: 10, - enableCcd: true, - }, - meshUrl: 'http://localhost:4001/Cubing.glb', -}) - -for (let i = 0; i < 4; i++) { - const cube = new Cube({ - position: { - x: 10 * i, - y: 10 * i, - z: 0, - }, - physicsProperties: { - mass: 1, - angularDamping: 0.5, - enableCcd: true, - }, - }) - const proximityPromptComponent = new ProximityPromptComponent(cube.entity.id, { - text: 'Change color', - onInteract: (interactingEntity) => { - cube.entity - .getComponent(DynamicRigidBodyComponent) - .body.applyImpulse(new Rapier.Vector3(0, 5, 0), true) - - const colorComponent = cube.entity.getComponent(ColorComponent) - if (colorComponent) { - // randomize color - colorComponent.color = '#' + Math.floor(Math.random() * 16777215).toString(16) - colorComponent.updated = true - } - }, - maxInteractDistance: 10, - interactionCooldown: 200, - holdDuration: 0, - }) - cube.entity.addNetworkComponent(proximityPromptComponent) -} - -const sphereParams = { - radius: 1.4, - position: { - x: 40, - y: 10, - z: 10, - }, - meshUrl: 'https://notbloxo.fra1.cdn.digitaloceanspaces.com/Notblox-Assets/base/Ball.glb', - physicsProperties: { - mass: 1, - // Enable continuous collision detection to prevent the ball from going through the walls - enableCcd: true, - angularDamping: 0.5, - }, -} - -let ball -// Initialize the ball using SphereParams -ball = new Sphere(sphereParams) - -// That's why the proximity prompt component is added to the network data component to be synced with the front -const proximityPromptComponent = new ProximityPromptComponent(ball.entity.id, { - text: 'Kick', - onInteract: (playerEntity) => { - const ballRigidbody = ball.entity.getComponent(DynamicRigidBodyComponent) - const playerRotationComponent = playerEntity.getComponent(RotationComponent) - - if (ballRigidbody && playerRotationComponent && playerEntity.getComponent(InputComponent)) { - // Convert rotation to direction vector - const direction = playerRotationComponent.getForwardDirection() - // Calculate player looking direction - // sendChatMessage('⚽', `Player shot the ball !`) - const playerLookingDirectionVector = new Rapier.Vector3( - direction.x * 500, - 0, - direction.z * 500 - ) - - ballRigidbody.body.applyImpulse(playerLookingDirectionVector, true) - } - }, - maxInteractDistance: 10, - interactionCooldown: 2000, - holdDuration: 0, -}) -ball.entity.addNetworkComponent(proximityPromptComponent) - -// const proximityPromptComponent = new ProximityPromptComponent(car.entity.id, { -// text: 'Kick', -// onInteract: (playerEntity) => { -// const ballRigidbody = car.entity.getComponent(DynamicRigidBodyComponent) -// const playerRotationComponent = playerEntity.getComponent(RotationComponent) - -// if (ballRigidbody && playerRotationComponent && playerEntity.getComponent(InputComponent)) { -// // Convert rotation to direction vector -// const direction = playerRotationComponent.getForwardDirection() -// // Calculate player looking direction -// const playerLookingDirectionVector = new Rapier.Vector3( -// direction.x * 52500, -// 0, -// direction.z * 52500 -// ) - -// ballRigidbody.body.applyImpulse(playerLookingDirectionVector, true) -// } -// }, -// maxInteractDistance: 15, -// interactionCooldown: 2000, -// holdDuration: 0, -// }) -// const networkDataComponent = car.entity.getComponent(NetworkDataComponent) -// networkDataComponent.addComponent(proximityPromptComponent) -// car.entity.addComponent(proximityPromptComponent) - -// for (let i = 1; i < 5; i++) { -// new Cube({ -// position: { -// x: 10 + i * 10, -// y: 10 + i * 10, -// z: 0, -// }, -// size: { -// width: i / 2, -// height: i / 2, -// depth: i / 2, -// }, -// physicsProperties: { -// mass: 0.1, -// angularDamping: 0, -// linearDamping: 0, -// enableCcd: true, -// }, -// }) -// } - -// setInterval(() => { -// console.log(car.entity.getComponent(TextComponent)) -// car.entity.getComponent(TextComponent).text = 'Hello' + Math.random() -// car.entity.getComponent(TextComponent).updated = true -// }, 1000) - -// // --------- -// for (let i = 0; i < 100; i++) { -// const cube = new Cube({ -// position: { -// x: i * 20, -// y: i * 20, -// z: 100, -// }, -// physicsProperties: { -// mass: 1, -// angularDamping: 0.5, -// enableCcd: true, -// }, -// }) -// const proximityPromptComponent = new ProximityPromptComponent(cube.entity.id, { -// text: 'Press E to change color', -// onInteract: (interactingEntity) => { -// cube.entity -// .getComponent(DynamicRigidBodyComponent) -// .body.applyImpulse(new Rapier.Vector3(0, 5, 0), true) - -// const colorComponent = cube.entity.getComponent(ColorComponent) -// if (colorComponent) { -// // randomize color -// colorComponent.color = '#' + Math.floor(Math.random() * 16777215).toString(16) -// colorComponent.updated = true -// } -// }, -// maxInteractDistance: 10, -// interactionCooldown: 200, -// holdDuration: 0, -// }) -// cube.entity.addComponent(proximityPromptComponent) -// const networkDataComponent = cube.entity.getComponent(NetworkDataComponent) -// networkDataComponent.addComponent(proximityPromptComponent) - -// setTimeout(() => { -// EventSystem.addNetworkEvent(new EntityDestroyedEvent(cube.entity.id)) -// }, i * 1000) -// } diff --git a/back/src/scripts/defaultScript.js b/back/src/scripts/defaultScript.js index ce0b5b9..2e88a8e 100644 --- a/back/src/scripts/defaultScript.js +++ b/back/src/scripts/defaultScript.js @@ -11,7 +11,7 @@ new MapWorld('https://notbloxo.fra1.cdn.digitaloceanspaces.com/Notblox-Assets/wo // Create a basic cube const basicCubeParams = { - position: { x: 0, y: 5, z: -20 }, + position: { x: 0, y: 5, z: -50 }, size: { width: 3, height: 3, depth: 3 }, } new Cube(basicCubeParams) @@ -24,13 +24,6 @@ const basicSphereParams = { } new Sphere(basicSphereParams) -const basicSphereParams2 = { - position: { x: 5, y: 10, z: -10 }, - radius: 6, - color: '#ffffff', -} -new Sphere(basicSphereParams2) - // === Interactive Trigger Zone Example === // Creates an invisible trigger zone that detects when players enter/exit const triggerCube = new TriggerCube( diff --git a/front/game/ecs/system/TextComponentSystem.ts b/front/game/ecs/system/TextComponentSystem.ts index d669b91..31c6ac3 100644 --- a/front/game/ecs/system/TextComponentSystem.ts +++ b/front/game/ecs/system/TextComponentSystem.ts @@ -267,7 +267,9 @@ export class TextComponentSystem { this.updateVisibility(entity, currentPlayerEntity, textComponent) } - // Update the visibility of the text based on the distance from the player + // Updates text visibility based on two conditions: + // 1. The text must be within displayDistance units of the player + // 2. The text content must not be empty private updateVisibility( entityWithText: Entity, currentPlayerEntity: Entity, @@ -284,7 +286,7 @@ export class TextComponentSystem { const distance = this.calculateDistance(position, playerPosition) - textObject.visible = distance <= textComponent.displayDistance + textObject.visible = distance <= textComponent.displayDistance && textComponent.text !== '' } private calculateDistance(pos1: PositionComponent, pos2: PositionComponent): number {