Colliding Doodads #1

Closed
kirsle wants to merge 6 commits from dev into master
10 changed files with 190 additions and 30 deletions
Showing only changes of commit 5b3e679b2a - Show all commits

View File

@ -20,9 +20,6 @@ type Actor interface {
// Movement commands. // Movement commands.
MoveBy(render.Point) // Add {X,Y} to current Position. MoveBy(render.Point) // Add {X,Y} to current Position.
MoveTo(render.Point) // Set current Position to {X,Y}. MoveTo(render.Point) // Set current Position to {X,Y}.
// Implement the Draw function.
Draw(render.Engine)
} }
// GetBoundingRect computes the full pairs of points for the collision box // GetBoundingRect computes the full pairs of points for the collision box

75
doodads/drawing.go Normal file
View File

@ -0,0 +1,75 @@
package doodads
import (
"git.kirsle.net/apps/doodle/render"
uuid "github.com/satori/go.uuid"
)
// Drawing is a Doodad Actor that is based on drawings made inside the game.
type Drawing struct {
Doodad *Doodad
id string
point render.Point
velocity render.Point
size render.Rect
grounded bool
}
// NewDrawing creates a Drawing actor based on a Doodad drawing. If you pass
// an empty ID string, it will make a random UUIDv4 ID.
func NewDrawing(id string, doodad *Doodad) Drawing {
if id == "" {
id = uuid.Must(uuid.NewV4()).String()
}
return Drawing{
id: id,
Doodad: doodad,
size: doodad.Rect(),
}
}
// ID to get the Drawing ID.
func (d *Drawing) ID() string {
return d.id
}
// Position returns the Drawing's position.
func (d *Drawing) Position() render.Point {
return d.point
}
// Velocity returns the Drawing's velocity.
func (d *Drawing) Velocity() render.Point {
return d.velocity
}
// Size returns the Drawing's size.
func (d *Drawing) Size() render.Rect {
return d.size
}
// Grounded returns whether the Drawing is standing on solid ground.
func (d *Drawing) Grounded() bool {
return d.grounded
}
// SetGrounded sets the grounded state.
func (d *Drawing) SetGrounded(v bool) {
d.grounded = v
}
// MoveBy a relative value.
func (d *Drawing) MoveBy(by render.Point) {
d.point.Add(by)
}
// MoveTo an absolute world value.
func (d *Drawing) MoveTo(to render.Point) {
d.point = to
}
// Draw the drawing.
func (d *Drawing) Draw(e render.Engine) {
}

16
doodads/dummy/dummy.go Normal file
View File

@ -0,0 +1,16 @@
// Package dummy implements a dummy doodads.Drawing.
package dummy
import "git.kirsle.net/apps/doodle/doodads"
// Drawing is a dummy doodads.Drawing that has no data.
type Drawing struct {
doodads.Drawing
}
// NewDrawing creates a new dummy drawing.
func NewDrawing(id string, doodad *doodads.Doodad) *Drawing {
return &Drawing{
Drawing: doodads.NewDrawing(id, doodad),
}
}

11
doodads/dummy/player.go Normal file
View File

@ -0,0 +1,11 @@
// Package dummy implements a dummy doodads.Drawing.
package dummy
import "git.kirsle.net/apps/doodle/doodads"
// NewPlayer creates a dummy player object.
func NewPlayer() *Drawing {
return &Drawing{
Drawing: doodads.NewDrawing("PLAYER", doodads.New(32)),
}
}

View File

@ -8,6 +8,7 @@ import (
"git.kirsle.net/apps/doodle/balance" "git.kirsle.net/apps/doodle/balance"
"git.kirsle.net/apps/doodle/enum" "git.kirsle.net/apps/doodle/enum"
"git.kirsle.net/apps/doodle/events" "git.kirsle.net/apps/doodle/events"
"git.kirsle.net/apps/doodle/pkg/userdir"
"git.kirsle.net/apps/doodle/render" "git.kirsle.net/apps/doodle/render"
"github.com/kirsle/golog" "github.com/kirsle/golog"
) )
@ -216,7 +217,7 @@ func (d *Doodle) EditDrawing(filename string) error {
func (d *Doodle) PlayLevel(filename string) error { func (d *Doodle) PlayLevel(filename string) error {
log.Info("Loading level from file: %s", filename) log.Info("Loading level from file: %s", filename)
scene := &PlayScene{ scene := &PlayScene{
Filename: filename, Filename: userdir.LevelPath(filename),
} }
d.Goto(scene) d.Goto(scene)
return nil return nil

View File

@ -58,6 +58,7 @@ func (s *EditorScene) Setup(d *Doodle) error {
if s.Level != nil { if s.Level != nil {
log.Debug("EditorScene.Setup: received level from scene caller") log.Debug("EditorScene.Setup: received level from scene caller")
s.UI.Canvas.LoadLevel(s.Level) s.UI.Canvas.LoadLevel(s.Level)
s.UI.Canvas.InstallActors(s.Level.Actors)
} else if s.filename != "" && s.OpenFile { } else if s.filename != "" && s.OpenFile {
log.Debug("EditorScene.Setup: Loading map from filename at %s", s.filename) log.Debug("EditorScene.Setup: Loading map from filename at %s", s.filename)
if err := s.LoadLevel(s.filename); err != nil { if err := s.LoadLevel(s.filename); err != nil {

4
fps.go
View File

@ -42,7 +42,7 @@ var (
// DrawDebugOverlay draws the debug FPS text on the SDL canvas. // DrawDebugOverlay draws the debug FPS text on the SDL canvas.
func (d *Doodle) DrawDebugOverlay() { func (d *Doodle) DrawDebugOverlay() {
if !d.Debug || !DebugOverlay { if !DebugOverlay {
return return
} }
@ -97,7 +97,7 @@ func (d *Doodle) DrawDebugOverlay() {
// DrawCollisionBox draws the collision box around a Doodad. // DrawCollisionBox draws the collision box around a Doodad.
func (d *Doodle) DrawCollisionBox(actor doodads.Actor) { func (d *Doodle) DrawCollisionBox(actor doodads.Actor) {
if !d.Debug || !DebugCollision { if !DebugCollision {
return return
} }

View File

@ -5,6 +5,7 @@ import (
"git.kirsle.net/apps/doodle/balance" "git.kirsle.net/apps/doodle/balance"
"git.kirsle.net/apps/doodle/doodads" "git.kirsle.net/apps/doodle/doodads"
"git.kirsle.net/apps/doodle/doodads/dummy"
"git.kirsle.net/apps/doodle/events" "git.kirsle.net/apps/doodle/events"
"git.kirsle.net/apps/doodle/level" "git.kirsle.net/apps/doodle/level"
"git.kirsle.net/apps/doodle/render" "git.kirsle.net/apps/doodle/render"
@ -21,7 +22,7 @@ type PlayScene struct {
drawing *uix.Canvas drawing *uix.Canvas
// Player character // Player character
Player doodads.Actor Player *uix.Actor
} }
// Name of the scene. // Name of the scene.
@ -40,12 +41,14 @@ func (s *PlayScene) Setup(d *Doodle) error {
if s.Level != nil { if s.Level != nil {
log.Debug("PlayScene.Setup: received level from scene caller") log.Debug("PlayScene.Setup: received level from scene caller")
s.drawing.LoadLevel(s.Level) s.drawing.LoadLevel(s.Level)
s.drawing.InstallActors(s.Level.Actors)
} else if s.Filename != "" { } else if s.Filename != "" {
log.Debug("PlayScene.Setup: loading map from file %s", s.Filename) log.Debug("PlayScene.Setup: loading map from file %s", s.Filename)
s.LoadLevel(s.Filename) s.LoadLevel(s.Filename)
} }
s.Player = doodads.NewPlayer() player := dummy.NewPlayer()
s.Player = uix.NewActor(player.ID(), &level.Actor{}, player.Doodad)
if s.Level == nil { if s.Level == nil {
log.Debug("PlayScene.Setup: no grid given, initializing empty grid") log.Debug("PlayScene.Setup: no grid given, initializing empty grid")
@ -60,6 +63,17 @@ func (s *PlayScene) Setup(d *Doodle) error {
// Loop the editor scene. // Loop the editor scene.
func (s *PlayScene) Loop(d *Doodle, ev *events.State) error { func (s *PlayScene) Loop(d *Doodle, ev *events.State) error {
// Has the window been resized?
if resized := ev.Resized.Read(); resized {
w, h := d.Engine.WindowSize()
if w != d.width || h != d.height {
d.width = w
d.height = h
s.drawing.Resize(render.NewRect(int32(d.width), int32(d.height)))
return nil
}
}
// Switching to Edit Mode? // Switching to Edit Mode?
if ev.KeyName.Read() == "e" { if ev.KeyName.Read() == "e" {
log.Info("Edit Mode, Go!") log.Info("Edit Mode, Go!")
@ -70,7 +84,7 @@ func (s *PlayScene) Loop(d *Doodle, ev *events.State) error {
return nil return nil
} }
// s.drawing.Loop(ev) s.drawing.Loop(ev)
s.movePlayer(ev) s.movePlayer(ev)
return nil return nil
} }
@ -84,9 +98,16 @@ func (s *PlayScene) Draw(d *Doodle) error {
s.drawing.Present(d.Engine, s.drawing.Point()) s.drawing.Present(d.Engine, s.drawing.Point())
// Draw our hero. // Draw our hero.
s.Player.Draw(d.Engine) {
d.Engine.DrawBox(render.RGBA(255, 255, 153, 255), render.Rect{
X: s.Player.Position().X,
Y: s.Player.Position().Y,
W: s.Player.Size().W,
H: s.Player.Size().H,
})
}
// Draw out bounding boxes. // Draw our bounding boxes.
d.DrawCollisionBox(s.Player) d.DrawCollisionBox(s.Player)
return nil return nil
@ -141,6 +162,8 @@ func (s *PlayScene) LoadLevel(filename string) error {
s.Level = level s.Level = level
s.drawing.LoadLevel(s.Level) s.drawing.LoadLevel(s.Level)
s.drawing.InstallActors(s.Level.Actors)
s.drawing.AddActor(s.Player)
return nil return nil
} }

48
uix/actor.go Normal file
View File

@ -0,0 +1,48 @@
package uix
import (
"git.kirsle.net/apps/doodle/doodads"
"git.kirsle.net/apps/doodle/level"
"git.kirsle.net/apps/doodle/render"
uuid "github.com/satori/go.uuid"
)
// Actor is an object that marries together the three things that make a
// Doodad instance "tick" while inside a Canvas:
//
// - uix.Actor is a doodads.Drawing so it fulfills doodads.Actor to be a
// dynamic object during gameplay.
// - It has a pointer to the level.Actor indicating its static level data
// as defined in the map: its spawn coordinate and configuration.
// - A uix.Canvas that can present the actor's graphics to the screen.
type Actor struct {
doodads.Drawing
Actor *level.Actor
Canvas *Canvas
}
// NewActor sets up a uix.Actor.
// If the id is blank, a new UUIDv4 is generated.
func NewActor(id string, levelActor *level.Actor, doodad *doodads.Doodad) *Actor {
if id == "" {
id = uuid.Must(uuid.NewV4()).String()
}
size := int32(doodad.Layers[0].Chunker.Size)
can := NewCanvas(int(size), false)
can.Name = id
can.actor = levelActor
// TODO: if the Background is render.Invisible it gets defaulted to
// White somewhere and the Doodad masks the level drawing behind it.
can.SetBackground(render.RGBA(0, 0, 1, 0))
can.LoadDoodad(doodad)
can.Resize(render.NewRect(size, size))
return &Actor{
Drawing: doodads.NewDrawing(id, doodad),
Actor: levelActor,
Canvas: can,
}
}

View File

@ -53,12 +53,6 @@ type Canvas struct {
Scroll render.Point // Scroll offset for which parts of canvas are visible. Scroll render.Point // Scroll offset for which parts of canvas are visible.
} }
// Actor is an instance of an actor with a Canvas attached.
type Actor struct {
Actor *level.Actor
Canvas *Canvas
}
// NewCanvas initializes a Canvas widget. // NewCanvas initializes a Canvas widget.
// //
// If editable is true, Scrollable is also set to true, which means the arrow // If editable is true, Scrollable is also set to true, which means the arrow
@ -123,23 +117,17 @@ func (w *Canvas) InstallActors(actors level.ActorMap) error {
return fmt.Errorf("InstallActors: %s", err) return fmt.Errorf("InstallActors: %s", err)
} }
size := int32(doodad.Layers[0].Chunker.Size) w.actors = append(w.actors, NewActor(id, actor, doodad))
can := NewCanvas(int(size), false)
can.Name = id
can.actor = actor
// TODO: if the Background is render.Invisible it gets defaulted to
// White somewhere and the Doodad masks the level drawing behind it.
can.SetBackground(render.RGBA(0, 0, 1, 0))
can.LoadDoodad(doodad)
can.Resize(render.NewRect(size, size))
w.actors = append(w.actors, &Actor{
Actor: actor,
Canvas: can,
})
} }
return nil return nil
} }
// AddActor injects additional actors into the canvas, such as a Player doodad.
func (w *Canvas) AddActor(actor *Actor) error {
w.actors = append(w.actors, actor)
return nil
}
// SetSwatch changes the currently selected swatch for editing. // SetSwatch changes the currently selected swatch for editing.
func (w *Canvas) SetSwatch(s *level.Swatch) { func (w *Canvas) SetSwatch(s *level.Swatch) {
w.Palette.ActiveSwatch = s w.Palette.ActiveSwatch = s