mirror of
https://github.com/OpenDiablo2/OpenDiablo2
synced 2024-11-20 03:16:26 -05:00
92 lines
2.5 KiB
Go
92 lines
2.5 KiB
Go
package d2vector
|
|
|
|
import (
|
|
"fmt"
|
|
"math"
|
|
)
|
|
|
|
const subTilesPerTile float64 = 5
|
|
|
|
// Position is a vector in world space. The stored value is the one returned by Position.World()
|
|
type Position struct {
|
|
Vector
|
|
}
|
|
|
|
// NewPosition creates a new Position at the given float64 world position.
|
|
func NewPosition(x, y float64) Position {
|
|
p := Position{NewVector(x, y)}
|
|
p.checkValues()
|
|
|
|
return p
|
|
}
|
|
|
|
// EntityPosition returns a Position struct based on the given entity spawn point.
|
|
// The value given should be the one set in d2mapstamp.Stamp.Entities:
|
|
// (tileOffsetX*5)+object.X, (tileOffsetY*5)+object.Y
|
|
// TODO: This probably doesn't support positions in between sub tiles so will only be suitable for spawning entities from map generation, not for multiplayer syncing.
|
|
func EntityPosition(x, y int) Position {
|
|
return NewPosition(float64(x)/5, float64(y)/5)
|
|
}
|
|
|
|
// Set sets this position to the given x and y values.
|
|
func (p *Position) Set(x, y float64) {
|
|
p.x, p.y = x, y
|
|
p.checkValues()
|
|
}
|
|
|
|
func (p *Position) checkValues() {
|
|
if math.IsNaN(p.x) || math.IsNaN(p.y) {
|
|
panic(fmt.Sprintf("float value is NaN: %s", p.Vector))
|
|
}
|
|
|
|
if math.IsInf(p.x, 0) || math.IsInf(p.y, 0) {
|
|
panic(fmt.Sprintf("float value is Inf: %s", p.Vector))
|
|
}
|
|
}
|
|
|
|
// World is the position, where 1 = one map tile.
|
|
// unused
|
|
func (p *Position) World() *Vector {
|
|
return &p.Vector
|
|
}
|
|
|
|
// Tile is the tile position, always a whole number. (tileX, tileY)
|
|
func (p *Position) Tile() *Vector {
|
|
c := p.World().Clone()
|
|
return c.Floor()
|
|
}
|
|
|
|
// TileOffset is the offset from the tile position, always < 1.
|
|
// unused
|
|
func (p *Position) TileOffset() *Vector {
|
|
c := p.World().Clone()
|
|
return c.Subtract(p.Tile())
|
|
}
|
|
|
|
// SubWorld is the position, where 5 = one map tile. (locationX, locationY)
|
|
func (p *Position) SubWorld() *Vector {
|
|
c := p.World().Clone()
|
|
return c.Scale(subTilesPerTile)
|
|
}
|
|
|
|
// SubTile is the tile position in sub tiles, always a multiple of 5.
|
|
// unused
|
|
func (p *Position) SubTile() *Vector {
|
|
return p.Tile().Scale(subTilesPerTile)
|
|
}
|
|
|
|
// SubTileOffset is the offset from the sub tile position in sub tiles, always < 1.
|
|
// unused
|
|
func (p *Position) SubTileOffset() *Vector {
|
|
return p.SubWorld().Subtract(p.SubTile())
|
|
}
|
|
|
|
// TODO: understand this and maybe improve/remove it
|
|
// SubTileOffset() + 1. It's used for rendering. It seems to always do this:
|
|
// v.offsetX+int((v.subcellX-v.subcellY)*16),
|
|
// v.offsetY+int(((v.subcellX+v.subcellY)*8)-5),
|
|
// ^ Maybe similar to Viewport.OrthoToWorld? (subCellX, subCellY)
|
|
func (p *Position) SubCell() *Vector {
|
|
return p.SubTileOffset().AddScalar(1)
|
|
}
|