doodle/pkg/level/actors.go
Noah Petherbridge 405aaf509d Link Start Flags to Change Characters
New feature: link a Start Flag to another doodad in your level
and you will play as that doodad instead of Boy. All Creatures
are designed to be playable. Playing as "other" doodads leads
to interesting effects, like not being able to activate buttons,
switches, or warp doors and not having an inventory to pick up
keys. The Anvil is fun: it can destroy other mobile doodads by
jumping on them.

If the actor does not specify that it has gravity, the gameplay
starts in antigravity mode. This will be the vast majority of
non-mobile doodads and the Bird.

Other changes:

* The Blue and Red Azulians now share a doodad script.
* The Azulians AI is still to walk back and forth, pickup keys and
  press buttons. The Blue Azulian walks slower than the red one.
* The Blue Azulian is no longer hidden from the doodads list.
* Actor UUID values in levels are now V1 UUIDs (time-ordered).
  This will help to reliably resolve conflicts in draw order
  of overlapping doodads (newest added to level wins).
* Link Tool: clicking on a pair of already-linked doodads will
  now unlink them, so you don't have to delete one to delete
  the link.
* Actor Tool: deleting an actor immediately calls PruneLinks()
  to clean up any links that the deleted doodad might have.
2021-08-11 20:40:31 -07:00

82 lines
1.8 KiB
Go

package level
import (
"git.kirsle.net/go/render"
"github.com/google/uuid"
)
// ActorMap holds the doodad information by their ID in the level data.
type ActorMap map[string]*Actor
// Inflate assigns each actor its ID from the hash map for their self reference.
func (m ActorMap) Inflate() {
for id, actor := range m {
actor.id = id
}
}
// Add a new Actor to the map. If it doesn't already have an ID it will be
// given a random UUIDv4 ID.
func (m ActorMap) Add(a *Actor) {
if a.id == "" {
a.id = uuid.Must(uuid.NewUUID()).String()
}
m[a.id] = a
}
// Remove an Actor from the map. The ID must be set at the very least, so to
// remove by ID just create an Actor{id: x}
func (m ActorMap) Remove(a *Actor) bool {
if _, ok := m[a.id]; ok {
delete(m, a.id)
return true
}
return false
}
// Actor is an instance of a Doodad in the level.
type Actor struct {
id string // NOTE: read only, use ID() to access.
Filename string `json:"filename"` // like "exit.doodad"
Point render.Point `json:"point"`
Links []string `json:"links,omitempty"` // IDs of linked actors
}
// ID returns the actor's ID.
func (a *Actor) ID() string {
return a.id
}
// AddLink adds a linked Actor to an Actor. Add the linked actor by its ID.
func (a *Actor) AddLink(id string) {
// Don't add a duplicate ID to the links array.
for _, exist := range a.Links {
if exist == id {
return
}
}
a.Links = append(a.Links, id)
}
// Unlink removes the linked actor's ID.
func (a *Actor) Unlink(id string) {
var newLinks []string
for _, exist := range a.Links {
if exist == id {
continue
}
newLinks = append(newLinks, exist)
}
a.Links = newLinks
}
// IsLinked checks if the actor is linked to the other actor's ID.
func (a *Actor) IsLinked(id string) bool {
for _, exist := range a.Links {
if exist == id {
return true
}
}
return false
}