diff --git a/dev-assets/doodads/buttons/button.js b/dev-assets/doodads/buttons/button.js index 3745467..c31e342 100644 --- a/dev-assets/doodads/buttons/button.js +++ b/dev-assets/doodads/buttons/button.js @@ -2,17 +2,30 @@ function main() { var timer = 0; var pressed = false; + // Has a linked Sticky Button been pressed permanently down? + var stickyDown = false; + Message.Subscribe("sticky:down", function(down) { + stickyDown = down; + Self.ShowLayer(stickyDown ? 1 : 0); + }); + Events.OnCollide(function(e) { if (!e.Settled) { return; } + // If a linked Sticky Button is pressed, button stays down too and + // doesn't interact. + if (stickyDown) { + return; + } + // Verify they've touched the button. if (e.Overlap.Y + e.Overlap.H < 24) { return; } - if (!pressed) { + if (!pressed && !stickyDown) { Sound.Play("button-down.wav") Message.Publish("power", true); pressed = true; diff --git a/dev-assets/doodads/buttons/sticky.js b/dev-assets/doodads/buttons/sticky.js index 0958454..a715a59 100644 --- a/dev-assets/doodads/buttons/sticky.js +++ b/dev-assets/doodads/buttons/sticky.js @@ -8,6 +8,7 @@ function main() { pressed = false; Sound.Play("button-up.wav") Message.Publish("power", false); + Message.Publish("sticky:down", false); } }) @@ -29,5 +30,6 @@ function main() { Self.ShowLayer(1); pressed = true; Message.Publish("power", true); + Message.Publish("sticky:down", true); }); } diff --git a/dev-assets/doodads/crumbly-floor/fallen.png b/dev-assets/doodads/crumbly-floor/fallen.png index 6c16dd0..ffd3423 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/doors/electric-door.js b/dev-assets/doodads/doors/electric-door.js index 646cf4f..1f4be7c 100644 --- a/dev-assets/doodads/doors/electric-door.js +++ b/dev-assets/doodads/doors/electric-door.js @@ -1,31 +1,59 @@ +var animating = false; +var opened = false; +var powerState = false; + +// Function to handle the door opening or closing. +function setPoweredState(powered) { + powerState = powered; + + console.log("setPoweredState: %+v", powered) + if (powered) { + if (animating || opened) { + return; + } + + animating = true; + Sound.Play("electric-door.wav") + Self.PlayAnimation("open", function() { + opened = true; + animating = false; + }); + } else { + animating = true; + Sound.Play("electric-door.wav") + Self.PlayAnimation("close", function() { + opened = false; + animating = false; + }) + } +} + function main() { Self.AddAnimation("open", 100, [0, 1, 2, 3]); Self.AddAnimation("close", 100, [3, 2, 1, 0]); - var animating = false; - var opened = false; + Self.SetHitbox(0, 0, 34, 76); - Message.Subscribe("power", function(powered) { - if (powered) { - if (animating || opened) { - return; - } + // A linked Switch that activates the door will send the Toggle signal + // immediately before the Power signal. The door can just invert its + // state on this signal, and ignore the very next Power signal. Ordinary + // power sources like Buttons will work as normal, as they emit only a power + // signal. + var ignoreNextPower = false; + Message.Subscribe("switch:toggle", function(powered) { + console.log("A switch powered %+v, setPoweredState(%+v) to opposite", powered, powerState); + ignoreNextPower = true; + setPoweredState(!powerState); + }) - animating = true; - Sound.Play("electric-door.wav") - Self.PlayAnimation("open", function() { - opened = true; - animating = false; - }); - } else { - animating = true; - Sound.Play("electric-door.wav") - Self.PlayAnimation("close", function() { - opened = false; - animating = false; - }) + Message.Subscribe("power", function(powered) { + if (ignoreNextPower) { + ignoreNextPower = false; + return; } + + setPoweredState(powered); }); Events.OnCollide(function(e) { diff --git a/dev-assets/doodads/switches/switch.js b/dev-assets/doodads/switches/switch.js index f51f9cc..88e8eaf 100644 --- a/dev-assets/doodads/switches/switch.js +++ b/dev-assets/doodads/switches/switch.js @@ -20,6 +20,9 @@ function main() { if (collide === false) { Sound.Play("button-down.wav") state = !state; + + var nonce = Math.random() * 2147483647; + Message.Publish("switch:toggle", state); Message.Publish("power", state); showState(state); diff --git a/dev-assets/doodads/trapdoors/down1.png b/dev-assets/doodads/trapdoors/down1.png index 4af2ba4..f4871d5 100644 Binary files a/dev-assets/doodads/trapdoors/down1.png and b/dev-assets/doodads/trapdoors/down1.png differ diff --git a/dev-assets/doodads/trapdoors/down2.png b/dev-assets/doodads/trapdoors/down2.png index 51a7c8c..62adb46 100644 Binary files a/dev-assets/doodads/trapdoors/down2.png and b/dev-assets/doodads/trapdoors/down2.png differ diff --git a/dev-assets/doodads/trapdoors/down3.png b/dev-assets/doodads/trapdoors/down3.png index 986e8b4..6c1f191 100644 Binary files a/dev-assets/doodads/trapdoors/down3.png and b/dev-assets/doodads/trapdoors/down3.png differ diff --git a/dev-assets/doodads/trapdoors/down4.png b/dev-assets/doodads/trapdoors/down4.png index 5e6e5f2..a15da36 100644 Binary files a/dev-assets/doodads/trapdoors/down4.png and b/dev-assets/doodads/trapdoors/down4.png differ diff --git a/dev-assets/doodads/trapdoors/left1.png b/dev-assets/doodads/trapdoors/left1.png index e8cc2a6..6bb04d2 100644 Binary files a/dev-assets/doodads/trapdoors/left1.png and b/dev-assets/doodads/trapdoors/left1.png differ diff --git a/dev-assets/doodads/trapdoors/left2.png b/dev-assets/doodads/trapdoors/left2.png index 9c74728..cd29dd5 100644 Binary files a/dev-assets/doodads/trapdoors/left2.png and b/dev-assets/doodads/trapdoors/left2.png differ diff --git a/dev-assets/doodads/trapdoors/left3.png b/dev-assets/doodads/trapdoors/left3.png index d9a21bc..b7cbb41 100644 Binary files a/dev-assets/doodads/trapdoors/left3.png and b/dev-assets/doodads/trapdoors/left3.png differ diff --git a/dev-assets/doodads/trapdoors/left4.png b/dev-assets/doodads/trapdoors/left4.png index 96d1537..dec5a61 100644 Binary files a/dev-assets/doodads/trapdoors/left4.png and b/dev-assets/doodads/trapdoors/left4.png differ diff --git a/dev-assets/doodads/trapdoors/right1.png b/dev-assets/doodads/trapdoors/right1.png index 85e4394..5ac6228 100644 Binary files a/dev-assets/doodads/trapdoors/right1.png and b/dev-assets/doodads/trapdoors/right1.png differ diff --git a/dev-assets/doodads/trapdoors/right2.png b/dev-assets/doodads/trapdoors/right2.png index d4b090f..e7f33d4 100644 Binary files a/dev-assets/doodads/trapdoors/right2.png and b/dev-assets/doodads/trapdoors/right2.png differ diff --git a/dev-assets/doodads/trapdoors/right3.png b/dev-assets/doodads/trapdoors/right3.png index 73bc55b..88ee3db 100644 Binary files a/dev-assets/doodads/trapdoors/right3.png and b/dev-assets/doodads/trapdoors/right3.png differ diff --git a/dev-assets/doodads/trapdoors/right4.png b/dev-assets/doodads/trapdoors/right4.png index cf7a4e0..8c0d01d 100644 Binary files a/dev-assets/doodads/trapdoors/right4.png and b/dev-assets/doodads/trapdoors/right4.png differ diff --git a/dev-assets/doodads/trapdoors/trapdoor.js b/dev-assets/doodads/trapdoors/trapdoor.js index 5ad50c2..54dca12 100644 --- a/dev-assets/doodads/trapdoors/trapdoor.js +++ b/dev-assets/doodads/trapdoors/trapdoor.js @@ -5,8 +5,8 @@ function main() { var timer = 0; // Set our hitbox based on our orientation. - var thickness = 6; - var doodadSize = 72; + var thickness = 10; + var doodadSize = 86; if (direction === "left") { Self.SetHitbox(48, 0, doodadSize, doodadSize); } else if (direction === "right") { diff --git a/dev-assets/doodads/trapdoors/up1.png b/dev-assets/doodads/trapdoors/up1.png index 686664b..bc7830c 100644 Binary files a/dev-assets/doodads/trapdoors/up1.png and b/dev-assets/doodads/trapdoors/up1.png differ diff --git a/dev-assets/doodads/trapdoors/up2.png b/dev-assets/doodads/trapdoors/up2.png index 9898ed1..bd92a0c 100644 Binary files a/dev-assets/doodads/trapdoors/up2.png and b/dev-assets/doodads/trapdoors/up2.png differ diff --git a/dev-assets/doodads/trapdoors/up3.png b/dev-assets/doodads/trapdoors/up3.png index 1d75b3d..a18640e 100644 Binary files a/dev-assets/doodads/trapdoors/up3.png and b/dev-assets/doodads/trapdoors/up3.png differ diff --git a/dev-assets/doodads/trapdoors/up4.png b/dev-assets/doodads/trapdoors/up4.png index cd880a8..dc68a2d 100644 Binary files a/dev-assets/doodads/trapdoors/up4.png and b/dev-assets/doodads/trapdoors/up4.png differ diff --git a/go.mod b/go.mod index f2b845d..4541617 100644 --- a/go.mod +++ b/go.mod @@ -24,6 +24,7 @@ require ( github.com/robertkrimen/otto v0.0.0-20200922221731-ef014fd054ac github.com/stripe/safesql v0.2.0 // indirect github.com/tomnomnom/xtermcolor v0.0.0-20160428124646-b78803f00a7e // indirect + github.com/tsenart/deadcode v0.0.0-20160724212837-210d2dc333e9 // indirect github.com/urfave/cli v1.22.5 github.com/urfave/cli/v2 v2.3.0 github.com/veandco/go-sdl2 v0.4.4 @@ -38,3 +39,4 @@ require ( mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b // indirect mvdan.cc/unparam v0.0.0-20200501210554-b37ab49443f7 // indirect ) + diff --git a/pkg/branding/branding.go b/pkg/branding/branding.go index a1c736e..0dcb5b7 100644 --- a/pkg/branding/branding.go +++ b/pkg/branding/branding.go @@ -2,11 +2,11 @@ package branding // Constants for branding and version information. const ( - AppName = "Project: Doodle" + AppName = "Sketchy Maze" Summary = "A drawing-based maze game" - Version = "0.4.0-alpha" - Website = "https://www.kirsle.net/tagged/Doodle" - Copyright = "2020 Noah Petherbridge" + Version = "0.5.0-alpha" + Website = "https://www.sketchymaze.com" + Copyright = "2021 Noah Petherbridge" // Update check URL UpdateCheckJSON = "https://download.sketchymaze.com/version.json" diff --git a/pkg/collision/collide_level.go b/pkg/collision/collide_level.go index ac960cd..0e50cee 100644 --- a/pkg/collision/collide_level.go +++ b/pkg/collision/collide_level.go @@ -25,7 +25,7 @@ type Collide struct { MoveTo render.Point // Swatch attributes affecting the collision at this time. - InFire bool + InFire string // the name of the swatch, Fire = general ouchy color. InWater bool } @@ -222,7 +222,7 @@ func CollidesWithGrid(d Actor, grid *level.Chunker, target render.Point) (*Colli // IsColliding returns whether any sort of collision has occurred. func (c *Collide) IsColliding() bool { return c.Top || c.Bottom || c.Left || c.Right || - c.InFire || c.InWater + c.InFire != "" || c.InWater } // ScanBoundingBox scans all of the pixels in a bounding box on the grid and @@ -276,7 +276,7 @@ func (c *Collide) ScanGridLine(p1, p2 render.Point, grid *level.Chunker, side Si // in our result. If non-solid, we'll collect attributes from it // and return them in the final result for gameplay behavior. if swatch.Fire { - c.InFire = true + c.InFire = swatch.Name } if swatch.Water { c.InWater = true diff --git a/pkg/play_scene.go b/pkg/play_scene.go index aca3dd1..5db1890 100644 --- a/pkg/play_scene.go +++ b/pkg/play_scene.go @@ -138,9 +138,11 @@ func (s *PlayScene) Setup(d *Doodle) error { // Handler when an actor touches water or fire. s.drawing.OnLevelCollision = func(a *uix.Actor, col *collision.Collide) { - if col.InFire { + if col.InFire != "" { a.Canvas.MaskColor = render.Black - s.DieByFire() + if a.ID() == "PLAYER" { // only the player dies in fire. + s.DieByFire(col.InFire) + } } else if col.InWater { a.Canvas.MaskColor = render.DarkBlue } else { @@ -352,11 +354,11 @@ func (s *PlayScene) RestartLevel() { }) } -// DieByFire ends the level by fire. -func (s *PlayScene) DieByFire() { - log.Info("Watch out for fire!") +// DieByFire ends the level by "fire", or w/e the swatch is named. +func (s *PlayScene) DieByFire(name string) { + log.Info("Watch out for %s!", name) s.alertBox.Title = "You've died!" - s.alertBoxLabel.Text = "Watch out for fire!" + s.alertBoxLabel.Text = fmt.Sprintf("Watch out for %s!", name) s.alertReplayButton.Show() if s.CanEdit { diff --git a/pkg/uix/canvas.go b/pkg/uix/canvas.go index a4e1fe4..c99f0ae 100644 --- a/pkg/uix/canvas.go +++ b/pkg/uix/canvas.go @@ -108,6 +108,7 @@ func NewCanvas(size int, editable bool) *Canvas { Editable: editable, Scrollable: editable, Palette: level.NewPalette(), + BrushSize: 1, chunks: level.NewChunker(size), actors: make([]*Actor, 0), wallpaper: &Wallpaper{}, diff --git a/pkg/windows/add_edit_level.go b/pkg/windows/add_edit_level.go index 121483d..d6efc62 100644 --- a/pkg/windows/add_edit_level.go +++ b/pkg/windows/add_edit_level.go @@ -43,7 +43,7 @@ func NewAddEditLevel(config AddEditLevel) *ui.Window { window.SetButtons(ui.CloseButton) window.Configure(ui.Config{ Width: 400, - Height: 180, + Height: 240, Background: render.Grey, }) @@ -167,6 +167,73 @@ func NewAddEditLevel(config AddEditLevel) *ui.Window { }(t) } + /****************** + * Frame for giving the level a title. + ******************/ + + if config.EditLevel != nil { + label3 := ui.NewLabel(ui.Label{ + Text: "Metadata", + Font: balance.LabelFont, + }) + frame.Pack(label3, ui.Pack{ + Side: ui.N, + FillX: true, + }) + + type metadataObj struct { + Label string + Binding *string + Update func(string) + } + var metaRows = []metadataObj{ + {"Title:", &config.EditLevel.Title, func(v string) { config.EditLevel.Title = v }}, + {"Author:", &config.EditLevel.Author, func(v string) { config.EditLevel.Author = v }}, + } + + for _, mr := range metaRows { + mr := mr + mrFrame := ui.NewFrame("Metadata " + mr.Label + "Frame") + frame.Pack(mrFrame, ui.Pack{ + Side: ui.N, + FillX: true, + PadY: 2, + }) + + // The label. + mrLabel := ui.NewLabel(ui.Label{ + Text: mr.Label, + Font: balance.MenuFont, + }) + mrLabel.Configure(ui.Config{ + Width: 75, + }) + mrFrame.Pack(mrLabel, ui.Pack{ + Side: ui.W, + }) + + // The button. + mrButton := ui.NewButton(mr.Label, ui.NewLabel(ui.Label{ + TextVariable: mr.Binding, + Font: balance.MenuFont, + })) + mrButton.Handle(ui.Click, func(ed ui.EventData) error { + shmem.Prompt("Enter a new "+mr.Label, func(answer string) { + if answer != "" { + mr.Update(answer) + } + }) + return nil + }) + config.Supervisor.Add(mrButton) + mrFrame.Pack(mrButton, ui.Pack{ + Side: ui.W, + Expand: true, + PadX: 2, + }) + } + } + /****************** * Confirm/cancel buttons. ******************/