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.
|
// Camera ignores Scene.Draw and calls Scene's children's Draw.
|
||||||
type Camera struct {
|
type Camera struct {
|
||||||
ID
|
ID
|
||||||
Scene *Scene
|
Scene Scener
|
||||||
|
|
||||||
// Camera controls
|
// Camera controls
|
||||||
Centre image.Point // world coordinates
|
Centre image.Point // world coordinates
|
||||||
|
@ -37,14 +37,14 @@ type Camera struct {
|
||||||
|
|
||||||
// Draw applies transformations to opts, then calls c.Scene.Draw with it.
|
// Draw applies transformations to opts, then calls c.Scene.Draw with it.
|
||||||
func (c *Camera) Draw(screen *ebiten.Image, opts ebiten.DrawImageOptions) {
|
func (c *Camera) Draw(screen *ebiten.Image, opts ebiten.DrawImageOptions) {
|
||||||
if c.Scene.Hidden {
|
if c.Scene.Scene().Hidden {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// The lower bound on zoom is the larger of
|
// The lower bound on zoom is the larger of
|
||||||
// { (ScreenWidth / BoundsWidth), (ScreenHeight / BoundsHeight) }
|
// { (ScreenWidth / BoundsWidth), (ScreenHeight / BoundsHeight) }
|
||||||
zoom := c.Zoom
|
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 {
|
if z := float64(c.game.ScreenWidth) / float64(sz.X); zoom < z {
|
||||||
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)) }.
|
// Camera frame currently Rectangle{ centre ± (screen/(2*zoom)) }.
|
||||||
sw2, sh2 := float64(c.game.ScreenWidth/2), float64(c.game.ScreenHeight/2)
|
sw2, sh2 := float64(c.game.ScreenWidth/2), float64(c.game.ScreenHeight/2)
|
||||||
swz, shz := int(sw2/zoom), int(sh2/zoom)
|
swz, shz := int(sw2/zoom), int(sh2/zoom)
|
||||||
if centre.X-swz < c.Scene.Bounds.Min.X {
|
if centre.X-swz < c.Scene.Scene().Bounds.Min.X {
|
||||||
centre.X = c.Scene.Bounds.Min.X + swz
|
centre.X = c.Scene.Scene().Bounds.Min.X + swz
|
||||||
}
|
}
|
||||||
if centre.Y-shz < c.Scene.Bounds.Min.Y {
|
if centre.Y-shz < c.Scene.Scene().Bounds.Min.Y {
|
||||||
centre.Y = c.Scene.Bounds.Min.Y + shz
|
centre.Y = c.Scene.Scene().Bounds.Min.Y + shz
|
||||||
}
|
}
|
||||||
if centre.X+swz > c.Scene.Bounds.Max.X {
|
if centre.X+swz > c.Scene.Scene().Bounds.Max.X {
|
||||||
centre.X = c.Scene.Bounds.Max.X - swz
|
centre.X = c.Scene.Scene().Bounds.Max.X - swz
|
||||||
}
|
}
|
||||||
if centre.Y+shz > c.Scene.Bounds.Max.Y {
|
if centre.Y+shz > c.Scene.Scene().Bounds.Max.Y {
|
||||||
centre.Y = c.Scene.Bounds.Max.Y - shz
|
centre.Y = c.Scene.Scene().Bounds.Max.Y - shz
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply other options
|
// Apply other options
|
||||||
|
@ -101,7 +101,7 @@ func (c *Camera) Draw(screen *ebiten.Image, opts ebiten.DrawImageOptions) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update passes the call to c.Scene.
|
// 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).
|
// Scan returns the only child (c.Scene).
|
||||||
func (c *Camera) Scan() []interface{} { return []interface{}{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.
|
// 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 {
|
type Game struct {
|
||||||
ScreenWidth int
|
ScreenWidth int
|
||||||
ScreenHeight int
|
ScreenHeight int
|
||||||
Scener
|
Root DrawUpdater // typically a *Scene or SceneRef though
|
||||||
|
|
||||||
componentsByID map[string]interface{}
|
componentsByID map[string]interface{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw draws the entire thing, with default draw options.
|
// Draw draws the entire thing, with default draw options.
|
||||||
func (g *Game) Draw(screen *ebiten.Image) {
|
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.
|
// 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
|
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
|
// RegisterComponent tells the game there is a new component. Currently this is
|
||||||
// only necessary for components with IDs.
|
// only necessary for components with IDs.
|
||||||
func (g *Game) RegisterComponent(c interface{}) {
|
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] }
|
func (g *Game) Component(id string) interface{} { return g.componentsByID[id] }
|
||||||
|
|
||||||
// Scan implements Scanner.
|
// 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,
|
// Walk calls v with every component reachable from c via Scan, recursively,
|
||||||
// for as long as visit returns nil.
|
// 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).
|
// Load calls Load on all Loaders reachable via Scan (using Walk).
|
||||||
// It stops on the first error.
|
// It stops on the first error.
|
||||||
func (g *Game) Load() 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)
|
l, ok := c.(Loader)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil
|
return nil
|
||||||
|
@ -99,11 +104,11 @@ func (g *Game) Load() error {
|
||||||
// fastidiously calling RegisterComponent/UnregisterComponent).
|
// fastidiously calling RegisterComponent/UnregisterComponent).
|
||||||
func (g *Game) Prepare() {
|
func (g *Game) Prepare() {
|
||||||
g.componentsByID = make(map[string]interface{})
|
g.componentsByID = make(map[string]interface{})
|
||||||
Walk(g.Scener, func(c interface{}) error {
|
Walk(g.Root, func(c interface{}) error {
|
||||||
g.RegisterComponent(c)
|
g.RegisterComponent(c)
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
Walk(g.Scener, func(c interface{}) error {
|
Walk(g.Root, func(c interface{}) error {
|
||||||
if p, ok := c.(Prepper); ok {
|
if p, ok := c.(Prepper); ok {
|
||||||
p.Prepare(g)
|
p.Prepare(g)
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,13 @@ type DrawOrderer interface {
|
||||||
DrawOrder() float64
|
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
|
// Identifier components have a sense of self. This makes it easier for
|
||||||
// components to find and interact with one another.
|
// components to find and interact with one another.
|
||||||
type Identifier interface {
|
type Identifier interface {
|
||||||
|
|
2
main.go
2
main.go
|
@ -105,7 +105,7 @@ func main() {
|
||||||
game := &engine.Game{
|
game := &engine.Game{
|
||||||
ScreenHeight: 240,
|
ScreenHeight: 240,
|
||||||
ScreenWidth: 320,
|
ScreenWidth: 320,
|
||||||
Scener: &engine.Scene{
|
Root: &engine.Scene{
|
||||||
ID: "root",
|
ID: "root",
|
||||||
Components: []interface{}{
|
Components: []interface{}{
|
||||||
&engine.GobDumper{
|
&engine.GobDumper{
|
||||||
|
|
Loading…
Reference in a new issue