New Doodad: Anvil

* The Anvil doodad is affected by gravity and becomes dangerous when
  falling. If it lands on the player character, you die! If it lands on
  any other mobile doodad, it destroys it! It can land on solid doodads
  such as the Electric Trapdoor and the Crumbly Floor. It will activate
  a Crumbly Floor if it lands on one, and can activate buttons and
  switches that it passes.
* JavaScript API: FailLevel(message) can be called from a doodad to kill
  the player character. The Anvil does this if it collides with the
  player while it's been falling.
This commit is contained in:
Noah 2021-08-08 21:54:37 -07:00
bovenliggende 810ba193d9
commit 0518df226c
13 gewijzigde bestanden met toevoegingen van 117 en 13 verwijderingen

Bestand weergeven

@ -41,9 +41,6 @@ function main() {
// When we receive power, we reset to our original position.
var origPoint = Self.Position();
Message.Subscribe("power", function (powered) {
console.error("Box received power! %+v", powered);
console.error("MoveTo: %+v", origPoint);
console.error("Keys: %+v", Object.keys(Self));
Self.MoveTo(origPoint);
Self.SetVelocity(Vector(0, 0));
});

Bestand weergeven

@ -58,6 +58,10 @@ objects() {
cd box/
make
cd ..
cd crumbly-floor/
make
cd ..
}
onoff() {

Bestand weergeven

@ -2,10 +2,16 @@ ALL: build
.PHONY: build
build:
# Start Flag
doodad convert -t "Start Flag" start-flag.png start-flag.doodad
# Exit Flag
doodad convert -t "Exit Flag" exit-flag.png exit-flag.doodad
doodad install-script exit-flag.js exit-flag.doodad
doodad convert -t "Start Flag" start-flag.png start-flag.doodad
# Anvil
doodad convert -t "Anvil" anvil.png anvil.doodad
doodad install-script anvil.js anvil.doodad
for i in *.doodad; do\
doodad edit-doodad --tag "category=objects" $${i};\

Bestand weergeven

@ -0,0 +1,51 @@
// Anvil
var falling = false;
function main() {
// Note: doodad is not "solid" but hurts if it falls on you.
Self.SetHitbox(0, 0, 48, 25);
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 anvils!");
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));
});
}

Binair bestand niet weergegeven.

Na

Breedte:  |  Hoogte:  |  Grootte: 796 B

Bestand weergeven

