Split doodads into new repository

pull/84/head
Noah 2022-09-24 15:35:47 -07:00
parent ec0b5ba6ca
commit 83f0a2fb49
293 changed files with 0 additions and 2909 deletions

View File

@ -1,27 +0,0 @@
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
doodad convert -t "White Azulian" white-front.png white-back.png \
white-wr{1,2,3,4}.png white-wl{1,2,3,4}.png azu-white.doodad
doodad edit-doodad --tag "color=white" azu-white.doodad
doodad install-script azulian.js azu-white.doodad
# Tag the category for these doodads
for i in *.doodad; do\
doodad edit-doodad --tag "category=creatures" $${i};\
done
cp *.doodad ../../../assets/doodads/

View File

@ -1,178 +0,0 @@
// Azulian (Red and Blue)
const color = Self.GetTag("color");
var playerSpeed = color === 'blue' ? 2 : 4,
swimSpeed = playerSpeed * 0.4,
aggroX = 250, // X/Y distance sensitivity from player
aggroY = color === 'blue' ? 100 : 200,
jumpSpeed = color === 'blue' ? 14 : 18,
swimJumpSpeed = jumpSpeed * 0.4,
animating = false,
direction = "right",
lastDirection = "right";
// white Azulian is faster yet than the red
if (color === 'white') {
aggroX = 1000;
aggroY = 400;
playerSpeed = 8;
swimSpeed = playerSpeed * 0.4;
jumpSpeed = 20;
swimJumpSpeed = jumpSpeed * 0.4;
}
function setupAnimations(color) {
let left = color === 'blue' ? 'blu-wl' : color + '-wl',
right = color === 'blue' ? 'blu-wr' : color + '-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() {
playerSpeed = color === 'blue' ? 2 : 4;
let swimJumpCooldownTick = 0, // minimum Game Tick before we can jump while swimming
swimJumpCooldown = 10; // CONFIG: delta of ticks between jumps while swimming
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.
let sampleTick = 0;
let sampleRate = 5;
let lastSampledX = 0;
// Get the player on touch.
Events.OnCollide((e) => {
// If we're diving and we hit the player, game over!
// Azulians are friendly to Thieves though!
if (e.Settled && isPlayerFood(e.Actor)) {
FailLevel("Watch out for the Azulians!");
return;
}
});
setInterval(() => {
// If the player is nearby, walk towards them. Otherwise, default pattern
// is to walk back and forth.
let player = Actors.FindPlayer(),
followPlayer = false,
jump = false;
// Don't follow boring players.
if (player !== null && isPlayerFood(player)) {
let playerPt = player.Position(),
myPt = Self.Position();
// If the player is within aggro range, move towards.
if ((Math.abs(playerPt.X - myPt.X) < aggroX && Math.abs(playerPt.Y - myPt.Y) < aggroY)
|| (Level.Difficulty > 0)) {
direction = playerPt.X < myPt.X ? "left" : "right";
followPlayer = true;
if (playerPt.Y + player.Size().H < myPt.Y + Self.Size().H) {
jump = true;
}
}
}
// Default AI: sample position so we turn around on obstacles.
if (!followPlayer) {
if (sampleTick % sampleRate === 0) {
let curX = Self.Position().X;
let delta = Math.abs(curX - lastSampledX);
if (delta < 5) {
direction = direction === "right" ? "left" : "right";
}
lastSampledX = curX;
}
sampleTick++;
}
// Handle being underwater.
let canJump = Self.Grounded();
if (Self.IsWet()) {
let tick = GetTick();
if (tick > swimJumpCooldownTick) {
canJump = true;
swimJumpCooldownTick = tick + swimJumpCooldown;
}
}
// How speedy would our movement and jump be?
let xspeed = playerSpeed, yspeed = jumpSpeed;
if (Self.IsWet()) {
xspeed = swimSpeed;
yspeed = swimJumpSpeed;
}
let Vx = parseFloat(xspeed * (direction === "left" ? -1 : 1)),
Vy = jump && canJump ? parseFloat(-yspeed) : Self.GetVelocity().Y;
Self.SetVelocity(Vector(Vx, Vy));
// 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;
}, 10);
}
function playerControls() {
// Note: player speed is controlled by the engine.
Events.OnKeypress((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;
}
})
}
// Logic to decide if the player is interesting to the Azulian (aka, if the Azulian
// will be hostile towards the player). Boring players will not be chased after and
// the Azulian will not harm them if they make contact.
function isPlayerFood(actor) {
// Not a player or is invulnerable, or Peaceful difficulty.
if (!actor.IsPlayer() || actor.Invulnerable() || Level.Difficulty < 0) {
return false;
}
// On hard mode they are hostile to any player.
if (Level.Difficulty > 0) {
return true;
}
// Azulians are friendly to Thieves and other Azulians.
if (actor.Doodad().Filename === "thief.doodad" || actor.Doodad().Title.indexOf("Azulian") > -1) {
return false;
}
return true;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 864 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 829 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 878 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 910 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 853 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 833 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 820 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 893 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 816 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 844 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 826 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 839 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 803 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 816 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 800 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 819 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 829 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 834 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 815 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 838 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1004 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1002 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 994 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 985 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 999 B

View File

@ -1,22 +0,0 @@
ALL: build
.PHONY: build
build:
doodad convert -t "Bird (red)" red/left-1.png red/left-2.png red/right-1.png \
red/right-2.png red/dive-left.png red/dive-right.png \
bird-red.doodad
doodad install-script bird.js bird-red.doodad
doodad edit-doodad --tag "color=red" bird-red.doodad
doodad convert -t "Bird (blue)" blue/left-1.png blue/left-2.png blue/right-1.png \
blue/right-2.png blue/dive-left.png blue/dive-right.png \
bird-blue.doodad
doodad install-script bird.js bird-blue.doodad
doodad edit-doodad --tag "color=blue" bird-blue.doodad
# Tag the category for these doodads
for i in *.doodad; do\
doodad edit-doodad --tag "category=creatures" $${i};\
done
cp *.doodad ../../../assets/doodads/

View File

@ -1,274 +0,0 @@
// Bird (red and blue)
/*
Base A.I. behaviors (red bird) are:
- Tries to maintain original altitude in level and flies left/right.
- Divebombs the player to attack, then climbs back to its original
altitude when it hits a floor/wall.
Blue bird:
- Flies in a sine wave pattern (its target altitude fluctuates
around the bird's original placement on the level).
- Longer aggro radius to dive.
*/
let speed = 4,
Vx = Vy = 0,
color = Self.GetTag("color"), // informs our A.I. behaviors
searchStep = 12 // pixels to step while searching for a player
searchLimit = color === "blue" ? 24 : 12, // multiples of searchStep for aggro radius
altitude = Self.Position().Y, // original height in level
targetAltitude = altitude; // bird's target height to maintain
let direction = "left",
lastDirection = "left";
let states = {
flying: 0,
diving: 1,
};
let state = states.flying;
function main() {
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((e) => {
// If we're diving and we hit the player, game over!
if (e.Settled && state === states.diving && e.Actor.IsPlayer()) {
FailLevel("Watch out for birds!");
return;
}
if (e.Actor.IsMobile() && e.Actor.HasGravity() && e.InHitbox) {
return false;
}
});
// Sample our X position every few frames and detect if we've hit a solid wall.
let sampleTick = 0,
sampleRate = 2,
lastSampled = Point(0, 0);
setInterval(() => {
// Run blue bird A.I. if we are blue: moves our target altitude along a sine wave.
if (color === "blue") {
AI_BlueBird();
}
// Sample how far we've moved to detect hitting a wall.
if (sampleTick % sampleRate === 0) {
let curP = Self.Position()
let delta = Math.abs(curP.X - lastSampled.X);
if (delta < 5) {
direction = direction === "right" ? "left" : "right";
}
// If we were diving, check Y delta too for if we hit floor
if (state === states.diving && Math.abs(curP.Y - lastSampled.Y) < 5) {
state = states.flying;
}
lastSampled = curP
}
sampleTick++;
// Are we diving?
if (state === states.diving) {
Vy = speed
} else {
// If we are not flying at our original altitude, correct for that.
let curV = Self.Position();
Vy = 0.0;
if (curV.Y != targetAltitude) {
Vy = curV.Y < targetAltitude ? 1 : -1;
}
// Scan for the player character and dive.
try {
AI_ScanForPlayer()
} catch (e) {
console.error("Error in AI_ScanForPlayer: %s", e);
}
}
// TODO: Vector() requires floats, pain in the butt for JS,
// the JS API should be friendlier and custom...
let Vx = parseFloat(speed * (direction === "left" ? -1 : 1));
Self.SetVelocity(Vector(Vx, Vy));
// If diving, exit - don't edit animation.
if (state === states.diving) {
Self.ShowLayerNamed("dive-" + direction);
lastDirection = direction;
return;
}
// 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);
}
// A.I. subroutine: scan for the player character.
// The bird scans in a 45 degree angle downwards, if the
// player is seen nearby in that scan it will begin a dive.
// It's not hostile towards characters that can fly (having
// no gravity).
function AI_ScanForPlayer() {
// If Peaceful difficulty, do not attack.
if (Level.Difficulty < 0) {
return
}
let stepY = searchStep, // number of pixels to skip
stepX = stepY,
limit = stepX * searchLimit, // furthest we'll scan
scanX = scanY = 0,
size = Self.Size(),
fromPoint = Self.Position();
// From what point do we begin the scan?
if (direction === 'left') {
stepX = -stepX;
fromPoint.Y += size.H;
} else {
fromPoint.Y += size.H;
fromPoint.X += size.W;
}
scanX = fromPoint.X;
scanY = fromPoint.Y;
for (let i = 0; i < limit; i += stepY) {
scanX += stepX;
scanY += stepY;
for (let actor of Actors.At(Point(scanX, scanY))) {
if (actor.IsPlayer() && actor.HasGravity()) {
state = states.diving;
return;
}
}
}
return;
}
// Sine wave controls for the Blue bird.
var sineLimit = 32,
sineCounter = 0,
sineDirection = 1,
sineFrequency = 5, // every 500ms
sineStep = 16;
// A.I. Subroutine: sine wave pattern (Blue bird).
function AI_BlueBird() {
// The main loop runs on a 100ms interval, control how frequently
// to adjust the bird's target velocity.
if (sineCounter > 0 && (sineCounter % sineFrequency) > 1) {
sineCounter++;
return;
}
sineCounter++;
targetAltitude += sineStep*sineDirection;
// Cap the distance between our starting altitude and sine-wave target.
if (targetAltitude < altitude && altitude - targetAltitude >= sineLimit) {
targetAltitude = altitude - sineLimit;
sineDirection = 1
} else if (targetAltitude > altitude && targetAltitude - altitude >= sineLimit) {
targetAltitude = altitude + sineLimit;
sineDirection = -1
}
}
// If under control of the player character.
function player() {
let playerSpeed = 12,
diving = false,
falling = false;
// The player can dive by moving downwards and laterally, but
// de-cheese their ability to just sweep across the ground; if
// they aren't seen to be moving downwards, cancel the dive.
let lastPoint = Self.Position();
setInterval(() => {
let nowAt = Self.Position();
if (nowAt.Y > lastPoint.Y) {
falling = true;
} else {
falling = false;
}
lastPoint = nowAt;
}, 100);
Events.OnKeypress((ev) => {
Vx = 0;
Vy = 0;
if (ev.Right) {
direction = "right";
} else if (ev.Left) {
direction = "left";
}
// Dive!
if (ev.Down && ev.Right && falling) {
Self.StopAnimation();
Self.ShowLayerNamed("dive-right");
diving = falling;
} else if (ev.Down && ev.Left && falling) {
Self.StopAnimation();
Self.ShowLayerNamed("dive-left");
diving = falling;
} else if (ev.Right) {
// Fly right.
if (!Self.IsAnimating()) {
Self.PlayAnimation("fly-right", null);
}
Vx = playerSpeed;
diving = false;
} else if (ev.Left) {
// Fly left.
if (!Self.IsAnimating()) {
Self.PlayAnimation("fly-left", null);
}
Vx = -playerSpeed;
diving = false;
} else {
// Hover in place.
if (!Self.IsAnimating()) {
Self.PlayAnimation("fly-" + direction);
}
diving = false;
}
// Player is invulnerable while diving.
Self.SetInvulnerable(diving);
});
Events.OnCollide((e) => {
// If the player is diving at an enemy mob, destroy it.
if (diving && e.Settled && e.Actor.IsMobile() && !e.Actor.Invulnerable()) {
Sound.Play("crumbly-break.wav");
e.Actor.Destroy();
}
});
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 959 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 989 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1022 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

View File

@ -1,13 +0,0 @@
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/

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -1,73 +0,0 @@
// Pushable Box.
const speed = 4,
size = 75;
function main() {
Self.SetMobile(true);
Self.SetInvulnerable(true);
Self.SetGravity(true);
Self.SetHitbox(0, 0, size, size);
Events.OnCollide((e) => {
// Ignore events from neighboring Boxes.
if (e.Actor.Actor.Filename === "box.doodad") {
return false;
}
if (e.Actor.IsMobile() && e.InHitbox) {
let overlap = e.Overlap;
if (overlap.Y === 0 && !(overlap.X === 0 && overlap.W < 5) && !(overlap.X === size)) {
// Be sure to position them snug on top.
// TODO: this might be a nice general solution in the
// collision detector...
e.Actor.MoveTo(Point(
e.Actor.Position().X,
Self.Position().Y - e.Actor.Hitbox().Y - e.Actor.Hitbox().H - 2,
))
e.Actor.SetGrounded(true);
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.
let origPoint = Self.Position();
Message.Subscribe("power", (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]);
let running = false;
setInterval(() => {
if (!running) {
running = true;
Self.PlayAnimation("animate", function () {
running = false;
})
}
}, 100);
}

View File

@ -1,15 +0,0 @@
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 \
idle-right-1.png idle-right-2.png idle-right-3.png \
idle-left-1.png idle-left-2.png idle-left-3.png \
boy.doodad
doodad install-script boy.js boy.doodad
doodad edit-doodad --tag "category=creatures" boy.doodad
cp *.doodad ../../../assets/doodads/

View File

@ -1,62 +0,0 @@
const playerSpeed = 12;
let Vx = Vy = 0,
walking = false,
direction = "right",
lastDirection = direction;
function main() {
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"]);
Self.AddAnimation("idle-left", 200, ["idle-left-1", "idle-left-2", "idle-left-3", "idle-left-2"]);
Self.AddAnimation("idle-right", 200, ["idle-right-1", "idle-right-2", "idle-right-3", "idle-right-2"]);
// If the player suddenly changes direction, reset the animation state to quickly switch over.
let lastVelocity = Vector(0, 0);
Events.OnKeypress((ev) => {
Vx = 0;
Vy = 0;
let curVelocity = Self.GetVelocity();
if ((lastVelocity.X < 0 && curVelocity.X > 0) ||
(lastVelocity.X > 0 && curVelocity.X < 0)) {
Self.StopAnimation();
}
lastVelocity = curVelocity;
lastDirection = direction;
let wasWalking = walking;
if (ev.Right) {
direction = "right";
Vx = playerSpeed;
walking = true;
} else if (ev.Left) {
direction = "left";
Vx = -playerSpeed;
walking = true;
} else {
// Has stopped walking!
walking = false;
stoppedWalking = true;
}
// Should we stop animating? (changed state)
if (direction !== lastDirection || wasWalking !== walking) {
Self.StopAnimation();
}
// And play what animation?
if (!Self.IsAnimating()) {
if (walking) {
Self.PlayAnimation("walk-"+direction, null);
} else {
Self.PlayAnimation("idle-"+direction, null);
}
}
})
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

View File

@ -1,114 +0,0 @@
#!/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 ..
cd gems/
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 ..
}
creatures() {
cd snake/
make
cd ..
cd crusher/
make
cd ..
}
boy
buttons
switches
doors
trapdoors
azulians
mobs
objects
onoff
warpdoor
creatures
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

View File

@ -1,19 +0,0 @@
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/

View File

@ -1,12 +0,0 @@
# 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
```

View File

@ -1,60 +0,0 @@
function main() {
let timer = 0;
let pressed = false;
// Has a linked Sticky Button been pressed permanently down?
let stickyDown = false;
Message.Subscribe("sticky:down", (down) => {
stickyDown = down;
Self.ShowLayer(stickyDown ? 1 : 0);
});
// Track who all is colliding with us.
let colliders = {};
Events.OnCollide((e) => {
if (!e.Settled) {
return;
}
if (colliders[e.Actor.ID()] == undefined) {
colliders[e.Actor.ID()] = true;
}
// 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);
});
Events.OnLeave((e) => {
delete colliders[e.Actor.ID()];
if (Object.keys(colliders).length === 0 && !stickyDown) {
Sound.Play("button-up.wav")
Self.ShowLayer(0);
Message.Publish("power", false);
timer = 0;
pressed = false;
}
});
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 769 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 728 B

View File

@ -1,35 +0,0 @@
function main() {
let pressed = false;
// When a sticky button receives power, it pops back up.
Message.Subscribe("power", (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((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);
});
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 767 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 726 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 736 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 695 B

View File

@ -1,12 +0,0 @@
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/

View File

@ -1,59 +0,0 @@
// 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.
let recover = 5000;
// States of the floor.
let stateSolid = 0;
let stateShaking = 1;
let stateFalling = 2;
let stateFallen = 3;
let state = stateSolid;
Events.OnCollide((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", () => {
state = stateFalling;
Self.PlayAnimation("fall", () => {
Sound.Play("crumbly-break.wav")
state = stateFallen;
Self.ShowLayerNamed("fallen");
// Recover after a while.
setTimeout(() => {
Self.ShowLayer(0);
state = stateSolid;
}, recover);
});
})
}
return false;
}
});
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

View File

@ -1,14 +0,0 @@
ALL: build
.PHONY: build
build:
doodad convert -t "Crusher" sleep.png peek-left.png peek-right.png \
angry.png ouch.png crusher.doodad
doodad install-script crusher.js crusher.doodad
# Tag the category for these doodads
for i in *.doodad; do\
doodad edit-doodad --tag "category=creatures" $${i};\
done
cp *.doodad ../../../assets/doodads/

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

View File

@ -1,207 +0,0 @@
// Crusher
/*
A.I. Behaviors:
- Sleeps and hangs in the air in a high place.
- When a player gets nearby, it begins "peeking" in their direction.
- When the player is below, tries to drop and crush them or any
other mobile doodad.
- The top edge is safe to walk on and ride back up like an elevator.
*/
let direction = "left",
dropSpeed = 12,
riseSpeed = 4,
watchRadius = 300, // player nearby distance to start peeking
fallRadius = 120, // player distance before it drops
helmetThickness = 48, // safe solid hitbox height
fireThickness = 12, // dangerous bottom thickness
targetAltitude = Self.Position()
lastAltitude = targetAltitude.Y
size = Self.Size();
const states = {
idle: 0,
peeking: 1,
drop: 2,
falling: 3,
hit: 4,
rising: 5,
};
let state = states.idle;
function main() {
Self.SetMobile(true);
Self.SetGravity(false);
Self.SetInvulnerable(true);
Self.SetHitbox(5, 2, 90, 73);
Self.AddAnimation("hit", 50,
["angry", "ouch", "angry", "angry", "angry", "angry",
"sleep", "sleep", "sleep", "sleep", "sleep", "sleep",
"sleep", "sleep", "sleep", "sleep", "sleep", "sleep",
"sleep", "sleep", "sleep", "sleep", "sleep", "sleep"],
)
// Player Character controls?
if (Self.IsPlayer()) {
return player();
}
let hitbox = Self.Hitbox();
Events.OnCollide((e) => {
// The bottom is deadly if falling.
if (state === states.falling || state === states.hit && e.Settled) {
if (e.Actor.IsMobile() && e.InHitbox && !e.Actor.Invulnerable()) {
if (e.Overlap.H > 72) {
if (e.Actor.IsPlayer()) {
FailLevel("Don't get crushed!");
return;
} else {
e.Actor.Destroy();
}
}
}
}
// Our top edge is always solid.
if (e.Actor.IsPlayer() && e.InHitbox) {
if (e.Overlap.Y < helmetThickness) {
// Be sure to position them snug on top.
// TODO: this might be a nice general solution in the
// collision detector...
e.Actor.MoveTo(Point(
e.Actor.Position().X,
Self.Position().Y - e.Actor.Hitbox().Y - e.Actor.Hitbox().H,
))
e.Actor.SetGrounded(true);
}
}
// The whole hitbox is ordinarily solid.
if (state !== state.falling) {
if (e.Actor.IsMobile() && e.InHitbox) {
return false;
}
}
});
setInterval(() => {
// Find the player.
let player = Actors.FindPlayer(),
playerPoint = player.Position(),
point = Self.Position(),
delta = 0,
nearby = false,
below = false;
// Face the player.
if (playerPoint.X < point.X + (size.W / 2)) {
direction = "left";
delta = Math.abs(playerPoint.X - (point.X + (size.W/2)));
}
else if (playerPoint.X > point.X + (size.W / 2)) {
direction = "right";
delta = Math.abs(playerPoint.X - (point.X + (size.W/2)));
}
if (delta < watchRadius) {
nearby = true;
}
if (delta < fallRadius) {
// Check if the player is below us.
if (playerPoint.Y > point.Y + size.H) {
below = true;
}
}
switch (state) {
case states.idle:
if (nearby) {
Self.ShowLayerNamed("peek-"+direction);
} else {
Self.ShowLayerNamed("sleep");
}
if (below) {
state = states.drop;
} else if (nearby) {
state = states.peeking;
}
break;
case states.peeking:
if (nearby) {
Self.ShowLayerNamed("peek-"+direction);
} else {
state = states.idle;
break;
}
if (below) {
state = states.drop;
}
break;
case states.drop:
// Begin the fall.
Self.ShowLayerNamed("angry");
Self.SetVelocity(Vector(0.0, dropSpeed));
lastAltitude = -point.Y;
state = states.falling;
case states.falling:
Self.ShowLayerNamed("angry");
Self.SetVelocity(Vector(0.0, dropSpeed));
// Landed?
if (point.Y === lastAltitude) {
Sound.Play("crumbly-break.wav")
state = states.hit;
Self.PlayAnimation("hit", () => {
state = states.rising;
});
}
break;
case states.hit:
// A transitory state while the hit animation
// plays out.
break;
case states.rising:
Self.ShowLayerNamed("sleep");
Self.SetVelocity(Vector(0, -riseSpeed));
point = Self.Position();
if (point.Y <= targetAltitude.Y+4 || point.Y === lastAltitude.Y) {
Self.MoveTo(targetAltitude);
Self.SetVelocity(Vector(0, 0))
state = states.idle;
}
}
lastAltitude = point.Y;
}, 100);
}
// If under control of the player character.
function player() {
Events.OnKeypress((ev) => {
if (ev.Right) {
direction = "right";
} else if (ev.Left) {
direction = "left";
}
// Jump!
if (ev.Down) {
Self.ShowLayerNamed("angry");
return;
} else if (ev.Right && ev.Left) {
Self.ShowLayerNamed("ouch");
} else if (ev.Right || ev.Left) {
Self.ShowLayerNamed("peek-"+direction);
} else {
Self.ShowLayerNamed("sleep");
}
});
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

View File

@ -1,7 +0,0 @@
SHELL = /bin/bash
ALL: build
.PHONY: build
build:
./build.sh

View File

@ -1,15 +0,0 @@
# 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
```

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

Some files were not shown because too many files have changed in this diff Show More