doodle/pkg/doodads/doodad.go
Noah Petherbridge 7866f618da First-class Doodad Hitboxes + Generic Item Script
A new property is added to the Doodad struct: Hitbox (Rect).

The uix.Actor for Play Mode will defer to the Doodad.Hitbox until the
JavaScript has manually set its own via Self.SetHitbox(). So in effect,
scripts no longer need to worry about their hitbox! The one assigned to
the Doodad will be the default.

Scripts can check if their hitbox is zero before setting a default:

  if (Self.Hitbox().IsZero()) {
    var size = Self.Size()           // get doodad canvas size
    Self.SetHitbox(0, 0, size, size) // the full square
  }

The built-in generic doodad scripts have made this change, so that your
simple doodad can have a custom hitbox defined easily using in-game
tools.

Other changes:

* New script: Generic Collectible Item. Selecting it will add a
  "quantity" tag to your doodad, to easily configure the script.
* JavaScript API: "Self.Hitbox()" returns your doodad's current hitbox.
  You can check "Self.Hitbox.IsZero()" to check if it's empty.
2021-09-03 20:39:44 -07:00

80 lines
1.9 KiB
Go

package doodads
import (
"git.kirsle.net/apps/doodle/pkg/balance"
"git.kirsle.net/apps/doodle/pkg/level"
"git.kirsle.net/apps/doodle/pkg/log"
"git.kirsle.net/go/render"
)
// Doodad is a reusable component for Levels that have scripts and graphics.
type Doodad struct {
level.Base
Filename string `json:"-"` // used internally, not saved in json
Hidden bool `json:"hidden,omitempty"`
Palette *level.Palette `json:"palette"`
Script string `json:"script"`
Hitbox render.Rect `json:"hitbox"`
Layers []Layer `json:"layers"`
Tags map[string]string `json:"data"` // arbitrary key/value data storage
}
// Layer holds a layer of drawing data for a Doodad.
type Layer struct {
Name string `json:"name"`
Chunker *level.Chunker `json:"chunks"`
}
// New creates a new Doodad.
func New(size int) *Doodad {
if size == 0 {
size = balance.DoodadSize
}
return &Doodad{
Base: level.Base{
Version: 1,
},
Palette: level.DefaultPalette(),
Hitbox: render.NewRect(size, size),
Layers: []Layer{
{
Name: "main",
Chunker: level.NewChunker(size),
},
},
Tags: map[string]string{},
}
}
// Tag gets a value from the doodad's tags.
func (d *Doodad) Tag(name string) string {
if v, ok := d.Tags[name]; ok {
return v
}
log.Warn("Doodad(%s).Tag(%s): tag not defined", d.Title, name)
return ""
}
// ChunkSize returns the chunk size of the Doodad's first layer.
func (d *Doodad) ChunkSize() int {
return d.Layers[0].Chunker.Size
}
// Rect returns a rect of the ChunkSize for scaling a Canvas widget.
func (d *Doodad) Rect() render.Rect {
var size = d.ChunkSize()
return render.Rect{
W: size,
H: size,
}
}
// Inflate attaches the pixels to their swatches after loading from disk.
func (d *Doodad) Inflate() {
d.Palette.Inflate()
for _, layer := range d.Layers {
layer.Chunker.Inflate(d.Palette)
}
}