mirror of
https://github.com/OpenDiablo2/OpenDiablo2
synced 2025-02-03 07:07:25 -05:00
transform component, scene testing
* removed position,scale,rotation components * added Transform component that contains position, rotation, and scale * scene graph update now regenerates the local mat4 using the transform component * akara bugfix: adding new subscriptions will process existing entities * added `--testscene` arg for testing individual scenes in isolation * added rotation support to d2interface.Surface
This commit is contained in:
parent
13ae64af8c
commit
2e814f29b0
11
d2app/app_ecs.go
Normal file
11
d2app/app_ecs.go
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
package d2app
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2systems"
|
||||||
|
"github.com/gravestench/akara"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Run() {
|
||||||
|
cfg := akara.NewWorldConfig().With(&d2systems.AppBootstrap{})
|
||||||
|
akara.NewWorld(cfg)
|
||||||
|
}
|
@ -1,10 +1,9 @@
|
|||||||
package rectangle
|
package rectangle
|
||||||
|
|
||||||
import (
|
import "github.com/gravestench/pho/geom/point"
|
||||||
"github.com/gravestench/pho/geom/point"
|
|
||||||
)
|
|
||||||
|
|
||||||
type RectangleNamespace interface {
|
type RectangleNamespace interface {
|
||||||
|
New(x, y, w, h float64) *Rectangle
|
||||||
Contains(r *Rectangle, x, y float64) bool
|
Contains(r *Rectangle, x, y float64) bool
|
||||||
GetPoint(r *Rectangle, position float64, p *point.Point) *point.Point
|
GetPoint(r *Rectangle, position float64, p *point.Point) *point.Point
|
||||||
GetPoints(r *Rectangle, quantity int, stepRate float64, points []*point.Point) []*point.Point
|
GetPoints(r *Rectangle, quantity int, stepRate float64, points []*point.Point) []*point.Point
|
||||||
@ -31,6 +30,11 @@ type RectangleNamespace interface {
|
|||||||
|
|
||||||
type Namespace struct{}
|
type Namespace struct{}
|
||||||
|
|
||||||
|
// New creates a new Rectangle instance.
|
||||||
|
func (*Namespace) New(x, y, w, h float64) *Rectangle {
|
||||||
|
return New(x, y, w, h)
|
||||||
|
}
|
||||||
|
|
||||||
// Contains checks if the given x, y is inside the Rectangle's bounds.
|
// Contains checks if the given x, y is inside the Rectangle's bounds.
|
||||||
func (*Namespace) Contains(r *Rectangle, x, y float64) bool {
|
func (*Namespace) Contains(r *Rectangle, x, y float64) bool {
|
||||||
return Contains(r, x, y)
|
return Contains(r, x, y)
|
||||||
|
@ -8,7 +8,7 @@ import (
|
|||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Animation is an animation
|
// Sprite is an Sprite
|
||||||
type Sprite interface {
|
type Sprite interface {
|
||||||
BindRenderer(Renderer)
|
BindRenderer(Renderer)
|
||||||
Clone() Sprite
|
Clone() Sprite
|
||||||
|
@ -24,6 +24,7 @@ type Surface interface {
|
|||||||
PushTranslation(x, y int)
|
PushTranslation(x, y int)
|
||||||
PushSkew(x, y float64)
|
PushSkew(x, y float64)
|
||||||
PushScale(x, y float64)
|
PushScale(x, y float64)
|
||||||
|
PushRotate(theta float64)
|
||||||
PushBrightness(brightness float64)
|
PushBrightness(brightness float64)
|
||||||
PushSaturation(saturation float64)
|
PushSaturation(saturation float64)
|
||||||
Render(surface Surface)
|
Render(surface Surface)
|
||||||
|
@ -20,6 +20,38 @@ type Matrix4 struct {
|
|||||||
Values [numMatrix4Values]float64
|
Values [numMatrix4Values]float64
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Decompose this matrix into vec3 for translation, rotation, and scale
|
||||||
|
func (m *Matrix4) Decompose() (t, r, s *Vector3) {
|
||||||
|
t = NewVector3(m.Values[12], m.Values[13], m.Values[14])
|
||||||
|
|
||||||
|
s = NewVector3(
|
||||||
|
NewVector3(m.Values[0], m.Values[1], m.Values[2]).Length(),
|
||||||
|
NewVector3(m.Values[4], m.Values[5], m.Values[6]).Length(),
|
||||||
|
NewVector3(m.Values[8], m.Values[9], m.Values[10]).Length(),
|
||||||
|
)
|
||||||
|
|
||||||
|
e := NewEuler(0, 0, 0, EulerOrderDefault)
|
||||||
|
|
||||||
|
rotmat := m.Clone()
|
||||||
|
rotmat.Values[0] /= s.X
|
||||||
|
rotmat.Values[1] /= s.Y
|
||||||
|
rotmat.Values[2] /= s.Z
|
||||||
|
|
||||||
|
rotmat.Values[4] /= s.X
|
||||||
|
rotmat.Values[5] /= s.Y
|
||||||
|
rotmat.Values[6] /= s.Z
|
||||||
|
|
||||||
|
rotmat.Values[8] /= s.X
|
||||||
|
rotmat.Values[9] /= s.Y
|
||||||
|
rotmat.Values[10] /= s.Z
|
||||||
|
|
||||||
|
e.SetFromRotationMatrix(rotmat, EulerOrderZYX)
|
||||||
|
|
||||||
|
r = NewVector3(e.XYZ())
|
||||||
|
|
||||||
|
return t, r, s
|
||||||
|
}
|
||||||
|
|
||||||
// Clone makes a clone of this Matrix4.
|
// Clone makes a clone of this Matrix4.
|
||||||
func (m *Matrix4) Clone() *Matrix4 {
|
func (m *Matrix4) Clone() *Matrix4 {
|
||||||
return NewMatrix4(m)
|
return NewMatrix4(m)
|
||||||
@ -47,12 +79,10 @@ func (m *Matrix4) Set(other *Matrix4) *Matrix4 {
|
|||||||
|
|
||||||
// SetValues sets the values of this Matrix4.
|
// SetValues sets the values of this Matrix4.
|
||||||
func (m *Matrix4) SetValues(a, b, c, d, e, f, g, h, i, j, k, l, mm, n, o, p float64) *Matrix4 {
|
func (m *Matrix4) SetValues(a, b, c, d, e, f, g, h, i, j, k, l, mm, n, o, p float64) *Matrix4 {
|
||||||
v := m.Values[:]
|
m.Values[0], m.Values[1], m.Values[2], m.Values[3] = a, b, c, d
|
||||||
|
m.Values[4], m.Values[5], m.Values[6], m.Values[7] = e, f, g, h
|
||||||
v[0], v[1], v[2], v[3] = a, b, c, d
|
m.Values[8], m.Values[9], m.Values[10], m.Values[11] = i, j, k, l
|
||||||
v[4], v[5], v[6], v[7] = e, f, g, h
|
m.Values[12], m.Values[13], m.Values[14], m.Values[15] = mm, n, o, p
|
||||||
v[8], v[9], v[10], v[11] = i, j, k, l
|
|
||||||
v[12], v[13], v[14], v[15] = mm, n, o, p
|
|
||||||
|
|
||||||
return m
|
return m
|
||||||
}
|
}
|
||||||
@ -130,27 +160,25 @@ func (m *Matrix4) SetScaling(x, y, z float64) *Matrix4 {
|
|||||||
|
|
||||||
// Transpose this Matrix.
|
// Transpose this Matrix.
|
||||||
func (m *Matrix4) Transpose() *Matrix4 {
|
func (m *Matrix4) Transpose() *Matrix4 {
|
||||||
a := m.Values[:]
|
a01 := m.Values[1]
|
||||||
|
a02 := m.Values[2]
|
||||||
|
a03 := m.Values[3]
|
||||||
|
a12 := m.Values[6]
|
||||||
|
a13 := m.Values[7]
|
||||||
|
a23 := m.Values[11]
|
||||||
|
|
||||||
a01 := a[1]
|
m.Values[1] = m.Values[4]
|
||||||
a02 := a[2]
|
m.Values[2] = m.Values[8]
|
||||||
a03 := a[3]
|
m.Values[3] = m.Values[12]
|
||||||
a12 := a[6]
|
m.Values[4] = a01
|
||||||
a13 := a[7]
|
m.Values[6] = m.Values[9]
|
||||||
a23 := a[11]
|
m.Values[7] = m.Values[13]
|
||||||
|
m.Values[8] = a02
|
||||||
a[1] = a[4]
|
m.Values[9] = a12
|
||||||
a[2] = a[8]
|
m.Values[11] = m.Values[14]
|
||||||
a[3] = a[12]
|
m.Values[12] = a03
|
||||||
a[4] = a01
|
m.Values[13] = a13
|
||||||
a[6] = a[9]
|
m.Values[14] = a23
|
||||||
a[7] = a[13]
|
|
||||||
a[8] = a02
|
|
||||||
a[9] = a12
|
|
||||||
a[11] = a[14]
|
|
||||||
a[12] = a03
|
|
||||||
a[13] = a13
|
|
||||||
a[14] = a23
|
|
||||||
|
|
||||||
return m
|
return m
|
||||||
}
|
}
|
||||||
@ -162,12 +190,10 @@ func (m *Matrix4) GetInverse(other *Matrix4) *Matrix4 {
|
|||||||
|
|
||||||
// Invert this Matrix.
|
// Invert this Matrix.
|
||||||
func (m *Matrix4) Invert() *Matrix4 {
|
func (m *Matrix4) Invert() *Matrix4 {
|
||||||
a := m.Values[:]
|
a00, a01, a02, a03 := m.Values[0], m.Values[1], m.Values[2], m.Values[3]
|
||||||
|
a10, a11, a12, a13 := m.Values[4], m.Values[5], m.Values[6], m.Values[7]
|
||||||
a00, a01, a02, a03 := a[0], a[1], a[2], a[3]
|
a20, a21, a22, a23 := m.Values[8], m.Values[9], m.Values[10], m.Values[11]
|
||||||
a10, a11, a12, a13 := a[4], a[5], a[6], a[7]
|
a30, a31, a32, a33 := m.Values[12], m.Values[13], m.Values[14], m.Values[15]
|
||||||
a20, a21, a22, a23 := a[8], a[9], a[10], a[11]
|
|
||||||
a30, a31, a32, a33 := a[12], a[13], a[14], a[15]
|
|
||||||
|
|
||||||
b00 := a00*a11 - a01*a10
|
b00 := a00*a11 - a01*a10
|
||||||
b01 := a00*a12 - a02*a10
|
b01 := a00*a12 - a02*a10
|
||||||
@ -213,12 +239,10 @@ func (m *Matrix4) Invert() *Matrix4 {
|
|||||||
|
|
||||||
// Adjoint calculates the adjoint, or adjugate, of this Matrix.
|
// Adjoint calculates the adjoint, or adjugate, of this Matrix.
|
||||||
func (m *Matrix4) Adjoint() *Matrix4 {
|
func (m *Matrix4) Adjoint() *Matrix4 {
|
||||||
a := m.Values[:]
|
a00, a01, a02, a03 := m.Values[0], m.Values[1], m.Values[2], m.Values[3]
|
||||||
|
a10, a11, a12, a13 := m.Values[4], m.Values[5], m.Values[6], m.Values[7]
|
||||||
a00, a01, a02, a03 := a[0], a[1], a[2], a[3]
|
a20, a21, a22, a23 := m.Values[8], m.Values[9], m.Values[10], m.Values[11]
|
||||||
a10, a11, a12, a13 := a[4], a[5], a[6], a[7]
|
a30, a31, a32, a33 := m.Values[12], m.Values[13], m.Values[14], m.Values[15]
|
||||||
a20, a21, a22, a23 := a[8], a[9], a[10], a[11]
|
|
||||||
a30, a31, a32, a33 := a[12], a[13], a[14], a[15]
|
|
||||||
|
|
||||||
return m.SetValues(
|
return m.SetValues(
|
||||||
a11*(a22*a33-a23*a32)-a21*(a12*a33-a13*a32)+a31*(a12*a23-a13*a22),
|
a11*(a22*a33-a23*a32)-a21*(a12*a33-a13*a32)+a31*(a12*a23-a13*a22),
|
||||||
@ -242,12 +266,10 @@ func (m *Matrix4) Adjoint() *Matrix4 {
|
|||||||
|
|
||||||
// Determinant calculates the determinant of this Matrix.
|
// Determinant calculates the determinant of this Matrix.
|
||||||
func (m *Matrix4) Determinant() float64 {
|
func (m *Matrix4) Determinant() float64 {
|
||||||
a := m.Values[:]
|
a00, a01, a02, a03 := m.Values[0], m.Values[1], m.Values[2], m.Values[3]
|
||||||
|
a10, a11, a12, a13 := m.Values[4], m.Values[5], m.Values[6], m.Values[7]
|
||||||
a00, a01, a02, a03 := a[0], a[1], a[2], a[3]
|
a20, a21, a22, a23 := m.Values[8], m.Values[9], m.Values[10], m.Values[11]
|
||||||
a10, a11, a12, a13 := a[4], a[5], a[6], a[7]
|
a30, a31, a32, a33 := m.Values[12], m.Values[13], m.Values[14], m.Values[15]
|
||||||
a20, a21, a22, a23 := a[8], a[9], a[10], a[11]
|
|
||||||
a30, a31, a32, a33 := a[12], a[13], a[14], a[15]
|
|
||||||
|
|
||||||
b00 := a00*a11 - a01*a10
|
b00 := a00*a11 - a01*a10
|
||||||
b01 := a00*a12 - a02*a10
|
b01 := a00*a12 - a02*a10
|
||||||
@ -267,62 +289,58 @@ func (m *Matrix4) Determinant() float64 {
|
|||||||
|
|
||||||
// Multiply this Matrix4 by the given Matrix4.
|
// Multiply this Matrix4 by the given Matrix4.
|
||||||
func (m *Matrix4) Multiply(other *Matrix4) *Matrix4 {
|
func (m *Matrix4) Multiply(other *Matrix4) *Matrix4 {
|
||||||
a, b := m.Values, other.Values
|
a00, a01, a02, a03 := m.Values[0], m.Values[1], m.Values[2], m.Values[3]
|
||||||
|
a10, a11, a12, a13 := m.Values[4], m.Values[5], m.Values[6], m.Values[7]
|
||||||
a00, a01, a02, a03 := a[0], a[1], a[2], a[3]
|
a20, a21, a22, a23 := m.Values[8], m.Values[9], m.Values[10], m.Values[11]
|
||||||
a10, a11, a12, a13 := a[4], a[5], a[6], a[7]
|
a30, a31, a32, a33 := m.Values[12], m.Values[13], m.Values[14], m.Values[15]
|
||||||
a20, a21, a22, a23 := a[8], a[9], a[10], a[11]
|
|
||||||
a30, a31, a32, a33 := a[12], a[13], a[14], a[15]
|
|
||||||
|
|
||||||
// Cache only the current line of the second matrix
|
// Cache only the current line of the second matrix
|
||||||
b0, b1, b2, b3 := b[0], b[1], b[2], b[3]
|
b0, b1, b2, b3 := other.Values[0], other.Values[1], other.Values[2], other.Values[3]
|
||||||
a[0] = b0*a00 + b1*a10 + b2*a20 + b3*a30
|
m.Values[0] = b0*a00 + b1*a10 + b2*a20 + b3*a30
|
||||||
a[1] = b0*a01 + b1*a11 + b2*a21 + b3*a31
|
m.Values[1] = b0*a01 + b1*a11 + b2*a21 + b3*a31
|
||||||
a[2] = b0*a02 + b1*a12 + b2*a22 + b3*a32
|
m.Values[2] = b0*a02 + b1*a12 + b2*a22 + b3*a32
|
||||||
a[3] = b0*a03 + b1*a13 + b2*a23 + b3*a33
|
m.Values[3] = b0*a03 + b1*a13 + b2*a23 + b3*a33
|
||||||
|
|
||||||
b0, b1, b2, b3 = b[4], b[5], b[6], b[7]
|
b0, b1, b2, b3 = other.Values[4], other.Values[5], other.Values[6], other.Values[7]
|
||||||
a[4] = b0*a00 + b1*a10 + b2*a20 + b3*a30
|
m.Values[4] = b0*a00 + b1*a10 + b2*a20 + b3*a30
|
||||||
a[5] = b0*a01 + b1*a11 + b2*a21 + b3*a31
|
m.Values[5] = b0*a01 + b1*a11 + b2*a21 + b3*a31
|
||||||
a[6] = b0*a02 + b1*a12 + b2*a22 + b3*a32
|
m.Values[6] = b0*a02 + b1*a12 + b2*a22 + b3*a32
|
||||||
a[7] = b0*a03 + b1*a13 + b2*a23 + b3*a33
|
m.Values[7] = b0*a03 + b1*a13 + b2*a23 + b3*a33
|
||||||
|
|
||||||
b0, b1, b2, b3 = b[8], b[9], b[10], b[11]
|
b0, b1, b2, b3 = other.Values[8], other.Values[9], other.Values[10], other.Values[11]
|
||||||
a[8] = b0*a00 + b1*a10 + b2*a20 + b3*a30
|
m.Values[8] = b0*a00 + b1*a10 + b2*a20 + b3*a30
|
||||||
a[9] = b0*a01 + b1*a11 + b2*a21 + b3*a31
|
m.Values[9] = b0*a01 + b1*a11 + b2*a21 + b3*a31
|
||||||
a[10] = b0*a02 + b1*a12 + b2*a22 + b3*a32
|
m.Values[10] = b0*a02 + b1*a12 + b2*a22 + b3*a32
|
||||||
a[11] = b0*a03 + b1*a13 + b2*a23 + b3*a33
|
m.Values[11] = b0*a03 + b1*a13 + b2*a23 + b3*a33
|
||||||
|
|
||||||
b0, b1, b2, b3 = b[12], b[13], b[14], b[15]
|
b0, b1, b2, b3 = other.Values[12], other.Values[13], other.Values[14], other.Values[15]
|
||||||
a[12] = b0*a00 + b1*a10 + b2*a20 + b3*a30
|
m.Values[12] = b0*a00 + b1*a10 + b2*a20 + b3*a30
|
||||||
a[13] = b0*a01 + b1*a11 + b2*a21 + b3*a31
|
m.Values[13] = b0*a01 + b1*a11 + b2*a21 + b3*a31
|
||||||
a[14] = b0*a02 + b1*a12 + b2*a22 + b3*a32
|
m.Values[14] = b0*a02 + b1*a12 + b2*a22 + b3*a32
|
||||||
a[15] = b0*a03 + b1*a13 + b2*a23 + b3*a33
|
m.Values[15] = b0*a03 + b1*a13 + b2*a23 + b3*a33
|
||||||
|
|
||||||
return m
|
return m
|
||||||
}
|
}
|
||||||
|
|
||||||
// MultiplyLocal multiplies the values of this Matrix4 by those given in the `other` argument.
|
// MultiplyLocal multiplies the values of this Matrix4 by those given in the `other` argument.
|
||||||
func (m *Matrix4) MultiplyLocal(other *Matrix4) *Matrix4 {
|
func (m *Matrix4) MultiplyLocal(other *Matrix4) *Matrix4 {
|
||||||
a, b := m.Values, other.Values
|
|
||||||
|
|
||||||
return m.SetValues(
|
return m.SetValues(
|
||||||
a[0]*b[0]+a[1]*b[4]+a[2]*b[8]+a[3]*b[12],
|
m.Values[0]*other.Values[0]+m.Values[1]*other.Values[4]+m.Values[2]*other.Values[8]+m.Values[3]*other.Values[12],
|
||||||
a[0]*b[1]+a[1]*b[5]+a[2]*b[9]+a[3]*b[13],
|
m.Values[0]*other.Values[1]+m.Values[1]*other.Values[5]+m.Values[2]*other.Values[9]+m.Values[3]*other.Values[13],
|
||||||
a[0]*b[2]+a[1]*b[6]+a[2]*b[10]+a[3]*b[14],
|
m.Values[0]*other.Values[2]+m.Values[1]*other.Values[6]+m.Values[2]*other.Values[10]+m.Values[3]*other.Values[14],
|
||||||
a[0]*b[3]+a[1]*b[7]+a[2]*b[11]+a[3]*b[15],
|
m.Values[0]*other.Values[3]+m.Values[1]*other.Values[7]+m.Values[2]*other.Values[11]+m.Values[3]*other.Values[15],
|
||||||
a[4]*b[0]+a[5]*b[4]+a[6]*b[8]+a[7]*b[12],
|
m.Values[4]*other.Values[0]+m.Values[5]*other.Values[4]+m.Values[6]*other.Values[8]+m.Values[7]*other.Values[12],
|
||||||
a[4]*b[1]+a[5]*b[5]+a[6]*b[9]+a[7]*b[13],
|
m.Values[4]*other.Values[1]+m.Values[5]*other.Values[5]+m.Values[6]*other.Values[9]+m.Values[7]*other.Values[13],
|
||||||
a[4]*b[2]+a[5]*b[6]+a[6]*b[10]+a[7]*b[14],
|
m.Values[4]*other.Values[2]+m.Values[5]*other.Values[6]+m.Values[6]*other.Values[10]+m.Values[7]*other.Values[14],
|
||||||
a[4]*b[3]+a[5]*b[7]+a[6]*b[11]+a[7]*b[15],
|
m.Values[4]*other.Values[3]+m.Values[5]*other.Values[7]+m.Values[6]*other.Values[11]+m.Values[7]*other.Values[15],
|
||||||
a[8]*b[0]+a[9]*b[4]+a[10]*b[8]+a[11]*b[12],
|
m.Values[8]*other.Values[0]+m.Values[9]*other.Values[4]+m.Values[10]*other.Values[8]+m.Values[11]*other.Values[12],
|
||||||
a[8]*b[1]+a[9]*b[5]+a[10]*b[9]+a[11]*b[13],
|
m.Values[8]*other.Values[1]+m.Values[9]*other.Values[5]+m.Values[10]*other.Values[9]+m.Values[11]*other.Values[13],
|
||||||
a[8]*b[2]+a[9]*b[6]+a[10]*b[10]+a[11]*b[14],
|
m.Values[8]*other.Values[2]+m.Values[9]*other.Values[6]+m.Values[10]*other.Values[10]+m.Values[11]*other.Values[14],
|
||||||
a[8]*b[3]+a[9]*b[7]+a[10]*b[11]+a[11]*b[15],
|
m.Values[8]*other.Values[3]+m.Values[9]*other.Values[7]+m.Values[10]*other.Values[11]+m.Values[11]*other.Values[15],
|
||||||
a[12]*b[0]+a[13]*b[4]+a[14]*b[8]+a[15]*b[12],
|
m.Values[12]*other.Values[0]+m.Values[13]*other.Values[4]+m.Values[14]*other.Values[8]+m.Values[15]*other.Values[12],
|
||||||
a[12]*b[1]+a[13]*b[5]+a[14]*b[9]+a[15]*b[13],
|
m.Values[12]*other.Values[1]+m.Values[13]*other.Values[5]+m.Values[14]*other.Values[9]+m.Values[15]*other.Values[13],
|
||||||
a[12]*b[2]+a[13]*b[6]+a[14]*b[10]+a[15]*b[14],
|
m.Values[12]*other.Values[2]+m.Values[13]*other.Values[6]+m.Values[14]*other.Values[10]+m.Values[15]*other.Values[14],
|
||||||
a[12]*b[3]+a[13]*b[7]+a[14]*b[11]+a[15]*b[15],
|
m.Values[12]*other.Values[3]+m.Values[13]*other.Values[7]+m.Values[14]*other.Values[11]+m.Values[15]*other.Values[15],
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -333,41 +351,39 @@ func (m *Matrix4) PreMultiply(other *Matrix4) *Matrix4 {
|
|||||||
|
|
||||||
// MultiplyMatrices multiplies the two given Matrix4 objects and stores the results in this Matrix.
|
// MultiplyMatrices multiplies the two given Matrix4 objects and stores the results in this Matrix.
|
||||||
func (m *Matrix4) MultiplyMatrices(a, b *Matrix4) *Matrix4 {
|
func (m *Matrix4) MultiplyMatrices(a, b *Matrix4) *Matrix4 {
|
||||||
am, bm := a.Values, b.Values
|
a11 := a.Values[0]
|
||||||
|
a12 := a.Values[4]
|
||||||
|
a13 := a.Values[8]
|
||||||
|
a14 := a.Values[12]
|
||||||
|
a21 := a.Values[1]
|
||||||
|
a22 := a.Values[5]
|
||||||
|
a23 := a.Values[9]
|
||||||
|
a24 := a.Values[13]
|
||||||
|
a31 := a.Values[2]
|
||||||
|
a32 := a.Values[6]
|
||||||
|
a33 := a.Values[10]
|
||||||
|
a34 := a.Values[14]
|
||||||
|
a41 := a.Values[3]
|
||||||
|
a42 := a.Values[7]
|
||||||
|
a43 := a.Values[11]
|
||||||
|
a44 := a.Values[15]
|
||||||
|
|
||||||
a11 := am[0]
|
b11 := b.Values[0]
|
||||||
a12 := am[4]
|
b12 := b.Values[4]
|
||||||
a13 := am[8]
|
b13 := b.Values[8]
|
||||||
a14 := am[12]
|
b14 := b.Values[12]
|
||||||
a21 := am[1]
|
b21 := b.Values[1]
|
||||||
a22 := am[5]
|
b22 := b.Values[5]
|
||||||
a23 := am[9]
|
b23 := b.Values[9]
|
||||||
a24 := am[13]
|
b24 := b.Values[13]
|
||||||
a31 := am[2]
|
b31 := b.Values[2]
|
||||||
a32 := am[6]
|
b32 := b.Values[6]
|
||||||
a33 := am[10]
|
b33 := b.Values[10]
|
||||||
a34 := am[14]
|
b34 := b.Values[14]
|
||||||
a41 := am[3]
|
b41 := b.Values[3]
|
||||||
a42 := am[7]
|
b42 := b.Values[7]
|
||||||
a43 := am[11]
|
b43 := b.Values[11]
|
||||||
a44 := am[15]
|
b44 := b.Values[15]
|
||||||
|
|
||||||
b11 := bm[0]
|
|
||||||
b12 := bm[4]
|
|
||||||
b13 := bm[8]
|
|
||||||
b14 := bm[12]
|
|
||||||
b21 := bm[1]
|
|
||||||
b22 := bm[5]
|
|
||||||
b23 := bm[9]
|
|
||||||
b24 := bm[13]
|
|
||||||
b31 := bm[2]
|
|
||||||
b32 := bm[6]
|
|
||||||
b33 := bm[10]
|
|
||||||
b34 := bm[14]
|
|
||||||
b41 := bm[3]
|
|
||||||
b42 := bm[7]
|
|
||||||
b43 := bm[11]
|
|
||||||
b44 := bm[15]
|
|
||||||
|
|
||||||
return m.SetValues(
|
return m.SetValues(
|
||||||
a11*b11+a12*b21+a13*b31+a14*b41,
|
a11*b11+a12*b21+a13*b31+a14*b41,
|
||||||
@ -396,12 +412,10 @@ func (m *Matrix4) Translate(v Vector3Like) *Matrix4 {
|
|||||||
|
|
||||||
// TranslateXYZ translates this Matrix using the given values.
|
// TranslateXYZ translates this Matrix using the given values.
|
||||||
func (m *Matrix4) TranslateXYZ(x, y, z float64) *Matrix4 {
|
func (m *Matrix4) TranslateXYZ(x, y, z float64) *Matrix4 {
|
||||||
a := m.Values[:]
|
m.Values[12] = m.Values[0]*x + m.Values[4]*y + m.Values[8]*z + m.Values[12]
|
||||||
|
m.Values[13] = m.Values[1]*x + m.Values[5]*y + m.Values[9]*z + m.Values[13]
|
||||||
a[12] = a[0]*x + a[4]*y + a[8]*z + a[12]
|
m.Values[14] = m.Values[2]*x + m.Values[6]*y + m.Values[10]*z + m.Values[14]
|
||||||
a[13] = a[1]*x + a[5]*y + a[9]*z + a[13]
|
m.Values[15] = m.Values[3]*x + m.Values[7]*y + m.Values[11]*z + m.Values[15]
|
||||||
a[14] = a[2]*x + a[6]*y + a[10]*z + a[14]
|
|
||||||
a[15] = a[3]*x + a[7]*y + a[11]*z + a[15]
|
|
||||||
|
|
||||||
return m
|
return m
|
||||||
}
|
}
|
||||||
@ -413,11 +427,9 @@ func (m *Matrix4) Scale(v Vector3Like) *Matrix4 {
|
|||||||
|
|
||||||
// ScaleXYZ applies a scale transformation to this Matrix.
|
// ScaleXYZ applies a scale transformation to this Matrix.
|
||||||
func (m *Matrix4) ScaleXYZ(x, y, z float64) *Matrix4 {
|
func (m *Matrix4) ScaleXYZ(x, y, z float64) *Matrix4 {
|
||||||
a := m.Values[:]
|
m.Values[0], m.Values[1], m.Values[2], m.Values[3] = m.Values[0]*x, m.Values[1]*x, m.Values[2]*x, m.Values[3]*x
|
||||||
|
m.Values[4], m.Values[5], m.Values[6], m.Values[7] = m.Values[4]*y, m.Values[5]*y, m.Values[6]*y, m.Values[7]*y
|
||||||
a[0], a[1], a[2], a[3] = a[0]*x, a[1]*x, a[2]*x, a[3]*x
|
m.Values[8], m.Values[9], m.Values[10], m.Values[11] = m.Values[8]*z, m.Values[9]*z, m.Values[10]*z, m.Values[11]*z
|
||||||
a[4], a[5], a[6], a[7] = a[4]*y, a[5]*y, a[6]*y, a[7]*y
|
|
||||||
a[8], a[9], a[10], a[11] = a[8]*z, a[9]*z, a[10]*z, a[11]*z
|
|
||||||
|
|
||||||
return m
|
return m
|
||||||
}
|
}
|
||||||
@ -439,7 +451,6 @@ func (m *Matrix4) MakeRotationAxis(axis Vector3Like, radians float64) *Matrix4 {
|
|||||||
|
|
||||||
// Rotate applies a rotation transformation to this Matrix.
|
// Rotate applies a rotation transformation to this Matrix.
|
||||||
func (m *Matrix4) Rotate(radians float64, axis Vector3Like) *Matrix4 {
|
func (m *Matrix4) Rotate(radians float64, axis Vector3Like) *Matrix4 {
|
||||||
a := m.Values[:]
|
|
||||||
x, y, z := axis.XYZ()
|
x, y, z := axis.XYZ()
|
||||||
length := math.Sqrt(x*x + y*y + z*z)
|
length := math.Sqrt(x*x + y*y + z*z)
|
||||||
|
|
||||||
@ -455,10 +466,10 @@ func (m *Matrix4) Rotate(radians float64, axis Vector3Like) *Matrix4 {
|
|||||||
c, s := math.Cos(radians), math.Sin(radians)
|
c, s := math.Cos(radians), math.Sin(radians)
|
||||||
t := 1 - c
|
t := 1 - c
|
||||||
|
|
||||||
a00, a01, a02, a03 := a[0], a[1], a[2], a[3]
|
a00, a01, a02, a03 := m.Values[0], m.Values[1], m.Values[2], m.Values[3]
|
||||||
a10, a11, a12, a13 := a[4], a[5], a[6], a[7]
|
a10, a11, a12, a13 := m.Values[4], m.Values[5], m.Values[6], m.Values[7]
|
||||||
a20, a21, a22, a23 := a[8], a[9], a[10], a[11]
|
a20, a21, a22, a23 := m.Values[8], m.Values[9], m.Values[10], m.Values[11]
|
||||||
a30, a31, a32, a33 := a[12], a[13], a[14], a[15]
|
a30, a31, a32, a33 := m.Values[12], m.Values[13], m.Values[14], m.Values[15]
|
||||||
|
|
||||||
b00, b01, b02 := x*x*t+c, y*x*t+z*s, z*x*t-y*s
|
b00, b01, b02 := x*x*t+c, y*x*t+z*s, z*x*t-y*s
|
||||||
b10, b11, b12 := x*y*t-z*s, y*y*t+c, z*y*t+x*s
|
b10, b11, b12 := x*y*t-z*s, y*y*t+c, z*y*t+x*s
|
||||||
@ -483,63 +494,60 @@ func (m *Matrix4) Rotate(radians float64, axis Vector3Like) *Matrix4 {
|
|||||||
|
|
||||||
// RotateX rotates this matrix on its X axis.
|
// RotateX rotates this matrix on its X axis.
|
||||||
func (m *Matrix4) RotateX(radians float64) *Matrix4 {
|
func (m *Matrix4) RotateX(radians float64) *Matrix4 {
|
||||||
a := m.Values[:]
|
|
||||||
c, s := math.Cos(radians), math.Sin(radians)
|
c, s := math.Cos(radians), math.Sin(radians)
|
||||||
|
|
||||||
a10, a11, a12, a13 := a[4], a[5], a[6], a[7]
|
a10, a11, a12, a13 := m.Values[4], m.Values[5], m.Values[6], m.Values[7]
|
||||||
a20, a21, a22, a23 := a[8], a[9], a[10], a[11]
|
a20, a21, a22, a23 := m.Values[8], m.Values[9], m.Values[10], m.Values[11]
|
||||||
|
|
||||||
// Perform axis-specific matrix multiplication
|
// Perform axis-specific matrix multiplication
|
||||||
a[4] = a10*c + a20*s
|
m.Values[4] = a10*c + a20*s
|
||||||
a[5] = a11*c + a21*s
|
m.Values[5] = a11*c + a21*s
|
||||||
a[6] = a12*c + a22*s
|
m.Values[6] = a12*c + a22*s
|
||||||
a[7] = a13*c + a23*s
|
m.Values[7] = a13*c + a23*s
|
||||||
a[8] = a20*c - a10*s
|
m.Values[8] = a20*c - a10*s
|
||||||
a[9] = a21*c - a11*s
|
m.Values[9] = a21*c - a11*s
|
||||||
a[10] = a22*c - a12*s
|
m.Values[10] = a22*c - a12*s
|
||||||
a[11] = a23*c - a13*s
|
m.Values[11] = a23*c - a13*s
|
||||||
|
|
||||||
return m
|
return m
|
||||||
}
|
}
|
||||||
|
|
||||||
// RotateY rotates this matrix on its X axis.
|
// RotateY rotates this matrix on its X axis.
|
||||||
func (m *Matrix4) RotateY(radians float64) *Matrix4 {
|
func (m *Matrix4) RotateY(radians float64) *Matrix4 {
|
||||||
a := m.Values[:]
|
|
||||||
c, s := math.Cos(radians), math.Sin(radians)
|
c, s := math.Cos(radians), math.Sin(radians)
|
||||||
|
|
||||||
a00, a01, a02, a03 := a[0], a[1], a[2], a[3]
|
a00, a01, a02, a03 := m.Values[0], m.Values[1], m.Values[2], m.Values[3]
|
||||||
a20, a21, a22, a23 := a[8], a[9], a[10], a[11]
|
a20, a21, a22, a23 := m.Values[8], m.Values[9], m.Values[10], m.Values[11]
|
||||||
|
|
||||||
// Perform axis-specific matrix multiplication
|
// Perform axis-specific matrix multiplication
|
||||||
a[0] = a00*c + a20*s
|
m.Values[0] = a00*c + a20*s
|
||||||
a[1] = a01*c + a21*s
|
m.Values[1] = a01*c + a21*s
|
||||||
a[2] = a02*c + a22*s
|
m.Values[2] = a02*c + a22*s
|
||||||
a[3] = a03*c + a23*s
|
m.Values[3] = a03*c + a23*s
|
||||||
a[4] = a20*c - a00*s
|
m.Values[4] = a20*c - a00*s
|
||||||
a[5] = a21*c - a01*s
|
m.Values[5] = a21*c - a01*s
|
||||||
a[6] = a22*c - a02*s
|
m.Values[6] = a22*c - a02*s
|
||||||
a[7] = a23*c - a03*s
|
m.Values[7] = a23*c - a03*s
|
||||||
|
|
||||||
return m
|
return m
|
||||||
}
|
}
|
||||||
|
|
||||||
// RotateZ rotates this matrix on its X axis.
|
// RotateZ rotates this matrix on its X axis.
|
||||||
func (m *Matrix4) RotateZ(radians float64) *Matrix4 {
|
func (m *Matrix4) RotateZ(radians float64) *Matrix4 {
|
||||||
a := m.Values[:]
|
|
||||||
c, s := math.Cos(radians), math.Sin(radians)
|
c, s := math.Cos(radians), math.Sin(radians)
|
||||||
|
|
||||||
a00, a01, a02, a03 := a[0], a[1], a[2], a[3]
|
a00, a01, a02, a03 := m.Values[0], m.Values[1], m.Values[2], m.Values[3]
|
||||||
a10, a11, a12, a13 := a[4], a[5], a[6], a[7]
|
a10, a11, a12, a13 := m.Values[4], m.Values[5], m.Values[6], m.Values[7]
|
||||||
|
|
||||||
// Perform axis-specific matrix multiplication
|
// Perform axis-specific matrix multiplication
|
||||||
a[0] = a00*c + a10*s
|
m.Values[0] = a00*c + a10*s
|
||||||
a[1] = a01*c + a11*s
|
m.Values[1] = a01*c + a11*s
|
||||||
a[2] = a02*c + a12*s
|
m.Values[2] = a02*c + a12*s
|
||||||
a[3] = a03*c + a13*s
|
m.Values[3] = a03*c + a13*s
|
||||||
a[4] = a10*c - a00*s
|
m.Values[4] = a10*c - a00*s
|
||||||
a[5] = a11*c - a01*s
|
m.Values[5] = a11*c - a01*s
|
||||||
a[6] = a12*c - a02*s
|
m.Values[6] = a12*c - a02*s
|
||||||
a[7] = a13*c - a03*s
|
m.Values[7] = a13*c - a03*s
|
||||||
|
|
||||||
return m
|
return m
|
||||||
}
|
}
|
||||||
|
@ -380,17 +380,15 @@ func (q *Quaternion) SetFromEuler(e *Euler) *Quaternion {
|
|||||||
|
|
||||||
// SetFromRotationMatrix sets the rotation of this Quaternion from the given Matrix4.
|
// SetFromRotationMatrix sets the rotation of this Quaternion from the given Matrix4.
|
||||||
func (q *Quaternion) SetFromRotationMatrix(m4 *Matrix4) *Quaternion {
|
func (q *Quaternion) SetFromRotationMatrix(m4 *Matrix4) *Quaternion {
|
||||||
m := m4.Values
|
m11 := m4.Values[0]
|
||||||
|
m12 := m4.Values[4]
|
||||||
m11 := m[0]
|
m13 := m4.Values[8]
|
||||||
m12 := m[4]
|
m21 := m4.Values[1]
|
||||||
m13 := m[8]
|
m22 := m4.Values[5]
|
||||||
m21 := m[1]
|
m23 := m4.Values[9]
|
||||||
m22 := m[5]
|
m31 := m4.Values[2]
|
||||||
m23 := m[9]
|
m32 := m4.Values[6]
|
||||||
m31 := m[2]
|
m33 := m4.Values[10]
|
||||||
m32 := m[6]
|
|
||||||
m33 := m[10]
|
|
||||||
|
|
||||||
trace := m11 + m22 + m33
|
trace := m11 + m22 + m33
|
||||||
var s float64
|
var s float64
|
||||||
|
@ -83,7 +83,7 @@ func (a *Sprite) Advance(elapsed time.Duration) error {
|
|||||||
a.lastFrameTime += elapsed
|
a.lastFrameTime += elapsed
|
||||||
|
|
||||||
framesAdvanced := int(float64(a.lastFrameTime) / float64(frameLength))
|
framesAdvanced := int(float64(a.lastFrameTime) / float64(frameLength))
|
||||||
a.lastFrameTime -= time.Duration(float64(framesAdvanced) * float64(frameLength))
|
a.lastFrameTime -= time.Duration(float64(framesAdvanced)) * frameLength
|
||||||
|
|
||||||
for i := 0; i < framesAdvanced; i++ {
|
for i := 0; i < framesAdvanced; i++ {
|
||||||
startIndex := 0
|
startIndex := 0
|
||||||
|
@ -20,7 +20,6 @@ var _ akara.Component = &Camera{}
|
|||||||
|
|
||||||
// Camera represents a camera that can be rendered to
|
// Camera represents a camera that can be rendered to
|
||||||
type Camera struct {
|
type Camera struct {
|
||||||
Position *d2math.Vector3
|
|
||||||
PerspectiveMatrix *d2math.Matrix4
|
PerspectiveMatrix *d2math.Matrix4
|
||||||
OrthogonalMatrix *d2math.Matrix4
|
OrthogonalMatrix *d2math.Matrix4
|
||||||
Size *d2math.Vector2
|
Size *d2math.Vector2
|
||||||
@ -31,7 +30,6 @@ type Camera struct {
|
|||||||
// The camera defaults to position (0,0), 800x600 resolution, and zoom of 1.0
|
// The camera defaults to position (0,0), 800x600 resolution, and zoom of 1.0
|
||||||
func (*Camera) New() akara.Component {
|
func (*Camera) New() akara.Component {
|
||||||
c := &Camera{
|
c := &Camera{
|
||||||
Position: d2math.NewVector3(0, 0, defaultCameraZ),
|
|
||||||
Size: d2math.NewVector2(defaultCameraWidth, defaultCameraHeight),
|
Size: d2math.NewVector2(defaultCameraWidth, defaultCameraHeight),
|
||||||
Clip: d2math.NewVector2(defaultCameraNear, defaultCameraFar),
|
Clip: d2math.NewVector2(defaultCameraNear, defaultCameraFar),
|
||||||
}
|
}
|
||||||
|
@ -1,45 +0,0 @@
|
|||||||
//nolint:dupl,golint,stylecheck // component declarations are supposed to look the same
|
|
||||||
package d2components
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/gravestench/akara"
|
|
||||||
|
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2math"
|
|
||||||
)
|
|
||||||
|
|
||||||
// static check that Position implements Component
|
|
||||||
var _ akara.Component = &Position{}
|
|
||||||
|
|
||||||
// Position contains an embedded d2vector.Position, which is a vector with
|
|
||||||
// helper methods for translating between screen, isometric, tile, and sub-tile space.
|
|
||||||
type Position struct {
|
|
||||||
*d2math.Vector3
|
|
||||||
}
|
|
||||||
|
|
||||||
// New creates a new Position. By default, the position is (0,0)
|
|
||||||
func (*Position) New() akara.Component {
|
|
||||||
return &Position{
|
|
||||||
Vector3: d2math.NewVector3(0, 0, 0),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// PositionFactory is a wrapper for the generic component factory that returns Position component instances.
|
|
||||||
// This can be embedded inside of a system to give them the methods for adding, retrieving, and removing a Position.
|
|
||||||
type PositionFactory struct {
|
|
||||||
Position *akara.ComponentFactory
|
|
||||||
}
|
|
||||||
|
|
||||||
// AddPosition adds a Position component to the given entity and returns it
|
|
||||||
func (m *PositionFactory) AddPosition(id akara.EID) *Position {
|
|
||||||
return m.Position.Add(id).(*Position)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetPosition returns the Position component for the given entity, and a bool for whether or not it exists
|
|
||||||
func (m *PositionFactory) GetPosition(id akara.EID) (*Position, bool) {
|
|
||||||
component, found := m.Position.Get(id)
|
|
||||||
if !found {
|
|
||||||
return nil, found
|
|
||||||
}
|
|
||||||
|
|
||||||
return component.(*Position), found
|
|
||||||
}
|
|
@ -1,43 +0,0 @@
|
|||||||
//nolint:dupl,golint,stylecheck // component declarations are supposed to look the same
|
|
||||||
package d2components
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2math"
|
|
||||||
"github.com/gravestench/akara"
|
|
||||||
)
|
|
||||||
|
|
||||||
// static check that Scale implements Component
|
|
||||||
var _ akara.Component = &Scale{}
|
|
||||||
|
|
||||||
// Scale represents an entities x,y axis scale as a vector
|
|
||||||
type Scale struct {
|
|
||||||
*d2math.Vector3
|
|
||||||
}
|
|
||||||
|
|
||||||
// New creates a new Scale instance. By default, the scale is (1,1)
|
|
||||||
func (*Scale) New() akara.Component {
|
|
||||||
return &Scale{
|
|
||||||
Vector3: d2math.NewVector3(1, 1, 1),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ScaleFactory is a wrapper for the generic component factory that returns Scale component instances.
|
|
||||||
// This can be embedded inside of a system to give them the methods for adding, retrieving, and removing a Scale.
|
|
||||||
type ScaleFactory struct {
|
|
||||||
Scale *akara.ComponentFactory
|
|
||||||
}
|
|
||||||
|
|
||||||
// AddScale adds a Scale component to the given entity and returns it
|
|
||||||
func (m *ScaleFactory) AddScale(id akara.EID) *Scale {
|
|
||||||
return m.Scale.Add(id).(*Scale)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetScale returns the Scale component for the given entity, and a bool for whether or not it exists
|
|
||||||
func (m *ScaleFactory) GetScale(id akara.EID) (*Scale, bool) {
|
|
||||||
component, found := m.Scale.Get(id)
|
|
||||||
if !found {
|
|
||||||
return nil, found
|
|
||||||
}
|
|
||||||
|
|
||||||
return component.(*Scale), found
|
|
||||||
}
|
|
57
d2core/d2components/transform.go
Normal file
57
d2core/d2components/transform.go
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
//nolint:dupl,golint,stylecheck // component declarations are supposed to look the same
|
||||||
|
package d2components
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/gravestench/akara"
|
||||||
|
|
||||||
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2math"
|
||||||
|
)
|
||||||
|
|
||||||
|
// static check that Transform implements Component
|
||||||
|
var _ akara.Component = &Transform{}
|
||||||
|
|
||||||
|
// Transform contains a vec3 for Translation, Rotation, and Scale
|
||||||
|
type Transform struct {
|
||||||
|
Translation *d2math.Vector3
|
||||||
|
Rotation *d2math.Vector3
|
||||||
|
Scale *d2math.Vector3
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Transform) GetMatrix() *d2math.Matrix4 {
|
||||||
|
return d2math.NewMatrix4(nil).
|
||||||
|
Translate(t.Translation).
|
||||||
|
RotateX(t.Rotation.X).
|
||||||
|
RotateY(t.Rotation.Y).
|
||||||
|
RotateZ(t.Rotation.Z).
|
||||||
|
ScaleXYZ(t.Scale.XYZ())
|
||||||
|
}
|
||||||
|
|
||||||
|
// New creates a new Transform. By default, the position is (0,0)
|
||||||
|
func (*Transform) New() akara.Component {
|
||||||
|
return &Transform{
|
||||||
|
Translation: d2math.NewVector3(0, 0, 0),
|
||||||
|
Rotation: d2math.NewVector3(0, 0, 0),
|
||||||
|
Scale: d2math.NewVector3(1, 1, 1),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TransformFactory is a wrapper for the generic component factory that returns Transform component instances.
|
||||||
|
// This can be embedded inside of a system to give them the methods for adding, retrieving, and removing a Transform.
|
||||||
|
type TransformFactory struct {
|
||||||
|
Transform *akara.ComponentFactory
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddTransform adds a Transform component to the given entity and returns it
|
||||||
|
func (m *TransformFactory) AddTransform(id akara.EID) *Transform {
|
||||||
|
return m.Transform.Add(id).(*Transform)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetTransform returns the Transform component for the given entity, and a bool for whether or not it exists
|
||||||
|
func (m *TransformFactory) GetTransform(id akara.EID) (*Transform, bool) {
|
||||||
|
component, found := m.Transform.Get(id)
|
||||||
|
if !found {
|
||||||
|
return nil, found
|
||||||
|
}
|
||||||
|
|
||||||
|
return component.(*Transform), found
|
||||||
|
}
|
@ -23,6 +23,7 @@ const (
|
|||||||
defaultSkewY = 0.0
|
defaultSkewY = 0.0
|
||||||
defaultScaleX = 1.0
|
defaultScaleX = 1.0
|
||||||
defaultScaleY = 1.0
|
defaultScaleY = 1.0
|
||||||
|
defaultRotate = 0.0
|
||||||
)
|
)
|
||||||
|
|
||||||
type renderCallback = func(surface d2interface.Surface) error
|
type renderCallback = func(surface d2interface.Surface) error
|
||||||
@ -129,6 +130,7 @@ func (r *Renderer) CreateSurface(surface d2interface.Surface) (d2interface.Surfa
|
|||||||
skewY: defaultSkewY,
|
skewY: defaultSkewY,
|
||||||
scaleX: defaultScaleX,
|
scaleX: defaultScaleX,
|
||||||
scaleY: defaultScaleY,
|
scaleY: defaultScaleY,
|
||||||
|
rotate: defaultRotate,
|
||||||
}
|
}
|
||||||
result := createEbitenSurface(r, img, sfcState)
|
result := createEbitenSurface(r, img, sfcState)
|
||||||
|
|
||||||
|
@ -89,6 +89,12 @@ func (s *ebitenSurface) PushScale(scaleX, scaleY float64) {
|
|||||||
s.stateCurrent.scaleY = scaleY
|
s.stateCurrent.scaleY = scaleY
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PushRotate pushes a rotation to the state stack
|
||||||
|
func (s *ebitenSurface) PushRotate(theta float64) {
|
||||||
|
s.stateStack = append(s.stateStack, s.stateCurrent)
|
||||||
|
s.stateCurrent.rotate = theta
|
||||||
|
}
|
||||||
|
|
||||||
// PushEffect pushes an effect to the state stack
|
// PushEffect pushes an effect to the state stack
|
||||||
func (s *ebitenSurface) PushEffect(effect d2enum.DrawEffect) {
|
func (s *ebitenSurface) PushEffect(effect d2enum.DrawEffect) {
|
||||||
s.stateStack = append(s.stateStack, s.stateCurrent)
|
s.stateStack = append(s.stateStack, s.stateCurrent)
|
||||||
@ -178,14 +184,9 @@ func (s *ebitenSurface) RenderSection(sfc d2interface.Surface, bound image.Recta
|
|||||||
func (s *ebitenSurface) createDrawImageOptions() *ebiten.DrawImageOptions {
|
func (s *ebitenSurface) createDrawImageOptions() *ebiten.DrawImageOptions {
|
||||||
opts := &ebiten.DrawImageOptions{}
|
opts := &ebiten.DrawImageOptions{}
|
||||||
|
|
||||||
if s.stateCurrent.skewX != 0 || s.stateCurrent.skewY != 0 {
|
opts.GeoM.Skew(s.stateCurrent.skewX, s.stateCurrent.skewY)
|
||||||
opts.GeoM.Skew(s.stateCurrent.skewX, s.stateCurrent.skewY)
|
opts.GeoM.Scale(s.stateCurrent.scaleX, s.stateCurrent.scaleY)
|
||||||
}
|
opts.GeoM.Rotate(s.stateCurrent.rotate)
|
||||||
|
|
||||||
if s.stateCurrent.scaleX != 1.0 || s.stateCurrent.scaleY != 1.0 {
|
|
||||||
opts.GeoM.Scale(s.stateCurrent.scaleX, s.stateCurrent.scaleY)
|
|
||||||
}
|
|
||||||
|
|
||||||
opts.GeoM.Translate(float64(s.stateCurrent.x), float64(s.stateCurrent.y))
|
opts.GeoM.Translate(float64(s.stateCurrent.x), float64(s.stateCurrent.y))
|
||||||
|
|
||||||
opts.Filter = s.stateCurrent.filter
|
opts.Filter = s.stateCurrent.filter
|
||||||
|
@ -18,4 +18,5 @@ type surfaceState struct {
|
|||||||
effect d2enum.DrawEffect
|
effect d2enum.DrawEffect
|
||||||
skewX, skewY float64
|
skewX, skewY float64
|
||||||
scaleX, scaleY float64
|
scaleX, scaleY float64
|
||||||
|
rotate float64
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
package d2systems
|
package d2systems
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
"gopkg.in/alecthomas/kingpin.v2"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
|
|
||||||
@ -19,12 +21,26 @@ const (
|
|||||||
logPrefixAppBootstrap = "App Bootstrap"
|
logPrefixAppBootstrap = "App Bootstrap"
|
||||||
)
|
)
|
||||||
|
|
||||||
// static check that the game config system implements the system interface
|
const (
|
||||||
var _ akara.System = &AppBootstrapSystem{}
|
sceneTestArg = "testscene"
|
||||||
|
sceneTestDesc = "test a scene"
|
||||||
|
|
||||||
// AppBootstrapSystem is responsible for the common initialization process between
|
serverArg = "server"
|
||||||
|
serverDesc = "run dedicated server"
|
||||||
|
|
||||||
|
counterArg = "counter"
|
||||||
|
counterDesc = "print updates/sec"
|
||||||
|
|
||||||
|
skipSplashArg = "nosplash"
|
||||||
|
skipSplashDesc = "skip the ebiten splash screen"
|
||||||
|
)
|
||||||
|
|
||||||
|
// static check that the game config system implements the system interface
|
||||||
|
var _ akara.System = &AppBootstrap{}
|
||||||
|
|
||||||
|
// AppBootstrap is responsible for the common initialization process between
|
||||||
// the app modes (eg common to the game client as well as the headless server)
|
// the app modes (eg common to the game client as well as the headless server)
|
||||||
type AppBootstrapSystem struct {
|
type AppBootstrap struct {
|
||||||
akara.BaseSubscriberSystem
|
akara.BaseSubscriberSystem
|
||||||
*d2util.Logger
|
*d2util.Logger
|
||||||
subscribedFiles *akara.Subscription
|
subscribedFiles *akara.Subscription
|
||||||
@ -37,7 +53,7 @@ type AppBootstrapSystem struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Init will inject (or use existing) components related to setting up the config sources
|
// Init will inject (or use existing) components related to setting up the config sources
|
||||||
func (m *AppBootstrapSystem) Init(world *akara.World) {
|
func (m *AppBootstrap) Init(world *akara.World) {
|
||||||
m.World = world
|
m.World = world
|
||||||
|
|
||||||
m.setupLogger()
|
m.setupLogger()
|
||||||
@ -49,16 +65,17 @@ func (m *AppBootstrapSystem) Init(world *akara.World) {
|
|||||||
m.injectSystems()
|
m.injectSystems()
|
||||||
m.setupConfigSources()
|
m.setupConfigSources()
|
||||||
m.setupConfigFile()
|
m.setupConfigFile()
|
||||||
|
m.parseCommandLineArgs()
|
||||||
|
|
||||||
m.Info("... initialization complete!")
|
m.Info("... initialization complete!")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *AppBootstrapSystem) setupLogger() {
|
func (m *AppBootstrap) setupLogger() {
|
||||||
m.Logger = d2util.NewLogger()
|
m.Logger = d2util.NewLogger()
|
||||||
m.SetPrefix(logPrefixAppBootstrap)
|
m.SetPrefix(logPrefixAppBootstrap)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *AppBootstrapSystem) setupSubscriptions() {
|
func (m *AppBootstrap) setupSubscriptions() {
|
||||||
m.Info("setting up component subscriptions")
|
m.Info("setting up component subscriptions")
|
||||||
|
|
||||||
// we are going to check entities that dont yet have loaded asset types
|
// we are going to check entities that dont yet have loaded asset types
|
||||||
@ -91,7 +108,7 @@ func (m *AppBootstrapSystem) setupSubscriptions() {
|
|||||||
m.subscribedConfigs = m.World.AddSubscription(gameConfigs)
|
m.subscribedConfigs = m.World.AddSubscription(gameConfigs)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *AppBootstrapSystem) setupFactories() {
|
func (m *AppBootstrap) setupFactories() {
|
||||||
m.Info("setting up component factories")
|
m.Info("setting up component factories")
|
||||||
|
|
||||||
m.InjectComponent(&d2components.GameConfig{}, &m.GameConfig)
|
m.InjectComponent(&d2components.GameConfig{}, &m.GameConfig)
|
||||||
@ -101,7 +118,7 @@ func (m *AppBootstrapSystem) setupFactories() {
|
|||||||
m.InjectComponent(&d2components.FileSource{}, &m.FileSource)
|
m.InjectComponent(&d2components.FileSource{}, &m.FileSource)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *AppBootstrapSystem) injectSystems() {
|
func (m *AppBootstrap) injectSystems() {
|
||||||
m.Info("injecting file type resolution system")
|
m.Info("injecting file type resolution system")
|
||||||
m.AddSystem(&FileTypeResolver{})
|
m.AddSystem(&FileTypeResolver{})
|
||||||
|
|
||||||
@ -116,9 +133,6 @@ func (m *AppBootstrapSystem) injectSystems() {
|
|||||||
|
|
||||||
m.Info("injecting asset loader system")
|
m.Info("injecting asset loader system")
|
||||||
m.AddSystem(&AssetLoaderSystem{})
|
m.AddSystem(&AssetLoaderSystem{})
|
||||||
|
|
||||||
m.Info("injecting game object factory system")
|
|
||||||
m.AddSystem(&GameObjectFactory{})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// we make two entities and assign file paths for the two directories that
|
// we make two entities and assign file paths for the two directories that
|
||||||
@ -126,7 +140,7 @@ func (m *AppBootstrapSystem) injectSystems() {
|
|||||||
// the file type resolver system, and then the file source resolver system. At that point,
|
// the file type resolver system, and then the file source resolver system. At that point,
|
||||||
// there will be sources for these two directories that can possibly resolve a config file.
|
// there will be sources for these two directories that can possibly resolve a config file.
|
||||||
// A new config file is created if one is not found.
|
// A new config file is created if one is not found.
|
||||||
func (m *AppBootstrapSystem) setupConfigSources() {
|
func (m *AppBootstrap) setupConfigSources() {
|
||||||
// make the two entities, these will be the file sources
|
// make the two entities, these will be the file sources
|
||||||
e1, e2 := m.NewEntity(), m.NewEntity()
|
e1, e2 := m.NewEntity(), m.NewEntity()
|
||||||
|
|
||||||
@ -152,7 +166,7 @@ func (m *AppBootstrapSystem) setupConfigSources() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *AppBootstrapSystem) setupConfigFile() {
|
func (m *AppBootstrap) setupConfigFile() {
|
||||||
// add an entity that will get picked up by the game config system and loaded
|
// add an entity that will get picked up by the game config system and loaded
|
||||||
m.AddFilePath(m.NewEntity()).Path = configFileName
|
m.AddFilePath(m.NewEntity()).Path = configFileName
|
||||||
m.Infof("setting up config file `%s` for processing", configFileName)
|
m.Infof("setting up config file `%s` for processing", configFileName)
|
||||||
@ -160,7 +174,7 @@ func (m *AppBootstrapSystem) setupConfigFile() {
|
|||||||
|
|
||||||
// Update will look for the first entity with a game config component
|
// Update will look for the first entity with a game config component
|
||||||
// and then add the mpq's as file sources
|
// and then add the mpq's as file sources
|
||||||
func (m *AppBootstrapSystem) Update() {
|
func (m *AppBootstrap) Update() {
|
||||||
configs := m.subscribedConfigs.GetEntities()
|
configs := m.subscribedConfigs.GetEntities()
|
||||||
if len(configs) < 1 {
|
if len(configs) < 1 {
|
||||||
return
|
return
|
||||||
@ -182,7 +196,7 @@ func (m *AppBootstrapSystem) Update() {
|
|||||||
m.SetActive(false)
|
m.SetActive(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *AppBootstrapSystem) initMpqSources(cfg *d2components.GameConfig) {
|
func (m *AppBootstrap) initMpqSources(cfg *d2components.GameConfig) {
|
||||||
for _, mpqFileName := range cfg.MpqLoadOrder {
|
for _, mpqFileName := range cfg.MpqLoadOrder {
|
||||||
fullMpqFilePath := path.Join(cfg.MpqPath, mpqFileName)
|
fullMpqFilePath := path.Join(cfg.MpqPath, mpqFileName)
|
||||||
|
|
||||||
@ -193,3 +207,44 @@ func (m *AppBootstrapSystem) initMpqSources(cfg *d2components.GameConfig) {
|
|||||||
mpqSource.Path = fullMpqFilePath
|
mpqSource.Path = fullMpqFilePath
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *AppBootstrap) parseCommandLineArgs() {
|
||||||
|
sceneTest := kingpin.Flag(sceneTestArg, sceneTestDesc).String()
|
||||||
|
server := kingpin.Flag(serverArg, serverDesc).Bool()
|
||||||
|
enableCounter := kingpin.Flag(counterArg, counterDesc).Bool()
|
||||||
|
_ = kingpin.Flag(skipSplashArg, skipSplashDesc).Bool() // see game client bootstrap
|
||||||
|
|
||||||
|
kingpin.Parse()
|
||||||
|
|
||||||
|
if *enableCounter {
|
||||||
|
m.World.AddSystem(&UpdateCounter{})
|
||||||
|
}
|
||||||
|
|
||||||
|
if *server {
|
||||||
|
fmt.Println("not yet implemented")
|
||||||
|
os.Exit(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
m.World.AddSystem(&RenderSystem{})
|
||||||
|
m.World.AddSystem(&InputSystem{})
|
||||||
|
|
||||||
|
switch *sceneTest {
|
||||||
|
case "splash":
|
||||||
|
m.Info("running ebiten splash scene")
|
||||||
|
m.World.AddSystem(NewEbitenSplashScene())
|
||||||
|
case "load":
|
||||||
|
m.Info("running loading scene")
|
||||||
|
m.World.AddSystem(NewLoadingScene())
|
||||||
|
case "mouse":
|
||||||
|
m.Info("running mouse cursor scene")
|
||||||
|
m.World.AddSystem(NewMouseCursorScene())
|
||||||
|
case "main":
|
||||||
|
m.Info("running main menu scene")
|
||||||
|
m.World.AddSystem(NewMainMenuScene())
|
||||||
|
case "terminal":
|
||||||
|
m.Info("running terminal scene")
|
||||||
|
m.World.AddSystem(NewTerminalScene())
|
||||||
|
default:
|
||||||
|
m.World.AddSystem(&GameClientBootstrap{})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,2 +1,2 @@
|
|||||||
// Package d2systems provides all of the ECS baseSystems
|
// Package d2systems provides all of the ECS sceneSystems
|
||||||
package d2systems
|
package d2systems
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
package d2systems
|
package d2systems
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/gravestench/akara"
|
|
||||||
|
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2util"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2util"
|
||||||
|
"github.com/gravestench/akara"
|
||||||
|
"gopkg.in/alecthomas/kingpin.v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -11,17 +11,17 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// static check that the game config system implements the system interface
|
// static check that the game config system implements the system interface
|
||||||
var _ akara.System = &GameClientBootstrapSystem{}
|
var _ akara.System = &GameClientBootstrap{}
|
||||||
|
|
||||||
// GameClientBootstrapSystem is responsible for setting up other
|
// GameClientBootstrap is responsible for setting up other
|
||||||
// baseSystems that are common to both the game client and the headless game server
|
// sceneSystems that are common to both the game client and the headless game server
|
||||||
type GameClientBootstrapSystem struct {
|
type GameClientBootstrap struct {
|
||||||
akara.BaseSubscriberSystem
|
akara.BaseSubscriberSystem
|
||||||
*d2util.Logger
|
*d2util.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
// Init injects the common baseSystems required by both the game client and headless server
|
// Init injects the common sceneSystems required by both the game client and headless server
|
||||||
func (m *GameClientBootstrapSystem) Init(world *akara.World) {
|
func (m *GameClientBootstrap) Init(world *akara.World) {
|
||||||
m.World = world
|
m.World = world
|
||||||
|
|
||||||
m.setupLogger()
|
m.setupLogger()
|
||||||
@ -37,20 +37,20 @@ func (m *GameClientBootstrapSystem) Init(world *akara.World) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *GameClientBootstrapSystem) setupLogger() {
|
func (m *GameClientBootstrap) setupLogger() {
|
||||||
m.Logger = d2util.NewLogger()
|
m.Logger = d2util.NewLogger()
|
||||||
m.SetPrefix(logPrefixGameClientBootstrap)
|
m.SetPrefix(logPrefixGameClientBootstrap)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *GameClientBootstrapSystem) injectSystems() {
|
func (m *GameClientBootstrap) injectSystems() {
|
||||||
m.Info("injecting render system")
|
m.Info("injecting terminal scene")
|
||||||
m.AddSystem(&RenderSystem{})
|
m.AddSystem(NewTerminalScene())
|
||||||
|
|
||||||
m.Info("injecting input system")
|
m.Info("injecting timescale scene")
|
||||||
m.AddSystem(&InputSystem{})
|
m.AddSystem(&TimeScaleSystem{})
|
||||||
|
|
||||||
m.Info("injecting update counter system")
|
m.Info("injecting game object factory system")
|
||||||
m.AddSystem(&UpdateCounter{})
|
m.AddSystem(&GameObjectFactory{})
|
||||||
|
|
||||||
m.Info("injecting loading scene")
|
m.Info("injecting loading scene")
|
||||||
m.AddSystem(NewLoadingScene())
|
m.AddSystem(NewLoadingScene())
|
||||||
@ -58,18 +58,20 @@ func (m *GameClientBootstrapSystem) injectSystems() {
|
|||||||
m.Info("injecting mouse cursor scene")
|
m.Info("injecting mouse cursor scene")
|
||||||
m.AddSystem(NewMouseCursorScene())
|
m.AddSystem(NewMouseCursorScene())
|
||||||
|
|
||||||
|
skipSplash := kingpin.Flag(skipSplashArg, skipSplashDesc).Bool()
|
||||||
|
kingpin.Parse()
|
||||||
|
|
||||||
|
if !*skipSplash {
|
||||||
|
m.Info("injecting ebiten splash scene")
|
||||||
|
m.AddSystem(NewEbitenSplashScene())
|
||||||
|
}
|
||||||
|
|
||||||
m.Info("injecting main menu scene")
|
m.Info("injecting main menu scene")
|
||||||
m.AddSystem(NewMainMenuScene())
|
m.AddSystem(NewMainMenuScene())
|
||||||
|
|
||||||
m.Info("injecting terminal scene")
|
|
||||||
m.AddSystem(NewTerminalScene())
|
|
||||||
|
|
||||||
m.Info("injecting ebiten splash scene")
|
|
||||||
m.AddSystem(NewEbitenSplashScene())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update does nothing, but exists to satisfy the `akara.System` interface
|
// Update does nothing, but exists to satisfy the `akara.System` interface
|
||||||
func (m *GameClientBootstrapSystem) Update() {
|
func (m *GameClientBootstrap) Update() {
|
||||||
m.Info("game client bootstrap complete, deactivating")
|
m.Info("game client bootstrap complete, deactivating")
|
||||||
m.RemoveSystem(m)
|
m.RemoveSystem(m)
|
||||||
}
|
}
|
||||||
|
@ -24,9 +24,9 @@ const (
|
|||||||
// to be found in, and it also adds an entity for the initial config file to be loaded.
|
// to be found in, and it also adds an entity for the initial config file to be loaded.
|
||||||
//
|
//
|
||||||
// This system is dependant on the FileTypeResolver, FileSourceResolver, and
|
// This system is dependant on the FileTypeResolver, FileSourceResolver, and
|
||||||
// FileHandleResolver baseSystems because this system subscribes to entities
|
// FileHandleResolver sceneSystems because this system subscribes to entities
|
||||||
// with components created by these other baseSystems. Nothing will break if these
|
// with components created by these other sceneSystems. Nothing will break if these
|
||||||
// other baseSystems are not present in the world, but no config files will be loaded by
|
// other sceneSystems are not present in the world, but no config files will be loaded by
|
||||||
// this system either...
|
// this system either...
|
||||||
type GameConfigSystem struct {
|
type GameConfigSystem struct {
|
||||||
akara.BaseSubscriberSystem
|
akara.BaseSubscriberSystem
|
||||||
|
@ -26,7 +26,7 @@ func Test_GameConfigSystem_Bootstrap(t *testing.T) {
|
|||||||
cfgSys.AddFilePath(world.NewEntity()).Path = testDataPath
|
cfgSys.AddFilePath(world.NewEntity()).Path = testDataPath
|
||||||
cfgSys.AddFilePath(world.NewEntity()).Path = "config.json"
|
cfgSys.AddFilePath(world.NewEntity()).Path = "config.json"
|
||||||
|
|
||||||
// at this point the world has initialized the baseSystems. when the world
|
// at this point the world has initialized the sceneSystems. when the world
|
||||||
// updates it should process the config dir to a source and then
|
// updates it should process the config dir to a source and then
|
||||||
// use the source to resolve a file handle, and finally the config file
|
// use the source to resolve a file handle, and finally the config file
|
||||||
// will get loaded by the config system.
|
// will get loaded by the config system.
|
||||||
|
@ -13,7 +13,7 @@ const (
|
|||||||
// static check that GameObjectFactory implements the System interface
|
// static check that GameObjectFactory implements the System interface
|
||||||
var _ akara.System = &GameObjectFactory{}
|
var _ akara.System = &GameObjectFactory{}
|
||||||
|
|
||||||
// GameObjectFactory is a wrapper system for subordinate baseSystems that
|
// GameObjectFactory is a wrapper system for subordinate sceneSystems that
|
||||||
// do the actual object creation work.
|
// do the actual object creation work.
|
||||||
type GameObjectFactory struct {
|
type GameObjectFactory struct {
|
||||||
akara.BaseSystem
|
akara.BaseSystem
|
||||||
@ -44,7 +44,7 @@ func (t *GameObjectFactory) injectSubSystems() {
|
|||||||
t.ShapeSystem = NewShapeSystem(t.BaseSystem, t.Logger)
|
t.ShapeSystem = NewShapeSystem(t.BaseSystem, t.Logger)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update updates all the sub-baseSystems
|
// Update updates all the sub-sceneSystems
|
||||||
func (t *GameObjectFactory) Update() {
|
func (t *GameObjectFactory) Update() {
|
||||||
t.SpriteFactory.Update()
|
t.SpriteFactory.Update()
|
||||||
t.ShapeSystem.Update()
|
t.ShapeSystem.Update()
|
||||||
|
@ -86,6 +86,8 @@ func (m *InputSystem) Update() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (m *InputSystem) updateInputState() {
|
func (m *InputSystem) updateInputState() {
|
||||||
|
m.inputState.Clear()
|
||||||
|
|
||||||
var keysToCheck = []d2input.Key{
|
var keysToCheck = []d2input.Key{
|
||||||
d2input.Key0, d2input.Key1, d2input.Key2, d2input.Key3, d2input.Key4, d2input.Key5, d2input.Key6,
|
d2input.Key0, d2input.Key1, d2input.Key2, d2input.Key3, d2input.Key4, d2input.Key5, d2input.Key6,
|
||||||
d2input.Key7, d2input.Key8, d2input.Key9, d2input.KeyA, d2input.KeyB, d2input.KeyC, d2input.KeyD,
|
d2input.Key7, d2input.Key8, d2input.Key9, d2input.KeyA, d2input.KeyB, d2input.KeyC, d2input.KeyD,
|
||||||
@ -118,17 +120,17 @@ func (m *InputSystem) updateInputState() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, key := range keysToCheck {
|
for _, key := range keysToCheck {
|
||||||
truth := m.InputService.IsKeyPressed(d2enum.Key(key))
|
truth := m.InputService.IsKeyJustPressed(d2enum.Key(key))
|
||||||
m.inputState.KeyVector.Set(key, truth)
|
m.inputState.KeyVector.Set(key, truth)
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, mod := range modifiersToCheck {
|
for _, mod := range modifiersToCheck {
|
||||||
truth := m.InputService.IsKeyPressed(d2enum.Key(mod))
|
truth := m.InputService.IsKeyJustPressed(d2enum.Key(mod))
|
||||||
m.inputState.ModifierVector.Set(mod, truth)
|
m.inputState.ModifierVector.Set(mod, truth)
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, btn := range buttonsToCheck {
|
for _, btn := range buttonsToCheck {
|
||||||
truth := m.InputService.IsMouseButtonPressed(d2enum.MouseButton(btn))
|
truth := m.InputService.IsMouseButtonJustPressed(d2enum.MouseButton(btn))
|
||||||
m.inputState.MouseButtonVector.Set(btn, truth)
|
m.inputState.MouseButtonVector.Set(btn, truth)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,7 @@ var _ akara.System = &MovementSystem{}
|
|||||||
type MovementSystem struct {
|
type MovementSystem struct {
|
||||||
akara.BaseSubscriberSystem
|
akara.BaseSubscriberSystem
|
||||||
*d2util.Logger
|
*d2util.Logger
|
||||||
d2components.PositionFactory
|
d2components.TransformFactory
|
||||||
d2components.VelocityFactory
|
d2components.VelocityFactory
|
||||||
movableEntities *akara.Subscription
|
movableEntities *akara.Subscription
|
||||||
}
|
}
|
||||||
@ -35,11 +35,11 @@ func (m *MovementSystem) Init(world *akara.World) {
|
|||||||
|
|
||||||
m.Info("initializing ...")
|
m.Info("initializing ...")
|
||||||
|
|
||||||
m.InjectComponent(&d2components.Position{}, &m.Position)
|
m.InjectComponent(&d2components.Transform{}, &m.Transform)
|
||||||
m.InjectComponent(&d2components.Velocity{}, &m.Velocity)
|
m.InjectComponent(&d2components.Velocity{}, &m.Velocity)
|
||||||
|
|
||||||
movable := m.NewComponentFilter().Require(
|
movable := m.NewComponentFilter().Require(
|
||||||
&d2components.Position{},
|
&d2components.Transform{},
|
||||||
&d2components.Velocity{},
|
&d2components.Velocity{},
|
||||||
).Build()
|
).Build()
|
||||||
|
|
||||||
@ -56,7 +56,7 @@ func (m *MovementSystem) Update() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (m *MovementSystem) move(id akara.EID) {
|
func (m *MovementSystem) move(id akara.EID) {
|
||||||
position, found := m.GetPosition(id)
|
transform, found := m.GetTransform(id)
|
||||||
if !found {
|
if !found {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -67,5 +67,5 @@ func (m *MovementSystem) move(id akara.EID) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
s := float64(m.World.TimeDelta) / float64(time.Second)
|
s := float64(m.World.TimeDelta) / float64(time.Second)
|
||||||
position.Add(velocity.Clone().Scale(s))
|
transform.Translation.Add(velocity.Clone().Scale(s))
|
||||||
}
|
}
|
||||||
|
@ -40,6 +40,7 @@ type RenderSystem struct {
|
|||||||
d2components.TextureFactory
|
d2components.TextureFactory
|
||||||
d2components.PriorityFactory
|
d2components.PriorityFactory
|
||||||
d2components.AlphaFactory
|
d2components.AlphaFactory
|
||||||
|
d2components.CameraFactory
|
||||||
lastUpdate time.Time
|
lastUpdate time.Time
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -69,6 +70,7 @@ func (m *RenderSystem) setupFactories() {
|
|||||||
m.InjectComponent(&d2components.Texture{}, &m.Texture)
|
m.InjectComponent(&d2components.Texture{}, &m.Texture)
|
||||||
m.InjectComponent(&d2components.Priority{}, &m.Priority)
|
m.InjectComponent(&d2components.Priority{}, &m.Priority)
|
||||||
m.InjectComponent(&d2components.Alpha{}, &m.Alpha)
|
m.InjectComponent(&d2components.Alpha{}, &m.Alpha)
|
||||||
|
m.InjectComponent(&d2components.Camera{}, &m.Camera)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *RenderSystem) setupSubscriptions() {
|
func (m *RenderSystem) setupSubscriptions() {
|
||||||
@ -77,6 +79,7 @@ func (m *RenderSystem) setupSubscriptions() {
|
|||||||
&d2components.Viewport{},
|
&d2components.Viewport{},
|
||||||
&d2components.MainViewport{},
|
&d2components.MainViewport{},
|
||||||
&d2components.Texture{},
|
&d2components.Texture{},
|
||||||
|
&d2components.Camera{},
|
||||||
).
|
).
|
||||||
Build()
|
Build()
|
||||||
|
|
||||||
@ -91,7 +94,7 @@ func (m *RenderSystem) setupSubscriptions() {
|
|||||||
// Update will initialize the renderer, start the game loop, and
|
// Update will initialize the renderer, start the game loop, and
|
||||||
// disable the system (to prevent it from being called during the game loop).
|
// disable the system (to prevent it from being called during the game loop).
|
||||||
//
|
//
|
||||||
// The reason why this isn't in the init step is because we use other baseSystems
|
// The reason why this isn't in the init step is because we use other sceneSystems
|
||||||
// for loading the config file, and it may take more than one iteration
|
// for loading the config file, and it may take more than one iteration
|
||||||
func (m *RenderSystem) Update() {
|
func (m *RenderSystem) Update() {
|
||||||
if m.renderer != nil {
|
if m.renderer != nil {
|
||||||
@ -108,7 +111,7 @@ func (m *RenderSystem) Update() {
|
|||||||
// this system and start the run loop.
|
// this system and start the run loop.
|
||||||
m.SetActive(false)
|
m.SetActive(false)
|
||||||
|
|
||||||
err := m.startGameLoop()
|
err := m.StartGameLoop()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
m.Fatal(err.Error())
|
m.Fatal(err.Error())
|
||||||
}
|
}
|
||||||
@ -173,6 +176,11 @@ func (m *RenderSystem) render(screen d2interface.Surface) error {
|
|||||||
return errors.New("main viewport not found")
|
return errors.New("main viewport not found")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cam, found := m.GetCamera(id)
|
||||||
|
if !found {
|
||||||
|
return errors.New("main viewport camera not found")
|
||||||
|
}
|
||||||
|
|
||||||
texture, found := m.GetTexture(id)
|
texture, found := m.GetTexture(id)
|
||||||
if !found {
|
if !found {
|
||||||
return errors.New("main viewport doesn't have a surface")
|
return errors.New("main viewport doesn't have a surface")
|
||||||
@ -191,11 +199,13 @@ func (m *RenderSystem) render(screen d2interface.Surface) error {
|
|||||||
|
|
||||||
screen.PushColor(color.Alpha{A: uint8(alpha.Alpha * maxAlpha)})
|
screen.PushColor(color.Alpha{A: uint8(alpha.Alpha * maxAlpha)})
|
||||||
screen.PushTranslation(vp.Left, vp.Top)
|
screen.PushTranslation(vp.Left, vp.Top)
|
||||||
|
screen.PushScale(float64(vp.Width)/cam.Size.X, float64(vp.Height)/cam.Size.Y)
|
||||||
|
|
||||||
screen.Render(texture.Texture)
|
screen.Render(texture.Texture)
|
||||||
|
|
||||||
screen.Pop()
|
screen.Pop()
|
||||||
screen.Pop()
|
screen.Pop()
|
||||||
|
screen.Pop()
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@ -209,7 +219,7 @@ func (m *RenderSystem) updateWorld() error {
|
|||||||
return m.World.Update(elapsed)
|
return m.World.Update(elapsed)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *RenderSystem) startGameLoop() error {
|
func (m *RenderSystem) StartGameLoop() error {
|
||||||
m.Infof("starting game loop ...")
|
m.Infof("starting game loop ...")
|
||||||
|
|
||||||
return m.renderer.Run(m.render, m.updateWorld, 800, 600, gameTitle)
|
return m.renderer.Run(m.render, m.updateWorld, 800, 600, gameTitle)
|
||||||
|
@ -29,8 +29,7 @@ func NewBaseScene(key string) *BaseScene {
|
|||||||
Logger: d2util.NewLogger(),
|
Logger: d2util.NewLogger(),
|
||||||
key: key,
|
key: key,
|
||||||
Viewports: make([]akara.EID, 0),
|
Viewports: make([]akara.EID, 0),
|
||||||
GameObjects: make([]akara.EID, 0),
|
SceneObjects: make([]akara.EID, 0),
|
||||||
baseSystems: &baseSystems{},
|
|
||||||
backgroundColor: color.Transparent,
|
backgroundColor: color.Transparent,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -41,20 +40,41 @@ func NewBaseScene(key string) *BaseScene {
|
|||||||
|
|
||||||
var _ akara.System = &BaseScene{}
|
var _ akara.System = &BaseScene{}
|
||||||
|
|
||||||
type baseSystems struct {
|
type sceneSystems struct {
|
||||||
*RenderSystem
|
*RenderSystem
|
||||||
*InputSystem
|
*InputSystem
|
||||||
*GameObjectFactory
|
*GameObjectFactory
|
||||||
}
|
}
|
||||||
|
|
||||||
// BaseScene encapsulates common behaviors for baseSystems that are considered "scenes",
|
type sceneComponents struct {
|
||||||
|
d2components.SceneGraphNodeFactory
|
||||||
|
d2components.ViewportFactory
|
||||||
|
d2components.MainViewportFactory
|
||||||
|
d2components.ViewportFilterFactory
|
||||||
|
d2components.PriorityFactory
|
||||||
|
d2components.CameraFactory
|
||||||
|
d2components.TextureFactory
|
||||||
|
d2components.InteractiveFactory
|
||||||
|
d2components.TransformFactory
|
||||||
|
d2components.SpriteFactory
|
||||||
|
d2components.OriginFactory
|
||||||
|
d2components.AlphaFactory
|
||||||
|
d2components.DrawEffectFactory
|
||||||
|
d2components.RectangleFactory
|
||||||
|
d2components.ColorFactory
|
||||||
|
d2components.CommandRegistrationFactory
|
||||||
|
d2components.DirtyFactory
|
||||||
|
}
|
||||||
|
|
||||||
|
// BaseScene encapsulates common behaviors for systems that are considered "scenes",
|
||||||
// such as the main menu, the in-game map, the console, etc.
|
// such as the main menu, the in-game map, the console, etc.
|
||||||
//
|
//
|
||||||
// The base scene is responsible for generic behaviors common to all scenes,
|
// The base scene is responsible for generic behaviors common to all scenes,
|
||||||
// like initializing the default viewport, or rendering game objects to the viewports.
|
// like initializing the default viewport, or rendering game objects to the viewports.
|
||||||
type BaseScene struct {
|
type BaseScene struct {
|
||||||
*akara.BaseSystem
|
*akara.BaseSystem
|
||||||
*baseSystems
|
sceneSystems
|
||||||
|
sceneComponents
|
||||||
Geom struct {
|
Geom struct {
|
||||||
Rectangle rectangle.Namespace
|
Rectangle rectangle.Namespace
|
||||||
}
|
}
|
||||||
@ -64,27 +84,9 @@ type BaseScene struct {
|
|||||||
paused bool
|
paused bool
|
||||||
Add *sceneObjectFactory
|
Add *sceneObjectFactory
|
||||||
Viewports []akara.EID
|
Viewports []akara.EID
|
||||||
GameObjects []akara.EID
|
SceneObjects []akara.EID
|
||||||
Graph *d2scene.Node // the root node
|
Graph *d2scene.Node // the root node
|
||||||
backgroundColor color.Color
|
backgroundColor color.Color
|
||||||
d2components.SceneGraphNodeFactory
|
|
||||||
d2components.ViewportFactory
|
|
||||||
d2components.MainViewportFactory
|
|
||||||
d2components.ViewportFilterFactory
|
|
||||||
d2components.PriorityFactory
|
|
||||||
d2components.CameraFactory
|
|
||||||
d2components.TextureFactory
|
|
||||||
d2components.InteractiveFactory
|
|
||||||
d2components.PositionFactory
|
|
||||||
d2components.ScaleFactory
|
|
||||||
d2components.SpriteFactory
|
|
||||||
d2components.OriginFactory
|
|
||||||
d2components.AlphaFactory
|
|
||||||
d2components.DrawEffectFactory
|
|
||||||
d2components.RectangleFactory
|
|
||||||
d2components.ColorFactory
|
|
||||||
d2components.CommandRegistrationFactory
|
|
||||||
d2components.DirtyFactory
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Booted returns whether or not the scene has booted
|
// Booted returns whether or not the scene has booted
|
||||||
@ -118,46 +120,46 @@ func (s *BaseScene) boot() {
|
|||||||
s.Add.SetPrefix(fmt.Sprintf("%s -> %s", s.key, "Object Factory"))
|
s.Add.SetPrefix(fmt.Sprintf("%s -> %s", s.key, "Object Factory"))
|
||||||
|
|
||||||
for idx := range s.Systems {
|
for idx := range s.Systems {
|
||||||
if rendersys, ok := s.Systems[idx].(*RenderSystem); ok && s.baseSystems.RenderSystem == nil {
|
if rendersys, ok := s.Systems[idx].(*RenderSystem); ok && s.sceneSystems.RenderSystem == nil {
|
||||||
s.baseSystems.RenderSystem = rendersys
|
s.sceneSystems.RenderSystem = rendersys
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if inputSys, ok := s.Systems[idx].(*InputSystem); ok && s.baseSystems.InputSystem == nil {
|
if inputSys, ok := s.Systems[idx].(*InputSystem); ok && s.sceneSystems.InputSystem == nil {
|
||||||
s.baseSystems.InputSystem = inputSys
|
s.sceneSystems.InputSystem = inputSys
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if objFactory, ok := s.Systems[idx].(*GameObjectFactory); ok && s.baseSystems.GameObjectFactory == nil {
|
if objFactory, ok := s.Systems[idx].(*GameObjectFactory); ok && s.sceneSystems.GameObjectFactory == nil {
|
||||||
s.baseSystems.GameObjectFactory = objFactory
|
s.sceneSystems.GameObjectFactory = objFactory
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if s.baseSystems.RenderSystem == nil {
|
if s.sceneSystems.RenderSystem == nil {
|
||||||
s.Info("waiting for render system ...")
|
s.Info("waiting for render system ...")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if s.baseSystems.RenderSystem.renderer == nil {
|
if s.sceneSystems.RenderSystem.renderer == nil {
|
||||||
s.Info("waiting for renderer instance ...")
|
s.Info("waiting for renderer instance ...")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if s.baseSystems.InputSystem == nil {
|
if s.sceneSystems.InputSystem == nil {
|
||||||
s.Info("waiting for input system")
|
s.Info("waiting for input system")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if s.baseSystems.GameObjectFactory == nil {
|
if s.sceneSystems.GameObjectFactory == nil {
|
||||||
s.Info("waiting for game object factory ...")
|
s.Info("waiting for game object factory ...")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
s.setupFactories()
|
s.setupFactories()
|
||||||
|
|
||||||
s.baseSystems.SpriteFactory.RenderSystem = s.baseSystems.RenderSystem
|
s.sceneSystems.SpriteFactory.RenderSystem = s.sceneSystems.RenderSystem
|
||||||
s.baseSystems.ShapeSystem.RenderSystem = s.baseSystems.RenderSystem
|
s.sceneSystems.ShapeSystem.RenderSystem = s.sceneSystems.RenderSystem
|
||||||
|
|
||||||
const (
|
const (
|
||||||
defaultWidth = 800
|
defaultWidth = 800
|
||||||
@ -180,8 +182,7 @@ func (s *BaseScene) setupFactories() {
|
|||||||
s.InjectComponent(&d2components.Priority{}, &s.Priority)
|
s.InjectComponent(&d2components.Priority{}, &s.Priority)
|
||||||
s.InjectComponent(&d2components.Texture{}, &s.Texture)
|
s.InjectComponent(&d2components.Texture{}, &s.Texture)
|
||||||
s.InjectComponent(&d2components.Interactive{}, &s.Interactive)
|
s.InjectComponent(&d2components.Interactive{}, &s.Interactive)
|
||||||
s.InjectComponent(&d2components.Position{}, &s.Position)
|
s.InjectComponent(&d2components.Transform{}, &s.Transform)
|
||||||
s.InjectComponent(&d2components.Scale{}, &s.Scale)
|
|
||||||
s.InjectComponent(&d2components.Origin{}, &s.Origin)
|
s.InjectComponent(&d2components.Origin{}, &s.Origin)
|
||||||
s.InjectComponent(&d2components.Alpha{}, &s.Alpha)
|
s.InjectComponent(&d2components.Alpha{}, &s.Alpha)
|
||||||
s.InjectComponent(&d2components.SceneGraphNode{}, &s.SceneGraphNode)
|
s.InjectComponent(&d2components.SceneGraphNode{}, &s.SceneGraphNode)
|
||||||
@ -208,17 +209,35 @@ func (s *BaseScene) Update() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
s.Graph.UpdateWorldMatrix()
|
s.updateSceneGraph()
|
||||||
s.renderViewports()
|
s.renderViewports()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *BaseScene) updateSceneGraph() {
|
||||||
|
for _, eid := range s.SceneObjects {
|
||||||
|
node, found := s.GetSceneGraphNode(eid)
|
||||||
|
if !found {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
transform, found := s.GetTransform(eid)
|
||||||
|
if !found {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
node.Local = transform.GetMatrix()
|
||||||
|
}
|
||||||
|
|
||||||
|
s.Graph.UpdateWorldMatrix()
|
||||||
|
}
|
||||||
|
|
||||||
func (s *BaseScene) renderViewports() {
|
func (s *BaseScene) renderViewports() {
|
||||||
if s.baseSystems.RenderSystem == nil {
|
if s.sceneSystems.RenderSystem == nil {
|
||||||
s.Warning("render system not present")
|
s.Warning("render system not present")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if s.baseSystems.RenderSystem.renderer == nil {
|
if s.sceneSystems.RenderSystem.renderer == nil {
|
||||||
s.Warning("render system doesn't have a renderer instance")
|
s.Warning("render system doesn't have a renderer instance")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -244,7 +263,7 @@ func (s *BaseScene) renderViewports() {
|
|||||||
func (s *BaseScene) binGameObjectsByViewport() map[int][]akara.EID {
|
func (s *BaseScene) binGameObjectsByViewport() map[int][]akara.EID {
|
||||||
bins := make(map[int][]akara.EID)
|
bins := make(map[int][]akara.EID)
|
||||||
|
|
||||||
for _, eid := range s.GameObjects {
|
for _, eid := range s.SceneObjects {
|
||||||
vpfilter, found := s.GetViewportFilter(eid)
|
vpfilter, found := s.GetViewportFilter(eid)
|
||||||
if !found {
|
if !found {
|
||||||
vpfilter = s.AddViewportFilter(eid)
|
vpfilter = s.AddViewportFilter(eid)
|
||||||
@ -267,116 +286,108 @@ func (s *BaseScene) binGameObjectsByViewport() map[int][]akara.EID {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *BaseScene) renderViewport(idx int, objects []akara.EID) {
|
func (s *BaseScene) renderViewport(idx int, objects []akara.EID) {
|
||||||
id := s.Viewports[idx]
|
viewportEID := s.Viewports[idx]
|
||||||
|
|
||||||
// the first viewport is always the main viewport
|
// the first viewport is always the main viewport
|
||||||
if idx == mainViewport {
|
if idx == mainViewport {
|
||||||
s.AddMainViewport(id)
|
s.AddMainViewport(viewportEID)
|
||||||
} else {
|
} else {
|
||||||
s.MainViewport.Remove(id)
|
s.MainViewport.Remove(viewportEID)
|
||||||
}
|
}
|
||||||
|
|
||||||
camera, found := s.GetCamera(id)
|
sfc, found := s.GetTexture(viewportEID)
|
||||||
if !found {
|
if !found || sfc.Texture == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
node, found := s.GetSceneGraphNode(id)
|
|
||||||
if !found {
|
|
||||||
node = s.AddSceneGraphNode(id)
|
|
||||||
}
|
|
||||||
|
|
||||||
// translate the camera position using the camera's scene graph node
|
|
||||||
cx, cy := camera.Position.Clone().ApplyMatrix4(node.Local).XY()
|
|
||||||
cw, ch := camera.Size.XY()
|
|
||||||
|
|
||||||
sfc, found := s.GetTexture(id)
|
|
||||||
if !found {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if sfc.Texture == nil {
|
|
||||||
sfc.Texture = s.baseSystems.RenderSystem.renderer.NewSurface(int(cw), int(ch))
|
|
||||||
}
|
|
||||||
|
|
||||||
if idx == mainViewport {
|
if idx == mainViewport {
|
||||||
sfc.Texture.Clear(s.backgroundColor)
|
sfc.Texture.Clear(s.backgroundColor)
|
||||||
}
|
}
|
||||||
|
|
||||||
sfc.Texture.PushTranslation(int(-cx), int(-cy)) // negative because we're offsetting everything that gets rendered
|
for _, objectEID := range objects {
|
||||||
|
s.renderObject(viewportEID, objectEID)
|
||||||
for _, object := range objects {
|
|
||||||
s.renderObject(sfc.Texture, object)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sfc.Texture.Pop()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *BaseScene) renderObject(target d2interface.Surface, id akara.EID) {
|
func (s *BaseScene) renderObject(viewportEID, objectEID akara.EID) {
|
||||||
texture, found := s.GetTexture(id)
|
vpTexture, found := s.GetTexture(viewportEID)
|
||||||
|
if !found || vpTexture.Texture == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
vpNode, found := s.GetSceneGraphNode(viewportEID)
|
||||||
|
if !found {
|
||||||
|
vpNode = s.AddSceneGraphNode(viewportEID)
|
||||||
|
}
|
||||||
|
|
||||||
|
// translation, rotation, and scale vec3's
|
||||||
|
vpTrans, vpRot, vpScale := vpNode.Local.Invert().Decompose()
|
||||||
|
|
||||||
|
objTexture, found := s.GetTexture(objectEID)
|
||||||
if !found {
|
if !found {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
position, found := s.GetPosition(id)
|
|
||||||
|
alpha, found := s.GetAlpha(objectEID)
|
||||||
if !found {
|
if !found {
|
||||||
position = s.AddPosition(id)
|
alpha = s.AddAlpha(objectEID)
|
||||||
}
|
}
|
||||||
|
|
||||||
scale, found := s.GetScale(id)
|
origin, found := s.GetOrigin(objectEID)
|
||||||
if !found {
|
if !found {
|
||||||
scale = s.AddScale(id)
|
origin = s.AddOrigin(objectEID)
|
||||||
}
|
}
|
||||||
|
|
||||||
alpha, found := s.GetAlpha(id)
|
node, found := s.GetSceneGraphNode(objectEID)
|
||||||
if !found {
|
if !found {
|
||||||
alpha = s.AddAlpha(id)
|
node = s.AddSceneGraphNode(objectEID)
|
||||||
}
|
|
||||||
|
|
||||||
origin, found := s.GetOrigin(id)
|
|
||||||
if !found {
|
|
||||||
origin = s.AddOrigin(id)
|
|
||||||
}
|
|
||||||
|
|
||||||
node, found := s.GetSceneGraphNode(id)
|
|
||||||
if !found {
|
|
||||||
node = s.AddSceneGraphNode(id)
|
|
||||||
node.SetParent(s.Graph)
|
node.SetParent(s.Graph)
|
||||||
}
|
}
|
||||||
|
|
||||||
drawEffect, found := s.GetDrawEffect(id)
|
drawEffect, found := s.GetDrawEffect(objectEID)
|
||||||
if found {
|
if found {
|
||||||
target.PushEffect(drawEffect.DrawEffect)
|
vpTexture.Texture.PushEffect(drawEffect.DrawEffect)
|
||||||
defer target.Pop()
|
defer vpTexture.Texture.Pop()
|
||||||
}
|
}
|
||||||
|
|
||||||
// translate the entity position using the scene graph node
|
objNode, found := s.GetSceneGraphNode(objectEID)
|
||||||
x, y := position.Clone().
|
if !found {
|
||||||
Add(origin.Vector3).
|
objNode = s.AddSceneGraphNode(objectEID)
|
||||||
ApplyMatrix4(node.Local).
|
}
|
||||||
XY()
|
|
||||||
|
|
||||||
target.PushTranslation(int(x), int(y))
|
// translation, rotation, and scale vec3's
|
||||||
defer target.Pop()
|
objTrans, objRot, objScale := objNode.Local.Decompose()
|
||||||
|
|
||||||
target.PushScale(scale.Clone().ApplyMatrix4(node.Local).XY())
|
ox, oy := origin.X, origin.Y
|
||||||
defer target.Pop()
|
tx, ty := objTrans.Add(vpTrans).XY()
|
||||||
|
|
||||||
|
vpTexture.Texture.PushTranslation(int(tx+ox), int(ty+oy))
|
||||||
|
defer vpTexture.Texture.Pop()
|
||||||
|
|
||||||
|
vpTexture.Texture.PushScale(objScale.Multiply(vpScale).XY())
|
||||||
|
defer vpTexture.Texture.Pop()
|
||||||
|
|
||||||
|
vpTexture.Texture.PushRotate(objRot.Add(vpRot).Z)
|
||||||
|
defer vpTexture.Texture.Pop()
|
||||||
|
|
||||||
const maxAlpha = 255
|
const maxAlpha = 255
|
||||||
|
|
||||||
target.PushColor(color.Alpha{A: uint8(alpha.Alpha * maxAlpha)})
|
vpTexture.Texture.PushColor(color.Alpha{A: uint8(alpha.Alpha * maxAlpha)})
|
||||||
defer target.Pop()
|
defer vpTexture.Texture.Pop()
|
||||||
|
|
||||||
segment, found := s.baseSystems.SpriteFactory.GetSegmentedSprite(id)
|
segment, found := s.sceneSystems.SpriteFactory.GetSegmentedSprite(objectEID)
|
||||||
if found {
|
if found {
|
||||||
s.renderSegmentedSprite(target, id, segment)
|
s.renderSegmentedSprite(vpTexture.Texture, objectEID, segment)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
target.Render(texture.Texture)
|
vpTexture.Texture.Render(objTexture.Texture)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *BaseScene) renderSegmentedSprite(target d2interface.Surface, id akara.EID, seg *d2components.SegmentedSprite) {
|
func (s *BaseScene) renderSegmentedSprite(screen d2interface.Surface, id akara.EID, seg *d2components.SegmentedSprite) {
|
||||||
|
target := screen.Renderer().NewSurface(screen.GetSize())
|
||||||
|
|
||||||
animation, found := s.GetSprite(id)
|
animation, found := s.GetSprite(id)
|
||||||
if !found {
|
if !found {
|
||||||
return
|
return
|
||||||
@ -393,7 +404,7 @@ func (s *BaseScene) renderSegmentedSprite(target d2interface.Surface, id akara.E
|
|||||||
for x := 0; x < segmentsX; x++ {
|
for x := 0; x < segmentsX; x++ {
|
||||||
idx := x + y*segmentsX + frameOffset*segmentsX*segmentsY
|
idx := x + y*segmentsX + frameOffset*segmentsX*segmentsY
|
||||||
if err := animation.SetCurrentFrame(idx); err != nil {
|
if err := animation.SetCurrentFrame(idx); err != nil {
|
||||||
s.Error("SetCurrentFrame error" + err.Error())
|
s.Error("SetCurrentFrame error " + err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
target.PushTranslation(x+offsetX, y+offsetY)
|
target.PushTranslation(x+offsetX, y+offsetY)
|
||||||
@ -407,6 +418,8 @@ func (s *BaseScene) renderSegmentedSprite(target d2interface.Surface, id akara.E
|
|||||||
|
|
||||||
offsetY += maxFrameHeight - 1
|
offsetY += maxFrameHeight - 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
screen.Render(target)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *BaseScene) renderViewportsToMainViewport() {
|
func (s *BaseScene) renderViewportsToMainViewport() {
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
package d2systems
|
package d2systems
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2input"
|
||||||
|
"github.com/gravestench/akara"
|
||||||
"image/color"
|
"image/color"
|
||||||
"math"
|
"math"
|
||||||
|
|
||||||
"github.com/gravestench/akara"
|
|
||||||
|
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -121,6 +121,20 @@ func (s *EbitenSplashScene) createSplash() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interactive := s.AddInteractive(s.NewEntity())
|
||||||
|
|
||||||
|
interactive.InputVector.SetMouseButton(d2input.MouseButtonLeft)
|
||||||
|
|
||||||
|
interactive.Callback = func() bool {
|
||||||
|
s.Info("hiding splash scene")
|
||||||
|
|
||||||
|
s.timeElapsed = splashTimeout
|
||||||
|
|
||||||
|
interactive.Enabled = false
|
||||||
|
|
||||||
|
return true // prevent propagation
|
||||||
|
}
|
||||||
|
|
||||||
s.squares = squares
|
s.squares = squares
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -133,9 +147,11 @@ func (s *EbitenSplashScene) updateSplash() {
|
|||||||
// fade out after timeout
|
// fade out after timeout
|
||||||
if s.timeElapsed >= splashTimeout {
|
if s.timeElapsed >= splashTimeout {
|
||||||
vpAlpha, _ := s.GetAlpha(s.Viewports[0])
|
vpAlpha, _ := s.GetAlpha(s.Viewports[0])
|
||||||
vpAlpha.Alpha -= 0.1225
|
vpAlpha.Alpha -= 0.0425
|
||||||
if vpAlpha.Alpha <= 0 {
|
if vpAlpha.Alpha <= 0 {
|
||||||
vpAlpha.Alpha = 0
|
vpAlpha.Alpha = 0
|
||||||
|
|
||||||
|
s.Info("finished, deactivating")
|
||||||
s.SetActive(false)
|
s.SetActive(false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -145,7 +161,7 @@ func (s *EbitenSplashScene) updateSplash() {
|
|||||||
|
|
||||||
// fade all of the squares
|
// fade all of the squares
|
||||||
for idx, id := range s.squares {
|
for idx, id := range s.squares {
|
||||||
a := math.Sin(s.timeElapsed + -90 + (float64(idx)/numSquares))
|
a := math.Sin(s.timeElapsed*2 + -90 + (float64(idx)/numSquares))
|
||||||
a = (a+1)/2 // clamp between 0..1
|
a = (a+1)/2 // clamp between 0..1
|
||||||
|
|
||||||
alpha, found := s.GetAlpha(id)
|
alpha, found := s.GetAlpha(id)
|
||||||
|
1
d2core/d2systems/scene_graph_testing.go
Normal file
1
d2core/d2systems/scene_graph_testing.go
Normal file
@ -0,0 +1 @@
|
|||||||
|
package d2systems
|
@ -234,7 +234,7 @@ func (s *LoadingScene) updateLoadingSpritePosition() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
position, found := s.GetPosition(s.loadingSprite)
|
transform, found := s.GetTransform(s.loadingSprite)
|
||||||
if !found {
|
if !found {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -243,7 +243,11 @@ func (s *LoadingScene) updateLoadingSpritePosition() {
|
|||||||
frameW, frameH := sprite.GetCurrentFrameSize()
|
frameW, frameH := sprite.GetCurrentFrameSize()
|
||||||
|
|
||||||
// we add the frameH in the Y because sprites are supposed to be drawn from bottom to top
|
// we add the frameH in the Y because sprites are supposed to be drawn from bottom to top
|
||||||
position.X, position.Y = float64(centerX-(frameW/2)), float64(centerY+(frameH/2))
|
transform.Translation.Set(
|
||||||
|
float64(centerX-(frameW/2)),
|
||||||
|
float64(centerY+(frameH/2)),
|
||||||
|
transform.Translation.Z,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *LoadingScene) updateLoadingSpriteFrame() {
|
func (s *LoadingScene) updateLoadingSpriteFrame() {
|
||||||
|
@ -38,6 +38,7 @@ type MouseCursorScene struct {
|
|||||||
debug struct {
|
debug struct {
|
||||||
enabled bool
|
enabled bool
|
||||||
}
|
}
|
||||||
|
test bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *MouseCursorScene) Init(world *akara.World) {
|
func (s *MouseCursorScene) Init(world *akara.World) {
|
||||||
@ -77,32 +78,33 @@ func (s *MouseCursorScene) Update() {
|
|||||||
s.boot()
|
s.boot()
|
||||||
}
|
}
|
||||||
|
|
||||||
s.updateCursorPosition()
|
s.updateCursorTransform()
|
||||||
s.handleCursorFade()
|
s.handleCursorFade()
|
||||||
|
|
||||||
s.BaseScene.Update()
|
s.BaseScene.Update()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *MouseCursorScene) updateCursorPosition() {
|
func (s *MouseCursorScene) updateCursorTransform() {
|
||||||
position, found := s.GetPosition(s.cursor)
|
transform, found := s.GetTransform(s.cursor)
|
||||||
if !found {
|
if !found {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
cx, cy := s.CursorPosition()
|
cx, cy := s.CursorPosition()
|
||||||
|
tx, ty := transform.Translation.XY()
|
||||||
|
|
||||||
if int(position.X) != cx || int(position.Y) != cy {
|
if int(tx) != cx || int(ty) != cy {
|
||||||
s.lastTimeMoved = time.Now()
|
s.lastTimeMoved = time.Now()
|
||||||
|
|
||||||
switch s.debug.enabled {
|
switch s.debug.enabled {
|
||||||
case true:
|
case true:
|
||||||
s.Infof("position: (%d, %d)", int(position.X), int(position.Y))
|
s.Infof("transform: (%d, %d)", int(tx), int(ty))
|
||||||
default:
|
default:
|
||||||
s.Debugf("position: (%d, %d)", int(position.X), int(position.Y))
|
s.Debugf("transform: (%d, %d)", int(tx), int(ty))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
position.X, position.Y = float64(cx), float64(cy)
|
transform.Translation.X, transform.Translation.Y = float64(cx), float64(cy)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *MouseCursorScene) handleCursorFade() {
|
func (s *MouseCursorScene) handleCursorFade() {
|
||||||
|
@ -26,8 +26,8 @@ func (s *sceneObjectFactory) addBasicComponents(id akara.EID) {
|
|||||||
func (s *sceneObjectFactory) Sprite(x, y float64, imgPath, palPath string) akara.EID {
|
func (s *sceneObjectFactory) Sprite(x, y float64, imgPath, palPath string) akara.EID {
|
||||||
s.Debugf("creating sprite: %s, %s", filepath.Base(imgPath), palPath)
|
s.Debugf("creating sprite: %s, %s", filepath.Base(imgPath), palPath)
|
||||||
|
|
||||||
eid := s.baseSystems.SpriteFactory.Sprite(x, y, imgPath, palPath)
|
eid := s.sceneSystems.SpriteFactory.Sprite(x, y, imgPath, palPath)
|
||||||
s.GameObjects = append(s.GameObjects, eid)
|
s.SceneObjects = append(s.SceneObjects, eid)
|
||||||
|
|
||||||
s.addBasicComponents(eid)
|
s.addBasicComponents(eid)
|
||||||
|
|
||||||
@ -37,8 +37,8 @@ func (s *sceneObjectFactory) Sprite(x, y float64, imgPath, palPath string) akara
|
|||||||
func (s *sceneObjectFactory) SegmentedSprite(x, y float64, imgPath, palPath string, xseg, yseg, frame int) akara.EID {
|
func (s *sceneObjectFactory) SegmentedSprite(x, y float64, imgPath, palPath string, xseg, yseg, frame int) akara.EID {
|
||||||
s.Debugf("creating segmented sprite: %s, %s", filepath.Base(imgPath), palPath)
|
s.Debugf("creating segmented sprite: %s, %s", filepath.Base(imgPath), palPath)
|
||||||
|
|
||||||
eid := s.baseSystems.SpriteFactory.SegmentedSprite(x, y, imgPath, palPath, xseg, yseg, frame)
|
eid := s.sceneSystems.SpriteFactory.SegmentedSprite(x, y, imgPath, palPath, xseg, yseg, frame)
|
||||||
s.GameObjects = append(s.GameObjects, eid)
|
s.SceneObjects = append(s.SceneObjects, eid)
|
||||||
|
|
||||||
s.addBasicComponents(eid)
|
s.addBasicComponents(eid)
|
||||||
|
|
||||||
@ -60,7 +60,7 @@ func (s *sceneObjectFactory) Viewport(priority, width, height int) akara.EID {
|
|||||||
camera.Size.X = float64(width)
|
camera.Size.X = float64(width)
|
||||||
camera.Size.Y = float64(height)
|
camera.Size.Y = float64(height)
|
||||||
|
|
||||||
sfc := s.baseSystems.RenderSystem.renderer.NewSurface(width, height)
|
sfc := s.sceneSystems.RenderSystem.renderer.NewSurface(width, height)
|
||||||
|
|
||||||
sfc.Clear(color.Transparent)
|
sfc.Clear(color.Transparent)
|
||||||
|
|
||||||
@ -73,17 +73,17 @@ func (s *sceneObjectFactory) Viewport(priority, width, height int) akara.EID {
|
|||||||
return eid
|
return eid
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *sceneObjectFactory) Rectangle(x, y, width, height int, color color.Color) akara.EID {
|
func (s *sceneObjectFactory) Rectangle(x, y, width, height int, c color.Color) akara.EID {
|
||||||
s.Debug("creating rectangle")
|
s.Debug("creating rectangle")
|
||||||
|
|
||||||
eid := s.baseSystems.ShapeSystem.Rectangle(x, y, width, height, color)
|
eid := s.sceneSystems.ShapeSystem.Rectangle(x, y, width, height, c)
|
||||||
|
|
||||||
s.addBasicComponents(eid)
|
s.addBasicComponents(eid)
|
||||||
|
|
||||||
position := s.AddPosition(eid)
|
transform := s.AddTransform(eid)
|
||||||
position.X, position.Y = float64(x), float64(y)
|
transform.Translation.X, transform.Translation.Y = float64(x), float64(y)
|
||||||
|
|
||||||
s.GameObjects = append(s.GameObjects, eid)
|
s.SceneObjects = append(s.SceneObjects, eid)
|
||||||
|
|
||||||
return eid
|
return eid
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@ package d2systems
|
|||||||
const (
|
const (
|
||||||
scenePriorityMainMenu = iota
|
scenePriorityMainMenu = iota
|
||||||
scenePriorityLoading
|
scenePriorityLoading
|
||||||
scenePriorityMouseCursor
|
|
||||||
scenePriorityTerminal
|
scenePriorityTerminal
|
||||||
|
scenePriorityMouseCursor
|
||||||
scenePriorityEbitenSplash
|
scenePriorityEbitenSplash
|
||||||
)
|
)
|
||||||
|
@ -29,7 +29,7 @@ type ShapeSystem struct {
|
|||||||
akara.BaseSubscriberSystem
|
akara.BaseSubscriberSystem
|
||||||
*d2util.Logger
|
*d2util.Logger
|
||||||
RenderSystem *RenderSystem
|
RenderSystem *RenderSystem
|
||||||
d2components.PositionFactory
|
d2components.TransformFactory
|
||||||
d2components.ColorFactory
|
d2components.ColorFactory
|
||||||
d2components.RectangleFactory
|
d2components.RectangleFactory
|
||||||
d2components.TextureFactory
|
d2components.TextureFactory
|
||||||
@ -54,7 +54,7 @@ func (t *ShapeSystem) Init(world *akara.World) {
|
|||||||
|
|
||||||
func (t *ShapeSystem) setupFactories() {
|
func (t *ShapeSystem) setupFactories() {
|
||||||
t.InjectComponent(&d2components.Color{}, &t.ColorFactory.Color)
|
t.InjectComponent(&d2components.Color{}, &t.ColorFactory.Color)
|
||||||
t.InjectComponent(&d2components.Position{}, &t.PositionFactory.Position)
|
t.InjectComponent(&d2components.Transform{}, &t.TransformFactory.Transform)
|
||||||
t.InjectComponent(&d2components.Texture{}, &t.TextureFactory.Texture)
|
t.InjectComponent(&d2components.Texture{}, &t.TextureFactory.Texture)
|
||||||
t.InjectComponent(&d2components.Origin{}, &t.OriginFactory.Origin)
|
t.InjectComponent(&d2components.Origin{}, &t.OriginFactory.Origin)
|
||||||
t.InjectComponent(&d2components.Size{}, &t.SizeFactory.Size)
|
t.InjectComponent(&d2components.Size{}, &t.SizeFactory.Size)
|
||||||
@ -69,7 +69,7 @@ func (t *ShapeSystem) setupSubscriptions() {
|
|||||||
|
|
||||||
shapesToUpdate := t.NewComponentFilter().
|
shapesToUpdate := t.NewComponentFilter().
|
||||||
RequireOne(&d2components.Rectangle{}).
|
RequireOne(&d2components.Rectangle{}).
|
||||||
Require(&d2components.Position{}, &d2components.Size{}).
|
Require(&d2components.Transform{}, &d2components.Size{}).
|
||||||
Build()
|
Build()
|
||||||
|
|
||||||
t.shapesToRender = t.AddSubscription(shapesToRender)
|
t.shapesToRender = t.AddSubscription(shapesToRender)
|
||||||
@ -109,7 +109,7 @@ func (t *ShapeSystem) Rectangle(x, y, width, height int, color color.Color) akar
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (t *ShapeSystem) updateShape(eid akara.EID) {
|
func (t *ShapeSystem) updateShape(eid akara.EID) {
|
||||||
position, found := t.GetPosition(eid)
|
transform, found := t.GetTransform(eid)
|
||||||
if !found {
|
if !found {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -126,7 +126,7 @@ func (t *ShapeSystem) updateShape(eid akara.EID) {
|
|||||||
|
|
||||||
rectangle, rectangleFound := t.GetRectangle(eid)
|
rectangle, rectangleFound := t.GetRectangle(eid)
|
||||||
if rectangleFound {
|
if rectangleFound {
|
||||||
position.X, position.Y = rectangle.X, rectangle.Y
|
transform.Translation.X, transform.Translation.Y = rectangle.X, rectangle.Y
|
||||||
size.X, size.Y = rectangle.Width, rectangle.Height
|
size.X, size.Y = rectangle.Width, rectangle.Height
|
||||||
|
|
||||||
tw, th := texture.Texture.GetSize()
|
tw, th := texture.Texture.GetSize()
|
||||||
|
@ -40,7 +40,7 @@ type SpriteFactory struct {
|
|||||||
*d2util.Logger
|
*d2util.Logger
|
||||||
RenderSystem *RenderSystem
|
RenderSystem *RenderSystem
|
||||||
d2components.FilePathFactory
|
d2components.FilePathFactory
|
||||||
d2components.PositionFactory
|
d2components.TransformFactory
|
||||||
d2components.Dc6Factory
|
d2components.Dc6Factory
|
||||||
d2components.DccFactory
|
d2components.DccFactory
|
||||||
d2components.PaletteFactory
|
d2components.PaletteFactory
|
||||||
@ -67,7 +67,7 @@ func (t *SpriteFactory) Init(world *akara.World) {
|
|||||||
|
|
||||||
func (t *SpriteFactory) setupFactories() {
|
func (t *SpriteFactory) setupFactories() {
|
||||||
t.InjectComponent(&d2components.FilePath{}, &t.FilePath)
|
t.InjectComponent(&d2components.FilePath{}, &t.FilePath)
|
||||||
t.InjectComponent(&d2components.Position{}, &t.Position)
|
t.InjectComponent(&d2components.Transform{}, &t.Transform)
|
||||||
t.InjectComponent(&d2components.Dc6{}, &t.Dc6)
|
t.InjectComponent(&d2components.Dc6{}, &t.Dc6)
|
||||||
t.InjectComponent(&d2components.Dcc{}, &t.Dcc)
|
t.InjectComponent(&d2components.Dcc{}, &t.Dcc)
|
||||||
t.InjectComponent(&d2components.Palette{}, &t.Palette)
|
t.InjectComponent(&d2components.Palette{}, &t.Palette)
|
||||||
@ -112,8 +112,8 @@ func (t *SpriteFactory) Update() {
|
|||||||
func (t *SpriteFactory) Sprite(x, y float64, imgPath, palPath string) akara.EID {
|
func (t *SpriteFactory) Sprite(x, y float64, imgPath, palPath string) akara.EID {
|
||||||
spriteID := t.NewEntity()
|
spriteID := t.NewEntity()
|
||||||
|
|
||||||
position := t.AddPosition(spriteID)
|
transform := t.AddTransform(spriteID)
|
||||||
position.X, position.Y = x, y
|
transform.Translation.X, transform.Translation.Y = x, y
|
||||||
|
|
||||||
imgID, palID := t.NewEntity(), t.NewEntity()
|
imgID, palID := t.NewEntity(), t.NewEntity()
|
||||||
t.AddFilePath(imgID).Path = imgPath
|
t.AddFilePath(imgID).Path = imgPath
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package d2systems
|
package d2systems
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2components"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2util"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2util"
|
||||||
@ -16,18 +17,6 @@ const (
|
|||||||
logPrefixTimeScaleSystem = "Time Scale"
|
logPrefixTimeScaleSystem = "Time Scale"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewTimeScaleSystem creates a timescale system
|
|
||||||
func NewTimeScaleSystem() *TimeScaleSystem {
|
|
||||||
m := &TimeScaleSystem{
|
|
||||||
BaseSystem: &akara.BaseSystem{},
|
|
||||||
Logger: d2util.NewLogger(),
|
|
||||||
}
|
|
||||||
|
|
||||||
m.SetPrefix(logPrefixTimeScaleSystem)
|
|
||||||
|
|
||||||
return m
|
|
||||||
}
|
|
||||||
|
|
||||||
// static check that TimeScaleSystem implements the System interface
|
// static check that TimeScaleSystem implements the System interface
|
||||||
var _ akara.System = &TimeScaleSystem{}
|
var _ akara.System = &TimeScaleSystem{}
|
||||||
|
|
||||||
@ -35,29 +24,50 @@ var _ akara.System = &TimeScaleSystem{}
|
|||||||
// apply a scalar the world's TimeDelta between frames. It's useful for slowing down or speeding
|
// apply a scalar the world's TimeDelta between frames. It's useful for slowing down or speeding
|
||||||
// up the game time without affecting the render rate.
|
// up the game time without affecting the render rate.
|
||||||
type TimeScaleSystem struct {
|
type TimeScaleSystem struct {
|
||||||
*akara.BaseSystem
|
akara.BaseSystem
|
||||||
*d2util.Logger
|
*d2util.Logger
|
||||||
scale float64
|
scale float64
|
||||||
lastScale float64
|
d2components.DirtyFactory
|
||||||
|
d2components.CommandRegistrationFactory
|
||||||
}
|
}
|
||||||
|
|
||||||
// Init will initialize the TimeScale system
|
// Init will initialize the TimeScale system
|
||||||
func (t *TimeScaleSystem) Init(world *akara.World) {
|
func (t *TimeScaleSystem) Init(world *akara.World) {
|
||||||
t.World = world
|
t.World = world
|
||||||
|
|
||||||
|
t.Logger = d2util.NewLogger()
|
||||||
|
t.SetPrefix(logPrefixTimeScaleSystem)
|
||||||
|
|
||||||
t.Info("initializing ...")
|
t.Info("initializing ...")
|
||||||
|
|
||||||
|
t.InjectComponent(&d2components.CommandRegistration{}, &t.CommandRegistration)
|
||||||
|
t.InjectComponent(&d2components.Dirty{}, &t.Dirty)
|
||||||
|
|
||||||
|
t.registerCommands()
|
||||||
|
|
||||||
t.scale = defaultScale
|
t.scale = defaultScale
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update scales the worlds time delta for this frame
|
// Update scales the worlds time delta for this frame
|
||||||
func (t *TimeScaleSystem) Update() {
|
func (t *TimeScaleSystem) Update() {
|
||||||
if !t.Active() || t.scale == t.lastScale {
|
if !t.Active() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
t.Infof("setting time scale to %.1f", t.scale)
|
t.World.TimeDelta = time.Duration(float64(t.World.TimeDelta) * t.scale)
|
||||||
t.lastScale = t.scale
|
}
|
||||||
|
|
||||||
t.World.TimeDelta *= time.Duration(t.scale)
|
func (t *TimeScaleSystem) registerCommands() {
|
||||||
|
e := t.NewEntity()
|
||||||
|
|
||||||
|
reg := t.AddCommandRegistration(e)
|
||||||
|
|
||||||
|
t.AddDirty(e)
|
||||||
|
|
||||||
|
reg.Name = "timescale"
|
||||||
|
reg.Description = "set the time scale of the game (default is 1.0)"
|
||||||
|
reg.Callback = func(scale float64) {
|
||||||
|
t.Infof("setting time scale to %.1f", scale)
|
||||||
|
t.scale = scale
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
2
go.mod
2
go.mod
@ -8,7 +8,7 @@ require (
|
|||||||
github.com/alecthomas/units v0.0.0-20201120081800-1786d5ef83d4 // indirect
|
github.com/alecthomas/units v0.0.0-20201120081800-1786d5ef83d4 // indirect
|
||||||
github.com/go-restruct/restruct v1.2.0-alpha
|
github.com/go-restruct/restruct v1.2.0-alpha
|
||||||
github.com/google/uuid v1.1.2
|
github.com/google/uuid v1.1.2
|
||||||
github.com/gravestench/akara v0.0.0-20201203202918-85b8a01d1130
|
github.com/gravestench/akara v0.0.0-20201206061149-9be03b4110f2
|
||||||
github.com/gravestench/pho v0.0.0-20201029002250-f9afbd637e4d
|
github.com/gravestench/pho v0.0.0-20201029002250-f9afbd637e4d
|
||||||
github.com/hajimehoshi/ebiten/v2 v2.0.1
|
github.com/hajimehoshi/ebiten/v2 v2.0.1
|
||||||
github.com/pkg/profile v1.5.0
|
github.com/pkg/profile v1.5.0
|
||||||
|
2
go.sum
2
go.sum
@ -21,6 +21,8 @@ github.com/gravestench/akara v0.0.0-20201203202116-00c2a0dbae5d h1:8xg2B0KGOHLwp
|
|||||||
github.com/gravestench/akara v0.0.0-20201203202116-00c2a0dbae5d/go.mod h1:fTeda1SogMg5Lkd4lXMEd/Pk/a5/gQuLGaAI2rn1PBQ=
|
github.com/gravestench/akara v0.0.0-20201203202116-00c2a0dbae5d/go.mod h1:fTeda1SogMg5Lkd4lXMEd/Pk/a5/gQuLGaAI2rn1PBQ=
|
||||||
github.com/gravestench/akara v0.0.0-20201203202918-85b8a01d1130 h1:09fkM2hfORgZJ5hhtHzOMszOgx3Xs14+z7kpto8w7Ys=
|
github.com/gravestench/akara v0.0.0-20201203202918-85b8a01d1130 h1:09fkM2hfORgZJ5hhtHzOMszOgx3Xs14+z7kpto8w7Ys=
|
||||||
github.com/gravestench/akara v0.0.0-20201203202918-85b8a01d1130/go.mod h1:fTeda1SogMg5Lkd4lXMEd/Pk/a5/gQuLGaAI2rn1PBQ=
|
github.com/gravestench/akara v0.0.0-20201203202918-85b8a01d1130/go.mod h1:fTeda1SogMg5Lkd4lXMEd/Pk/a5/gQuLGaAI2rn1PBQ=
|
||||||
|
github.com/gravestench/akara v0.0.0-20201206061149-9be03b4110f2 h1:mOIIK6AgIyaEslKsu+tsguzFWaMLGjlMuUKqOlABhGk=
|
||||||
|
github.com/gravestench/akara v0.0.0-20201206061149-9be03b4110f2/go.mod h1:fTeda1SogMg5Lkd4lXMEd/Pk/a5/gQuLGaAI2rn1PBQ=
|
||||||
github.com/gravestench/pho v0.0.0-20201029002250-f9afbd637e4d h1:CP+/y9SAdv9LifYvicxYdQNmzugykEahAiUhYolMROM=
|
github.com/gravestench/pho v0.0.0-20201029002250-f9afbd637e4d h1:CP+/y9SAdv9LifYvicxYdQNmzugykEahAiUhYolMROM=
|
||||||
github.com/gravestench/pho v0.0.0-20201029002250-f9afbd637e4d/go.mod h1:yi5GHMLLWtHhs9tz3q1csUlgGKz5MhZoJcxV8NFBtkk=
|
github.com/gravestench/pho v0.0.0-20201029002250-f9afbd637e4d/go.mod h1:yi5GHMLLWtHhs9tz3q1csUlgGKz5MhZoJcxV8NFBtkk=
|
||||||
github.com/hajimehoshi/bitmapfont/v2 v2.1.0/go.mod h1:2BnYrkTQGThpr/CY6LorYtt/zEPNzvE/ND69CRTaHMs=
|
github.com/hajimehoshi/bitmapfont/v2 v2.1.0/go.mod h1:2BnYrkTQGThpr/CY6LorYtt/zEPNzvE/ND69CRTaHMs=
|
||||||
|
42
main.go
42
main.go
@ -1,45 +1,7 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import "github.com/OpenDiablo2/OpenDiablo2/d2app"
|
||||||
"log"
|
|
||||||
|
|
||||||
"github.com/gravestench/akara"
|
|
||||||
"gopkg.in/alecthomas/kingpin.v2"
|
|
||||||
|
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2app"
|
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2systems"
|
|
||||||
)
|
|
||||||
|
|
||||||
// GitBranch is set by the CI build process to the name of the branch
|
|
||||||
//nolint:gochecknoglobals // This is filled in by the build system
|
|
||||||
var GitBranch string
|
|
||||||
|
|
||||||
// GitCommit is set by the CI build process to the commit hash
|
|
||||||
//nolint:gochecknoglobals // This is filled in by the build system
|
|
||||||
var GitCommit string
|
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
ecs := kingpin.Flag("ecs", "start the ecs implementation").Bool()
|
d2app.Run()
|
||||||
kingpin.Parse()
|
|
||||||
|
|
||||||
if *ecs {
|
|
||||||
cfg := akara.NewWorldConfig()
|
|
||||||
|
|
||||||
cfg.
|
|
||||||
With(&d2systems.AppBootstrapSystem{}).
|
|
||||||
With(&d2systems.GameClientBootstrapSystem{})
|
|
||||||
|
|
||||||
akara.NewWorld(cfg)
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
log.SetFlags(log.Lshortfile)
|
|
||||||
log.Println("OpenDiablo2 - Open source Diablo 2 engine")
|
|
||||||
|
|
||||||
instance := d2app.Create(GitBranch, GitCommit)
|
|
||||||
|
|
||||||
if err := instance.Run(); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user