Doodads: Warp Doors, Bird, Larger State Blocks
* The blue and orange ON/OFF state blocks have all been increased in size to better match the player character (42x42 up from 33x33) * Added a new mob: the Red Bird. It flies back and forth while maintaining its altitude, similar to the Red Azulian. Planned AI behavior is to divebomb the player when it gets close. Dive sprites are included but not yet hooked up in JavaScript. * Warp Doors! (WIP). They have a golden "W" on them and come in three varieties: Brown, Blue and Orange. The blue and orange ones are sensitive to the State Block and will become dotted outlines when inactive (and can not be entered in this state). The door opens for the player character, makes him disappear, then closes again. The plan is it will then warp you to the location of a linked Warp Door elsewhere on the level, but for now it will just make the player re-appear after completing the Close Door animation.
54
dev-assets/doodads/bird/bird.js
Normal file
|
@ -0,0 +1,54 @@
|
|||
// Red bird mob.
|
||||
function main() {
|
||||
var speed = 4;
|
||||
var Vx = Vy = 0;
|
||||
var altitude = Self.Position().Y; // original height in the level
|
||||
|
||||
console.log("Bird altitude is %d", altitude);
|
||||
|
||||
var direction = "left";
|
||||
var states = {
|
||||
flying: 0,
|
||||
diving: 1,
|
||||
};
|
||||
var state = states.flying;
|
||||
|
||||
Self.SetMobile(true);
|
||||
Self.SetGravity(false);
|
||||
Self.SetHitbox(0, 10, 46, 32);
|
||||
Self.AddAnimation("fly-left", 100, ["left-1", "left-2"]);
|
||||
Self.AddAnimation("fly-right", 100, ["right-1", "right-2"]);
|
||||
|
||||
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 (!Self.IsAnimating()) {
|
||||
Self.PlayAnimation("fly-"+direction, null);
|
||||
}
|
||||
}, 100);
|
||||
}
|
BIN
dev-assets/doodads/bird/dive-left.png
Normal file
After Width: | Height: | Size: 959 B |
BIN
dev-assets/doodads/bird/dive-right.png
Normal file
After Width: | Height: | Size: 989 B |
BIN
dev-assets/doodads/bird/left-1.png
Normal file
After Width: | Height: | Size: 1.0 KiB |
BIN
dev-assets/doodads/bird/left-2.png
Normal file
After Width: | Height: | Size: 1022 B |
BIN
dev-assets/doodads/bird/right-1.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
dev-assets/doodads/bird/right-2.png
Normal file
After Width: | Height: | Size: 1.0 KiB |
|
@ -98,6 +98,17 @@ azulians() {
|
|||
cd ..
|
||||
}
|
||||
|
||||
mobs() {
|
||||
cd bird/
|
||||
|
||||
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
|
||||
|
||||
cp *.doodad ../../../assets/doodads/
|
||||
cd ..
|
||||
}
|
||||
|
||||
objects() {
|
||||
cd objects/
|
||||
|
||||
|
@ -136,14 +147,38 @@ onoff() {
|
|||
cd ..
|
||||
}
|
||||
|
||||
warpdoor() {
|
||||
cd warp-door/
|
||||
|
||||
doodad convert -t "Warp Door" door-1.png door-2.png door-3.png door-4.png warp-door.doodad
|
||||
doodad edit-doodad -q --tag color=none warp-door.doodad
|
||||
doodad install-script warp-door.js warp-door.doodad
|
||||
|
||||
doodad convert -t "Warp Door (Blue)" blue-1.png blue-2.png blue-3.png blue-4.png blue-off.png \
|
||||
warp-door-blue.doodad
|
||||
doodad edit-doodad -q --tag color=blue warp-door-blue.doodad
|
||||
doodad install-script warp-door.js warp-door-blue.doodad
|
||||
|
||||
doodad convert -t "Warp Door (Orange)" orange-off.png orange-1.png orange-2.png orange-3.png orange-4.png \
|
||||
warp-door-orange.doodad
|
||||
doodad edit-doodad -q --tag color=orange warp-door-orange.doodad
|
||||
doodad install-script warp-door.js warp-door-orange.doodad
|
||||
|
||||
cp *.doodad ../../../assets/doodads/
|
||||
|
||||
cd ..
|
||||
}
|
||||
|
||||
boy
|
||||
buttons
|
||||
switches
|
||||
doors
|
||||
trapdoors
|
||||
azulians
|
||||
mobs
|
||||
objects
|
||||
onoff
|
||||
warpdoor
|
||||
doodad edit-doodad -quiet -lock -author "Noah" ../../assets/doodads/*.doodad
|
||||
doodad edit-doodad -hide ../../assets/doodads/azu-blu.doodad
|
||||
doodad edit-doodad -hide ../../assets/doodads/boy.doodad
|
||||
|
|
Before Width: | Height: | Size: 741 B After Width: | Height: | Size: 785 B |
Before Width: | Height: | Size: 648 B After Width: | Height: | Size: 668 B |
Before Width: | Height: | Size: 683 B After Width: | Height: | Size: 713 B |
Before Width: | Height: | Size: 751 B After Width: | Height: | Size: 805 B |
Before Width: | Height: | Size: 650 B After Width: | Height: | Size: 669 B |
Before Width: | Height: | Size: 687 B After Width: | Height: | Size: 717 B |
|
@ -1,6 +1,6 @@
|
|||
// Blue State Block
|
||||
function main() {
|
||||
Self.SetHitbox(0, 0, 33, 33);
|
||||
Self.SetHitbox(0, 0, 42, 42);
|
||||
|
||||
// Blue block is ON by default.
|
||||
var state = true;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// Orange State Block
|
||||
function main() {
|
||||
Self.SetHitbox(0, 0, 33, 33);
|
||||
Self.SetHitbox(0, 0, 42, 42);
|
||||
|
||||
// Orange block is OFF by default.
|
||||
var state = false;
|
||||
|
|
|
@ -5,7 +5,7 @@ var state = false;
|
|||
|
||||
function main() {
|
||||
console.log("%s ID '%s' initialized!", Self.Title, Self.ID());
|
||||
Self.SetHitbox(0, 0, 33, 33);
|
||||
Self.SetHitbox(0, 0, 42, 42);
|
||||
|
||||
// When the button is activated, don't keep toggling state until we're not
|
||||
// being touched again.
|
||||
|
|
BIN
dev-assets/doodads/warp-door/blue-1.png
Normal file
After Width: | Height: | Size: 850 B |
BIN
dev-assets/doodads/warp-door/blue-2.png
Normal file
After Width: | Height: | Size: 976 B |
BIN
dev-assets/doodads/warp-door/blue-3.png
Normal file
After Width: | Height: | Size: 934 B |
BIN
dev-assets/doodads/warp-door/blue-4.png
Normal file
After Width: | Height: | Size: 807 B |
BIN
dev-assets/doodads/warp-door/blue-off.png
Normal file
After Width: | Height: | Size: 685 B |
BIN
dev-assets/doodads/warp-door/door-1.png
Normal file
After Width: | Height: | Size: 891 B |
BIN
dev-assets/doodads/warp-door/door-2.png
Normal file
After Width: | Height: | Size: 1003 B |
BIN
dev-assets/doodads/warp-door/door-3.png
Normal file
After Width: | Height: | Size: 957 B |
BIN
dev-assets/doodads/warp-door/door-4.png
Normal file
After Width: | Height: | Size: 830 B |
BIN
dev-assets/doodads/warp-door/orange-1.png
Normal file
After Width: | Height: | Size: 832 B |
BIN
dev-assets/doodads/warp-door/orange-2.png
Normal file
After Width: | Height: | Size: 967 B |
BIN
dev-assets/doodads/warp-door/orange-3.png
Normal file
After Width: | Height: | Size: 922 B |
BIN
dev-assets/doodads/warp-door/orange-4.png
Normal file
After Width: | Height: | Size: 803 B |
BIN
dev-assets/doodads/warp-door/orange-off.png
Normal file
After Width: | Height: | Size: 687 B |
81
dev-assets/doodads/warp-door/warp-door.js
Normal file
|
@ -0,0 +1,81 @@
|
|||
// Warp Doors
|
||||
function main() {
|
||||
console.log("Warp Door %s Initialized", Self.Title);
|
||||
|
||||
Self.SetHitbox(0, 0, 34, 76);
|
||||
|
||||
// Are we a blue or orange door? Regular warp door will be 'none'
|
||||
var color = Self.GetTag("color");
|
||||
var isStateDoor = color === 'blue' || color === 'orange';
|
||||
var state = color === 'blue'; // Blue door is ON by default.
|
||||
|
||||
var animating = false;
|
||||
var collide = false;
|
||||
|
||||
// Declare animations and sprite names.
|
||||
var animSpeed = 100;
|
||||
var spriteDefault, spriteDisabled; // the latter for state doors.
|
||||
if (color === 'blue') {
|
||||
Self.AddAnimation("open", animSpeed, ["blue-2", "blue-3", "blue-4"]);
|
||||
Self.AddAnimation("close", animSpeed, ["blue-4", "blue-3", "blue-2", "blue-1"]);
|
||||
spriteDefault = "blue-1";
|
||||
spriteDisabled = "blue-off";
|
||||
} else if (color === 'orange') {
|
||||
Self.AddAnimation("open", animSpeed, ["orange-2", "orange-3", "orange-4"]);
|
||||
Self.AddAnimation("close", animSpeed, ["orange-4", "orange-3", "orange-2", "orange-1"]);
|
||||
spriteDefault = "orange-1";
|
||||
spriteDisabled = "orange-off";
|
||||
} else {
|
||||
Self.AddAnimation("open", animSpeed, ["door-2", "door-3", "door-4"]);
|
||||
Self.AddAnimation("close", animSpeed, ["door-4", "door-3", "door-2", "door-1"]);
|
||||
spriteDefault = "door-1";
|
||||
}
|
||||
|
||||
console.log("Warp %s: default=%s disabled=%+v color=%s isState=%+v state=%+v", Self.Title, spriteDefault, spriteDisabled, color, isStateDoor, state);
|
||||
|
||||
// Subscribe to the global state-change if we are a state door.
|
||||
if (isStateDoor) {
|
||||
Message.Subscribe("broadcast:state-change", function(newState) {
|
||||
console.log("Warp %s: received state to %+v", Self.Title, newState);
|
||||
state = color === 'blue' ? !newState : newState;
|
||||
|
||||
// Activate or deactivate the door.
|
||||
Self.ShowLayerNamed(state ? spriteDefault : spriteDisabled);
|
||||
});
|
||||
}
|
||||
|
||||
// TODO: respond to a "Use" button instead of a Collide to open the door.
|
||||
Events.OnCollide(function(e) {
|
||||
if (!e.Settled) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (animating || collide) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Only players can use doors for now.
|
||||
if (e.Actor.IsPlayer() && e.InHitbox) {
|
||||
if (isStateDoor && !state) {
|
||||
// The state door is inactive (dotted outline).
|
||||
return;
|
||||
}
|
||||
|
||||
// Play the open and close animation.
|
||||
animating = true;
|
||||
collide = true;
|
||||
Self.PlayAnimation("open", function() {
|
||||
e.Actor.Hide()
|
||||
Self.PlayAnimation("close", function() {
|
||||
Self.ShowLayerNamed(isStateDoor && !state ? spriteDisabled : spriteDefault);
|
||||
e.Actor.Show()
|
||||
animating = false;
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
Events.OnLeave(function(e) {
|
||||
collide = false;
|
||||
});
|
||||
}
|