#load "shader"
#load "input"
#load "physics"
+#load "player"
// Onyx library code
#load "stb_truetype"
#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;
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);
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;
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;
}
+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,
+ };
+}
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 };
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));
}