light renaming and 3 space stuff
This commit is contained in:
parent
882d0c623d
commit
464cf9a678
9 changed files with 115 additions and 30 deletions
|
@ -37,6 +37,6 @@ func (b *Billboard) Draw(screen *ebiten.Image, opts *ebiten.DrawImageOptions) {
|
||||||
func (b *Billboard) Scan() []interface{} { return []interface{}{&b.Src} }
|
func (b *Billboard) Scan() []interface{} { return []interface{}{&b.Src} }
|
||||||
|
|
||||||
func (b *Billboard) Transform() (opts ebiten.DrawImageOptions) {
|
func (b *Billboard) Transform() (opts ebiten.DrawImageOptions) {
|
||||||
opts.GeoM.Translate(pfloat(b.Pos))
|
opts.GeoM.Translate(cfloat(b.Pos))
|
||||||
return opts
|
return opts
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,7 +59,7 @@ func (c *Camera) PointAt(centre image.Point, zoom float64) {
|
||||||
|
|
||||||
// If the configured centre puts the camera out of bounds, move it.
|
// If the configured centre puts the camera out of bounds, move it.
|
||||||
// Camera frame currently Rectangle{ centre ± (screen/(2*zoom)) }.
|
// Camera frame currently Rectangle{ centre ± (screen/(2*zoom)) }.
|
||||||
sw2, sh2 := pfloat(c.game.ScreenSize.Div(2))
|
sw2, sh2 := cfloat(c.game.ScreenSize.Div(2))
|
||||||
swz, shz := int(sw2/zoom), int(sh2/zoom)
|
swz, shz := int(sw2/zoom), int(sh2/zoom)
|
||||||
if centre.X-swz < br.Min.X {
|
if centre.X-swz < br.Min.X {
|
||||||
centre.X = br.Min.X + swz
|
centre.X = br.Min.X + swz
|
||||||
|
@ -87,9 +87,9 @@ func (c *Camera) Scan() []interface{} { return []interface{}{c.Child} }
|
||||||
|
|
||||||
// Transform returns the camera transform.
|
// Transform returns the camera transform.
|
||||||
func (c *Camera) Transform() (opts ebiten.DrawImageOptions) {
|
func (c *Camera) Transform() (opts ebiten.DrawImageOptions) {
|
||||||
opts.GeoM.Translate(pfloat(c.Centre.Mul(-1)))
|
opts.GeoM.Translate(cfloat(c.Centre.Mul(-1)))
|
||||||
opts.GeoM.Scale(c.Zoom, c.Zoom)
|
opts.GeoM.Scale(c.Zoom, c.Zoom)
|
||||||
opts.GeoM.Rotate(c.Rotation)
|
opts.GeoM.Rotate(c.Rotation)
|
||||||
opts.GeoM.Translate(pfloat(c.game.ScreenSize.Div(2)))
|
opts.GeoM.Translate(cfloat(c.game.ScreenSize.Div(2)))
|
||||||
return opts
|
return opts
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,94 @@
|
||||||
package engine
|
package engine
|
||||||
|
|
||||||
|
import "strconv"
|
||||||
|
|
||||||
|
// Point3 is a en element of int^3.
|
||||||
|
type Point3 struct {
|
||||||
|
X, Y, Z int
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pt3(x, y, z) is shorthand for Point3{x, y, z}.
|
||||||
|
func Pt3(x, y, z int) Point3 {
|
||||||
|
return Point3{x, y, z}
|
||||||
|
}
|
||||||
|
|
||||||
|
// String returns a string representation of p like "(3,4,5)".
|
||||||
|
func (p Point3) String() string {
|
||||||
|
return "(" + strconv.Itoa(p.X) + "," + strconv.Itoa(p.Y) + "," + strconv.Itoa(p.Z) + ")"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add performs vector addition.
|
||||||
|
func (p Point3) Add(q Point3) Point3 {
|
||||||
|
return Point3{p.X + q.X, p.Y + q.Y, p.Z + q.Z}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sub performs vector subtraction.
|
||||||
|
func (p Point3) Sub(q Point3) Point3 {
|
||||||
|
return p.Add(q.Neg())
|
||||||
|
}
|
||||||
|
|
||||||
|
// CMul performs componentwise multiplication.
|
||||||
|
func (p Point3) CMul(q Point3) Point3 {
|
||||||
|
return Point3{p.X * q.X, p.Y * q.Y, p.Z * q.Z}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mul performs scalar multiplication.
|
||||||
|
func (p Point3) Mul(k int) Point3 {
|
||||||
|
return Point3{p.X * k, p.Y * k, p.Z * k}
|
||||||
|
}
|
||||||
|
|
||||||
|
// CDiv performs componentwise division.
|
||||||
|
func (p Point3) CDiv(q Point3) Point3 {
|
||||||
|
return Point3{p.X / q.X, p.Y / q.Y, p.Z / q.Z}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Div performs scalar division by k.
|
||||||
|
func (p Point3) Div(k int) Point3 {
|
||||||
|
return Point3{p.X / k, p.Y / k, p.Z / k}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Neg returns the vector pointing in the opposite direction.
|
||||||
|
func (p Point3) Neg() Point3 {
|
||||||
|
return Point3{-p.X, -p.Y, -p.Z}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Coord returns the components of the vector.
|
||||||
|
func (p Point3) Coord() (x, y, z int) {
|
||||||
|
return p.X, p.Y, p.Z
|
||||||
|
}
|
||||||
|
|
||||||
// Box describes an axis-aligned rectangular prism.
|
// Box describes an axis-aligned rectangular prism.
|
||||||
type Box struct {
|
type Box struct {
|
||||||
X, Y, Z int // coordinate of the left-top-farthest corner
|
Min, Max Point3
|
||||||
W, H, D int // width, height, depth
|
}
|
||||||
|
|
||||||
|
// String returns a string representation of b like "(3,4,5)-(6,5,8)".
|
||||||
|
func (b Box) String() string {
|
||||||
|
return b.Min.String() + "-" + b.Max.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Empty reports whether the box contains no points.
|
||||||
|
func (b Box) Empty() bool {
|
||||||
|
return b.Min.X >= b.Max.X || b.Min.Y >= b.Max.Y || b.Min.Z >= b.Max.Z
|
||||||
|
}
|
||||||
|
|
||||||
|
// Eq reports whether b and c contain the same set of points. All empty boxes
|
||||||
|
// are considered equal.
|
||||||
|
func (b Box) Eq(c Box) bool {
|
||||||
|
return b == c || b.Empty() && c.Empty()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Overlaps reports whether b and c have non-empty intersection.
|
||||||
|
func (b Box) Overlaps(c Box) bool {
|
||||||
|
return !b.Empty() && !c.Empty() &&
|
||||||
|
b.Min.X < c.Max.X && c.Min.X < b.Max.X &&
|
||||||
|
b.Min.Y < c.Max.Y && c.Min.Y < b.Max.Y &&
|
||||||
|
b.Min.Z < c.Max.Z && c.Min.Z < b.Max.Z
|
||||||
|
}
|
||||||
|
|
||||||
|
// Size returns b's width, height, and depth.
|
||||||
|
func (b Box) Size() Point3 {
|
||||||
|
return b.Max.Sub(b.Min)
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsoProjection translates an integer 3D coordinate into an integer 2D
|
// IsoProjection translates an integer 3D coordinate into an integer 2D
|
||||||
|
|
|
@ -44,20 +44,20 @@ type ZOrder float64
|
||||||
// DrawOrder returns z as a float64.
|
// DrawOrder returns z as a float64.
|
||||||
func (z ZOrder) DrawOrder() float64 { return float64(z) }
|
func (z ZOrder) DrawOrder() float64 { return float64(z) }
|
||||||
|
|
||||||
// ---------- Some math helpers for image.Point ----------
|
// ---------- Some helpers for image.Point ----------
|
||||||
|
|
||||||
func pmul(p, q image.Point) image.Point {
|
// cmul performs componentwise multiplication of two image.Points.
|
||||||
p.X *= q.X
|
func cmul(p, q image.Point) image.Point {
|
||||||
p.Y *= q.Y
|
return image.Point{p.X * q.X, p.Y * q.Y}
|
||||||
return p
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func pdiv(p, q image.Point) image.Point {
|
// cdiv performs componentwise division of two image.Points.
|
||||||
p.X /= q.X
|
func cdiv(p, q image.Point) image.Point {
|
||||||
p.Y /= q.Y
|
return image.Point{p.X / q.X, p.Y / q.Y}
|
||||||
return p
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func pfloat(p image.Point) (float64, float64) {
|
// cfloat returns the components of an image.Point as two floats.
|
||||||
|
func cfloat(p image.Point) (x, y float64) {
|
||||||
return float64(p.X), float64(p.Y)
|
return float64(p.X), float64(p.Y)
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,7 +42,7 @@ func (p *Parallax) Scan() []interface{} { return []interface{}{p.Child} }
|
||||||
|
|
||||||
// Transform returns a GeoM translation of Factor * camera.Centre.
|
// Transform returns a GeoM translation of Factor * camera.Centre.
|
||||||
func (p *Parallax) Transform() (opts ebiten.DrawImageOptions) {
|
func (p *Parallax) Transform() (opts ebiten.DrawImageOptions) {
|
||||||
x, y := pfloat(p.camera.Centre)
|
x, y := cfloat(p.camera.Centre)
|
||||||
opts.GeoM.Translate(x*p.Factor, y*p.Factor)
|
opts.GeoM.Translate(x*p.Factor, y*p.Factor)
|
||||||
return opts
|
return opts
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,7 +41,7 @@ func (s *Sheet) Scan() []interface{} { return []interface{}{&s.Src} }
|
||||||
|
|
||||||
// SubImage returns an *ebiten.Image corresponding to the given cell index.
|
// SubImage returns an *ebiten.Image corresponding to the given cell index.
|
||||||
func (s *Sheet) SubImage(i int) *ebiten.Image {
|
func (s *Sheet) SubImage(i int) *ebiten.Image {
|
||||||
p := pmul(image.Pt(i%s.w, i/s.w), s.CellSize)
|
p := cmul(image.Pt(i%s.w, i/s.w), s.CellSize)
|
||||||
r := image.Rectangle{p, p.Add(s.CellSize)}
|
r := image.Rectangle{p, p.Add(s.CellSize)}
|
||||||
return s.Src.Image().SubImage(r).(*ebiten.Image)
|
return s.Src.Image().SubImage(r).(*ebiten.Image)
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,7 +54,7 @@ func (s *Sprite) SetAnim(a *Anim) {
|
||||||
|
|
||||||
// Transform returns a translation by the FrameOffset.
|
// Transform returns a translation by the FrameOffset.
|
||||||
func (s *Sprite) Transform() (opts ebiten.DrawImageOptions) {
|
func (s *Sprite) Transform() (opts ebiten.DrawImageOptions) {
|
||||||
opts.GeoM.Translate(pfloat(s.Actor.Pos.Add(s.FrameOffset)))
|
opts.GeoM.Translate(cfloat(s.Actor.Pos.Add(s.FrameOffset)))
|
||||||
return opts
|
return opts
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -54,8 +54,8 @@ func (t *Tilemap) CollidesWith(r image.Rectangle) bool {
|
||||||
|
|
||||||
// Probe the map at all tilespace coordinates overlapping the rect.
|
// Probe the map at all tilespace coordinates overlapping the rect.
|
||||||
r = r.Sub(t.Offset)
|
r = r.Sub(t.Offset)
|
||||||
min := pdiv(r.Min, t.Sheet.CellSize)
|
min := cdiv(r.Min, t.Sheet.CellSize)
|
||||||
max := pdiv(r.Max.Sub(image.Pt(1, 1)), t.Sheet.CellSize) // NB: fencepost
|
max := cdiv(r.Max.Sub(image.Pt(1, 1)), t.Sheet.CellSize) // NB: fencepost
|
||||||
|
|
||||||
for j := min.Y; j <= max.Y; j++ {
|
for j := min.Y; j <= max.Y; j++ {
|
||||||
for i := min.X; i <= max.X; i++ {
|
for i := min.X; i <= max.X; i++ {
|
||||||
|
@ -75,7 +75,7 @@ func (t *Tilemap) Draw(screen *ebiten.Image, opts *ebiten.DrawImageOptions) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
var geom ebiten.GeoM
|
var geom ebiten.GeoM
|
||||||
geom.Translate(pfloat(pmul(p, t.Sheet.CellSize)))
|
geom.Translate(cfloat(cmul(p, t.Sheet.CellSize)))
|
||||||
geom.Concat(og)
|
geom.Concat(og)
|
||||||
opts.GeoM = geom
|
opts.GeoM = geom
|
||||||
|
|
||||||
|
@ -110,24 +110,24 @@ func (t *Tilemap) Scan() []interface{} {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Tilemap) Transform() (opts ebiten.DrawImageOptions) {
|
func (t *Tilemap) Transform() (opts ebiten.DrawImageOptions) {
|
||||||
opts.GeoM.Translate(pfloat(t.Offset))
|
opts.GeoM.Translate(cfloat(t.Offset))
|
||||||
return opts
|
return opts
|
||||||
}
|
}
|
||||||
|
|
||||||
// TileAt returns the tile present at the given world coordinate.
|
// TileAt returns the tile present at the given world coordinate.
|
||||||
func (t *Tilemap) TileAt(wc image.Point) Tile {
|
func (t *Tilemap) TileAt(wc image.Point) Tile {
|
||||||
return t.Map[pdiv(wc.Sub(t.Offset), t.Sheet.CellSize)]
|
return t.Map[cdiv(wc.Sub(t.Offset), t.Sheet.CellSize)]
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetTileAt sets the tile at the given world coordinate.
|
// SetTileAt sets the tile at the given world coordinate.
|
||||||
func (t *Tilemap) SetTileAt(wc image.Point, tile Tile) {
|
func (t *Tilemap) SetTileAt(wc image.Point, tile Tile) {
|
||||||
t.Map[pdiv(wc.Sub(t.Offset), t.Sheet.CellSize)] = tile
|
t.Map[cdiv(wc.Sub(t.Offset), t.Sheet.CellSize)] = tile
|
||||||
}
|
}
|
||||||
|
|
||||||
// TileBounds returns a rectangle describing the tile boundary for the tile
|
// TileBounds returns a rectangle describing the tile boundary for the tile
|
||||||
// at the given world coordinate.
|
// at the given world coordinate.
|
||||||
func (t *Tilemap) TileBounds(wc image.Point) image.Rectangle {
|
func (t *Tilemap) TileBounds(wc image.Point) image.Rectangle {
|
||||||
p := pmul(pdiv(wc.Sub(t.Offset), t.Sheet.CellSize), t.Sheet.CellSize).Add(t.Offset)
|
p := cmul(cdiv(wc.Sub(t.Offset), t.Sheet.CellSize), t.Sheet.CellSize).Add(t.Offset)
|
||||||
return image.Rectangle{p, p.Add(t.Sheet.CellSize)}
|
return image.Rectangle{p, p.Add(t.Sheet.CellSize)}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -46,8 +46,8 @@ func (w *Wall) CollidesWith(r image.Rectangle) bool {
|
||||||
|
|
||||||
// Probe the map at all tilespace coordinates overlapping the rect.
|
// Probe the map at all tilespace coordinates overlapping the rect.
|
||||||
r = r.Sub(w.Offset)
|
r = r.Sub(w.Offset)
|
||||||
min := pdiv(r.Min, w.UnitSize)
|
min := cdiv(r.Min, w.UnitSize)
|
||||||
max := pdiv(r.Max.Sub(image.Pt(1, 1)), w.UnitSize) // NB: fencepost
|
max := cdiv(r.Max.Sub(image.Pt(1, 1)), w.UnitSize) // NB: fencepost
|
||||||
|
|
||||||
for j := min.Y; j <= max.Y; j++ {
|
for j := min.Y; j <= max.Y; j++ {
|
||||||
for i := min.X; i <= max.X; i++ {
|
for i := min.X; i <= max.X; i++ {
|
||||||
|
@ -80,7 +80,7 @@ func (w *Wall) Prepare(*Game) error {
|
||||||
|
|
||||||
// Transform returns a GeoM translation by Offset.
|
// Transform returns a GeoM translation by Offset.
|
||||||
func (w *Wall) Transform() (opts ebiten.DrawImageOptions) {
|
func (w *Wall) Transform() (opts ebiten.DrawImageOptions) {
|
||||||
opts.GeoM.Translate(pfloat(w.Offset))
|
opts.GeoM.Translate(cfloat(w.Offset))
|
||||||
return opts
|
return opts
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,6 +106,6 @@ func (u *WallUnit) Draw(screen *ebiten.Image, opts *ebiten.DrawImageOptions) {
|
||||||
func (u *WallUnit) Scan() []interface{} { return []interface{}{u.Tile} }
|
func (u *WallUnit) Scan() []interface{} { return []interface{}{u.Tile} }
|
||||||
|
|
||||||
func (u *WallUnit) Transform() (opts ebiten.DrawImageOptions) {
|
func (u *WallUnit) Transform() (opts ebiten.DrawImageOptions) {
|
||||||
opts.GeoM.Translate(pfloat(pmul(u.Pos, u.wall.UnitSize).Add(u.wall.UnitOffset)))
|
opts.GeoM.Translate(cfloat(cmul(u.Pos, u.wall.UnitSize).Add(u.wall.UnitOffset)))
|
||||||
return opts
|
return opts
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue