improved parallax implementation

This commit is contained in:
Josh Deprez 2021-09-01 10:27:13 +10:00
parent 3b15a57cf5
commit 840847b25b
6 changed files with 71 additions and 39 deletions

View file

@ -11,7 +11,6 @@ import (
var _ interface {
Identifier
Drawer
ParallaxScaler
Scanner
Transformer
} = &Billboard{}
@ -24,7 +23,6 @@ func init() {
type Billboard struct {
ID
Hidden
Parallax
Pos image.Point
Src ImageRef
ZOrder

View file

@ -12,22 +12,21 @@ import (
var (
// TypeOf(pointer to interface).Elem() is "idiomatic" -
// see https://pkg.go.dev/reflect#example-TypeOf
AnimerType = reflect.TypeOf((*Animer)(nil)).Elem()
BounderType = reflect.TypeOf((*Bounder)(nil)).Elem()
ColliderType = reflect.TypeOf((*Collider)(nil)).Elem()
DisablerType = reflect.TypeOf((*Disabler)(nil)).Elem()
DrawerType = reflect.TypeOf((*Drawer)(nil)).Elem()
DrawUpdaterType = reflect.TypeOf((*DrawUpdater)(nil)).Elem()
HiderType = reflect.TypeOf((*Hider)(nil)).Elem()
IdentifierType = reflect.TypeOf((*Identifier)(nil)).Elem()
LoaderType = reflect.TypeOf((*Loader)(nil)).Elem()
ParallaxScalerType = reflect.TypeOf((*ParallaxScaler)(nil)).Elem()
PrepperType = reflect.TypeOf((*Prepper)(nil)).Elem()
ScannerType = reflect.TypeOf((*Scanner)(nil)).Elem()
ScenerType = reflect.TypeOf((*Scener)(nil)).Elem()
SaverType = reflect.TypeOf((*Saver)(nil)).Elem()
TransformerType = reflect.TypeOf((*Transformer)(nil)).Elem()
UpdaterType = reflect.TypeOf((*Updater)(nil)).Elem()
AnimerType = reflect.TypeOf((*Animer)(nil)).Elem()
BounderType = reflect.TypeOf((*Bounder)(nil)).Elem()
ColliderType = reflect.TypeOf((*Collider)(nil)).Elem()
DisablerType = reflect.TypeOf((*Disabler)(nil)).Elem()
DrawerType = reflect.TypeOf((*Drawer)(nil)).Elem()
DrawUpdaterType = reflect.TypeOf((*DrawUpdater)(nil)).Elem()
HiderType = reflect.TypeOf((*Hider)(nil)).Elem()
IdentifierType = reflect.TypeOf((*Identifier)(nil)).Elem()
LoaderType = reflect.TypeOf((*Loader)(nil)).Elem()
PrepperType = reflect.TypeOf((*Prepper)(nil)).Elem()
ScannerType = reflect.TypeOf((*Scanner)(nil)).Elem()
ScenerType = reflect.TypeOf((*Scener)(nil)).Elem()
SaverType = reflect.TypeOf((*Saver)(nil)).Elem()
TransformerType = reflect.TypeOf((*Transformer)(nil)).Elem()
UpdaterType = reflect.TypeOf((*Updater)(nil)).Elem()
// Behaviours lists all the behaviours that can be queried with Game.Query.
Behaviours = []reflect.Type{
@ -40,7 +39,6 @@ var (
HiderType,
IdentifierType,
LoaderType,
ParallaxScalerType,
PrepperType,
ScannerType,
ScenerType,
@ -109,12 +107,6 @@ type Loader interface {
Load(fs.FS) error
}
// ParallaxScaler components have a scaling factor. This is used for
// parallax layers in a scene, and can be thought of as 1/distance.
type ParallaxScaler interface {
ParallaxFactor() float64
}
// Prepper components can be prepared. It is called after the component
// database has been populated but before the game is run. The component can
// store the reference to game, if needed, and also query the component database.

View file

@ -38,12 +38,6 @@ func (h *Hidden) Hide() { *h = true }
// Show sets h to false.
func (h *Hidden) Show() { *h = false }
// Parallax implements ParallaxScaler directly (as a float64 value).
type Parallax float64
// ParallaxFactor returns s as a float64.
func (s Parallax) ParallaxFactor() float64 { return float64(s) }
// ZOrder implements DrawOrder (in Drawer) directly (as a float64 value).
type ZOrder float64

45
engine/parallax.go Normal file
View file

@ -0,0 +1,45 @@
package engine
import (
"encoding/gob"
"fmt"
"github.com/hajimehoshi/ebiten/v2"
)
var _ interface {
Prepper
Scanner
Transformer
} = &Parallax{}
func init() {
gob.Register(&Parallax{})
}
// Parallax is a container that changes its transform based on the position of a
// camera, intended to produce a "parallax" like effect.
type Parallax struct {
CameraID string
Factor float64 // how much to change in response to the camera
Child interface{}
camera *Camera
}
func (p *Parallax) Prepare(game *Game) error {
c, ok := game.Component(p.CameraID).(*Camera)
if !ok {
return fmt.Errorf("component %q type != *Camera", p.CameraID)
}
p.camera = c
return nil
}
func (p *Parallax) Scan() []interface{} { return []interface{}{p.Child} }
func (p *Parallax) Transform() (opts ebiten.DrawImageOptions) {
x, y := float2(p.camera.Centre)
opts.GeoM.Translate(x*p.Factor, y*p.Factor)
return opts
}

Binary file not shown.

19
main.go
View file

@ -16,7 +16,7 @@ import (
func main() {
// Change to true to enable cpu profile
if true && runtime.GOOS != "js" {
if false && runtime.GOOS != "js" {
f, err := os.Create("cpuprofile.pprof")
if err != nil {
log.Fatal("could not create CPU profile: ", err)
@ -33,7 +33,7 @@ func main() {
ebiten.SetWindowTitle("TODO")
// Change to true to rewrite level1.gobz
if false && runtime.GOOS != "js" {
if true && runtime.GOOS != "js" {
writeLevel1()
}
@ -116,12 +116,15 @@ func writeLevel1() {
Color: color.Gray{100},
ZOrder: 0,
},
&engine.Billboard{
ID: "bg_image",
Parallax: 0.5,
ZOrder: 1,
Pos: image.Pt(-160, -120),
Src: engine.ImageRef{Path: "assets/space.png"},
&engine.Parallax{
CameraID: "game_camera",
Child: &engine.Billboard{
ID: "bg_image",
ZOrder: 1,
Pos: image.Pt(-160, -120),
Src: engine.ImageRef{Path: "assets/space.png"},
},
Factor: 0.5,
},
&engine.Tilemap{
ID: "terrain",