From 54b89f5a68bf4cca2320a02f76146089c718fa38 Mon Sep 17 00:00:00 2001 From: Per Hultqvist Date: Mon, 14 Oct 2024 12:11:58 +0200 Subject: [PATCH] 3d camera first person example updated to match https://www.raylib.com/examples/core/loader.html?name=core_3d_camera_first_person --- examples/core/3d_camera_first_person/main.go | 165 ++++++++++++++++--- 1 file changed, 146 insertions(+), 19 deletions(-) diff --git a/examples/core/3d_camera_first_person/main.go b/examples/core/3d_camera_first_person/main.go index 7b42f47..7eba060 100644 --- a/examples/core/3d_camera_first_person/main.go +++ b/examples/core/3d_camera_first_person/main.go @@ -1,22 +1,43 @@ package main import ( + "fmt" + rl "github.com/gen2brain/raylib-go/raylib" ) const ( - maxColumns = 20 + maxColumns = 20 + screenWidth = 800 + screenHeight = 450 + False = 0 + True = 1 ) -func main() { - rl.InitWindow(800, 450, "raylib [core] example - 3d camera first person") +var camModes = map[rl.CameraMode]string{ + rl.CameraFree: "FREE", + rl.CameraOrbital: "ORBITAL", + rl.CameraFirstPerson: "FIRST PERSON", + rl.CameraThirdPerson: "THIRD PERSON", +} +var camProjections = map[rl.CameraProjection]string{ + rl.CameraPerspective: "PERSPECTIVE", + rl.CameraOrthographic: "ORTHOGRAPHIC", +} + +func main() { + rl.InitWindow(screenWidth, screenHeight, "raylib [core] example - 3d camera first person") + + // Define the camera to look into our 3d world (position, target, up vector) camera := rl.Camera3D{} - camera.Position = rl.NewVector3(4.0, 2.0, 4.0) - camera.Target = rl.NewVector3(0.0, 1.8, 0.0) - camera.Up = rl.NewVector3(0.0, 1.0, 0.0) - camera.Fovy = 60.0 - camera.Projection = rl.CameraPerspective + camera.Position = rl.NewVector3(0.0, 2.0, 4.0) // Camera position + camera.Target = rl.NewVector3(0.0, 2.0, 0.0) // Camera looking at point + camera.Up = rl.NewVector3(0.0, 1.0, 0.0) // Camera up vector (rotation towards target) + camera.Fovy = 60.0 // Camera field-of-view Y + camera.Projection = rl.CameraPerspective // Camera projection type + + cameraMode := rl.CameraFirstPerson // Generates some random columns heights := make([]float32, maxColumns) @@ -24,15 +45,81 @@ func main() { colors := make([]rl.Color, maxColumns) for i := 0; i < maxColumns; i++ { - heights[i] = float32(rl.GetRandomValue(1, 12)) - positions[i] = rl.NewVector3(float32(rl.GetRandomValue(-15, 15)), heights[i]/2, float32(rl.GetRandomValue(-15, 15))) - colors[i] = rl.NewColor(uint8(rl.GetRandomValue(20, 255)), uint8(rl.GetRandomValue(10, 55)), 30, 255) + heights[i] = rndF(1, 12) + positions[i] = rl.NewVector3(rndF(-15, 15), heights[i]/2, rndF(-15, 15)) + colors[i] = rl.NewColor(rndU(20, 255), rndU(10, 55), 30, 255) } - rl.SetTargetFPS(60) + rl.DisableCursor() // Limit cursor to relative movement inside the window + rl.SetTargetFPS(60) // Set our game to run at 60 frames-per-second - for !rl.WindowShouldClose() { - rl.UpdateCamera(&camera, rl.CameraFirstPerson) // Update camera with first person mode + // Main game loop + for !rl.WindowShouldClose() { // Detect window close button or ESC key + // Switch camera mode + if rl.IsKeyPressed(rl.KeyOne) { + cameraMode = rl.CameraFree + camera.Up = rl.NewVector3(0.0, 1.0, 0.0) // Reset roll + } + if rl.IsKeyPressed(rl.KeyTwo) { + cameraMode = rl.CameraFirstPerson + camera.Up = rl.NewVector3(0.0, 1.0, 0.0) // Reset roll + } + if rl.IsKeyPressed(rl.KeyThree) { + cameraMode = rl.CameraThirdPerson + camera.Up = rl.NewVector3(0.0, 1.0, 0.0) // Reset roll + } + if rl.IsKeyPressed(rl.KeyFour) { + cameraMode = rl.CameraOrbital + camera.Up = rl.NewVector3(0.0, 1.0, 0.0) // Reset roll + } + + // Switch camera projection + if rl.IsKeyPressed(rl.KeyP) { + cameraMode = rl.CameraThirdPerson + if camera.Projection == rl.CameraPerspective { + // Create isometric view + // Note: The target distance is related to the render distance in the orthographic projection + camera.Position = rl.NewVector3(0.0, 2.0, -100.0) + camera.Target = rl.NewVector3(0.0, 2.0, 0.0) + camera.Up = rl.NewVector3(0.0, 1.0, 0.0) + camera.Projection = rl.CameraOrthographic + camera.Fovy = 20.0 // near plane width in CAMERA_ORTHOGRAPHIC + rl.CameraYaw(&camera, -135*rl.Deg2rad, True) + rl.CameraPitch(&camera, -45*rl.Deg2rad, True, True, False) + } else if camera.Projection == rl.CameraOrthographic { + // Reset to default view + camera.Position = rl.NewVector3(0.0, 2.0, 10.0) + camera.Target = rl.NewVector3(0.0, 2.0, 0.0) + camera.Up = rl.NewVector3(0.0, 1.0, 0.0) + camera.Projection = rl.CameraPerspective + camera.Fovy = 60.0 + } + } + + // Update camera computes movement internally depending on the camera mode. + // Some default standard keyboard/mouse inputs are hardcoded to simplify use. + // For advance camera controls, it's recommended to compute camera movement manually. + rl.UpdateCamera(&camera, cameraMode) // Update camera + + /* + // Camera PRO usage example (EXPERIMENTAL) + // This new camera function allows custom movement/rotation values to be directly provided + // as input parameters, with this approach, rcamera module is internally independent of raylib inputs + UpdateCameraPro(&camera, + (Vector3){ + (IsKeyDown(KEY_W) || IsKeyDown(KEY_UP))*0.1f - // Move forward-backward + (IsKeyDown(KEY_S) || IsKeyDown(KEY_DOWN))*0.1f, + (IsKeyDown(KEY_D) || IsKeyDown(KEY_RIGHT))*0.1f - // Move right-left + (IsKeyDown(KEY_A) || IsKeyDown(KEY_LEFT))*0.1f, + 0.0f // Move up-down + }, + (Vector3){ + GetMouseDelta().x*0.05f, // Rotation: yaw + GetMouseDelta().y*0.05f, // Rotation: pitch + 0.0f // Rotation: roll + }, + GetMouseWheelMove()*2.0f); // Move to target (zoom) + */ rl.BeginDrawing() @@ -51,17 +138,57 @@ func main() { rl.DrawCubeWires(positions[i], 2.0, heights[i], 2.0, rl.Maroon) } + // Draw player cube + if cameraMode == rl.CameraThirdPerson { + rl.DrawCube(camera.Target, 0.5, 0.5, 0.5, rl.Purple) + rl.DrawCubeWires(camera.Target, 0.5, 0.5, 0.5, rl.DarkPurple) + } + rl.EndMode3D() - rl.DrawRectangle(10, 10, 220, 70, rl.Fade(rl.SkyBlue, 0.5)) - rl.DrawRectangleLines(10, 10, 220, 70, rl.Blue) + // Draw info boxes + rl.DrawRectangle(5, 5, 330, 100, rl.Fade(rl.SkyBlue, 0.5)) + rl.DrawRectangleLines(5, 5, 330, 100, rl.Blue) - rl.DrawText("First person camera default controls:", 20, 20, 10, rl.Black) - rl.DrawText("- Move with keys: W, A, S, D", 40, 40, 10, rl.DarkGray) - rl.DrawText("- Mouse move to look around", 40, 60, 10, rl.DarkGray) + rl.DrawText("Camera controls:", 15, 15, 10, rl.Black) + rl.DrawText("- Move keys: W, A, S, D, Space, Left-Ctrl", 15, 30, 10, rl.Black) + rl.DrawText("- Look around: arrow keys or mouse", 15, 45, 10, rl.Black) + rl.DrawText("- Camera mode keys: 1,2,3,4", 15, 60, 10, rl.Black) + rl.DrawText("- Zoom keys: num-plus, num-minus or mouse scroll", 15, 75, 10, rl.Black) + rl.DrawText("- Camera projection key: P", 15, 90, 10, rl.Black) + + rl.DrawRectangle(600, 5, 195, 100, rl.Fade(rl.SkyBlue, 0.5)) + rl.DrawRectangleLines(600, 5, 195, 100, rl.Blue) + + rl.DrawText("Camera status:", 610, 15, 10, rl.Black) + rl.DrawText(s2T("Mode:", camModes[cameraMode]), 610, 30, 10, rl.Black) + rl.DrawText(s2T("Projection:", camProjections[camera.Projection]), 610, 45, 10, rl.Black) + rl.DrawText(s2T("Position:", v2T(camera.Position)), 610, 60, 10, rl.Black) + rl.DrawText(s2T("Target:", v2T(camera.Target)), 610, 75, 10, rl.Black) + rl.DrawText(s2T("Up:", v2T(camera.Up)), 610, 90, 10, rl.Black) rl.EndDrawing() } rl.CloseWindow() } + +// rndU generates a random uint8 value between min and max +func rndU(min, max int32) uint8 { + return uint8(rl.GetRandomValue(min, max)) +} + +// rndF generates a random float32 value between min and max +func rndF(min, max int32) float32 { + return float32(rl.GetRandomValue(min, max)) +} + +// s2t generates a Status item string from a name and value +func s2T(name, value string) string { + return fmt.Sprintf(" - %s %s", name, value) +} + +// v2T generates a string from a rl.Vector3 +func v2T(v rl.Vector3) string { + return fmt.Sprintf("%6.3f, %6.3f, %6.3f", v.X, v.Y, v.Z) +}