Generic Doodad Script Selection
In the Doodad Properties window, instead of browsing to select a .js file to install your script, a SelectBox of built-in generic scripts are available. These scripts implement simple behaviors and adapt to the full canvas size of the doodad. Built-in scripts so far include: * generic-anvil.js: behaves just like the Anvil. * generic-fire.js: the entire canvas hitbox acts like fire pixels, "burning" mobile doodads and failing the level for the player. * generic-solid.js: the entire canvas hitbox acts solid
This commit is contained in:
parent
0fa1bf8a76
commit
7ea86b4ffc
61
assets/scripts/generic-anvil.js
Normal file
61
assets/scripts/generic-anvil.js
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
// Generic "Anvil" Doodad Script
|
||||||
|
/*
|
||||||
|
A doodad that falls and is dangerous while it falls.
|
||||||
|
|
||||||
|
Can be attached to any doodad.
|
||||||
|
*/
|
||||||
|
|
||||||
|
var falling = false;
|
||||||
|
|
||||||
|
function main() {
|
||||||
|
// Make the hitbox be the full canvas size of this doodad.
|
||||||
|
// Adjust if you want a narrower hitbox.
|
||||||
|
var size = Self.Size()
|
||||||
|
Self.SetHitbox(0, 0, size.W, size.H)
|
||||||
|
|
||||||
|
// Note: doodad is not "solid" but hurts if it falls on you.
|
||||||
|
Self.SetMobile(true);
|
||||||
|
Self.SetGravity(true);
|
||||||
|
|
||||||
|
// Monitor our Y position to tell if we've been falling.
|
||||||
|
var lastPoint = Self.Position();
|
||||||
|
setInterval(function () {
|
||||||
|
var nowAt = Self.Position();
|
||||||
|
if (nowAt.Y > lastPoint.Y) {
|
||||||
|
falling = true;
|
||||||
|
} else {
|
||||||
|
falling = false;
|
||||||
|
}
|
||||||
|
lastPoint = nowAt;
|
||||||
|
}, 100);
|
||||||
|
|
||||||
|
Events.OnCollide(function (e) {
|
||||||
|
if (!e.Settled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Were we falling?
|
||||||
|
if (falling) {
|
||||||
|
if (e.InHitbox) {
|
||||||
|
if (e.Actor.IsPlayer()) {
|
||||||
|
// Fatal to the player.
|
||||||
|
Sound.Play("crumbly-break.wav");
|
||||||
|
FailLevel("Watch out for " + Self.Title + "!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (e.Actor.IsMobile()) {
|
||||||
|
// Destroy mobile doodads.
|
||||||
|
Sound.Play("crumbly-break.wav");
|
||||||
|
e.Actor.Destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// When we receive power, we reset to our original position.
|
||||||
|
var origPoint = Self.Position();
|
||||||
|
Message.Subscribe("power", function (powered) {
|
||||||
|
Self.MoveTo(origPoint);
|
||||||
|
Self.SetVelocity(Vector(0, 0));
|
||||||
|
});
|
||||||
|
}
|
36
assets/scripts/generic-fire.js
Normal file
36
assets/scripts/generic-fire.js
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
// Generic "Fire" Doodad Script
|
||||||
|
/*
|
||||||
|
The entire square shape of your doodad acts similar to "Fire"
|
||||||
|
pixels - killing the player character upon contact.
|
||||||
|
|
||||||
|
Can be attached to any doodad.
|
||||||
|
*/
|
||||||
|
|
||||||
|
function main() {
|
||||||
|
// Make the hitbox be the full canvas size of this doodad.
|
||||||
|
// Adjust if you want a narrower hitbox.
|
||||||
|
var size = Self.Size()
|
||||||
|
Self.SetHitbox(0, 0, size.W, size.H)
|
||||||
|
|
||||||
|
Events.OnCollide(function (e) {
|
||||||
|
if (!e.Settled || !e.InHitbox) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Turn mobile actors black, like real fire does.
|
||||||
|
if (e.Actor.IsMobile()) {
|
||||||
|
e.Actor.Canvas.MaskColor = RGBA(1, 1, 1, 255)
|
||||||
|
}
|
||||||
|
|
||||||
|
// End the level if it's the player.
|
||||||
|
if (e.Actor.IsPlayer()) {
|
||||||
|
FailLevel("Watch out for " + Self.Title + "!");
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
Events.OnLeave(function (e) {
|
||||||
|
if (e.Actor.IsMobile()) {
|
||||||
|
e.Actor.MaskColor = RGBA(0, 0, 0, 0)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
19
assets/scripts/generic-solid.js
Normal file
19
assets/scripts/generic-solid.js
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
// Generic "Solid" Doodad Script
|
||||||
|
/*
|
||||||
|
The entire square shape of your doodad acts similar to "solid"
|
||||||
|
pixels - blocking collision from all sides.
|
||||||
|
|
||||||
|
Can be attached to any doodad.
|
||||||
|
*/
|
||||||
|
|
||||||
|
function main() {
|
||||||
|
// Make the hitbox be the full canvas size of this doodad.
|
||||||
|
// Adjust if you want a narrower hitbox.
|
||||||
|
var size = Self.Size()
|
||||||
|
Self.SetHitbox(0, 0, size.W, size.H)
|
||||||
|
|
||||||
|
// Solid to all collisions.
|
||||||
|
Events.OnCollide(function (e) {
|
||||||
|
return false;
|
||||||
|
})
|
||||||
|
}
|
|
@ -12,7 +12,11 @@ func (w *Canvas) MakeSelfAPI(actor *Actor) map[string]interface{} {
|
||||||
"Title": actor.Doodad().Title,
|
"Title": actor.Doodad().Title,
|
||||||
|
|
||||||
// functions
|
// functions
|
||||||
"ID": actor.ID,
|
"ID": actor.ID,
|
||||||
|
"Size": func() render.Rect {
|
||||||
|
var size = actor.Doodad().ChunkSize()
|
||||||
|
return render.NewRect(size, size)
|
||||||
|
},
|
||||||
"GetTag": actor.Doodad().Tag,
|
"GetTag": actor.Doodad().Tag,
|
||||||
"Position": actor.Position,
|
"Position": actor.Position,
|
||||||
"MoveTo": func(p render.Point) {
|
"MoveTo": func(p render.Point) {
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
package windows
|
package windows
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"sort"
|
"sort"
|
||||||
|
|
||||||
|
"git.kirsle.net/apps/doodle/assets"
|
||||||
"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/log"
|
"git.kirsle.net/apps/doodle/pkg/log"
|
||||||
|
@ -16,6 +18,37 @@ import (
|
||||||
"git.kirsle.net/go/ui"
|
"git.kirsle.net/go/ui"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Some generic built-in doodad scripts users can attach.
|
||||||
|
var GenericScripts = []struct {
|
||||||
|
Label string
|
||||||
|
Help string
|
||||||
|
Filename string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
Label: "Generic Solid",
|
||||||
|
Help: "The whole canvas of your doodad acts solid.\n" +
|
||||||
|
"The player and other mobile doodads can walk on\n" +
|
||||||
|
"top of it, and it blocks movement from the sides.",
|
||||||
|
Filename: "assets/scripts/generic-solid.js",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Label: "Generic Fire",
|
||||||
|
Help: "The whole canvas of your doodad acts like fire.\n" +
|
||||||
|
"Mobile doodads who touch it turn dark, and if\n" +
|
||||||
|
"the player touches it - game over! The failure\n" +
|
||||||
|
"message says: 'Watch out for (title)!'",
|
||||||
|
Filename: "assets/scripts/generic-fire.js",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Label: "Generic Anvil",
|
||||||
|
Help: "This doodad will behave like the Anvil: fall with\n" +
|
||||||
|
"gravity and be deadly to any mobile doodad that it\n" +
|
||||||
|
"lands on! The failure message says:\n" +
|
||||||
|
"'Watch out for (title)!'",
|
||||||
|
Filename: "assets/scripts/generic-anvil.js",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
// DoodadProperties window.
|
// DoodadProperties window.
|
||||||
type DoodadProperties struct {
|
type DoodadProperties struct {
|
||||||
// Settings passed in by doodle
|
// Settings passed in by doodle
|
||||||
|
@ -247,39 +280,147 @@ func (c DoodadProperties) makeMetaTab(tabFrame *ui.TabFrame, Width, Height int)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Browse Script button.
|
// Attaching a Script Frame
|
||||||
btnBrowse := ui.NewButton("Browse Script", ui.NewLabel(ui.Label{
|
{
|
||||||
Text: "Attach a script...",
|
label := ui.NewLabel(ui.Label{
|
||||||
Font: balance.MenuFont,
|
Text: "Attach a Script",
|
||||||
}))
|
Font: balance.LabelFont,
|
||||||
btnBrowse.SetStyle(&balance.ButtonPrimary)
|
})
|
||||||
btnBrowse.Handle(ui.Click, func(ed ui.EventData) error {
|
tab.Pack(label, ui.Pack{
|
||||||
filename, err := native.OpenFile("Choose a .js file", "*.js")
|
Side: ui.N,
|
||||||
if err != nil {
|
FillX: true,
|
||||||
shmem.Flash("Couldn't show file dialog: %s", err)
|
})
|
||||||
|
|
||||||
|
frame := ui.NewFrame("Attach Script Frame")
|
||||||
|
tab.Pack(frame, ui.Pack{
|
||||||
|
Side: ui.N,
|
||||||
|
FillX: true,
|
||||||
|
})
|
||||||
|
|
||||||
|
// Browse Script label.
|
||||||
|
lblBrowse := ui.NewLabel(ui.Label{
|
||||||
|
Text: "Browse and attach a .js file:",
|
||||||
|
Font: balance.MenuFont,
|
||||||
|
})
|
||||||
|
frame.Pack(lblBrowse, ui.Pack{
|
||||||
|
Side: ui.W,
|
||||||
|
})
|
||||||
|
|
||||||
|
// Browse Script button.
|
||||||
|
btnBrowse := ui.NewButton("Browse Script", ui.NewLabel(ui.Label{
|
||||||
|
Text: "Attach a script...",
|
||||||
|
Font: balance.MenuFont,
|
||||||
|
}))
|
||||||
|
btnBrowse.SetStyle(&balance.ButtonPrimary)
|
||||||
|
btnBrowse.Handle(ui.Click, func(ed ui.EventData) error {
|
||||||
|
filename, err := native.OpenFile("Choose a .js file", "*.js")
|
||||||
|
if err != nil {
|
||||||
|
shmem.Flash("Couldn't show file dialog: %s", err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
data, err := ioutil.ReadFile(filename)
|
||||||
|
if err != nil {
|
||||||
|
shmem.Flash("Couldn't read file: %s", err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
c.EditDoodad.Script = string(data)
|
||||||
|
shmem.Flash("Attached %d-byte script to this doodad.", len(c.EditDoodad.Script))
|
||||||
|
|
||||||
|
// Toggle the if/else frames.
|
||||||
|
ifScript.Show()
|
||||||
|
elseScript.Hide()
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
})
|
||||||
|
c.Supervisor.Add(btnBrowse)
|
||||||
|
frame.Pack(btnBrowse, ui.Pack{
|
||||||
|
Side: ui.E,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Built-in Generic Scripts Frame
|
||||||
|
{
|
||||||
|
frame := ui.NewFrame("Generic Scripts Frame")
|
||||||
|
tab.Pack(frame, ui.Pack{
|
||||||
|
Side: ui.N,
|
||||||
|
FillX: true,
|
||||||
|
PadY: 4,
|
||||||
|
})
|
||||||
|
|
||||||
|
label := ui.NewLabel(ui.Label{
|
||||||
|
Text: "Or select from a generic script:",
|
||||||
|
Font: ui.MenuFont,
|
||||||
|
})
|
||||||
|
frame.Pack(label, ui.Pack{
|
||||||
|
Side: ui.W,
|
||||||
|
})
|
||||||
|
|
||||||
|
// SelectBox for the built-ins.
|
||||||
|
sb := ui.NewSelectBox("Select", ui.Label{
|
||||||
|
Font: ui.MenuFont,
|
||||||
|
})
|
||||||
|
tab.Pack(sb, ui.Pack{
|
||||||
|
Side: ui.N,
|
||||||
|
FillX: true,
|
||||||
|
})
|
||||||
|
|
||||||
|
for _, script := range GenericScripts {
|
||||||
|
sb.AddItem(script.Label, script.Filename, func() {})
|
||||||
|
}
|
||||||
|
sb.SetValue(GenericScripts[0].Filename)
|
||||||
|
sb.AlwaysChange = true
|
||||||
|
sb.Handle(ui.Change, func(ed ui.EventData) error {
|
||||||
|
if selection, ok := sb.GetValue(); ok {
|
||||||
|
if filename, ok := selection.Value.(string); ok {
|
||||||
|
// Get this script from the built-in assets.
|
||||||
|
data, err := assets.Asset(filename)
|
||||||
|
if err != nil {
|
||||||
|
shmem.Flash("Couldn't get script: %s", err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find the data from the builtins.
|
||||||
|
var label, help string
|
||||||
|
for _, script := range GenericScripts {
|
||||||
|
if script.Filename == filename {
|
||||||
|
label = script.Label
|
||||||
|
help = script.Help
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prompt the user + a description of this option.
|
||||||
|
var (
|
||||||
|
basename = filepath.Base(filename)
|
||||||
|
description = fmt.Sprintf(
|
||||||
|
"Do you want to install %s to your doodad?\n\n"+
|
||||||
|
"%s\n\n%s",
|
||||||
|
basename,
|
||||||
|
label,
|
||||||
|
help,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
modal.Confirm(description).Then(func() {
|
||||||
|
c.EditDoodad.Script = string(data)
|
||||||
|
|
||||||
|
shmem.Flash("Attached %s to your doodad", filepath.Base(filename))
|
||||||
|
|
||||||
|
// Toggle the if/else frames.
|
||||||
|
ifScript.Show()
|
||||||
|
elseScript.Hide()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
data, err := ioutil.ReadFile(filename)
|
|
||||||
if err != nil {
|
|
||||||
shmem.Flash("Couldn't read file: %s", err)
|
|
||||||
return nil
|
return nil
|
||||||
}
|
})
|
||||||
|
|
||||||
c.EditDoodad.Script = string(data)
|
sb.Supervise(c.Supervisor)
|
||||||
shmem.Flash("Attached %d-byte script to this doodad.", len(c.EditDoodad.Script))
|
c.Supervisor.Add(sb)
|
||||||
|
}
|
||||||
// Toggle the if/else frames.
|
|
||||||
ifScript.Show()
|
|
||||||
elseScript.Hide()
|
|
||||||
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
c.Supervisor.Add(btnBrowse)
|
|
||||||
tab.Pack(btnBrowse, ui.Pack{
|
|
||||||
Side: ui.N,
|
|
||||||
Padding: 4,
|
|
||||||
})
|
|
||||||
|
|
||||||
// Show/hide appropriate frames.
|
// Show/hide appropriate frames.
|
||||||
if c.EditDoodad.Script == "" {
|
if c.EditDoodad.Script == "" {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user