mirror of
https://github.com/OpenDiablo2/OpenDiablo2
synced 2025-02-07 00:56:51 -05:00
Position struct for managing world coordinates (#540)
* Fixed nil pointer in Copy() * Position added Added Floor() and String() methods to Vector. Also added Position which declares an embedded Vector2 and returns various forms of it. * Position tests improved
This commit is contained in:
parent
853ad7ae64
commit
07d90e9681
@ -40,4 +40,6 @@ type Vector interface {
|
||||
Reflect(normal Vector) Vector
|
||||
Mirror(axis Vector) Vector
|
||||
Rotate(delta *big.Float) Vector
|
||||
Floor() Vector
|
||||
String() string
|
||||
}
|
||||
|
56
d2common/d2math/d2vector/position.go
Normal file
56
d2common/d2math/d2vector/position.go
Normal file
@ -0,0 +1,56 @@
|
||||
package d2vector
|
||||
|
||||
import "github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||
|
||||
// Position is a vector in world space. The stored
|
||||
// value is the one returned by Position.World()
|
||||
type Position struct {
|
||||
d2interface.Vector
|
||||
}
|
||||
|
||||
// NewPosition creates a new Position at the given
|
||||
// float64 world position.
|
||||
func NewPosition(x, y float64) *Position {
|
||||
return &Position{New(x, y)}
|
||||
}
|
||||
|
||||
// World is the position, where 1 = one map
|
||||
// tile.
|
||||
func (p *Position) World() d2interface.Vector {
|
||||
return p.Vector
|
||||
}
|
||||
|
||||
// Tile is the tile position, always a whole
|
||||
// number.
|
||||
func (p *Position) Tile() d2interface.Vector {
|
||||
c := p.World().Clone()
|
||||
return c.Floor()
|
||||
}
|
||||
|
||||
// TileOffset is the offset from the tile position,
|
||||
// always < 1.
|
||||
func (p *Position) TileOffset() d2interface.Vector {
|
||||
c := p.World().Clone()
|
||||
return c.Subtract(p.Tile())
|
||||
}
|
||||
|
||||
// SubWorld is the position, where 5 = one map
|
||||
// tile.
|
||||
func (p *Position) SubWorld() d2interface.Vector {
|
||||
c := p.World().Clone()
|
||||
return c.Multiply(New(5, 5))
|
||||
}
|
||||
|
||||
// SubTile is the tile position in sub tiles,
|
||||
// always a multiple of 5.
|
||||
func (p *Position) SubTile() d2interface.Vector {
|
||||
c := p.Tile().Clone()
|
||||
return c.Multiply(New(5, 5))
|
||||
}
|
||||
|
||||
// SubTileOffset is the offset from the sub tile
|
||||
// position in sub tiles, always < 1.
|
||||
func (p *Position) SubTileOffset() d2interface.Vector {
|
||||
c := p.SubWorld().Clone()
|
||||
return c.Subtract(p.SubTile())
|
||||
}
|
62
d2common/d2math/d2vector/position_test.go
Normal file
62
d2common/d2math/d2vector/position_test.go
Normal file
@ -0,0 +1,62 @@
|
||||
package d2vector
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||
)
|
||||
|
||||
func validate(t *testing.T, original, got, want, unchanged d2interface.Vector) {
|
||||
if !got.FuzzyEquals(want) {
|
||||
t.Errorf("want %s: got %s", want, got)
|
||||
}
|
||||
|
||||
if !original.FuzzyEquals(unchanged) {
|
||||
t.Errorf("Position value %s was incorrectly changed to %s when calling this method", unchanged, original)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTile(t *testing.T) {
|
||||
p := NewPosition(1.6, 1.6)
|
||||
got := p.Tile()
|
||||
want := New(1, 1)
|
||||
unchanged := New(1.6, 1.6)
|
||||
|
||||
validate(t, p, got, want, unchanged)
|
||||
}
|
||||
|
||||
func TestTileOffset(t *testing.T) {
|
||||
p := NewPosition(1.6, 1.6)
|
||||
got := p.TileOffset()
|
||||
want := New(0.6, 0.6)
|
||||
unchanged := New(1.6, 1.6)
|
||||
|
||||
validate(t, p, got, want, unchanged)
|
||||
}
|
||||
|
||||
func TestSubWorld(t *testing.T) {
|
||||
p := NewPosition(1, 1)
|
||||
got := p.SubWorld()
|
||||
want := New(5, 5)
|
||||
unchanged := New(1, 1)
|
||||
|
||||
validate(t, p, got, want, unchanged)
|
||||
}
|
||||
|
||||
func TestSubTile(t *testing.T) {
|
||||
p := NewPosition(1, 1)
|
||||
got := p.SubTile()
|
||||
want := New(5, 5)
|
||||
unchanged := New(1, 1)
|
||||
|
||||
validate(t, p, got, want, unchanged)
|
||||
}
|
||||
|
||||
func TestSubTileOffset(t *testing.T) {
|
||||
p := NewPosition(1.1, 1.1)
|
||||
got := p.SubTileOffset()
|
||||
want := New(0.5, 0.5)
|
||||
unchanged := New(1.1, 1.1)
|
||||
|
||||
validate(t, p, got, want, unchanged)
|
||||
}
|
@ -2,6 +2,7 @@
|
||||
package d2vector
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"math/big"
|
||||
|
||||
@ -64,7 +65,7 @@ func (v *Vector2) Unmarshal(buf []byte) error {
|
||||
|
||||
// Clone creates a copy of this Vector
|
||||
func (v *Vector2) Clone() d2interface.Vector {
|
||||
result := &Vector2{}
|
||||
result := New(0, 0)
|
||||
result.Copy(v)
|
||||
|
||||
return result
|
||||
@ -359,32 +360,47 @@ func (v *Vector2) Rotate(angle *big.Float) d2interface.Vector {
|
||||
return v
|
||||
}
|
||||
|
||||
// Floor rounds the vector down to the nearest whole numbers.
|
||||
func (v *Vector2) Floor() d2interface.Vector {
|
||||
var xi, yi big.Int
|
||||
v.x.Int(&xi)
|
||||
v.y.Int(&yi)
|
||||
v.X().SetInt(&xi)
|
||||
v.Y().SetInt(&yi)
|
||||
|
||||
return v
|
||||
}
|
||||
|
||||
func (v *Vector2) String() string {
|
||||
return fmt.Sprintf("Vector2{%s, %s}", v.x.Text('f', 5), v.y.Text('f', 5))
|
||||
}
|
||||
|
||||
// Up returns a new vector (0, 1)
|
||||
func Up() *Vector2 {
|
||||
func Up() d2interface.Vector {
|
||||
return New(0, 1)
|
||||
}
|
||||
|
||||
// Down returns a new vector (0, -1)
|
||||
func Down() *Vector2 {
|
||||
func Down() d2interface.Vector {
|
||||
return New(0, -1)
|
||||
}
|
||||
|
||||
// Right returns a new vector (1, 0)
|
||||
func Right() *Vector2 {
|
||||
func Right() d2interface.Vector {
|
||||
return New(1, 0)
|
||||
}
|
||||
|
||||
// Left returns a new vector (-1, 0)
|
||||
func Left() *Vector2 {
|
||||
func Left() d2interface.Vector {
|
||||
return New(-1, 0)
|
||||
}
|
||||
|
||||
// One returns a new vector (1, 1)
|
||||
func One() *Vector2 {
|
||||
func One() d2interface.Vector {
|
||||
return New(1, 1)
|
||||
}
|
||||
|
||||
// Zero returns a new vector (0, 0)
|
||||
func Zero() *Vector2 {
|
||||
func Zero() d2interface.Vector {
|
||||
return New(0, 0)
|
||||
}
|
||||
|
33
d2common/d2math/d2vector/vector_test.go
Normal file
33
d2common/d2math/d2vector/vector_test.go
Normal file
@ -0,0 +1,33 @@
|
||||
package d2vector
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestClone(t *testing.T) {
|
||||
v := New(1, 1)
|
||||
want := New(1, 1)
|
||||
got := v.Clone()
|
||||
|
||||
if !got.Equals(want) {
|
||||
t.Errorf("wanted %s: got %s", want, got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAbs(t *testing.T) {
|
||||
v := New(-1, -1)
|
||||
want := New(1, 1)
|
||||
got := v.Abs()
|
||||
|
||||
if !got.Equals(want) {
|
||||
t.Errorf("wanted %s: got %s", want, got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFloor(t *testing.T) {
|
||||
v := New(1.6, 1.6)
|
||||
|
||||
want := New(1, 1)
|
||||
|
||||
if !v.Floor().Equals(want) {
|
||||
t.Errorf("want %s: got %s", want, v)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user