MoveZ, etc

This commit is contained in:
Josh Deprez 2021-09-02 16:55:12 +10:00
parent 09167208ea
commit db7590f767
6 changed files with 67 additions and 24 deletions

View file

@ -2,14 +2,10 @@ package engine
import (
"encoding/gob"
"image"
)
// Ensure Actor satisfies interfaces.
var _ interface {
Bounder
Prepper
} = &Actor{}
var _ Prepper = &Actor{}
func init() {
gob.Register(&Actor{})
@ -21,17 +17,14 @@ func init() {
// Actor handles basic movement.
type Actor struct {
CollisionDomain string // id of component to look for colliders inside of
Pos image.Point
Size image.Point
Pos, Size Point3
xRem, yRem, zRem float64
xRem, yRem float64
game *Game
}
func (a *Actor) BoundingRect() image.Rectangle { return image.Rectangle{a.Pos, a.Pos.Add(a.Size)} }
func (a *Actor) CollidesAt(p image.Point) bool {
bounds := image.Rectangle{Min: p, Max: p.Add(a.Size)}
func (a *Actor) CollidesAt(p Point3) bool {
bounds := Box{Min: p, Max: p.Add(a.Size)}.XY() // TODO: 3D collision
for c := range a.game.Query(a.CollisionDomain, ColliderType) {
if c.(Collider).CollidesWith(bounds) {
return true
@ -49,7 +42,7 @@ func (a *Actor) MoveX(dx float64, onCollide func()) {
a.xRem -= float64(move)
sign := sign(move)
for move != 0 {
if a.CollidesAt(a.Pos.Add(image.Pt(sign, 0))) {
if a.CollidesAt(a.Pos.Add(Pt3(sign, 0, 0))) {
if onCollide != nil {
onCollide()
}
@ -69,7 +62,7 @@ func (a *Actor) MoveY(dy float64, onCollide func()) {
a.yRem -= float64(move)
sign := sign(move)
for move != 0 {
if a.CollidesAt(a.Pos.Add(image.Pt(0, sign))) {
if a.CollidesAt(a.Pos.Add(Pt3(0, sign, 0))) {
if onCollide != nil {
onCollide()
}
@ -80,6 +73,26 @@ func (a *Actor) MoveY(dy float64, onCollide func()) {
}
}
func (a *Actor) MoveZ(dz float64, onCollide func()) {
a.yRem += dz
move := int(a.zRem + 0.5)
if move == 0 {
return
}
a.zRem -= float64(move)
sign := sign(move)
for move != 0 {
if a.CollidesAt(a.Pos.Add(Pt3(0, 0, 0))) {
if onCollide != nil {
onCollide()
}
return
}
a.Pos.Z += sign
move -= sign
}
}
func (a *Actor) Prepare(g *Game) error {
a.game = g
return nil

View file

@ -150,6 +150,34 @@ func (b Box) Size() Point3 {
return b.Max.Sub(b.Min)
}
// Back returns an image.Rectangle representing the back of the box, using
// the given projection π.
func (b Box) Back(π image.Point) image.Rectangle {
b.Max.Z = b.Min.Z
return image.Rectangle{
Min: b.Min.IsoProject(π),
Max: b.Max.IsoProject(π),
}
}
// Front returns an image.Rectangle representing the front of the box, using
// the given projection π.
func (b Box) Front(π image.Point) image.Rectangle {
b.Min.Z = b.Max.Z
return image.Rectangle{
Min: b.Min.IsoProject(π),
Max: b.Max.IsoProject(π),
}
}
// XY returns the image.Rectangle representing the box if we forgot about Z.
func (b Box) XY() image.Rectangle {
return image.Rectangle{
Min: b.Min.XY(),
Max: b.Max.XY(),
}
}
// IsoVoxmap implements a voxel map, painted using flat images in 2D.
type IsoVoxmap struct {
ID

View file

@ -25,7 +25,6 @@ type Sprite struct {
FrameOffset image.Point
Hidden
Sheet Sheet
ZOrder
anim *Anim
}
@ -35,6 +34,11 @@ func (s *Sprite) Draw(screen *ebiten.Image, opts *ebiten.DrawImageOptions) {
screen.DrawImage(s.Sheet.SubImage(s.anim.Cell()), opts)
}
// DrawOrder returns the Z position from Actor.Pos, and 0 bias.
func (s *Sprite) DrawOrder() (int, int) {
return s.Actor.Pos.Z, 0
}
// Scan returns the Actor and the Sheet.
func (s *Sprite) Scan() []interface{} {
return []interface{}{
@ -54,7 +58,7 @@ func (s *Sprite) SetAnim(a *Anim) {
// Transform returns a translation by the FrameOffset.
func (s *Sprite) Transform() (opts ebiten.DrawImageOptions) {
opts.GeoM.Translate(cfloat(s.Actor.Pos.Add(s.FrameOffset)))
opts.GeoM.Translate(cfloat(s.Actor.Pos.XY().Add(s.FrameOffset)))
return opts
}

Binary file not shown.

View file

@ -4,7 +4,6 @@ import (
"encoding/gob"
"errors"
"fmt"
"image"
"math"
"drjosh.dev/gurgle/engine"
@ -71,7 +70,7 @@ func (aw *Awakeman) Update() error {
if ebiten.IsKeyPressed(ebiten.KeyShift) {
z = 2.0
}
aw.camera.PointAt(aw.Sprite.Actor.Pos.Add(aw.Sprite.Actor.Size.Div(2)), z)
aw.camera.PointAt(aw.Sprite.Actor.Pos.XY().Add(aw.Sprite.Actor.Size.XY().Div(2)), z)
return nil
}
@ -116,7 +115,7 @@ func (aw *Awakeman) realUpdate() error {
ux, uy := aw.vx, aw.vy
// Has traction?
if aw.Sprite.Actor.CollidesAt(aw.Sprite.Actor.Pos.Add(image.Pt(0, 1))) {
if aw.Sprite.Actor.CollidesAt(aw.Sprite.Actor.Pos.Add(engine.Pt3(0, 1, 0))) {
// Not falling.
// Instantly decelerate (AW absorbs all kinetic E in legs, or something)
if aw.jumpBuffer > 0 {

View file

@ -187,8 +187,8 @@ func writeLevel1() {
Sprite: engine.Sprite{
Actor: engine.Actor{
CollisionDomain: "level_1",
Pos: image.Pt(100, 100),
Size: image.Pt(8, 16),
Pos: engine.Pt3(100, 100, 9),
Size: engine.Pt3(8, 16, 8),
},
FrameOffset: image.Pt(-1, 0),
Sheet: engine.Sheet{
@ -228,7 +228,6 @@ func writeLevel1() {
CellSize: image.Pt(10, 16),
Src: engine.ImageRef{Path: "assets/aw.png"},
},
ZOrder: 9,
},
},
},