factored player code; added basic physics
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Thu, 30 Dec 2021 21:36:44 +0000 (15:36 -0600)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Thu, 30 Dec 2021 21:36:44 +0000 (15:36 -0600)
src/build.onyx
src/main.onyx
src/physics.onyx
src/player.onyx
src/vecmath.onyx
src/world.onyx

index 3cacaa6312ba80f019ad263c841aae42d820f1d6..f7eaea827ec43ca6ff8e584de6c637c24ef630dd 100644 (file)
@@ -18,6 +18,7 @@
 #load "shader"
 #load "input"
 #load "physics"
+#load "player"
 
 // Onyx library code
 #load "stb_truetype"
index 32effe83f99db953f0f6646ff1335db3a0ff1b63..50fbcdc2bc1887825a519b44a2992d45422e1750 100644 (file)
@@ -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;
index bb905b0accc04dedac6496f95d5f556f522c98ac..c9eedb4d19fe89d70a405815b64015e8ac115c16 100644 (file)
@@ -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;
 }
 
 
index c90c8983257e46d73876f127a6aae2b00e7d0f49..e22ce4a84181c946d16b61a5276f1a0fd022982a 100644 (file)
@@ -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,
+    };
+}
index 35c913063931f1610aef3e50db6c70707e5ed17e..c57891d81ab3e982e8e2e0d063bbf26c8a9d2d1a 100644 (file)
@@ -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 };
index a12bc2be0fde436cbedc0683018405417ef6d94c..a852b1e27e8587863bbfb5568a556e1d3f23d09b 100644 (file)
@@ -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));
         }