Doodads: Small Key Door + Bigger Crumbly Floor

* The crumbly floor doodad was made 50% larger.
* New doodad: Small Key and Small Key Door. These work like the colored
  doors and locks except each Small Key is consumed when it unlocks a
  door. The door's appearance is of iron bars.
* The inventory HUD displays a small quantity label in the lower-right
  corner of items that have a quantity, such as the Small Key. This is
  done as a Canvas.CornerLabel string attribute on uix.Canvas.
* The "give all keys" cheat adds 99 Small Keys to your inventory.
This commit is contained in:
Noah 2021-01-03 17:06:33 -08:00
parent 3892087932
commit 837960c477
22 changed files with 108 additions and 66 deletions

View File

@ -1,6 +1,6 @@
// Crumbly Floor. // Crumbly Floor.
function main() { function main() {
Self.SetHitbox(0, 0, 65, 7); Self.SetHitbox(0, 0, 98, 11);
Self.AddAnimation("shake", 100, ["shake1", "shake2", "floor", "shake1", "shake2", "floor"]); Self.AddAnimation("shake", 100, ["shake1", "shake2", "floor", "shake1", "shake2", "floor"]);
Self.AddAnimation("fall", 100, ["fall1", "fall2", "fall3", "fall4"]); Self.AddAnimation("fall", 100, ["fall1", "fall2", "fall3", "fall4"]);

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1021 B

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 986 B

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 957 B

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 855 B

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 652 B

After

Width:  |  Height:  |  Size: 415 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 868 B

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 897 B

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 891 B

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@ -18,13 +18,9 @@ doodad convert -t "Yellow Door" yellow-closed.png yellow-unlocked.png yellow-rig
doodad edit-doodad -q --tag color=yellow door-yellow.doodad doodad edit-doodad -q --tag color=yellow door-yellow.doodad
doodad install-script colored-door.js door-yellow.doodad doodad install-script colored-door.js door-yellow.doodad
# doodad convert -t "Green Door" green1.png green2.png door-green.doodad doodad convert -t "Small Key Door" small-closed.png small-unlocked.png small-right.png small-left.png small-key-door.doodad
# doodad edit-doodad -q --tag color=green door-green.doodad doodad edit-doodad -q --tag color=small small-key-door.doodad
# doodad install-script locked-door.js door-green.doodad doodad install-script colored-door.js small-key-door.doodad
#
# doodad convert -t "Yellow Door" yellow1.png yellow2.png door-yellow.doodad
# doodad edit-doodad -q --tag color=yellow door-yellow.doodad
# doodad install-script locked-door.js door-yellow.doodad
doodad convert -t "Red Key" red-key.png key-red.doodad doodad convert -t "Red Key" red-key.png key-red.doodad
doodad edit-doodad -q --tag color=red key-red.doodad doodad edit-doodad -q --tag color=red key-red.doodad
@ -42,7 +38,11 @@ doodad convert -t "Yellow Key" yellow-key.png key-yellow.doodad
doodad edit-doodad -q --tag color=yellow key-yellow.doodad doodad edit-doodad -q --tag color=yellow key-yellow.doodad
doodad install-script keys.js key-yellow.doodad doodad install-script keys.js key-yellow.doodad
doodad convert -t "Small Key" small-key.png small-key.doodad
doodad edit-doodad -q --tag color=small small-key.doodad
doodad install-script keys.js small-key.doodad
doodad convert -t "Electric Door" electric{1,2,3,4}.png door-electric.doodad doodad convert -t "Electric Door" electric{1,2,3,4}.png door-electric.doodad
doodad install-script electric-door.js door-electric.doodad doodad install-script electric-door.js door-electric.doodad
cp door-*.doodad key-*.doodad ../../../assets/doodads/ cp door-*.doodad key-*.doodad small-*.doodad ../../../assets/doodads/

View File

@ -1,6 +1,6 @@
function main() { function main() {
var color = Self.GetTag("color"); var color = Self.GetTag("color");
var keyname = "key-" + color + ".doodad"; var keyname = color === "small" ? "small-key.doodad" : "key-" + color + ".doodad";
// Layers in the doodad image. // Layers in the doodad image.
var layer = { var layer = {
@ -46,7 +46,12 @@ function main() {
if (e.Settled) { if (e.Settled) {
unlocked = true; unlocked = true;
Self.ShowLayer(enterSide < 0 ? layer.right : layer.left); Self.ShowLayer(enterSide < 0 ? layer.right : layer.left);
Sound.Play("unlock.wav") Sound.Play("unlock.wav");
// If a Small Key door, consume a small key.
if (color === "small") {
e.Actor.RemoveItem(keyname, 1)
}
} }
} }
}); });

View File

@ -1,10 +1,11 @@
function main() { function main() {
var color = Self.GetTag("color"); var color = Self.GetTag("color");
var quantity = color === "small" ? 1 : 0;
Events.OnCollide(function(e) { Events.OnCollide(function(e) {
if (e.Settled) { if (e.Settled) {
Sound.Play("item-get.wav") Sound.Play("item-get.wav")
e.Actor.AddItem(Self.Filename, 0); e.Actor.AddItem(Self.Filename, quantity);
Self.Destroy(); Self.Destroy();
} }
}) })

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 682 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 935 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 936 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 932 B

View File

@ -72,6 +72,7 @@ func (c Command) cheatCommand(d *Doodle) bool {
playScene.Player.AddItem("key-blue.doodad", 0) playScene.Player.AddItem("key-blue.doodad", 0)
playScene.Player.AddItem("key-green.doodad", 0) playScene.Player.AddItem("key-green.doodad", 0)
playScene.Player.AddItem("key-yellow.doodad", 0) playScene.Player.AddItem("key-yellow.doodad", 0)
playScene.Player.AddItem("small-key.doodad", 99)
d.Flash("Given all keys to the player character.") d.Flash("Given all keys to the player character.")
} else { } else {
d.Flash("Use this cheat in Play Mode to get all colored keys.") d.Flash("Use this cheat in Play Mode to get all colored keys.")

View File

@ -1,6 +1,8 @@
package doodle package doodle
import ( import (
"fmt"
"git.kirsle.net/apps/doodle/pkg/balance" "git.kirsle.net/apps/doodle/pkg/balance"
"git.kirsle.net/apps/doodle/pkg/doodads" "git.kirsle.net/apps/doodle/pkg/doodads"
"git.kirsle.net/apps/doodle/pkg/uix" "git.kirsle.net/apps/doodle/pkg/uix"
@ -52,70 +54,77 @@ func (s *PlayScene) setupInventoryHud() {
// computeInventory adjusts the inventory HUD when the player's inventory changes. // computeInventory adjusts the inventory HUD when the player's inventory changes.
func (s *PlayScene) computeInventory() { func (s *PlayScene) computeInventory() {
items := s.Player.ListItems() items := s.Player.ListItems()
if len(items) != len(s.invenItems) {
// Inventory has changed! See which doodads we have
// and which we need to load.
var seen = map[string]interface{}{}
for _, filename := range items {
seen[filename] = nil
if _, ok := s.invenDoodads[filename]; !ok { // Inventory has changed! See which doodads we have
// Cache miss. Load the doodad here. // and which we need to load.
doodad, err := doodads.LoadFile(filename) var seen = map[string]interface{}{}
if err != nil { for _, filename := range items {
s.d.Flash("Inventory item '%s' error: %s", filename, err) seen[filename] = nil
continue
}
canvas := uix.NewCanvas(doodad.ChunkSize(), false) if _, ok := s.invenDoodads[filename]; !ok {
canvas.LoadDoodad(doodad) // Cache miss. Load the doodad here.
canvas.Resize(render.NewRect( doodad, err := doodads.LoadFile(filename)
doodad.ChunkSize(), doodad.ChunkSize(), if err != nil {
)) s.d.Flash("Inventory item '%s' error: %s", filename, err)
s.invenFrame.Pack(canvas, ui.Pack{ continue
Side: ui.W,
// TODO: work around a weird padding bug. item had too
// tall a top margin when added to the inventory frame!
PadX: 8,
})
s.invenDoodads[filename] = canvas
} }
s.invenDoodads[filename].Show() canvas := uix.NewCanvas(doodad.ChunkSize(), false)
canvas.SetBackground(render.RGBA(1, 0, 0, 0))
canvas.LoadDoodad(doodad)
canvas.Resize(render.NewRect(
doodad.ChunkSize(), doodad.ChunkSize(),
))
s.invenFrame.Pack(canvas, ui.Pack{
Side: ui.W,
// TODO: work around a weird padding bug. item had too
// tall a top margin when added to the inventory frame!
PadX: 8,
})
s.invenDoodads[filename] = canvas
} }
// Hide any doodad that used to be in the inventory but now is not. // For items with >1 quantity, show the quantity in the corner.
for filename, canvas := range s.invenDoodads { if qty := s.Player.HasItem(filename); qty > 0 {
if _, ok := seen[filename]; !ok { s.invenDoodads[filename].CornerLabel = fmt.Sprintf("%d", qty)
canvas.Hide()
}
}
// Recompute the size of the inventory frame.
// TODO: this works around a bug in ui.Frame, at the bottom of
// compute_packed, a frame Resize's itself to fit the children but this
// trips the "manually set size" boolean... packing more items after a
// computer doesn't resize the frame. So here, we resize-auto it to
// reset that boolean so the next compute, picks the right size.
s.invenFrame.Configure(ui.Config{
AutoResize: true,
Width: 1,
Height: 1,
})
s.invenFrame.Compute(s.d.Engine)
// If we removed all items, hide the frame.
if len(items) == 0 {
s.invenFrame.Hide()
} else { } else {
s.invenFrame.Show() s.invenDoodads[filename].CornerLabel = ""
} }
// Cache the item list so we don't run the above logic every single tick. s.invenDoodads[filename].Show()
s.invenItems = items
} }
// Hide any doodad that used to be in the inventory but now is not.
for filename, canvas := range s.invenDoodads {
if _, ok := seen[filename]; !ok {
canvas.Hide()
}
}
// Recompute the size of the inventory frame.
// TODO: this works around a bug in ui.Frame, at the bottom of
// compute_packed, a frame Resize's itself to fit the children but this
// trips the "manually set size" boolean... packing more items after a
// computer doesn't resize the frame. So here, we resize-auto it to
// reset that boolean so the next compute, picks the right size.
s.invenFrame.Configure(ui.Config{
AutoResize: true,
Width: 1,
Height: 1,
})
s.invenFrame.Compute(s.d.Engine)
// If we removed all items, hide the frame.
if len(items) == 0 {
s.invenFrame.Hide()
} else {
s.invenFrame.Show()
}
// Cache the item list so we don't run the above logic every single tick.
s.invenItems = items
// Compute the inventory frame so it positions and wraps the items. // Compute the inventory frame so it positions and wraps the items.
s.screen.Compute(s.d.Engine) s.screen.Compute(s.d.Engine)
} }

View File

@ -207,7 +207,11 @@ func (a *Actor) SetNoclip(v bool) {
// Item name is usually the doodad filename. // Item name is usually the doodad filename.
func (a *Actor) AddItem(itemName string, quantity int) { func (a *Actor) AddItem(itemName string, quantity int) {
a.muInventory.Lock() a.muInventory.Lock()
a.inventory[itemName] = quantity if _, ok := a.inventory[itemName]; ok {
a.inventory[itemName] += quantity
} else {
a.inventory[itemName] = quantity
}
a.muInventory.Unlock() a.muInventory.Unlock()
} }

View File

@ -31,6 +31,10 @@ type Canvas struct {
Scrollable bool // Cursor keys will scroll the viewport of this canvas. Scrollable bool // Cursor keys will scroll the viewport of this canvas.
Zoom int // Zoom level on the canvas. Zoom int // Zoom level on the canvas.
// Custom label to place in the lower-right corner of the canvas.
// Used for e.g. the quantity badge on Inventory items.
CornerLabel string
// Selected draw tool/mode, default Pencil, for editable canvases. // Selected draw tool/mode, default Pencil, for editable canvases.
Tool drawtool.Tool Tool drawtool.Tool
BrushSize int // thickness of selected brush BrushSize int // thickness of selected brush

View File

@ -152,6 +152,24 @@ func (w *Canvas) Present(e render.Engine, p render.Point) {
w.presentStrokes(e) w.presentStrokes(e)
w.presentCursor(e) w.presentCursor(e)
// Custom label in the canvas corner? (e.g. for Inventory item counts)
if w.CornerLabel != "" {
label := ui.NewLabel(ui.Label{
Text: w.CornerLabel,
Font: render.Text{
FontFilename: balance.ShellFontFilename,
Size: balance.ShellFontSizeSmall,
Color: render.White,
},
})
label.SetBackground(render.RGBA(0, 0, 50, 150))
label.Compute(e)
label.Present(e, render.Point{
X: p.X + S.W - label.Size().W - w.BoxThickness(1),
Y: p.Y + S.H - label.Size().H - w.BoxThickness(1),
})
}
// XXX: Debug, show label in canvas corner. // XXX: Debug, show label in canvas corner.
if balance.DebugCanvasLabel { if balance.DebugCanvasLabel {
rows := []string{ rows := []string{