package fpscontrols import ( "math" "github.com/go-gl/glfw/v3.3/glfw" "github.com/go-gl/mathgl/mgl32" ) type FPSControls struct { lookSpeed float32 moveSpeed float32 position mgl32.Vec3 rotation mgl32.Vec2 lastMousePos mgl32.Vec2 view mgl32.Mat4 window *glfw.Window lastTime float64 } var instance *FPSControls func (c *FPSControls) Update() { time := glfw.GetTime() var deltaTime float32 = float32(time - c.lastTime) c.lastTime = time _, right, _ := c.directions() globalUp := mgl32.Vec3{0, 1, 0} move := mgl32.Vec3{0, 0, 0} if c.window.GetKey(glfw.KeyA) == glfw.Press { move[0] += 1 } if c.window.GetKey(glfw.KeyD) == glfw.Press { move[0] -= 1 } if c.window.GetKey(glfw.KeySpace) == glfw.Press { move[1] += 1 } if c.window.GetKey(glfw.KeyLeftShift) == glfw.Press { move[1] -= 1 } if c.window.GetKey(glfw.KeyW) == glfw.Press { move[2] += 1 } if c.window.GetKey(glfw.KeyS) == glfw.Press { move[2] -= 1 } move = right.Mul(move.X()).Add(globalUp.Mul(move.Y())).Add(right.Cross(globalUp).Mul(move.Z())) c.position = c.position.Add(move.Mul(deltaTime * c.moveSpeed)) x, y := c.window.GetCursorPos() look := mgl32.Vec2{ float32(y) - c.lastMousePos.X(), c.lastMousePos.Y() - float32(x), }.Mul(deltaTime * c.lookSpeed) c.rotation = c.rotation.Add(look) c.rotation = mgl32.Vec2{ min(max(-89.9, c.rotation.X()), 89.9), float32(int32(c.rotation.Y())%360) + c.rotation.Y() - float32(int32(c.rotation.Y())), } c.lastMousePos[0] = float32(y) c.lastMousePos[1] = float32(x) forward, _, _ := c.directions() c.view = mgl32.LookAtV(c.position, c.position.Add(forward), globalUp) } func Get(lookSpeed, moveSpeed float32, position mgl32.Vec3, rotation mgl32.Vec2, window *glfw.Window) *FPSControls { if instance != nil { return instance } instance = &FPSControls{ moveSpeed: moveSpeed, lookSpeed: lookSpeed, position: position, rotation: rotation, window: window, } window.SetInputMode(glfw.CursorMode, glfw.CursorDisabled) return instance } func (c *FPSControls) directions() (mgl32.Vec3, mgl32.Vec3, mgl32.Vec3) { rad := mgl32.Vec2{ mgl32.DegToRad(c.rotation.X()), mgl32.DegToRad(c.rotation.Y()), } sin := mgl32.Vec2{ float32(math.Sin(float64(rad.X()))), float32(math.Sin(float64(rad.Y()))), } cos := mgl32.Vec2{ float32(math.Cos(float64(rad.X()))), float32(math.Cos(float64(rad.Y()))), } forward := mgl32.Vec3{ cos.X() * sin.Y(), -sin.X(), cos.X() * cos.Y(), } right := mgl32.Vec3{ cos.Y(), 0, -sin.Y(), } up := forward.Cross(right) return forward, right, up } func (c *FPSControls) View() mgl32.Mat4 { return c.view } func (c *FPSControls) Position() mgl32.Vec3 { return c.position } func (c *FPSControls) Rotation() mgl32.Vec2 { return c.rotation }