diff --git a/dev-assets/doodads/crumbly-floor/crumbly-floor.js b/dev-assets/doodads/crumbly-floor/crumbly-floor.js index 97c2be0..c7bdf08 100644 --- a/dev-assets/doodads/crumbly-floor/crumbly-floor.js +++ b/dev-assets/doodads/crumbly-floor/crumbly-floor.js @@ -1,6 +1,6 @@ // Crumbly Floor. 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("fall", 100, ["fall1", "fall2", "fall3", "fall4"]); diff --git a/dev-assets/doodads/crumbly-floor/fall1.png b/dev-assets/doodads/crumbly-floor/fall1.png index bc9710c..fdc1616 100644 Binary files a/dev-assets/doodads/crumbly-floor/fall1.png and b/dev-assets/doodads/crumbly-floor/fall1.png differ diff --git a/dev-assets/doodads/crumbly-floor/fall2.png b/dev-assets/doodads/crumbly-floor/fall2.png index 1524b6d..ac135c2 100644 Binary files a/dev-assets/doodads/crumbly-floor/fall2.png and b/dev-assets/doodads/crumbly-floor/fall2.png differ diff --git a/dev-assets/doodads/crumbly-floor/fall3.png b/dev-assets/doodads/crumbly-floor/fall3.png index 5b05d93..cad059d 100644 Binary files a/dev-assets/doodads/crumbly-floor/fall3.png and b/dev-assets/doodads/crumbly-floor/fall3.png differ diff --git a/dev-assets/doodads/crumbly-floor/fall4.png b/dev-assets/doodads/crumbly-floor/fall4.png index 97e8ee0..11f6c98 100644 Binary files a/dev-assets/doodads/crumbly-floor/fall4.png and b/dev-assets/doodads/crumbly-floor/fall4.png differ diff --git a/dev-assets/doodads/crumbly-floor/fallen.png b/dev-assets/doodads/crumbly-floor/fallen.png index dd5e57f..6c16dd0 100644 Binary files a/dev-assets/doodads/crumbly-floor/fallen.png and b/dev-assets/doodads/crumbly-floor/fallen.png differ diff --git a/dev-assets/doodads/crumbly-floor/floor.png b/dev-assets/doodads/crumbly-floor/floor.png index f89f16e..c592c09 100644 Binary files a/dev-assets/doodads/crumbly-floor/floor.png and b/dev-assets/doodads/crumbly-floor/floor.png differ diff --git a/dev-assets/doodads/crumbly-floor/shake1.png b/dev-assets/doodads/crumbly-floor/shake1.png index 4881adf..b59c251 100644 Binary files a/dev-assets/doodads/crumbly-floor/shake1.png and b/dev-assets/doodads/crumbly-floor/shake1.png differ diff --git a/dev-assets/doodads/crumbly-floor/shake2.png b/dev-assets/doodads/crumbly-floor/shake2.png index 42e770d..83723ef 100644 Binary files a/dev-assets/doodads/crumbly-floor/shake2.png and b/dev-assets/doodads/crumbly-floor/shake2.png differ diff --git a/dev-assets/doodads/doors/build.sh b/dev-assets/doodads/doors/build.sh index 52d6e18..384d486 100755 --- a/dev-assets/doodads/doors/build.sh +++ b/dev-assets/doodads/doors/build.sh @@ -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 install-script colored-door.js door-yellow.doodad -# doodad convert -t "Green Door" green1.png green2.png door-green.doodad -# doodad edit-doodad -q --tag color=green door-green.doodad -# doodad install-script locked-door.js door-green.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 "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=small small-key-door.doodad +doodad install-script colored-door.js small-key-door.doodad doodad convert -t "Red Key" red-key.png 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 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 install-script electric-door.js door-electric.doodad -cp door-*.doodad key-*.doodad ../../../assets/doodads/ +cp door-*.doodad key-*.doodad small-*.doodad ../../../assets/doodads/ diff --git a/dev-assets/doodads/doors/colored-door.js b/dev-assets/doodads/doors/colored-door.js index eaa1bcf..0bfba60 100644 --- a/dev-assets/doodads/doors/colored-door.js +++ b/dev-assets/doodads/doors/colored-door.js @@ -1,6 +1,6 @@ function main() { 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. var layer = { @@ -46,7 +46,12 @@ function main() { if (e.Settled) { unlocked = true; 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) + } } } }); diff --git a/dev-assets/doodads/doors/keys.js b/dev-assets/doodads/doors/keys.js index 00cc6d7..593b871 100644 --- a/dev-assets/doodads/doors/keys.js +++ b/dev-assets/doodads/doors/keys.js @@ -1,10 +1,11 @@ function main() { var color = Self.GetTag("color"); + var quantity = color === "small" ? 1 : 0; Events.OnCollide(function(e) { if (e.Settled) { Sound.Play("item-get.wav") - e.Actor.AddItem(Self.Filename, 0); + e.Actor.AddItem(Self.Filename, quantity); Self.Destroy(); } }) diff --git a/dev-assets/doodads/doors/small-closed.png b/dev-assets/doodads/doors/small-closed.png new file mode 100644 index 0000000..b97ae46 Binary files /dev/null and b/dev-assets/doodads/doors/small-closed.png differ diff --git a/dev-assets/doodads/doors/small-key.png b/dev-assets/doodads/doors/small-key.png new file mode 100644 index 0000000..11e4eca Binary files /dev/null and b/dev-assets/doodads/doors/small-key.png differ diff --git a/dev-assets/doodads/doors/small-left.png b/dev-assets/doodads/doors/small-left.png new file mode 100644 index 0000000..273786f Binary files /dev/null and b/dev-assets/doodads/doors/small-left.png differ diff --git a/dev-assets/doodads/doors/small-right.png b/dev-assets/doodads/doors/small-right.png new file mode 100644 index 0000000..4f55056 Binary files /dev/null and b/dev-assets/doodads/doors/small-right.png differ diff --git a/dev-assets/doodads/doors/small-unlocked.png b/dev-assets/doodads/doors/small-unlocked.png new file mode 100644 index 0000000..5596796 Binary files /dev/null and b/dev-assets/doodads/doors/small-unlocked.png differ diff --git a/pkg/cheats.go b/pkg/cheats.go index 07c7cf2..8ba5909 100644 --- a/pkg/cheats.go +++ b/pkg/cheats.go @@ -72,6 +72,7 @@ func (c Command) cheatCommand(d *Doodle) bool { playScene.Player.AddItem("key-blue.doodad", 0) playScene.Player.AddItem("key-green.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.") } else { d.Flash("Use this cheat in Play Mode to get all colored keys.") diff --git a/pkg/play_inventory.go b/pkg/play_inventory.go index 8fa18ff..8d69245 100644 --- a/pkg/play_inventory.go +++ b/pkg/play_inventory.go @@ -1,6 +1,8 @@ package doodle import ( + "fmt" + "git.kirsle.net/apps/doodle/pkg/balance" "git.kirsle.net/apps/doodle/pkg/doodads" "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. func (s *PlayScene) computeInventory() { 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 { - // Cache miss. Load the doodad here. - doodad, err := doodads.LoadFile(filename) - if err != nil { - s.d.Flash("Inventory item '%s' error: %s", filename, err) - continue - } + // 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 - canvas := uix.NewCanvas(doodad.ChunkSize(), false) - 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 + if _, ok := s.invenDoodads[filename]; !ok { + // Cache miss. Load the doodad here. + doodad, err := doodads.LoadFile(filename) + if err != nil { + s.d.Flash("Inventory item '%s' error: %s", filename, err) + continue } - 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 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() + // For items with >1 quantity, show the quantity in the corner. + if qty := s.Player.HasItem(filename); qty > 0 { + s.invenDoodads[filename].CornerLabel = fmt.Sprintf("%d", qty) } else { - s.invenFrame.Show() + s.invenDoodads[filename].CornerLabel = "" } - // Cache the item list so we don't run the above logic every single tick. - s.invenItems = items + s.invenDoodads[filename].Show() } + // 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. s.screen.Compute(s.d.Engine) } diff --git a/pkg/uix/actor.go b/pkg/uix/actor.go index 06a96b4..1756b56 100644 --- a/pkg/uix/actor.go +++ b/pkg/uix/actor.go @@ -207,7 +207,11 @@ func (a *Actor) SetNoclip(v bool) { // Item name is usually the doodad filename. func (a *Actor) AddItem(itemName string, quantity int) { 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() } diff --git a/pkg/uix/canvas.go b/pkg/uix/canvas.go index dbdc214..a4e1fe4 100644 --- a/pkg/uix/canvas.go +++ b/pkg/uix/canvas.go @@ -31,6 +31,10 @@ type Canvas struct { Scrollable bool // Cursor keys will scroll the viewport of this 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. Tool drawtool.Tool BrushSize int // thickness of selected brush diff --git a/pkg/uix/canvas_present.go b/pkg/uix/canvas_present.go index aadef58..741e7af 100644 --- a/pkg/uix/canvas_present.go +++ b/pkg/uix/canvas_present.go @@ -152,6 +152,24 @@ func (w *Canvas) Present(e render.Engine, p render.Point) { w.presentStrokes(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. if balance.DebugCanvasLabel { rows := []string{