projection.go, delete crap
This commit is contained in:
parent
86d076c89f
commit
1e029903a6
10 changed files with 44 additions and 47 deletions
Binary file not shown.
|
@ -38,21 +38,21 @@ func (b Box) Size() Point3 {
|
||||||
|
|
||||||
// Back returns an image.Rectangle representing the back of the box, using
|
// Back returns an image.Rectangle representing the back of the box, using
|
||||||
// the given projection π.
|
// the given projection π.
|
||||||
func (b Box) Back(π image.Point) image.Rectangle {
|
func (b Box) Back(π IntProjection) image.Rectangle {
|
||||||
b.Max.Z = b.Min.Z
|
b.Max.Z = b.Min.Z
|
||||||
return image.Rectangle{
|
return image.Rectangle{
|
||||||
Min: b.Min.IsoProject(π),
|
Min: π.Project(b.Min),
|
||||||
Max: b.Max.IsoProject(π),
|
Max: π.Project(b.Max),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Front returns an image.Rectangle representing the front of the box, using
|
// Front returns an image.Rectangle representing the front of the box, using
|
||||||
// the given projection π.
|
// the given projection π.
|
||||||
func (b Box) Front(π image.Point) image.Rectangle {
|
func (b Box) Front(π IntProjection) image.Rectangle {
|
||||||
b.Min.Z = b.Max.Z
|
b.Min.Z = b.Max.Z
|
||||||
return image.Rectangle{
|
return image.Rectangle{
|
||||||
Min: b.Min.IsoProject(π),
|
Min: π.Project(b.Min),
|
||||||
Max: b.Max.IsoProject(π),
|
Max: π.Project(b.Max),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,10 +25,10 @@ type Camera struct {
|
||||||
// Camera controls
|
// Camera controls
|
||||||
// These directly manipulate the camera. If you want to restrict the camera
|
// These directly manipulate the camera. If you want to restrict the camera
|
||||||
// view area to the child's bounding rectangle, use PointAt.
|
// view area to the child's bounding rectangle, use PointAt.
|
||||||
Centre image.Point // world coordinates
|
Centre image.Point // world coordinates
|
||||||
Rotation float64 // radians
|
Rotation float64 // radians
|
||||||
Zoom float64 // unitless
|
Zoom float64 // unitless
|
||||||
IsoProjection image.Point
|
Projection IntProjection
|
||||||
|
|
||||||
game *Game
|
game *Game
|
||||||
}
|
}
|
||||||
|
@ -39,7 +39,7 @@ func (c *Camera) PointAt(centre Point3, zoom float64) {
|
||||||
// Special sauce: if Child has a BoundingRect, make some adjustments
|
// Special sauce: if Child has a BoundingRect, make some adjustments
|
||||||
bnd, ok := c.Child.(Bounder)
|
bnd, ok := c.Child.(Bounder)
|
||||||
if !ok {
|
if !ok {
|
||||||
c.Centre = centre.IsoProject(c.IsoProjection)
|
c.Centre = c.Projection.Project(centre)
|
||||||
c.Zoom = zoom
|
c.Zoom = zoom
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -61,7 +61,7 @@ func (c *Camera) PointAt(centre Point3, zoom float64) {
|
||||||
// Camera frame currently Rectangle{ centre ± (screen/(2*zoom)) }.
|
// Camera frame currently Rectangle{ centre ± (screen/(2*zoom)) }.
|
||||||
sw2, sh2 := cfloat(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)
|
||||||
cent := centre.IsoProject(c.IsoProjection)
|
cent := c.Projection.Project(centre)
|
||||||
if cent.X-swz < br.Min.X {
|
if cent.X-swz < br.Min.X {
|
||||||
cent.X = br.Min.X + swz
|
cent.X = br.Min.X + swz
|
||||||
}
|
}
|
||||||
|
@ -88,7 +88,7 @@ func (c *Camera) Scan() []interface{} { return []interface{}{c.Child} }
|
||||||
|
|
||||||
// Transform returns the camera transform.
|
// Transform returns the camera transform.
|
||||||
func (c *Camera) Transform(pt Transform) (tf Transform) {
|
func (c *Camera) Transform(pt Transform) (tf Transform) {
|
||||||
tf.IsoProjection = c.IsoProjection
|
tf.Projection = c.Projection
|
||||||
tf.Opts.GeoM.Translate(cfloat(c.Centre.Mul(-1)))
|
tf.Opts.GeoM.Translate(cfloat(c.Centre.Mul(-1)))
|
||||||
tf.Opts.GeoM.Scale(c.Zoom, c.Zoom)
|
tf.Opts.GeoM.Scale(c.Zoom, c.Zoom)
|
||||||
tf.Opts.GeoM.Rotate(c.Rotation)
|
tf.Opts.GeoM.Rotate(c.Rotation)
|
||||||
|
|
|
@ -1,24 +1,29 @@
|
||||||
package engine
|
package engine
|
||||||
|
|
||||||
var (
|
import "image"
|
||||||
// Oblique projections
|
|
||||||
CabinetProjection = ParallelProjection{0.5, 0.5}
|
|
||||||
CavalierProjection = ParallelProjection{1, 1}
|
|
||||||
|
|
||||||
// Axonometric projections
|
type IntProjection image.Point
|
||||||
ElevationProjection = ParallelProjection{0, 0}
|
|
||||||
DimetricProjection = ParallelProjection{0, 0.5}
|
|
||||||
HexPrismProjection = ParallelProjection{0, 0.577350269189626} // 1 ÷ √3
|
|
||||||
IsometricProjection = ParallelProjection{0, 0.707106781186548} // 1 ÷ √2
|
|
||||||
TrimetricProjection = ParallelProjection{0, 1}
|
|
||||||
)
|
|
||||||
|
|
||||||
type ParallelProjection struct {
|
// Project performs an integer parallel projection of a 3D coordinate into 2D.
|
||||||
ZX, ZY float64
|
//
|
||||||
}
|
// If π.X = 0, the x returned is p.X; similarly for π.Y and y.
|
||||||
|
// Otherwise, x projects to x + z/π.X and y projects to y + z/π.Y.
|
||||||
func (π ParallelProjection) Project(p Point3) (px, py float64) {
|
func (π IntProjection) Project(p Point3) image.Point {
|
||||||
px = float64(p.X) + π.ZX*float64(p.Z)
|
/*
|
||||||
py = float64(p.Y) + π.ZY*float64(p.Z)
|
I'm using the π character because I'm a maths wanker.
|
||||||
return px, py
|
|
||||||
|
Dividing is used because there's little reason for an isometric
|
||||||
|
projection in a game to exaggerate the Z position.
|
||||||
|
|
||||||
|
Integers are used to preserve that "pixel perfect" calculation in case
|
||||||
|
you are making the next Celeste.
|
||||||
|
*/
|
||||||
|
q := p.XY()
|
||||||
|
if π.X != 0 {
|
||||||
|
q.X += p.Z / π.X
|
||||||
|
}
|
||||||
|
if π.Y != 0 {
|
||||||
|
q.Y += p.Z / π.Y
|
||||||
|
}
|
||||||
|
return q
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,7 +59,7 @@ func (s *Sprite) SetAnim(a *Anim) {
|
||||||
// Transform returns a translation by the DrawOffset and the iso-projected Pos.
|
// Transform returns a translation by the DrawOffset and the iso-projected Pos.
|
||||||
func (s *Sprite) Transform(pt Transform) (tf Transform) {
|
func (s *Sprite) Transform(pt Transform) (tf Transform) {
|
||||||
tf.Opts.GeoM.Translate(cfloat(
|
tf.Opts.GeoM.Translate(cfloat(
|
||||||
s.Actor.Pos.IsoProject(pt.IsoProjection).Add(s.DrawOffset),
|
pt.Projection.Project(s.Actor.Pos).Add(s.DrawOffset),
|
||||||
))
|
))
|
||||||
return tf.Concat(pt)
|
return tf.Concat(pt)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,13 @@
|
||||||
package engine
|
package engine
|
||||||
|
|
||||||
import (
|
import "github.com/hajimehoshi/ebiten/v2"
|
||||||
"image"
|
|
||||||
|
|
||||||
"github.com/hajimehoshi/ebiten/v2"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Transform is a bucket of things that affect drawing.
|
// Transform is a bucket of things that affect drawing.
|
||||||
type Transform struct {
|
type Transform struct {
|
||||||
// IsoProjection is used by isometric 3D components to project their
|
// Projection is used by isometric 3D components to project their
|
||||||
// coordinates into 2D. There's usually only one component in the tree that
|
// coordinates into 2D. There's usually only one component in the tree that
|
||||||
// sets this field, but it would apply to all descendants.
|
// sets this field, but it would apply to all descendants.
|
||||||
IsoProjection image.Point
|
Projection IntProjection
|
||||||
|
|
||||||
// Opts contains the 2D geometry matrix, the colour matrix, filter mode, and
|
// Opts contains the 2D geometry matrix, the colour matrix, filter mode, and
|
||||||
// composition mode.
|
// composition mode.
|
||||||
|
@ -21,8 +17,8 @@ type Transform struct {
|
||||||
// Concat returns the combined transform (a transform equivalent to applying t
|
// Concat returns the combined transform (a transform equivalent to applying t
|
||||||
// and then u).
|
// and then u).
|
||||||
func (t Transform) Concat(u Transform) Transform {
|
func (t Transform) Concat(u Transform) Transform {
|
||||||
if u.IsoProjection != (image.Point{}) {
|
if u.Projection != (IntProjection{}) {
|
||||||
t.IsoProjection = u.IsoProjection
|
t.Projection = u.Projection
|
||||||
}
|
}
|
||||||
t.Opts.ColorM.Concat(u.Opts.ColorM)
|
t.Opts.ColorM.Concat(u.Opts.ColorM)
|
||||||
t.Opts.GeoM.Concat(u.Opts.GeoM)
|
t.Opts.GeoM.Concat(u.Opts.GeoM)
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 1.3 KiB |
Binary file not shown.
Before Width: | Height: | Size: 1.2 KiB |
Binary file not shown.
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
6
main.go
6
main.go
|
@ -57,12 +57,8 @@ func main() {
|
||||||
&engine.Camera{
|
&engine.Camera{
|
||||||
ID: "game_camera",
|
ID: "game_camera",
|
||||||
Child: lev1,
|
Child: lev1,
|
||||||
// Each step in Z becomes -½ step in X plus ½ step in Y:
|
|
||||||
IsoProjection: image.Pt(-2, 2),
|
|
||||||
// Each step in Z becomes ½ step in Y:
|
|
||||||
//IsoProjection: image.Pt(0, 2),
|
|
||||||
// Each step in Z becomes a step in Y:
|
// Each step in Z becomes a step in Y:
|
||||||
//IsoProjection: image.Pt(0, 1),
|
Projection: engine.IntProjection{X: 0, Y: 1},
|
||||||
},
|
},
|
||||||
&engine.DebugToast{ID: "toast", Pos: image.Pt(0, 15)},
|
&engine.DebugToast{ID: "toast", Pos: image.Pt(0, 15)},
|
||||||
engine.PerfDisplay{},
|
engine.PerfDisplay{},
|
||||||
|
|
Loading…
Reference in a new issue