Add More Trapdoor Doodads

* Add the other trapdoor directions: Left, Right and Up.
* UI: Show a color square in each Palette Swatch button in Edit Mode.
  * Instead of just the label like "solid", "fire", "decoration" it also
    shows a square box colored as the swatch color. The label and box
    are left-aligned in the button.
* Minor Play Mode physics update:
  * The player jump is now limited: they may only continue to move
    upwards for 20 ticks, after which they must touch ground before
    jumping again.
  * Remove the "press Down to move down" button. Only gravity moves you
    down.
* Fix a crash in the Editor Mode when you dragged doodads on top of each
  other. Source of bug was the loopActorCollision() function, which only
  should be useful to Play Mode, and it expected the scripting engine to
  be attached to the Canvas. In EditorMode there is no scripting engine.
physics
Noah 2019-07-05 15:02:22 -07:00
parent 22440f436b
commit dc2695cfc9
19 changed files with 128 additions and 12 deletions

View File

@ -63,7 +63,13 @@ trapdoors() {
cd trapdoors/
doodad convert -t "Trapdoor" down{1,2,3,4}.png trapdoor-down.doodad
doodad install-script down.js trapdoor-down.doodad
doodad convert -t "Trapdoor Left" left{1,2,3,4}.png trapdoor-left.doodad
doodad convert -t "Trapdoor Right" right{1,2,3,4}.png trapdoor-right.doodad
doodad convert -t "Trapdoor Up" up{1,2,3,4}.png trapdoor-up.doodad
doodad install-script trapdoor.js trapdoor-down.doodad
doodad install-script trapdoor.js trapdoor-left.doodad
doodad install-script trapdoor.js trapdoor-right.doodad
doodad install-script trapdoor.js trapdoor-up.doodad
cp trapdoor-*.doodad ../../../assets/doodads/

Binary file not shown.

After

Width:  |  Height:  |  Size: 912 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1013 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1009 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 765 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 933 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1011 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 789 B

View File

@ -0,0 +1,71 @@
function main() {
// What direction is the trapdoor facing?
// - Titles are like "Trapdoor Left" or "Trapdoor Right"
// - The default (down) is called just "Trapdoor"
var direction = Self.Doodad.Title.split(" ")[1];
if (!direction) {
direction = "down";
}
direction = direction.toLowerCase();
console.log("Trapdoor(%s) initialized", direction);
var timer = 0;
// Set our hitbox based on our orientation.
var thickness = 6;
var doodadSize = 72;
if (direction === "left") {
Self.SetHitbox(48, 0, doodadSize, doodadSize);
} else if (direction === "right") {
Self.SetHitbox(0, 0, thickness+4, doodadSize);
} else if (direction === "up") {
Self.SetHitbox(0, doodadSize - thickness, doodadSize, doodadSize);
} else { // Down, default.
Self.SetHitbox(0, 0, 72, 6);
}
var animationSpeed = 100;
var opened = false;
// Register our animations.
var frames = [];
for (var i = 1; i <= 4; i++) {
frames.push(direction + i);
}
Self.AddAnimation("open", animationSpeed, frames);
frames.reverse();
Self.AddAnimation("close", animationSpeed, frames);
Events.OnCollide( function(e) {
if (opened) {
return;
}
// Is the actor colliding our solid part?
if (e.InHitbox) {
// Are they touching our opening side?
if (direction === "left" && (e.Overlap.X+e.Overlap.W) < (doodadSize-thickness)) {
return false;
} else if (direction === "right" && e.Overlap.X > 0) {
return false;
} else if (direction === "up" && (e.Overlap.Y+e.Overlap.H) < doodadSize) {
return false;
} else if (direction === "down" && e.Overlap.Y > 0) {
return false;
} else {
opened = true;
Self.PlayAnimation("open", null);
}
}
});
Events.OnLeave(function() {
if (opened) {
Self.PlayAnimation("close", function() {
opened = false;
});
}
})
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 831 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 964 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 846 B

View File

@ -19,7 +19,7 @@ import (
)
// Width of the panel frame.
var paletteWidth int32 = 150
var paletteWidth int32 = 160
// EditorUI manages the user interface for the Editor Scene.
type EditorUI struct {

View File

@ -1,6 +1,8 @@
package doodle
import (
"fmt"
"git.kirsle.net/apps/doodle/lib/render"
"git.kirsle.net/apps/doodle/lib/ui"
"git.kirsle.net/apps/doodle/pkg/balance"
@ -66,16 +68,42 @@ func (u *EditorUI) setupPaletteFrame(window *ui.Window) *ui.Frame {
// Draw the radio buttons for the palette.
if u.Canvas != nil && u.Canvas.Palette != nil {
for _, swatch := range u.Canvas.Palette.Swatches {
swFrame := ui.NewFrame(fmt.Sprintf("Swatch(%s) Button Frame", swatch.Name))
colorFrame := ui.NewFrame(fmt.Sprintf("Swatch(%s) Color Box", swatch.Name))
colorFrame.Configure(ui.Config{
Width: 16,
Height: 16,
Background: swatch.Color,
BorderSize: 1,
BorderStyle: ui.BorderSunken,
})
swFrame.Pack(colorFrame, ui.Pack{
Anchor: ui.W,
})
label := ui.NewLabel(ui.Label{
Text: swatch.Name,
Font: balance.StatusFont,
})
label.Font.Color = swatch.Color.Darken(128)
swFrame.Pack(label, ui.Pack{
Anchor: ui.W,
})
btn := ui.NewRadioButton("palette", &u.selectedSwatch, swatch.Name, label)
btn := ui.NewRadioButton("palette", &u.selectedSwatch, swatch.Name, swFrame)
btn.Handle(ui.Click, onClick)
u.Supervisor.Add(btn)
btn.Compute(u.d.Engine)
swFrame.Configure(ui.Config{
Height: label.Size().H,
// TODO: magic number, trying to left-align
// the label by making the frame as wide as possible.
Width: paletteWidth - 16,
})
frame.Pack(btn, ui.Pack{
Anchor: ui.N,
Fill: true,

View File

@ -47,7 +47,8 @@ type PlayScene struct {
debWorldIndex *string
// Player character
Player *uix.Actor
Player *uix.Actor
playerJumpCounter int // limit jump length
}
// Name of the scene.
@ -349,17 +350,22 @@ func (s *PlayScene) movePlayer(ev *events.State) {
var velocity render.Point
if ev.Down.Now {
velocity.Y = playerSpeed
}
if ev.Left.Now {
velocity.X = -playerSpeed
}
if ev.Right.Now {
velocity.X = playerSpeed
}
if ev.Up.Now {
if ev.Up.Now && (s.Player.Grounded() || s.playerJumpCounter >= 0) {
velocity.Y = -playerSpeed
if s.Player.Grounded() {
s.playerJumpCounter = 20
}
}
if !s.Player.Grounded() {
s.playerJumpCounter--
}
// // Apply gravity if not grounded.

View File

@ -1,6 +1,7 @@
package uix
import (
"errors"
"sync"
"time"
@ -16,9 +17,11 @@ import (
// loopActorCollision is the Loop function that checks if pairs of
// actors are colliding with each other, and handles their scripting
// responses to such collisions.
//
// boxes: array of Actor bounding box rects.
func (w *Canvas) loopActorCollision() error {
if w.scripting == nil {
return errors.New("Canvas.loopActorCollision: scripting engine not attached to Canvas")
}
var (
// Current time of this tick so we can advance animations.
now = time.Now()

View File

@ -215,8 +215,10 @@ func (w *Canvas) Loop(ev *events.State) error {
}
// Check collisions between actors.
if err := w.loopActorCollision(); err != nil {
log.Error("loopActorCollision: %s", err)
if w.scripting != nil {
if err := w.loopActorCollision(); err != nil {
log.Error("loopActorCollision: %s", err)
}
}
// If the canvas is editable, only care if it's over our space.