From 3cdd1703dc03b030e809cd0b9a87bd5ca173122b Mon Sep 17 00:00:00 2001 From: Brendan Hansen Date: Thu, 30 Dec 2021 15:36:44 -0600 Subject: [PATCH] factored player code; added basic physics --- src/build.onyx | 1 + src/main.onyx | 57 ++++-------------------------- src/physics.onyx | 40 ++++++++++++++++++--- src/player.onyx | 92 ++++++++++++++++++++++++++++++++++++++++++++++-- src/vecmath.onyx | 8 +++++ src/world.onyx | 2 +- 6 files changed, 142 insertions(+), 58 deletions(-) diff --git a/src/build.onyx b/src/build.onyx index 3cacaa6..f7eaea8 100644 --- a/src/build.onyx +++ b/src/build.onyx @@ -18,6 +18,7 @@ #load "shader" #load "input" #load "physics" +#load "player" // Onyx library code #load "stb_truetype" diff --git a/src/main.onyx b/src/main.onyx index 32effe8..50fbcdc 100644 --- a/src/main.onyx +++ b/src/main.onyx @@ -7,12 +7,14 @@ use package core.intrinsics.onyx { __initialize } #local runtime :: package runtime #local { - world: ^World; world_shader: Shader; font: Font; - selected_block: Vector3i; + player: Player; } +world: ^World; +selected_block: Vector3i; + @GlobalVariable window: GLFWwindow_p; @@ -97,9 +99,10 @@ setup_opengl :: () { shader_use(world_shader); world = world_make(); + player = player_make(); + player.camera = ^camera; __initialize(^camera); - camera.position = .{0,0,0}; camera_set_fov(^camera, 75); ww, wh: i32; glfwGetWindowSize(window, ^ww, ^wh); @@ -122,53 +125,7 @@ update :: (dt: f32) { return; } - mdx, mdy := mouse_get_delta(); - camera.y_rot += ~~(-mdx / 400); - camera.x_rot += ~~( mdy / 400); - while camera.y_rot >= 2 * math.PI do camera.y_rot -= 2 * math.PI; - while camera.y_rot < 0 do camera.y_rot += 2 * math.PI; - camera.x_rot = math.clamp(camera.x_rot, -math.PI / 2 + 0.1, math.PI / 2 - 0.1); - - speed := 7 * dt; - if is_key_down(GLFW_KEY_LEFT_CONTROL) { - speed = 15 * dt; - } - - forward := camera_get_forward(^camera); - facing := forward; - facing.y = 0; - facing = Vector3.norm(facing); - if is_key_down(GLFW_KEY_W) { - camera.position += facing * speed; - } - if is_key_down(GLFW_KEY_S) { - camera.position -= facing * speed; - } - if is_key_down(GLFW_KEY_D) { - camera.position += Vector3.norm(Vector3.cross(facing, .{0,1,0})) * speed; - } - if is_key_down(GLFW_KEY_A) { - camera.position -= Vector3.norm(Vector3.cross(facing, .{0,1,0})) * speed; - } - - dir: Vector3i; - if !ray_cast(.{ camera.position, forward }, 40, null, (_, p) => { - return world_get_block(world, p.x, p.y, p.z) != Block_Empty; - }, ^selected_block, ^dir) { - selected_block = .{0,0,0}; - } - - if is_key_down(GLFW_KEY_SPACE) { - camera.position.y += 7 * dt; - } - if is_key_down(GLFW_KEY_LEFT_SHIFT) { - camera.position.y -= 7 * dt; - } - - if is_button_just_down(GLFW_MOUSE_BUTTON_LEFT) { - world_set_block(world, selected_block.x, selected_block.y, selected_block.z, block_make(0,0,0,1)); - } - + player_update(^player, dt); if is_key_just_down(GLFW_KEY_F7) { debug_screen = !debug_screen; diff --git a/src/physics.onyx b/src/physics.onyx index bb905b0..c9eedb4 100644 --- a/src/physics.onyx +++ b/src/physics.onyx @@ -20,16 +20,46 @@ PhysicsBody :: struct { pos: Vector3; vel: Vector3; acc: Vector3; + + on_ground := false; + + get_collision_object: (pos: Vector3) -> AABB; // This will get expanded on when other collision objects are defined } +physics_apply_gravity :: (use body: ^PhysicsBody) { + acc.y = -30; +} + +physics_simulate :: (use body: ^PhysicsBody, dt: f32, world: ^World) { + aabb_buffer := (cast(^AABB) alloc.from_stack(sizeof [64] AABB))[0..64]; + + aabbs := world_get_aabbs(world, pos, 3, aabb_buffer); + vel += acc * dt; + + try_move :: macro (delta: Vector3) -> bool { + new_pos := body.pos + delta; + body_aabb := get_collision_object(new_pos); + + for^ aabbs { + if AABB.intersects(body_aabb, *it) { + if delta.y < 0 do on_ground = true; + return false; + } + } + + return true; + } -physics_body_move :: (use body: ^PhysicsBody, world: ^World) { - aabb_buffer := cast([16] AABB) alloc.from_stack(sizeof [16] AABB); + on_ground = false; + move_x := try_move(.{vel.x * dt, 0, 0}); + move_y := try_move(.{0, vel.y * dt, 0}); + move_z := try_move(.{0, 0, vel.z * dt}); - aabbs := world_get_aabbs(world, pos, Vector3.mag(vel)); - for aabb: aabbs { + if on_ground do vel.y = 0; - } + if move_x do pos.x += vel.x * dt; + if move_y do pos.y += vel.y * dt; + if move_z do pos.z += vel.z * dt; } diff --git a/src/player.onyx b/src/player.onyx index c90c898..e22ce4a 100644 --- a/src/player.onyx +++ b/src/player.onyx @@ -1,9 +1,97 @@ +use package core +use package glfw3 Player :: struct { camera: ^Camera; // Should the camera exist on the player? Or should the player just control the camera? body: PhysicsBody; } -player_update :: (player: ^Player) { +player_make :: () -> Player { + player: Player; -} \ No newline at end of file + player.camera = null; + player.body = .{ + .{0,10,0}, + .{0,0,0}, + .{0,0,0}, + + get_collision_object = player_get_aabb + }; + + return player; +} + +player_update :: (use player: ^Player, dt: f32) { + speed := 6f; + if is_key_down(GLFW_KEY_LEFT_CONTROL) { + speed = 10; + } + if is_key_down(GLFW_KEY_LEFT_SHIFT) { + speed = 1; + } + + mdx, mdy := mouse_get_delta(); + camera.y_rot += ~~(-mdx / 400); + camera.x_rot += ~~( mdy / 400); + while camera.y_rot >= 2 * math.PI do camera.y_rot -= 2 * math.PI; + while camera.y_rot < 0 do camera.y_rot += 2 * math.PI; + camera.x_rot = math.clamp(camera.x_rot, -math.PI / 2 + 0.01, math.PI / 2 - 0.01); + + body.vel = .{0,body.vel.y,0}; + + forward := camera_get_forward(camera); + facing := forward; + facing.y = 0; + facing = Vector3.norm(facing); + if is_key_down(GLFW_KEY_W) { + body.vel += facing * speed; + } + if is_key_down(GLFW_KEY_S) { + body.vel -= facing * speed; + } + if is_key_down(GLFW_KEY_D) { + body.vel += Vector3.norm(Vector3.cross(facing, .{0,1,0})) * speed; + } + if is_key_down(GLFW_KEY_A) { + body.vel -= Vector3.norm(Vector3.cross(facing, .{0,1,0})) * speed; + } + + physics_apply_gravity(^body); + + if is_key_down(GLFW_KEY_SPACE) && body.on_ground { + body.acc.y = 500; + } + + physics_simulate(^body, dt, world); + + // Fix falling off the world + if body.pos.y < -10 do body.pos = .{0,10,0}; + + camera.position = body.pos; + + dir: Vector3i; + if !ray_cast(.{ camera.position, forward }, 10, null, (_, p) => { + return world_get_block(world, p.x, p.y, p.z) != Block_Empty; + }, ^selected_block, ^dir) { + selected_block = .{0,0,0}; + } + + if is_button_just_down(GLFW_MOUSE_BUTTON_LEFT) { + world_set_block(world, selected_block.x, selected_block.y, selected_block.z, Block_Empty); + } + + if is_button_just_down(GLFW_MOUSE_BUTTON_RIGHT) { + world_set_block(world, selected_block.x + dir.x, selected_block.y + dir.y, selected_block.z + dir.z, block_make(1,0,0,1)); + } +} + +player_get_aabb :: (pos: Vector3) -> AABB { + return .{ + x0 = pos.x - 0.25f, + y0 = pos.y - 1.8f, + z0 = pos.z - 0.25f, + x1 = pos.x + 0.25f, + y1 = pos.y + 0.2f, + z1 = pos.z + 0.25f, + }; +} diff --git a/src/vecmath.onyx b/src/vecmath.onyx index 35c9130..c57891d 100644 --- a/src/vecmath.onyx +++ b/src/vecmath.onyx @@ -29,6 +29,14 @@ Vector3 :: struct [conv.Custom_Format.{format_vector3}] { v1.x * v2.y - v1.y * v2.x, }; } + + clamp :: macro (v: Vector3, min: Vector3, max: Vector3) -> Vector3 { + return .{ + math.clamp(v.x, min.x, max.x), + math.clamp(v.y, min.y, max.y), + math.clamp(v.z, min.z, max.z), + }; + } } #operator + macro (v1, v2: Vector3) => Vector3.{ v1.x + v2.x, v1.y + v2.y, v1.z + v2.z }; diff --git a/src/world.onyx b/src/world.onyx index a12bc2b..a852b1e 100644 --- a/src/world.onyx +++ b/src/world.onyx @@ -18,7 +18,7 @@ world_make :: (allocator := context.allocator) -> ^World { chunk_set(chunk, x, 0, z, block_make(0.2, 1, 0.2, 0.8)); } for z: 32 do for x: 32 { - if random.between(0, 10) >= 7 do continue; + if random.between(0, 10) >= 3 do continue; chunk_set(chunk, x, 1, z, block_make(random.float(0, 1), random.float(0, 1), random.float(0, 1), 1)); } -- 2.25.1