Scenerise Camera and i am g.Root
This commit is contained in:
parent
45e2b300e8
commit
af89c01dbd
4 changed files with 31 additions and 19 deletions
|
@ -25,7 +25,7 @@ func init() {
|
|||
// Camera ignores Scene.Draw and calls Scene's children's Draw.
|
||||
type Camera struct {
|
||||
ID
|
||||
Scene *Scene
|
||||
Scene Scener
|
||||
|
||||
// Camera controls
|
||||
Centre image.Point // world coordinates
|
||||
|
@ -37,14 +37,14 @@ type Camera struct {
|
|||
|
||||
// Draw applies transformations to opts, then calls c.Scene.Draw with it.
|
||||
func (c *Camera) Draw(screen *ebiten.Image, opts ebiten.DrawImageOptions) {
|
||||
if c.Scene.Hidden {
|
||||
if c.Scene.Scene().Hidden {
|
||||
return
|
||||
}
|
||||
|
||||
// The lower bound on zoom is the larger of
|
||||
// { (ScreenWidth / BoundsWidth), (ScreenHeight / BoundsHeight) }
|
||||
zoom := c.Zoom
|
||||
sz := c.Scene.Bounds.Size()
|
||||
sz := c.Scene.Scene().Bounds.Size()
|
||||
if z := float64(c.game.ScreenWidth) / float64(sz.X); zoom < z {
|
||||
zoom = z
|
||||
}
|
||||
|
@ -57,17 +57,17 @@ func (c *Camera) Draw(screen *ebiten.Image, opts ebiten.DrawImageOptions) {
|
|||
// Camera frame currently Rectangle{ centre ± (screen/(2*zoom)) }.
|
||||
sw2, sh2 := float64(c.game.ScreenWidth/2), float64(c.game.ScreenHeight/2)
|
||||
swz, shz := int(sw2/zoom), int(sh2/zoom)
|
||||
if centre.X-swz < c.Scene.Bounds.Min.X {
|
||||
centre.X = c.Scene.Bounds.Min.X + swz
|
||||
if centre.X-swz < c.Scene.Scene().Bounds.Min.X {
|
||||
centre.X = c.Scene.Scene().Bounds.Min.X + swz
|
||||
}
|
||||
if centre.Y-shz < c.Scene.Bounds.Min.Y {
|
||||
centre.Y = c.Scene.Bounds.Min.Y + shz
|
||||
if centre.Y-shz < c.Scene.Scene().Bounds.Min.Y {
|
||||
centre.Y = c.Scene.Scene().Bounds.Min.Y + shz
|
||||
}
|
||||
if centre.X+swz > c.Scene.Bounds.Max.X {
|
||||
centre.X = c.Scene.Bounds.Max.X - swz
|
||||
if centre.X+swz > c.Scene.Scene().Bounds.Max.X {
|
||||
centre.X = c.Scene.Scene().Bounds.Max.X - swz
|
||||
}
|
||||
if centre.Y+shz > c.Scene.Bounds.Max.Y {
|
||||
centre.Y = c.Scene.Bounds.Max.Y - shz
|
||||
if centre.Y+shz > c.Scene.Scene().Bounds.Max.Y {
|
||||
centre.Y = c.Scene.Scene().Bounds.Max.Y - shz
|
||||
}
|
||||
|
||||
// Apply other options
|
||||
|
@ -101,7 +101,7 @@ func (c *Camera) Draw(screen *ebiten.Image, opts ebiten.DrawImageOptions) {
|
|||
}
|
||||
|
||||
// Update passes the call to c.Scene.
|
||||
func (c *Camera) Update() error { return c.Scene.Update() }
|
||||
func (c *Camera) Update() error { return c.Scene.Scene().Update() }
|
||||
|
||||
// Scan returns the only child (c.Scene).
|
||||
func (c *Camera) Scan() []interface{} { return []interface{}{c.Scene} }
|
||||
|
|
|
@ -11,17 +11,19 @@ func init() {
|
|||
}
|
||||
|
||||
// Game implements the ebiten methods using a collection of components.
|
||||
// One component must be the designated root component - usually a
|
||||
// scene of some kind.
|
||||
type Game struct {
|
||||
ScreenWidth int
|
||||
ScreenHeight int
|
||||
Scener
|
||||
Root DrawUpdater // typically a *Scene or SceneRef though
|
||||
|
||||
componentsByID map[string]interface{}
|
||||
}
|
||||
|
||||
// Draw draws the entire thing, with default draw options.
|
||||
func (g *Game) Draw(screen *ebiten.Image) {
|
||||
g.Scene().Draw(screen, ebiten.DrawImageOptions{})
|
||||
g.Root.Draw(screen, ebiten.DrawImageOptions{})
|
||||
}
|
||||
|
||||
// Layout returns the configured screen width/height.
|
||||
|
@ -29,6 +31,9 @@ func (g *Game) Layout(outsideWidth, outsideHeight int) (w, h int) {
|
|||
return g.ScreenWidth, g.ScreenHeight
|
||||
}
|
||||
|
||||
// Update updates the scene.
|
||||
func (g *Game) Update() error { return g.Root.Update() }
|
||||
|
||||
// RegisterComponent tells the game there is a new component. Currently this is
|
||||
// only necessary for components with IDs.
|
||||
func (g *Game) RegisterComponent(c interface{}) {
|
||||
|
@ -61,7 +66,7 @@ func (g *Game) UnregisterComponent(c interface{}) {
|
|||
func (g *Game) Component(id string) interface{} { return g.componentsByID[id] }
|
||||
|
||||
// Scan implements Scanner.
|
||||
func (g *Game) Scan() []interface{} { return []interface{}{g.Scener} }
|
||||
func (g *Game) Scan() []interface{} { return []interface{}{g.Root} }
|
||||
|
||||
// Walk calls v with every component reachable from c via Scan, recursively,
|
||||
// for as long as visit returns nil.
|
||||
|
@ -84,7 +89,7 @@ func Walk(c interface{}, v func(interface{}) error) error {
|
|||
// Load calls Load on all Loaders reachable via Scan (using Walk).
|
||||
// It stops on the first error.
|
||||
func (g *Game) Load() error {
|
||||
return Walk(g.Scener, func(c interface{}) error {
|
||||
return Walk(g.Root, func(c interface{}) error {
|
||||
l, ok := c.(Loader)
|
||||
if !ok {
|
||||
return nil
|
||||
|
@ -99,11 +104,11 @@ func (g *Game) Load() error {
|
|||
// fastidiously calling RegisterComponent/UnregisterComponent).
|
||||
func (g *Game) Prepare() {
|
||||
g.componentsByID = make(map[string]interface{})
|
||||
Walk(g.Scener, func(c interface{}) error {
|
||||
Walk(g.Root, func(c interface{}) error {
|
||||
g.RegisterComponent(c)
|
||||
return nil
|
||||
})
|
||||
Walk(g.Scener, func(c interface{}) error {
|
||||
Walk(g.Root, func(c interface{}) error {
|
||||
if p, ok := c.(Prepper); ok {
|
||||
p.Prepare(g)
|
||||
}
|
||||
|
|
|
@ -23,6 +23,13 @@ type DrawOrderer interface {
|
|||
DrawOrder() float64
|
||||
}
|
||||
|
||||
// DrawUpdater components can be both drawn and updated.
|
||||
// Same comments as for Drawer and Updater.
|
||||
type DrawUpdater interface {
|
||||
Drawer
|
||||
Updater
|
||||
}
|
||||
|
||||
// Identifier components have a sense of self. This makes it easier for
|
||||
// components to find and interact with one another.
|
||||
type Identifier interface {
|
||||
|
|
2
main.go
2
main.go
|
@ -105,7 +105,7 @@ func main() {
|
|||
game := &engine.Game{
|
||||
ScreenHeight: 240,
|
||||
ScreenWidth: 320,
|
||||
Scener: &engine.Scene{
|
||||
Root: &engine.Scene{
|
||||
ID: "root",
|
||||
Components: []interface{}{
|
||||
&engine.GobDumper{
|
||||
|
|
Loading…
Reference in a new issue