From e73cbcf5db5c9f580dfc518ed35238fb92e79abd Mon Sep 17 00:00:00 2001 From: Paula Date: Sat, 14 Mar 2026 19:12:56 -0300 Subject: [PATCH] Collision --- client/client_world.ts | 4 +- client/components/collision.ts | 20 ++++++ client/components/player_controls.ts | 2 +- client/player.ts | 6 +- client/systems/collision_system.ts | 101 +++++++++++++++++++++++++++ client/systems/player_controls.ts | 11 ++- common/components/position.ts | 4 ++ 7 files changed, 138 insertions(+), 10 deletions(-) create mode 100644 client/components/collision.ts create mode 100644 client/systems/collision_system.ts diff --git a/client/client_world.ts b/client/client_world.ts index ad8a889..7841217 100644 --- a/client/client_world.ts +++ b/client/client_world.ts @@ -12,6 +12,7 @@ import { DimensionLogicSystem } from "./systems/dimension_logic.ts"; import { Dimension } from "./components/dimension.ts"; import { GuiRenderSystem, GuiTickSystem } from "./gui/gui_systems.ts"; import { WorldGenerationSystem } from "./systems/world_generation_system.ts"; +import { CollisionSystem } from "./systems/collision_system.ts"; export class ClientWorld extends World { paused = false; @@ -40,9 +41,10 @@ export class ClientWorld extends World { this.add_system(new UIInteractionSystem(), "paused"); this.add_system(new GuiTickSystem(), "game"); this.add_system(new PlayerControlsSystem(), "game"); - this.add_system(new MovementSystem(), "game"); this.add_system(new WorldGenerationSystem(), "game"); this.add_system(new DimensionLogicSystem(), "game"); + this.add_system(new CollisionSystem(), "game"); + this.add_system(new MovementSystem(), "game"); // render systems this.add_system(new RenderSystem(), "game"); diff --git a/client/components/collision.ts b/client/components/collision.ts new file mode 100644 index 0000000..8e1fbdc --- /dev/null +++ b/client/components/collision.ts @@ -0,0 +1,20 @@ +import { Component } from "$/common/ecs/mod.ts"; + +export class CollisionCuboid extends Component { + width: number; + height: number; + depth: number; + gravity: number; + + colliding_x: number = 0; + colliding_y: number = 0; + colliding_z: number = 0; + + constructor(width: number, height: number, depth: number, gravity = -9.8) { + super(); + this.width = width; + this.height = height; + this.depth = depth; + this.gravity = gravity; + } +} diff --git a/client/components/player_controls.ts b/client/components/player_controls.ts index 57ddf17..eb3629b 100644 --- a/client/components/player_controls.ts +++ b/client/components/player_controls.ts @@ -2,7 +2,7 @@ import { Component } from "$/common/ecs/mod.ts"; import { KeyCode } from "$/client/input_manager.ts"; export class PlayerControls extends Component { - move_speed: number = 50; + move_speed: number = 5; // Keys move_forward: KeyCode = "KeyW"; diff --git a/client/player.ts b/client/player.ts index 88174fc..15d06f2 100644 --- a/client/player.ts +++ b/client/player.ts @@ -6,6 +6,7 @@ import { ItemStack, PlayerInventory } from "./inventory.ts"; import { PlayerControls } from "$/client/components/player_controls.ts"; import { ClientWorld } from "./client_world.ts"; import { GuiScreen } from "./gui/gui_screen.ts"; +import { CollisionCuboid } from "./components/collision.ts"; export class PlayerComponent extends Component { player_inventory = new PlayerInventory(""); @@ -22,8 +23,8 @@ export class PlayerComponent extends Component { export function create_player(world: ClientWorld) { const player = new Entity("player"); - player.add(new Position(0, 0)); - player.add(new Velocity(0, 0)); + player.add(new Position(0, 100, 0)); + player.add(new Velocity(0, 0, 0)); player.add(new PlayerControls()); player.add(new PlayerComponent()); @@ -40,6 +41,7 @@ export function create_player(world: ClientWorld) { // player_inventory.container.add_item(new ItemStack("bworld:carrot_seeds", 64)); player_inventory.container.add_item(new ItemStack("bworld:furnace", 1)); player.add(new Camera()); + player.add(new CollisionCuboid(0.5, 1.79, 0.5)); world.add_entity(player); diff --git a/client/systems/collision_system.ts b/client/systems/collision_system.ts new file mode 100644 index 0000000..7814071 --- /dev/null +++ b/client/systems/collision_system.ts @@ -0,0 +1,101 @@ +import { System } from "$/common/ecs/mod.ts"; +import { Position } from "$/common/components/position.ts"; +import { ClientWorld } from "../client_world.ts"; +import { CollisionCuboid } from "$/client/components/collision.ts"; +import { Velocity } from "$/common/components/velocity.ts"; +import { Dimension } from "../components/dimension.ts"; + +export class CollisionSystem extends System { + override update(world: ClientWorld, delta: number): void { + for (const entity of world.get_entities()) { + const position = entity.get(Position); + const velocity = entity.get(Velocity); + const cuboid = entity.get(CollisionCuboid); + + if (!position || !velocity || !cuboid) { + continue; + } + + velocity.vy += cuboid.gravity * delta; + + let new_position = position.clone(); + + new_position.x += velocity.vx * delta; + + let collisions = this.check_collision(new_position, velocity, cuboid, world.dimension); + + cuboid.colliding_x = collisions.x; + if (collisions.x !== 0) { + velocity.vx = 0; + } + + new_position = position.clone(); + + new_position.y += velocity.vy * delta; + + collisions = this.check_collision(new_position, velocity, cuboid, world.dimension); + + cuboid.colliding_y = collisions.y; + if (collisions.y !== 0) { + velocity.vy = 0; + } + + new_position = position.clone(); + + new_position.z += velocity.vz * delta; + + collisions = this.check_collision(new_position, velocity, cuboid, world.dimension); + + cuboid.colliding_z = collisions.z; + if (collisions.z !== 0) { + velocity.vz = 0; + } + } + } + + check_collision( + position: Position, + velocity: Velocity, + cuboid: CollisionCuboid, + dimension: Dimension, + ): { x: number; y: number; z: number } { + const collisions = { x: 0, y: 0, z: 0 }; + + const min_x = Math.floor(position.x - cuboid.width / 2); + const max_x = Math.floor(position.x + cuboid.width / 2); + const min_y = Math.floor(position.y); + const max_y = Math.floor(position.y + cuboid.height); + const min_z = Math.floor(position.z - cuboid.depth / 2); + const max_z = Math.floor(position.z + cuboid.depth / 2); + + for (let x = min_x; x <= max_x; x++) { + for (let y = min_y; y <= max_y; y++) { + for (let z = min_z; z <= max_z; z++) { + const block = dimension.get_block(x, y, z); + if (block && block !== 0) { + if (velocity.vx > 0) { + collisions.x = -1; + } + if (velocity.vx < 0) { + collisions.x = 1; + } + if (velocity.vy > 0) { + collisions.y = -1; + } + if (velocity.vy < 0) { + collisions.y = 1; + } + if (velocity.vz > 0) { + collisions.z = -1; + } + if (velocity.vz < 0) { + collisions.z = 1; + } + } + } + } + } + + return collisions; + } +} diff --git a/client/systems/player_controls.ts b/client/systems/player_controls.ts index 9c11b7d..5081a6c 100644 --- a/client/systems/player_controls.ts +++ b/client/systems/player_controls.ts @@ -7,6 +7,7 @@ import { Camera } from "../components/camera.ts"; import { Position } from "../../common/components/position.ts"; import { PlayerComponent } from "../player.ts"; import { GuiPlayerInventory } from "../gui/gui_player_inventory.ts"; +import { CollisionCuboid } from "../components/collision.ts"; export class PlayerControlsSystem extends System { constructor() { @@ -55,12 +56,10 @@ export class PlayerControlsSystem extends System { velocity.vx = (forwardX * input_z + rightX * input_x) * controls.move_speed; velocity.vz = (forwardZ * input_z + rightZ * input_x) * controls.move_speed; - if (InputManager.is_key_down("Space")) { - velocity.vy += controls.move_speed / 10; - } else if (InputManager.is_key_down("ShiftLeft")) { - velocity.vy -= controls.move_speed / 10; - } else { - velocity.vy = 0; + const cuboid = player.get(CollisionCuboid); + + if (InputManager.is_key_pressed("Space") && cuboid?.colliding_y === 1) { + velocity.vy += controls.move_speed; } if (InputManager.is_key_pressed(controls.open_inventory)) { diff --git a/common/components/position.ts b/common/components/position.ts index b69f182..16a53d2 100644 --- a/common/components/position.ts +++ b/common/components/position.ts @@ -11,4 +11,8 @@ export class Position extends Component { this.y = y; this.z = z; } + + clone() { + return new Position(this.x, this.y, this.z); + } }