diff --git a/bot/client.go b/bot/client.go index 226df7a..23f7b27 100644 --- a/bot/client.go +++ b/bot/client.go @@ -24,6 +24,7 @@ type Client struct { settings Settings Wd world.World //the map data + Inputs phy.Inputs Physics phy.State lastPosTx time.Time diff --git a/bot/ingame.go b/bot/ingame.go index 6bd24fd..cf0105a 100644 --- a/bot/ingame.go +++ b/bot/ingame.go @@ -82,7 +82,7 @@ func (c *Client) HandleGame() error { case <-c.closing: return http.ErrServerClosed case <-cTick.C: - if err := c.Physics.Tick(&c.Wd); err != nil { + if err := c.Physics.Tick(c.Inputs, &c.Wd); err != nil { c.disconnect() return err } diff --git a/bot/phy/inputs.go b/bot/phy/inputs.go new file mode 100644 index 0000000..68a45e5 --- /dev/null +++ b/bot/phy/inputs.go @@ -0,0 +1,8 @@ +package phy + +// Inputs describes the desired movements of the player. +type Inputs struct { + Yaw, Pitch float32 + + ThrottleX, ThrottleZ float64 +} diff --git a/bot/phy/phy.go b/bot/phy/phy.go index fa14360..4450c77 100644 --- a/bot/phy/phy.go +++ b/bot/phy/phy.go @@ -14,7 +14,13 @@ const ( playerHeight = 1.8 resetVel = 0.003 - gravity = 0.08 + yawSpeed = 3.0 + + gravity = 0.08 + drag = 0.98 + acceleration = 0.02 + inertia = 0.91 + slipperiness = 0.6 ) // World represents a provider of information about the surrounding world. @@ -81,10 +87,33 @@ func (s *State) surroundings(query AABB, w World) Surrounds { return out } -func (s *State) Tick(w World) error { +func (s *State) applyInputs(input Inputs, acceleration, inertia float64) { + speed := math.Sqrt(input.ThrottleX*input.ThrottleX + input.ThrottleZ*input.ThrottleZ) + if speed < 0.01 { + return + } + speed = acceleration / math.Max(speed, 1) + + input.ThrottleX *= speed + input.ThrottleZ *= speed + + s.Vel.X += input.ThrottleX + s.Vel.Z += input.ThrottleZ +} + +func (s *State) Tick(input Inputs, w World) error { if !s.Run { return nil } + var inertia = inertia + var acceleration = acceleration + if s.onGround { + inertia *= slipperiness + acceleration = 0.1 * (0.1627714 / (inertia * inertia * inertia)) + } + s.applyInputs(input, acceleration, inertia) + + // Deadzone velocities when they get too low. if math.Abs(s.Vel.X) < resetVel { s.Vel.X = 0 } @@ -94,7 +123,12 @@ func (s *State) Tick(w World) error { if math.Abs(s.Vel.Z) < resetVel { s.Vel.Z = 0 } + // Gravity s.Vel.Y -= gravity + // Drag & friction. + s.Vel.Y *= drag + s.Vel.X *= inertia + s.Vel.Z *= inertia // Apply collision. var ( diff --git a/bot/world/world.go b/bot/world/world.go index bed33b8..5221d36 100644 --- a/bot/world/world.go +++ b/bot/world/world.go @@ -60,7 +60,7 @@ type ChunkLoc struct { func (w *World) GetBlockStatus(x, y, z int) BlockStatus { // Use n>>4 rather then n/16. It acts wrong if n<0. c := w.Chunks[ChunkLoc{x >> 4, z >> 4}] - if c != nil { + if c != nil && y >= 0 { if sec := c.Sections[y>>4]; sec != nil { return sec.GetBlock(SectionIdx(x&15, y&15, z&15)) }