@ -7,13 +7,13 @@ function main() {
var state = false;
var collide = false;
Message.Subscribe("power", function(powered) {
Message.Subscribe("power", function (powered) {
state = powered;
showState(state);
});
Events.OnCollide(function(e) {
if (!e.Settled) {
Events.OnCollide(function (e) {
if (!e.Settled || !e.Actor.IsMobile()) {
return;
}
@ -30,7 +30,7 @@ function main() {
}
});
Events.OnLeave(function(e) {
Events.OnLeave(function (e) {
collide = false;
});
}

Bestand weergeven

@ -49,6 +49,11 @@ function setPoweredState(powered) {
Self.PlayAnimation("open", function () {
isOpen = true;
animating = false;
// Had we lost power quickly?
if (!powerState) {
setPoweredState(false);
}
});
} else {
animating = true;

Bestand weergeven

@ -30,6 +30,7 @@ type API interface {
// Game functions.k
EndLevel() // Exit the current level with a victory
FailLevel(message)
/************************************
* Event Handler Callback Functions *

Bestand weergeven

@ -41,6 +41,7 @@ type PlayScene struct {
// buttons what to do next.
alertBox *ui.Window
alertBoxLabel *ui.Label
alertBoxValue string
alertReplayButton *ui.Button // Replay level
alertEditButton *ui.Button // Edit Level
alertNextButton *ui.Button // Next Level
@ -118,6 +119,29 @@ func (s *PlayScene) setupAsync(d *Doodle) error {
s.alertExitButton.Show()
// Show the alert box.
s.alertBox.Title = "Level Completed"
s.alertBoxValue = "Congratulations on clearing the level!"
s.alertBox.Show()
})
s.scripting.OnLevelFail(func(message string) {
d.Flash(message)
// Pause the simulation.
s.running = false
// Toggle the relevant buttons on.
if s.CanEdit {
s.alertEditButton.Show()
}
s.alertNextButton.Hide()
// Always-visible buttons.
s.alertReplayButton.Show()
s.alertExitButton.Show()
// Show the alert box.
s.alertBox.Title = "You've died!"
s.alertBoxValue = message
s.alertBox.Show()
})
@ -310,8 +334,8 @@ func (s *PlayScene) SetupAlertbox() {
******************/
s.alertBoxLabel = ui.NewLabel(ui.Label{
Text: "Congratulations on clearing the level!",
Font: balance.LabelFont,
TextVariable: &s.alertBoxValue,
Font: balance.LabelFont,
})
frame.Pack(s.alertBoxLabel, ui.Pack{
Side: ui.N,
@ -390,7 +414,7 @@ func (s *PlayScene) RestartLevel() {
func (s *PlayScene) DieByFire(name string) {
log.Info("Watch out for %s!", name)
s.alertBox.Title = "You've died!"
s.alertBoxLabel.Text = fmt.Sprintf("Watch out for %s!", name)
s.alertBoxValue = fmt.Sprintf("Watch out for %s!", name)
s.alertReplayButton.Show()
if s.CanEdit {

Bestand weergeven

@ -19,6 +19,8 @@ This adds the global methods `Message.Subscribe(name, func)` and
`Message.Publish(name, args)` to the JavaScript VM's scope.
*/
func RegisterPublishHooks(s *Supervisor, vm *VM) {
log.Error("RegisterPublishHooks called with %+v %+v", s, vm)
// Goroutine to watch the VM's inbound channel and invoke Subscribe handlers
// for any matching messages received.
go func() {

Bestand weergeven

@ -17,6 +17,7 @@ type Supervisor struct {
// Global event handlers.
onLevelExit func()
onLevelFail func(message string)
}
// NewSupervisor creates a new JavaScript Supervior.

Bestand weergeven

@ -10,14 +10,25 @@ Names registered:
*/
func RegisterEventHooks(s *Supervisor, vm *VM) {
vm.Set("EndLevel", func() {
if s.onLevelExit == nil {
panic("JS EndLevel(): no OnLevelExit handler attached to script supervisor")
if s.onLevelFail == nil {
panic("JS FailLevel(): No OnLevelFail handler attached to script supervisor")
}
s.onLevelExit()
})
vm.Set("FailLevel", func(message string) {
if s.onLevelFail == nil {
panic("JS FailLevel(): No OnLevelFail handler attached to script supervisor")
}
s.onLevelFail(message)
})
}
// OnLevelExit registers an event hook for when a Level Exit doodad is reached.
func (s *Supervisor) OnLevelExit(handler func()) {
s.onLevelExit = handler
}
// OnLevelFail registers an event hook for level failures (doodads killing the player).
func (s *Supervisor) OnLevelFail(handler func(string)) {
s.onLevelFail = handler
}

Bestand weergeven

@ -207,6 +207,7 @@ func (w *Canvas) loopActorCollision() error {
// Are they on top?
aHitbox := collision.SizePlusHitbox(collision.GetBoundingRect(a), a.Hitbox())
if render.AbsInt(test.Y+test.H-aHitbox.Y) == 0 {
// log.Error("ActorCollision: onTop=true at Y=%s", test.Y)
onTop = true
onTopY = test.Y
}
@ -217,6 +218,7 @@ func (w *Canvas) loopActorCollision() error {
lockY = lastGoodBox.Y
}
if onTop {
// log.Error("ActorCollision: setGrounded(true)", test.Y)
b.SetGrounded(true)
}
}