improved parallax implementation
This commit is contained in:
parent
3b15a57cf5
commit
840847b25b
6 changed files with 71 additions and 39 deletions
|
@ -11,7 +11,6 @@ import (
|
||||||
var _ interface {
|
var _ interface {
|
||||||
Identifier
|
Identifier
|
||||||
Drawer
|
Drawer
|
||||||
ParallaxScaler
|
|
||||||
Scanner
|
Scanner
|
||||||
Transformer
|
Transformer
|
||||||
} = &Billboard{}
|
} = &Billboard{}
|
||||||
|
@ -24,7 +23,6 @@ func init() {
|
||||||
type Billboard struct {
|
type Billboard struct {
|
||||||
ID
|
ID
|
||||||
Hidden
|
Hidden
|
||||||
Parallax
|
|
||||||
Pos image.Point
|
Pos image.Point
|
||||||
Src ImageRef
|
Src ImageRef
|
||||||
ZOrder
|
ZOrder
|
||||||
|
|
|
@ -12,22 +12,21 @@ import (
|
||||||
var (
|
var (
|
||||||
// TypeOf(pointer to interface).Elem() is "idiomatic" -
|
// TypeOf(pointer to interface).Elem() is "idiomatic" -
|
||||||
// see https://pkg.go.dev/reflect#example-TypeOf
|
// see https://pkg.go.dev/reflect#example-TypeOf
|
||||||
AnimerType = reflect.TypeOf((*Animer)(nil)).Elem()
|
AnimerType = reflect.TypeOf((*Animer)(nil)).Elem()
|
||||||
BounderType = reflect.TypeOf((*Bounder)(nil)).Elem()
|
BounderType = reflect.TypeOf((*Bounder)(nil)).Elem()
|
||||||
ColliderType = reflect.TypeOf((*Collider)(nil)).Elem()
|
ColliderType = reflect.TypeOf((*Collider)(nil)).Elem()
|
||||||
DisablerType = reflect.TypeOf((*Disabler)(nil)).Elem()
|
DisablerType = reflect.TypeOf((*Disabler)(nil)).Elem()
|
||||||
DrawerType = reflect.TypeOf((*Drawer)(nil)).Elem()
|
DrawerType = reflect.TypeOf((*Drawer)(nil)).Elem()
|
||||||
DrawUpdaterType = reflect.TypeOf((*DrawUpdater)(nil)).Elem()
|
DrawUpdaterType = reflect.TypeOf((*DrawUpdater)(nil)).Elem()
|
||||||
HiderType = reflect.TypeOf((*Hider)(nil)).Elem()
|
HiderType = reflect.TypeOf((*Hider)(nil)).Elem()
|
||||||
IdentifierType = reflect.TypeOf((*Identifier)(nil)).Elem()
|
IdentifierType = reflect.TypeOf((*Identifier)(nil)).Elem()
|
||||||
LoaderType = reflect.TypeOf((*Loader)(nil)).Elem()
|
LoaderType = reflect.TypeOf((*Loader)(nil)).Elem()
|
||||||
ParallaxScalerType = reflect.TypeOf((*ParallaxScaler)(nil)).Elem()
|
PrepperType = reflect.TypeOf((*Prepper)(nil)).Elem()
|
||||||
PrepperType = reflect.TypeOf((*Prepper)(nil)).Elem()
|
ScannerType = reflect.TypeOf((*Scanner)(nil)).Elem()
|
||||||
ScannerType = reflect.TypeOf((*Scanner)(nil)).Elem()
|
ScenerType = reflect.TypeOf((*Scener)(nil)).Elem()
|
||||||
ScenerType = reflect.TypeOf((*Scener)(nil)).Elem()
|
SaverType = reflect.TypeOf((*Saver)(nil)).Elem()
|
||||||
SaverType = reflect.TypeOf((*Saver)(nil)).Elem()
|
TransformerType = reflect.TypeOf((*Transformer)(nil)).Elem()
|
||||||
TransformerType = reflect.TypeOf((*Transformer)(nil)).Elem()
|
UpdaterType = reflect.TypeOf((*Updater)(nil)).Elem()
|
||||||
UpdaterType = reflect.TypeOf((*Updater)(nil)).Elem()
|
|
||||||
|
|
||||||
// Behaviours lists all the behaviours that can be queried with Game.Query.
|
// Behaviours lists all the behaviours that can be queried with Game.Query.
|
||||||
Behaviours = []reflect.Type{
|
Behaviours = []reflect.Type{
|
||||||
|
@ -40,7 +39,6 @@ var (
|
||||||
HiderType,
|
HiderType,
|
||||||
IdentifierType,
|
IdentifierType,
|
||||||
LoaderType,
|
LoaderType,
|
||||||
ParallaxScalerType,
|
|
||||||
PrepperType,
|
PrepperType,
|
||||||
ScannerType,
|
ScannerType,
|
||||||
ScenerType,
|
ScenerType,
|
||||||
|
@ -109,12 +107,6 @@ type Loader interface {
|
||||||
Load(fs.FS) error
|
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
|
// Prepper components can be prepared. It is called after the component
|
||||||
// database has been populated but before the game is run. The component can
|
// 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.
|
// store the reference to game, if needed, and also query the component database.
|
||||||
|
|
|
@ -38,12 +38,6 @@ func (h *Hidden) Hide() { *h = true }
|
||||||
// Show sets h to false.
|
// Show sets h to false.
|
||||||
func (h *Hidden) Show() { *h = 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).
|
// ZOrder implements DrawOrder (in Drawer) directly (as a float64 value).
|
||||||
type ZOrder float64
|
type ZOrder float64
|
||||||
|
|
||||||
|
|
45
engine/parallax.go
Normal file
45
engine/parallax.go
Normal 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
19
main.go
|
@ -16,7 +16,7 @@ import (
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
// Change to true to enable cpu profile
|
// Change to true to enable cpu profile
|
||||||
if true && runtime.GOOS != "js" {
|
if false && runtime.GOOS != "js" {
|
||||||
f, err := os.Create("cpuprofile.pprof")
|
f, err := os.Create("cpuprofile.pprof")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal("could not create CPU profile: ", err)
|
log.Fatal("could not create CPU profile: ", err)
|
||||||
|
@ -33,7 +33,7 @@ func main() {
|
||||||
ebiten.SetWindowTitle("TODO")
|
ebiten.SetWindowTitle("TODO")
|
||||||
|
|
||||||
// Change to true to rewrite level1.gobz
|
// Change to true to rewrite level1.gobz
|
||||||
if false && runtime.GOOS != "js" {
|
if true && runtime.GOOS != "js" {
|
||||||
writeLevel1()
|
writeLevel1()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -116,12 +116,15 @@ func writeLevel1() {
|
||||||
Color: color.Gray{100},
|
Color: color.Gray{100},
|
||||||
ZOrder: 0,
|
ZOrder: 0,
|
||||||
},
|
},
|
||||||
&engine.Billboard{
|
&engine.Parallax{
|
||||||
ID: "bg_image",
|
CameraID: "game_camera",
|
||||||
Parallax: 0.5,
|
Child: &engine.Billboard{
|
||||||
ZOrder: 1,
|
ID: "bg_image",
|
||||||
Pos: image.Pt(-160, -120),
|
ZOrder: 1,
|
||||||
Src: engine.ImageRef{Path: "assets/space.png"},
|
Pos: image.Pt(-160, -120),
|
||||||
|
Src: engine.ImageRef{Path: "assets/space.png"},
|
||||||
|
},
|
||||||
|
Factor: 0.5,
|
||||||
},
|
},
|
||||||
&engine.Tilemap{
|
&engine.Tilemap{
|
||||||
ID: "terrain",
|
ID: "terrain",
|
||||||
|
|
Loading…
Reference in a new issue