@ -0,0 +1 @@ |
|||
*.doodad |
@ -0,0 +1,4 @@ |
|||
# Sketchy Maze Assets |
|||
|
|||
All assets in this repository are copyright (C) 2021 Noah Petherbridge. |
|||
All rights reserved. |
@ -0,0 +1,17 @@ |
|||
# Sketchy Maze Assets |
|||
|
|||
This repo contains the game's built-in artwork (doodads and levels). The |
|||
assets here are licensed separately from the game's source code. |
|||
|
|||
The contents of this repository is copyright (C) 2021 Noah Petherbridge. |
|||
All rights reserved. Not for redistribution outside of official builds of |
|||
Sketchy Maze. |
|||
|
|||
## Doodads |
|||
|
|||
The doodads are in source form (png's and scripts) and need compiling. |
|||
They'll write and copy their outputs to "./assets/doodads" relative to |
|||
the root of this git repo. |
|||
|
|||
Make sure the `doodad` program is on your $PATH and the build.sh script |
|||
will compile all the doodads. |
@ -0,0 +1,22 @@ |
|||
SHELL = /bin/bash |
|||
|
|||
ALL: build |
|||
|
|||
.PHONY: build |
|||
build: |
|||
doodad convert -t "Blue Azulian" blu-front.png blu-back.png \
|
|||
blu-wr{1,2,3,4}.png blu-wl{1,2,3,4}.png azu-blu.doodad |
|||
doodad edit-doodad --tag "color=blue" azu-blu.doodad |
|||
doodad install-script azulian.js azu-blu.doodad |
|||
|
|||
doodad convert -t "Red Azulian" red-front.png red-back.png \
|
|||
red-wr{1,2,3,4}.png red-wl{1,2,3,4}.png azu-red.doodad |
|||
doodad edit-doodad --tag "color=red" azu-red.doodad |
|||
doodad install-script azulian.js azu-red.doodad |
|||
|
|||
# Tag the category for these doodads |
|||
for i in *.doodad; do\
|
|||
doodad edit-doodad --tag "category=creatures" $${i};\
|
|||
done |
|||
|
|||
cp *.doodad ../../../assets/doodads/ |
@ -0,0 +1,43 @@ |
|||
// Azulian (Red)
|
|||
// DEPRECATED: they both share azulian.js now.
|
|||
|
|||
function main() { |
|||
var playerSpeed = 4; |
|||
var gravity = 4; |
|||
var Vx = Vy = 0; |
|||
|
|||
var direction = "right"; |
|||
|
|||
Self.SetHitbox(0, 0, 32, 32) |
|||
Self.SetMobile(true); |
|||
Self.SetInventory(true); |
|||
Self.SetGravity(true); |
|||
Self.AddAnimation("walk-left", 100, ["red-wl1", "red-wl2", "red-wl3", "red-wl4"]); |
|||
Self.AddAnimation("walk-right", 100, ["red-wr1", "red-wr2", "red-wr3", "red-wr4"]); |
|||
|
|||
// Sample our X position every few frames and detect if we've hit a solid wall.
|
|||
var sampleTick = 0; |
|||
var sampleRate = 5; |
|||
var lastSampledX = 0; |
|||
|
|||
setInterval(function () { |
|||
if (sampleTick % sampleRate === 0) { |
|||
var curX = Self.Position().X; |
|||
var delta = Math.abs(curX - lastSampledX); |
|||
if (delta < 5) { |
|||
direction = direction === "right" ? "left" : "right"; |
|||
} |
|||
lastSampledX = curX; |
|||
} |
|||
sampleTick++; |
|||
|
|||
// TODO: Vector() requires floats, pain in the butt for JS,
|
|||
// the JS API should be friendlier and custom...
|
|||
var Vx = parseFloat(playerSpeed * (direction === "left" ? -1 : 1)); |
|||
Self.SetVelocity(Vector(Vx, 0.0)); |
|||
|
|||
if (!Self.IsAnimating()) { |
|||
Self.PlayAnimation("walk-" + direction, null); |
|||
} |
|||
}, 100); |
|||
} |
@ -0,0 +1,83 @@ |
|||
// Azulian (Red and Blue)
|
|||
var playerSpeed = 12, |
|||
animating = false, |
|||
direction = "right", |
|||
lastDirection = "right"; |
|||
|
|||
function setupAnimations(color) { |
|||
var left = color === 'blue' ? 'blu-wl' : 'red-wl', |
|||
right = color === 'blue' ? 'blu-wr' : 'red-wr', |
|||
leftFrames = [left + '1', left + '2', left + '3', left + '4'], |
|||
rightFrames = [right + '1', right + '2', right + '3', right + '4']; |
|||
|
|||
Self.AddAnimation("walk-left", 100, leftFrames); |
|||
Self.AddAnimation("walk-right", 100, rightFrames); |
|||
} |
|||
|
|||
function main() { |
|||
var color = Self.GetTag("color"); |
|||
playerSpeed = color === 'blue' ? 2 : 4; |
|||
|
|||
Self.SetMobile(true); |
|||
Self.SetGravity(true); |
|||
Self.SetInventory(true); |
|||
Self.SetHitbox(0, 0, 24, 32); |
|||
setupAnimations(color); |
|||
|
|||
if (Self.IsPlayer()) { |
|||
return playerControls(); |
|||
} |
|||
|
|||
// A.I. pattern: walks back and forth, turning around
|
|||
// when it meets resistance.
|
|||
|
|||
// Sample our X position every few frames and detect if we've hit a solid wall.
|
|||
var sampleTick = 0; |
|||
var sampleRate = 5; |
|||
var lastSampledX = 0; |
|||
|
|||
setInterval(function () { |
|||
if (sampleTick % sampleRate === 0) { |
|||
var curX = Self.Position().X; |
|||
var delta = Math.abs(curX - lastSampledX); |
|||
if (delta < 5) { |
|||
direction = direction === "right" ? "left" : "right"; |
|||
} |
|||
lastSampledX = curX; |
|||
} |
|||
sampleTick++; |
|||
|
|||
var Vx = parseFloat(playerSpeed * (direction === "left" ? -1 : 1)); |
|||
Self.SetVelocity(Vector(Vx, 0.0)); |
|||
|
|||
// If we changed directions, stop animating now so we can
|
|||
// turn around quickly without moonwalking.
|
|||
if (direction !== lastDirection) { |
|||
Self.StopAnimation(); |
|||
} |
|||
|
|||
if (!Self.IsAnimating()) { |
|||
Self.PlayAnimation("walk-" + direction, null); |
|||
} |
|||
|
|||
lastDirection = direction; |
|||
}, 100); |
|||
} |
|||
|
|||
function playerControls() { |
|||
// Note: player speed is controlled by the engine.
|
|||
Events.OnKeypress(function (ev) { |
|||
if (ev.Right) { |
|||
if (!Self.IsAnimating()) { |
|||
Self.PlayAnimation("walk-right", null); |
|||
} |
|||
} else if (ev.Left) { |
|||
if (!Self.IsAnimating()) { |
|||
Self.PlayAnimation("walk-left", null); |
|||
} |
|||
} else { |
|||
Self.StopAnimation(); |
|||
animating = false; |
|||
} |
|||
}) |
|||
} |
After Width: | Height: | Size: 864 B |
After Width: | Height: | Size: 829 B |
After Width: | Height: | Size: 878 B |
After Width: | Height: | Size: 910 B |
After Width: | Height: | Size: 853 B |
After Width: | Height: | Size: 833 B |
After Width: | Height: | Size: 820 B |
After Width: | Height: | Size: 893 B |
After Width: | Height: | Size: 816 B |
After Width: | Height: | Size: 844 B |
After Width: | Height: | Size: 826 B |
After Width: | Height: | Size: 839 B |
After Width: | Height: | Size: 803 B |
After Width: | Height: | Size: 816 B |
After Width: | Height: | Size: 800 B |
After Width: | Height: | Size: 819 B |
After Width: | Height: | Size: 829 B |
After Width: | Height: | Size: 834 B |
After Width: | Height: | Size: 815 B |
After Width: | Height: | Size: 838 B |
@ -0,0 +1,14 @@ |
|||
ALL: build |
|||
|
|||
.PHONY: build |
|||
build: |
|||
doodad convert -t "Bird (red)" left-1.png left-2.png right-1.png right-2.png \
|
|||
dive-left.png dive-right.png bird-red.doodad |
|||
doodad install-script bird.js bird-red.doodad |
|||
|
|||
# Tag the category for these doodads |
|||
for i in *.doodad; do\
|
|||
doodad edit-doodad --tag "category=creatures" $${i};\
|
|||
done |
|||
|
|||
cp *.doodad ../../../assets/doodads/ |
@ -0,0 +1,99 @@ |
|||
// Bird
|
|||
|
|||
function main() { |
|||
var speed = 4; |
|||
var Vx = Vy = 0; |
|||
var altitude = Self.Position().Y; // original height in the level
|
|||
|
|||
var direction = "left", |
|||
lastDirection = "left"; |
|||
var states = { |
|||
flying: 0, |
|||
diving: 1, |
|||
}; |
|||
var state = states.flying; |
|||
|
|||
Self.SetMobile(true); |
|||
Self.SetGravity(false); |
|||
Self.SetHitbox(0, 0, 46, 32); |
|||
Self.AddAnimation("fly-left", 100, ["left-1", "left-2"]); |
|||
Self.AddAnimation("fly-right", 100, ["right-1", "right-2"]); |
|||
|
|||
// Player Character controls?
|
|||
if (Self.IsPlayer()) { |
|||
return player(); |
|||
} |
|||
|
|||
Events.OnCollide(function (e) { |
|||
if (e.Actor.IsMobile() && e.InHitbox) { |
|||
return false; |
|||
} |
|||
}); |
|||
|
|||
// Sample our X position every few frames and detect if we've hit a solid wall.
|
|||
var sampleTick = 0; |
|||
var sampleRate = 2; |
|||
var lastSampledX = 0; |
|||
var lastSampledY = 0; |
|||
|
|||
setInterval(function () { |
|||
if (sampleTick % sampleRate === 0) { |
|||
var curX = Self.Position().X; |
|||
var delta = Math.abs(curX - lastSampledX); |
|||
if (delta < 5) { |
|||
direction = direction === "right" ? "left" : "right"; |
|||
} |
|||
lastSampledX = curX; |
|||
} |
|||
sampleTick++; |
|||
|
|||
// TODO: Vector() requires floats, pain in the butt for JS,
|
|||
// the JS API should be friendlier and custom...
|
|||
var Vx = parseFloat(speed * (direction === "left" ? -1 : 1)); |
|||
Self.SetVelocity(Vector(Vx, 0.0)); |
|||
|
|||
// If we changed directions, stop animating now so we can
|
|||
// turn around quickly without moonwalking.
|
|||
if (direction !== lastDirection) { |
|||
Self.StopAnimation(); |
|||
} |
|||
|
|||
if (!Self.IsAnimating()) { |
|||
Self.PlayAnimation("fly-" + direction, null); |
|||
} |
|||
|
|||
lastDirection = direction; |
|||
}, 100); |
|||
} |
|||
|
|||
// If under control of the player character.
|
|||
function player() { |
|||
Self.SetInventory(true); |
|||
Events.OnKeypress(function (ev) { |
|||
Vx = 0; |
|||
Vy = 0; |
|||
|
|||
if (ev.Up) { |
|||
Vy = -playerSpeed; |
|||
} else if (ev.Down) { |
|||
Vy = playerSpeed; |
|||
} |
|||
|
|||
if (ev.Right) { |
|||
if (!Self.IsAnimating()) { |
|||
Self.PlayAnimation("fly-right", null); |
|||
} |
|||
Vx = playerSpeed; |
|||
} else if (ev.Left) { |
|||
if (!Self.IsAnimating()) { |
|||
Self.PlayAnimation("fly-left", null); |
|||
} |
|||
Vx = -playerSpeed; |
|||
} else { |
|||
Self.StopAnimation(); |
|||
animating = false; |
|||
} |
|||
|
|||
Self.SetVelocity(Vector(Vx, Vy)); |
|||
}) |
|||
} |
After Width: | Height: | Size: 959 B |
After Width: | Height: | Size: 989 B |
After Width: | Height: | Size: 1.0 KiB |
After Width: | Height: | Size: 1022 B |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 1.0 KiB |
@ -0,0 +1,13 @@ |
|||
ALL: build |
|||
|
|||
.PHONY: build |
|||
build: |
|||
doodad convert -t "Box" box-1.png box-2.png \
|
|||
box-3.png box-4.png box.doodad |
|||
doodad install-script box.js box.doodad |
|||
|
|||
for i in *.doodad; do \
|
|||
doodad edit-doodad --tag "category=objects" $${i}; \
|
|||
done |
|||
|
|||
cp *.doodad ../../../assets/doodads/ |
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 1.5 KiB |
@ -0,0 +1,64 @@ |
|||
// Pushable Box.
|
|||
var speed = 4; |
|||
var size = 75; |
|||
|
|||
function main() { |
|||
Self.SetMobile(true); |
|||
Self.SetGravity(true); |
|||
Self.SetHitbox(0, 0, size, size); |
|||
|
|||
Events.OnCollide(function (e) { |
|||
// Ignore events from neighboring Boxes.
|
|||
if (e.Actor.Actor.Filename === "box.doodad") { |
|||
return false; |
|||
} |
|||
|
|||
if (e.Actor.IsMobile() && e.InHitbox) { |
|||
var overlap = e.Overlap; |
|||
|
|||
if (overlap.Y === 0 && !(overlap.X === 0 && overlap.W < 5) && !(overlap.X === size)) { |
|||
// Standing on top, ignore.
|
|||
return false; |
|||
} else if (overlap.Y === size) { |
|||
// From the bottom, boop it up.
|
|||
Self.SetVelocity(Vector(0, -speed * 2)) |
|||
} |
|||
|
|||
// If touching from the sides, slide away.
|
|||
if (overlap.X === 0) { |
|||
Self.SetVelocity(Vector(speed, 0)) |
|||
} else if (overlap.X === size) { |
|||
Self.SetVelocity(Vector(-speed, 0)) |
|||
} |
|||
|
|||
return false; |
|||
} |
|||
}); |
|||
Events.OnLeave(function (e) { |
|||
Self.SetVelocity(Vector(0, 0)); |
|||
}); |
|||
|
|||
// 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)); |
|||
}); |
|||
|
|||
// Start animation on a loop.
|
|||
animate(); |
|||
} |
|||
|
|||
function animate() { |
|||
Self.AddAnimation("animate", 100, [0, 1, 2, 3, 2, 1]); |
|||
|
|||
var running = false; |
|||
setInterval(function () { |
|||
if (!running) { |
|||
running = true; |
|||
Self.PlayAnimation("animate", function () { |
|||
running = false; |
|||
}) |
|||
} |
|||
}, 100); |
|||
} |
@ -0,0 +1,13 @@ |
|||
ALL: build |
|||
|
|||
.PHONY: build |
|||
build: |
|||
doodad convert -t "Boy" stand-right.png stand-left.png \
|
|||
walk-right-1.png walk-right-2.png walk-right-3.png \
|
|||
walk-left-1.png walk-left-2.png walk-left-3.png \
|
|||
boy.doodad |
|||
doodad install-script boy.js boy.doodad |
|||
|
|||
doodad edit-doodad --tag "category=creatures" boy.doodad |
|||
|
|||
cp *.doodad ../../../assets/doodads/ |
@ -0,0 +1,38 @@ |
|||
function main() { |
|||
var playerSpeed = 12; |
|||
var gravity = 4; |
|||
var Vx = Vy = 0; |
|||
|
|||
var animating = false; |
|||
var animStart = animEnd = 0; |
|||
var animFrame = animStart; |
|||
|
|||
Self.SetMobile(true); |
|||
Self.SetInventory(true); |
|||
Self.SetGravity(true); |
|||
Self.SetHitbox(0, 0, 32, 52); |
|||
Self.AddAnimation("walk-left", 200, ["stand-left", "walk-left-1", "walk-left-2", "walk-left-3", "walk-left-2", "walk-left-1"]); |
|||
Self.AddAnimation("walk-right", 200, ["stand-right", "walk-right-1", "walk-right-2", "walk-right-3", "walk-right-2", "walk-right-1"]); |
|||
|
|||
Events.OnKeypress(function (ev) { |
|||
Vx = 0; |
|||
Vy = 0; |
|||
|
|||
if (ev.Right) { |
|||
if (!Self.IsAnimating()) { |
|||
Self.PlayAnimation("walk-right", null); |
|||
} |
|||
Vx = playerSpeed; |
|||
} else if (ev.Left) { |
|||
if (!Self.IsAnimating()) { |
|||
Self.PlayAnimation("walk-left", null); |
|||
} |
|||
Vx = -playerSpeed; |
|||
} else { |
|||
Self.StopAnimation(); |
|||
animating = false; |
|||
} |
|||
|
|||
// Self.SetVelocity(Point(Vx, Vy));
|
|||
}) |
|||
} |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 3.3 KiB |
@ -0,0 +1,99 @@ |
|||
#!/bin/bash |
|||
|
|||
# Build all the doodads from their source files. |
|||
if [[ ! -d "./azulian" ]]; then |
|||
echo Run this script from the dev-assets/doodads/ working directory. |
|||
exit 1 |
|||
fi |
|||
|
|||
mkdir -p ../../assets/doodads |
|||
|
|||
boy() { |
|||
cd boy/ |
|||
make |
|||
cd .. |
|||
|
|||
cd thief/ |
|||
make |
|||
cd .. |
|||
} |
|||
|
|||
buttons() { |
|||
cd buttons/ |
|||
make |
|||
cd .. |
|||
} |
|||
|
|||
switches() { |
|||
cd switches/ |
|||
make |
|||
cd .. |
|||
} |
|||
|
|||
doors() { |
|||
cd doors/ |
|||
make |
|||
cd .. |
|||
} |
|||
|
|||
trapdoors() { |
|||
cd trapdoors/ |
|||
make |
|||
cd .. |
|||
} |
|||
|
|||
azulians() { |
|||
cd azulian/ |
|||
make |
|||
cd .. |
|||
} |
|||
|
|||
mobs() { |
|||
cd bird/ |
|||
make |
|||
cd .. |
|||
} |
|||
|
|||
objects() { |
|||
cd objects/ |
|||
make |
|||
cd .. |
|||
|
|||
cd box/ |
|||
make |
|||
cd .. |
|||
|
|||
cd crumbly-floor/ |
|||
make |
|||
cd .. |
|||
|
|||
cd regions/ |
|||
make |
|||
cd .. |
|||
} |
|||
|
|||
onoff() { |
|||
cd on-off/ |
|||
make |
|||
cd .. |
|||
} |
|||
|
|||
warpdoor() { |
|||
cd warp-door/ |
|||
make |
|||
cd .. |
|||
} |
|||
|
|||
boy |
|||
buttons |
|||
switches |
|||
doors |
|||
trapdoors |
|||
azulians |
|||
mobs |
|||
objects |
|||
onoff |
|||
warpdoor |
|||
doodad edit-doodad -quiet -lock -author "Noah" ../../assets/doodads/*.doodad |
|||
doodad edit-doodad ../../assets/doodads/azu-blu.doodad |
|||
doodad edit-doodad -hide ../../assets/doodads/boy.doodad |
@ -0,0 +1,19 @@ |
|||
ALL: build |
|||
|
|||
.PHONY: build |
|||
build: |
|||
doodad convert -t "Sticky Button" sticky1.png sticky2.png button-sticky.doodad |
|||
doodad install-script sticky.js button-sticky.doodad |
|||
|
|||
doodad convert -t "Button" button1.png button2.png button.doodad |
|||
doodad install-script button.js button.doodad |
|||
|
|||
doodad convert -t "Button Type B" typeB1.png typeB2.png button-typeB.doodad |
|||
doodad install-script button.js button-typeB.doodad |
|||
|
|||
# Tag the category for these doodads |
|||
for i in *.doodad; do\
|
|||
doodad edit-doodad --tag "category=gizmos" $${i};\
|
|||
done |
|||
|
|||
cp *.doodad ../../../assets/doodads/ |
@ -0,0 +1,12 @@ |
|||
# Button Doodads |
|||
|
|||
```bash |
|||
doodad convert -t "Sticky Button" sticky1.png sticky2.png sticky-button.doodad |
|||
doodad install-script sticky.js sticky-button.doodad |
|||
|
|||
doodad convert -t "Button" button1.png button2.png button.doodad |
|||
doodad install-script button.js button.doodad |
|||
|
|||
doodad convert -t "Button Type B" typeB1.png typeB2.png button-typeB.doodad |
|||
doodad install-script button.js button-typeB.doodad |
|||
``` |
@ -0,0 +1,48 @@ |
|||
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 && !stickyDown) { |
|||
Sound.Play("button-down.wav") |
|||
Message.Publish("power", true); |
|||
pressed = true; |
|||
} |
|||
|
|||
|
|||
if (timer > 0) { |
|||
clearTimeout(timer); |
|||
} |
|||
|
|||
Self.ShowLayer(1); |
|||
timer = setTimeout(function() { |
|||
Sound.Play("button-up.wav") |
|||
Self.ShowLayer(0); |
|||
Message.Publish("power", false); |
|||
timer = 0; |
|||
pressed = false; |
|||
}, 200); |
|||
}); |
|||
} |
After Width: | Height: | Size: 769 B |
After Width: | Height: | Size: 728 B |
@ -0,0 +1,35 @@ |
|||
function main() { |
|||
var pressed = false; |
|||
|
|||
// When a sticky button receives power, it pops back up.
|
|||
Message.Subscribe("power", function (powered) { |
|||
if (powered && pressed) { |
|||
Self.ShowLayer(0); |
|||
pressed = false; |
|||
Sound.Play("button-up.wav") |
|||
Message.Publish("power", false); |
|||
Message.Publish("sticky:down", false); |
|||
} |
|||
}) |
|||
|
|||
Events.OnCollide(function (e) { |
|||
if (!e.Settled) { |
|||
return; |
|||
} |
|||
|
|||
if (pressed) { |
|||
return; |
|||
} |
|||
|
|||
// Verify they've touched the button.
|
|||
if (e.Overlap.Y + e.Overlap.H < 24) { |
|||
return; |
|||
} |
|||
|
|||
Sound.Play("button-down.wav") |
|||
Self.ShowLayer(1); |
|||
pressed = true; |
|||
Message.Publish("power", true); |
|||
Message.Publish("sticky:down", true); |
|||
}); |
|||
} |
After Width: | Height: | Size: 767 B |
After Width: | Height: | Size: 726 B |
After Width: | Height: | Size: 736 B |
After Width: | Height: | Size: 695 B |
@ -0,0 +1,12 @@ |
|||
ALL: build |
|||
|
|||
.PHONY: build |
|||
build: |
|||
doodad convert -t "Crumbly Floor" floor.png shake1.png shake2.png \
|
|||
fall1.png fall2.png fall3.png fall4.png fallen.png \
|
|||
crumbly-floor.doodad |
|||
doodad install-script crumbly-floor.js crumbly-floor.doodad |
|||
for i in *.doodad; do\
|
|||
doodad edit-doodad --tag "category=objects" $${i};\
|
|||
done |
|||
cp *.doodad ../../../assets/doodads/ |
@ -0,0 +1,62 @@ |
|||
// Crumbly Floor.
|
|||
function main() { |
|||
Self.SetHitbox(0, 0, 98, 11); |
|||
|
|||
Self.AddAnimation("shake", 100, ["shake1", "shake2", "floor", "shake1", "shake2", "floor"]); |
|||
Self.AddAnimation("fall", 100, ["fall1", "fall2", "fall3", "fall4"]); |
|||
|
|||
// Recover time for the floor to respawn.
|
|||
var recover = 5000; |
|||
|
|||
// States of the floor.
|
|||
var stateSolid = 0; |
|||
var stateShaking = 1; |
|||
var stateFalling = 2; |
|||
var stateFallen = 3; |
|||
var state = stateSolid; |
|||
|
|||
// Started the animation?
|
|||
var startedAnimation = false; |
|||
|
|||
Events.OnCollide(function(e) { |
|||
|
|||
// If the floor is falling, the player passes right thru.
|
|||
if (state === stateFalling || state === stateFallen) { |
|||
return; |
|||
} |
|||
|
|||
// Floor is solid until it begins to fall.
|
|||
if (e.InHitbox && (state === stateSolid || state === stateShaking)) { |
|||
// Only activate when touched from the top.
|
|||
if (e.Overlap.Y > 0) { |
|||
return false; |
|||
} |
|||
|
|||
// If movement is not settled, be solid.
|
|||
if (!e.Settled) { |
|||
return false; |
|||
} |
|||
|
|||
// Begin the animation sequence if we're in the solid state.
|
|||
if (state === stateSolid) { |
|||
state = stateShaking; |
|||
Self.PlayAnimation("shake", function() { |
|||
state = stateFalling; |
|||
Self.PlayAnimation("fall", function() { |
|||
Sound.Play("crumbly-break.wav") |
|||
state = stateFallen; |
|||
Self.ShowLayerNamed("fallen"); |
|||
|
|||
// Recover after a while.
|
|||
setTimeout(function() { |
|||
Self.ShowLayer(0); |
|||
state = stateSolid; |
|||
}, recover); |
|||
}); |
|||
}) |
|||
} |
|||
|
|||
return false; |
|||
} |
|||
}); |
|||
} |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 5.2 KiB |
After Width: | Height: | Size: 1.0 KiB |
After Width: | Height: | Size: 1.0 KiB |
After Width: | Height: | Size: 1.0 KiB |
@ -0,0 +1,7 @@ |
|||
SHELL = /bin/bash |
|||
|
|||
ALL: build |
|||
|
|||
.PHONY: build |
|||
build: |
|||
./build.sh |
@ -0,0 +1,15 @@ |
|||
# Button Doodads |
|||
|
|||
```bash |
|||
doodad convert -t "Red Door" red1.png red2.png red-door.doodad |
|||
doodad convert -t "Blue Door" blue1.png blue2.png blue-door.doodad |
|||
doodad convert -t "Green Door" green1.png green2.png green-door.doodad |
|||
doodad convert -t "Yellow Door" yellow1.png yellow2.png yellow-door.doodad |
|||
|
|||
doodad convert -t "Red Key" red-key.png red-key.doodad |
|||
doodad convert -t "Blue Key" blue-key.png blue-key.doodad |
|||
doodad convert -t "Green Key" green-key.png green-key.doodad |
|||
doodad convert -t "Yellow Key" yellow-key.png yellow-key.doodad |
|||
|
|||
doodad convert -t "Electric Door" electric{1,2,3,4}.png electric-door.doodad |
|||
``` |
After Width: | Height: | Size: 1.0 KiB |
After Width: | Height: | Size: 732 B |
After Width: | Height: | Size: 892 B |
After Width: | Height: | Size: 884 B |
After Width: | Height: | Size: 906 B |
After Width: | Height: | Size: 787 B |
After Width: | Height: | Size: 743 B |
@ -0,0 +1,52 @@ |
|||
# doodad convert -t "Red Door" red1.png red2.png door-red.doodad |
|||
# doodad edit-doodad -q --tag color=red door-red.doodad |
|||
# doodad install-script locked-door.js door-red.doodad |
|||
|
|||
doodad convert -t "Red Door" red-closed.png red-unlocked.png red-right.png red-left.png door-red.doodad |
|||
doodad edit-doodad -q --tag color=red door-red.doodad |
|||
doodad install-script colored-door.js door-red.doodad |
|||
|
|||
doodad convert -t "Blue Door" blue-closed.png blue-unlocked.png blue-right.png blue-left.png door-blue.doodad |
|||
doodad edit-doodad -q --tag color=blue door-blue.doodad |
|||
doodad install-script colored-door.js door-blue.doodad |
|||
|
|||
doodad convert -t "Green Door" green-closed.png green-unlocked.png green-right.png green-left.png door-green.doodad |
|||
doodad edit-doodad -q --tag color=green door-green.doodad |
|||
doodad install-script colored-door.js door-green.doodad |
|||
|
|||
doodad convert -t "Yellow Door" yellow-closed.png yellow-unlocked.png yellow-right.png yellow-left.png door-yellow.doodad |
|||
doodad edit-doodad -q --tag color=yellow door-yellow.doodad |
|||
doodad install-script colored-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 |
|||
doodad install-script keys.js key-red.doodad |
|||
|
|||
doodad convert -t "Blue Key" blue-key.png key-blue.doodad |
|||
doodad edit-doodad -q --tag color=blue key-blue.doodad |
|||
doodad install-script keys.js key-blue.doodad |
|||
|
|||
doodad convert -t "Green Key" green-key.png key-green.doodad |
|||
doodad edit-doodad -q --tag color=green key-green.doodad |
|||
doodad install-script keys.js key-green.doodad |
|||
|
|||
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 |
|||
|
|||
# Tag the category for these doodads |
|||
for i in *.doodad; do doodad edit-doodad --tag "category=doors" $i; done |
|||
doodad edit-doodad --tag "category=doors,gizmos" door-electric.doodad |
|||
|
|||
cp *.doodad ../../../assets/doodads/ |
@ -0,0 +1,66 @@ |
|||
function main() { |
|||
var color = Self.GetTag("color"); |
|||
var keyname = color === "small" ? "small-key.doodad" : "key-" + color + ".doodad"; |
|||
|
|||
// Layers in the doodad image.
|
|||
var layer = { |
|||
closed: 0, |
|||
unlocked: 1, |
|||
right: 2, |
|||
left: 3, |
|||
}; |
|||
|
|||
// Variables that change in event handler.
|
|||
var unlocked = false; // Key has been used to unlock the door (one time).
|
|||
var opened = false; // If door is currently showing its opened state.
|
|||
var enterSide = 0; // Side of player entering the door, -1 or 1, left or right.
|
|||
|
|||
Self.SetHitbox(34, 0, 13, 76); |
|||
|
|||
Events.OnCollide(function(e) { |
|||
// Record the side that this actor has touched us, in case the door
|
|||
// needs to open.
|
|||
if (enterSide === 0) { |
|||
enterSide = e.Overlap.X > 0 ? 1 : -1; |
|||
} |
|||
|
|||
if (opened) { |
|||
return; |
|||
} |
|||
|
|||
if (e.InHitbox) { |
|||
if (unlocked) { |
|||
Self.ShowLayer(enterSide < 0 ? layer.right : layer.left); |
|||
opened = true; |
|||
Sound.Play("door-open.wav") |
|||
return; |
|||
} |
|||
|
|||
// Do they have our key?
|
|||
var hasKey = e.Actor.HasItem(keyname) >= 0; |
|||
if (!hasKey) { |
|||
// Door is locked.
|
|||
return false; |
|||
} |
|||
|
|||
if (e.Settled) { |
|||
unlocked = true; |
|||
Self.ShowLayer(enterSide < 0 ? layer.right : layer.left); |
|||
Sound.Play("unlock.wav"); |
|||
|
|||
// If a Small Key door, consume a small key.
|
|||
if (color === "small") { |
|||
e.Actor.RemoveItem(keyname, 1) |
|||
} |
|||
} |
|||
} |
|||
}); |
|||
Events.OnLeave(function(e) { |
|||
Self.ShowLayer(unlocked ? layer.unlocked : layer.closed); |
|||
// Sound.Play("door-close.wav")
|
|||
|
|||
// Reset collision state.
|
|||
opened = false; |
|||
enterSide = 0; |
|||
}); |
|||
} |
@ -0,0 +1,66 @@ |
|||
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]); |
|||
|
|||
|
|||
Self.SetHitbox(0, 0, 34, 76); |
|||
|
|||
// 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); |
|||
}) |
|||
|
|||
Message.Subscribe("power", function(powered) { |
|||
if (ignoreNextPower) { |
|||
ignoreNextPower = false; |
|||
return; |
|||
} |
|||
|
|||
setPoweredState(powered); |
|||
}); |
|||
|
|||
Events.OnCollide(function(e) { |
|||
if (e.InHitbox) { |
|||
if (!opened) { |
|||
return false; |
|||
} |
|||
} |
|||
}); |
|||
} |
After Width: | Height: | Size: 10 KiB |
After Width: | Height: | Size: 907 B |
After Width: | Height: | Size: 978 B |
After Width: | Height: | Size: 928 B |
After Width: | Height: | Size: 824 B |
After Width: | Height: | Size: 1.0 KiB |
After Width: | Height: | Size: 714 B |
After Width: | Height: | Size: 875 B |
After Width: | Height: | Size: 880 B |
After Width: | Height: | Size: 888 B |
After Width: | Height: | Size: 734 B |
After Width: | Height: | Size: 742 B |
@ -0,0 +1,14 @@ |
|||
function main() { |
|||
var color = Self.GetTag("color"); |
|||
var quantity = color === "small" ? 1 : 0; |
|||
|
|||
Events.OnCollide(function (e) { |
|||
if (e.Settled) { |
|||
if (e.Actor.HasInventory()) { |
|||
Sound.Play("item-get.wav") |
|||
e.Actor.AddItem(Self.Filename, quantity); |
|||
Self.Destroy(); |
|||
} |
|||
} |
|||
}) |
|||
} |
@ -0,0 +1,27 @@ |
|||
// DEPRECATED: old locked door script. Superceded by colored-door.js.
|
|||
function main() { |
|||
Self.AddAnimation("open", 0, [1]); |
|||
var unlocked = false; |
|||
var color = Self.GetTag("color"); |
|||
|
|||
Self.SetHitbox(16, 0, 32, 64); |
|||
|
|||
Events.OnCollide(function(e) { |
|||
if (unlocked) { |
|||
return; |
|||
} |
|||
|
|||
if (e.InHitbox) { |
|||
var data = e.Actor.GetData("key:" + color); |
|||
if (data === "") { |
|||
// Door is locked.
|
|||
return false; |
|||
} |
|||
|
|||
if (e.Settled) { |
|||
unlocked = true; |
|||
Self.PlayAnimation("open", null); |
|||
} |
|||
} |
|||
}); |
|||
} |
After Width: | Height: | Size: 1010 B |
After Width: | Height: | Size: 699 B |