diff --git a/game/game.odin b/game/game.odin index f79507f..5e0b90b 100644 --- a/game/game.odin +++ b/game/game.odin @@ -14,15 +14,17 @@ package game -import "core:math/linalg" import "core:fmt" +import "core:math/linalg" import rl "vendor:raylib" -PIXEL_WINDOW_HEIGHT :: 180 +PIXEL_WINDOW_HEIGHT :: 360 Game_Memory :: struct { - player_pos: rl.Vector2, - some_number: int, + player_pos: rl.Vector3, + camera_yaw_pitch: rl.Vector2, + camera_speed: f32, + mouse_captured: bool, } g_mem: ^Game_Memory @@ -31,20 +33,33 @@ game_camera :: proc() -> rl.Camera2D { w := f32(rl.GetScreenWidth()) h := f32(rl.GetScreenHeight()) + return {zoom = h / PIXEL_WINDOW_HEIGHT, target = g_mem.player_pos.xy, offset = {w / 2, h / 2}} +} + +camera_rotation_matrix :: proc() -> matrix[3, 3]f32 { + return linalg.matrix3_from_euler_angles_xy(g_mem.camera_yaw_pitch.x, g_mem.camera_yaw_pitch.y) +} + +camera_forward_vec :: proc() -> rl.Vector3 { + rotation_matrix := camera_rotation_matrix() + return rotation_matrix * rl.Vector3{0, 0, 1} +} + +game_camera_3d :: proc() -> rl.Camera3D { return { - zoom = h/PIXEL_WINDOW_HEIGHT, - target = g_mem.player_pos, - offset = { w/2, h/2 }, + position = g_mem.player_pos, + up = {0, 1, 0}, + fovy = 60, + target = g_mem.player_pos + camera_forward_vec(), + projection = .PERSPECTIVE, } } ui_camera :: proc() -> rl.Camera2D { - return { - zoom = f32(rl.GetScreenHeight())/PIXEL_WINDOW_HEIGHT, - } + return {zoom = f32(rl.GetScreenHeight()) / PIXEL_WINDOW_HEIGHT} } -update :: proc() { +update_free_look_camera :: proc() { input: rl.Vector2 if rl.IsKeyDown(.UP) || rl.IsKeyDown(.W) { @@ -60,24 +75,51 @@ update :: proc() { input.x += 1 } + if rl.IsKeyPressed(.ESCAPE) { + if g_mem.mouse_captured { + g_mem.mouse_captured = false + rl.EnableCursor() + } + } + + if g_mem.mouse_captured { + g_mem.camera_yaw_pitch += rl.GetMouseDelta().yx * -1 * 0.001 + } + + g_mem.camera_speed += rl.GetMouseWheelMove() * 0.01 + g_mem.camera_speed = linalg.clamp(g_mem.camera_speed, 0.01, 10) + + rotation_matrix := camera_rotation_matrix() + forward := -rotation_matrix[2] + right := linalg.cross(rl.Vector3{0, 1, 0}, forward) + input = linalg.normalize0(input) - g_mem.player_pos += input * rl.GetFrameTime() * 100 - g_mem.some_number += 1 + g_mem.player_pos += (input.x * right + input.y * forward) * g_mem.camera_speed +} + +update :: proc() { + if rl.IsMouseButtonPressed(.LEFT) { + g_mem.mouse_captured = true + rl.DisableCursor() + } + + update_free_look_camera() } draw :: proc() { rl.BeginDrawing() rl.ClearBackground(rl.BLACK) - rl.BeginMode2D(game_camera()) - rl.DrawRectangleV(g_mem.player_pos, {10, 20}, rl.WHITE) - rl.DrawRectangleV({20, 20}, {10, 10}, rl.RED) - rl.DrawRectangleV({-30, -20}, {10, 10}, rl.GREEN) - rl.EndMode2D() + { + rl.BeginMode3D(game_camera_3d()) + defer rl.EndMode3D() + + rl.DrawBoundingBox(rl.BoundingBox{min = -1, max = 1}, {255, 0, 0, 255}) + } rl.BeginMode2D(ui_camera()) // Note: main_hot_reload.odin clears the temp allocator at end of frame. - rl.DrawText(fmt.ctprintf("some_number: %v\nplayer_pos: %v", g_mem.some_number, g_mem.player_pos), 5, 5, 8, rl.WHITE) + rl.DrawText(fmt.ctprintf("player_pos: %v", g_mem.player_pos), 5, 5, 8, rl.WHITE) rl.EndMode2D() rl.EndDrawing() @@ -94,6 +136,7 @@ game_update :: proc() -> bool { game_init_window :: proc() { rl.SetConfigFlags({.WINDOW_RESIZABLE, .VSYNC_HINT}) rl.InitWindow(1280, 720, "Odin + Raylib + Hot Reload template!") + rl.SetExitKey(.KEY_NULL) rl.SetWindowPosition(200, 200) rl.SetTargetFPS(500) } @@ -102,9 +145,7 @@ game_init_window :: proc() { game_init :: proc() { g_mem = new(Game_Memory) - g_mem^ = Game_Memory { - some_number = 100, - } + g_mem^ = Game_Memory{} game_hot_reloaded(g_mem) }