| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169 |
- package main
- import "core:math"
- import "third-party:r3d-odin/r3d"
- import rl "vendor:raylib"
- GRAVITY :: -15.0
- MOVE_SPEED :: 5.0
- JUMP_FORCE :: 8.0
- capsule_center :: proc(caps: r3d.Capsule) -> rl.Vector3 {
- return (caps.start + caps.end) * 0.5
- }
- box_center :: proc(box: rl.BoundingBox) -> rl.Vector3 {
- return (box.min + box.max) * 0.5
- }
- main :: proc() {
- rl.InitWindow(2560, 1440, "[Dev] Sandbox")
- defer rl.CloseWindow()
- rl.SetTargetFPS(60)
- rl.SetWindowState({.VSYNC_HINT, .WINDOW_RESIZABLE})
- r3d.Init(rl.GetScreenWidth(), rl.GetScreenHeight())
- defer r3d.Close()
- r3d.SetTextureFilter(.ANISOTROPIC_8X)
- sky := r3d.GenCubemapSky(4096, r3d.CUBEMAP_SKY_BASE)
- ambient := r3d.GenAmbientMap(sky, {.ILLUMINATION, .REFLECTION})
- env := r3d.GetEnvironment()
- env.background.sky = sky
- env.ambient._map = ambient
- light := r3d.CreateLight(.DIR)
- r3d.SetLightDirection(light, {-1, -1, -1})
- r3d.SetLightRange(light, 16.0)
- r3d.SetLightActive(light, true)
- r3d.EnableShadow(light)
- r3d.SetShadowDepthBias(light, 0.005)
- // Load materials
- baseAlbedo := r3d.LoadAlbedoMap(
- "third-party/r3d-odin/examples/resources/images/placeholder.png",
- rl.WHITE,
- )
- groundMat := r3d.GetDefaultMaterial()
- groundMat.uvScale = {250.0, 250.0}
- groundMat.albedo = baseAlbedo
- slopeMat := r3d.GetDefaultMaterial()
- slopeMat.albedo.color = {255, 255, 0, 255}
- slopeMat.albedo.texture = baseAlbedo.texture
- // Ground
- groundMesh := r3d.GenMeshPlane(1000, 1000, 1, 1)
- defer r3d.UnloadMesh(groundMesh)
- groundBox: rl.BoundingBox = {
- min = {-500, -1, -500},
- max = {500, 0, 500},
- }
- // Slope obstacle
- slopeMeshData := r3d.GenMeshDataSlope(2, 2, 2, {0, 1, -1})
- defer r3d.UnloadMeshData(slopeMeshData)
- slopeMesh := r3d.LoadMesh(.TRIANGLES, slopeMeshData, nil, .STATIC_MESH)
- defer r3d.UnloadMesh(slopeMesh)
- slopeTransform := rl.MatrixTranslate(0, 1, 5)
- // Player capsule
- capsule: r3d.Capsule = {
- start = {0, 0.5, 0},
- end = {0, 1.5, 0},
- radius = 0.5,
- }
- capsMesh := r3d.GenMeshCapsule(0.5, 1.0, 64, 32)
- defer r3d.UnloadMesh(capsMesh)
- velocity: rl.Vector3 = {0, 0, 0}
- // Camera
- cameraAngle: f32 = 0.0
- cameraPitch: f32 = 30.0
- camera: rl.Camera3D = {
- position = {0, 5, 5},
- target = capsule_center(capsule),
- up = {0, 1, 0},
- fovy = 60,
- }
- rl.DisableCursor()
- for !rl.WindowShouldClose() {
- dt := rl.GetFrameTime()
- // Camera rotation
- mouseDelta := rl.GetMouseDelta()
- cameraAngle -= mouseDelta.x * 0.15
- cameraPitch = clamp(cameraPitch + mouseDelta.y * 0.15, -7.5, 80.0)
- // Movement input relative to camera
- dx := i32(rl.IsKeyDown(.A)) - i32(rl.IsKeyDown(.D))
- dz := i32(rl.IsKeyDown(.W)) - i32(rl.IsKeyDown(.S))
- moveInput: rl.Vector3 = {0, 0, 0}
- if dx != 0 || dz != 0 {
- angleRad := cameraAngle * rl.DEG2RAD
- right := rl.Vector3{math.cos_f32(angleRad), 0, -math.sin_f32(angleRad)}
- forward := rl.Vector3{math.sin_f32(angleRad), 0, math.cos_f32(angleRad)}
- moveInput = rl.Vector3Normalize(right * f32(dx) + forward * f32(dz))
- }
- // Check grounded
- isGrounded :=
- r3d.IsCapsuleGroundedBox(capsule, 0.01, groundBox, nil) ||
- r3d.IsCapsuleGroundedMesh(capsule, 0.3, slopeMeshData, slopeTransform, nil)
- // Jump and apply gravity
- if isGrounded && rl.IsKeyPressed(.SPACE) do velocity.y = JUMP_FORCE
- if !isGrounded do velocity.y += GRAVITY * dt
- else if velocity.y < 0 do velocity.y = 0
- // Calculate total movement
- movement := moveInput * MOVE_SPEED * dt
- movement.y = velocity.y * dt
- // Apply movement with collision
- movement = r3d.SlideCapsuleMesh(capsule, movement, slopeMeshData, slopeTransform, nil)
- capsule.start = capsule.start + movement
- capsule.end = capsule.end + movement
- // Ground clamp
- if capsule.start.y < 0.5 {
- correction := 0.5 - capsule.start.y
- capsule.start.y += correction
- capsule.end.y += correction
- velocity.y = 0
- }
- // Update camera position
- target := capsule_center(capsule)
- pitchRad := cameraPitch * rl.DEG2RAD
- angleRad := cameraAngle * rl.DEG2RAD
- camera.position = {
- target.x - math.sin_f32(angleRad) * math.cos_f32(pitchRad) * 5.0,
- target.y + math.sin_f32(pitchRad) * 5.0,
- target.z - math.cos_f32(angleRad) * math.cos_f32(pitchRad) * 5.0,
- }
- camera.target = target
- rl.BeginDrawing()
- rl.ClearBackground(rl.BLACK)
- r3d.Begin(camera)
- r3d.DrawMeshPro(slopeMesh, slopeMat, slopeTransform)
- r3d.DrawMesh(groundMesh, groundMat, {0, 0, 0}, 1.0)
- r3d.DrawMesh(capsMesh, r3d.GetDefaultMaterial(), capsule_center(capsule), 1.0)
- r3d.End()
- rl.DrawFPS(10, 10)
- rl.DrawText(
- isGrounded ? "GROUNDED" : "AIRBORNE",
- 10,
- rl.GetScreenHeight() - 30,
- 20,
- isGrounded ? rl.LIME : rl.YELLOW,
- )
- rl.EndDrawing()
- }
- }
|