Noah Petherbridge
9a51ac39f9
* New doodad: Invisible Warp Door * All warp doors require the player to be grounded (if affected by gravity) to open them. No jumping or falling thru and opening a warp door mid-air! * Title Screen now randomly selects from a couple of levels. * Title Screen: if it fails to load a level it sets up a basic blank level with a wallpaper instead. * New developer shell command: titlescreen <level> Opens the MainScene with a custom user level as the background. * Add Auto-save to the Editor to save your drawing every 5 minutes * Add a MenuBar to the Play Scene for easier navigation to other features of the game. * Doodad JS API: time.Since() now available.
158 lines
4.6 KiB
JavaScript
158 lines
4.6 KiB
JavaScript
// Warp Doors
|
|
function main() {
|
|
// 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 if (color === 'invisible') {
|
|
// Invisible Warp Door region.
|
|
Self.Hide();
|
|
Self.AddAnimation("open", animSpeed, [0, 0]);
|
|
Self.AddAnimation("close", animSpeed, [0, 0]);
|
|
} 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";
|
|
}
|
|
|
|
// Find our linked Warp Door.
|
|
var links = Self.GetLinks()
|
|
var linkedDoor = null;
|
|
for (var i = 0; i < links.length; i++) {
|
|
if (links[i].Title.indexOf("Warp Door") > -1) {
|
|
linkedDoor = links[i];
|
|
}
|
|
}
|
|
|
|
// Subscribe to the global state-change if we are a state door.
|
|
if (isStateDoor) {
|
|
Message.Subscribe("broadcast:state-change", function(newState) {
|
|
state = color === 'blue' ? !newState : newState;
|
|
|
|
// Activate or deactivate the door.
|
|
Self.ShowLayerNamed(state ? spriteDefault : spriteDisabled);
|
|
});
|
|
}
|
|
|
|
// For player groundedness work-around
|
|
var playerLastY = []; // last sampling of Y values
|
|
var lastUsed = time.Now();
|
|
|
|
// The player Uses the door.
|
|
var flashedCooldown = false; // "Locked Door" flashed message.
|
|
Events.OnUse(function(e) {
|
|
if (animating) {
|
|
return;
|
|
}
|
|
|
|
// Doors without linked exits are not usable.
|
|
if (linkedDoor === null) {
|
|
if (!flashedCooldown) {
|
|
Flash("This door is locked.");
|
|
flashedCooldown = true;
|
|
setTimeout(function() {
|
|
flashedCooldown = false;
|
|
}, 1000);
|
|
}
|
|
return;
|
|
}
|
|
|
|
// Only players can use doors for now.
|
|
if (e.Actor.IsPlayer()) {
|
|
if (isStateDoor && !state) {
|
|
// The state door is inactive (dotted outline).
|
|
return;
|
|
}
|
|
|
|
// The player must be grounded or have no gravity to open the door.
|
|
if (!e.Actor.Grounded() && e.Actor.HasGravity()) {
|
|
// Work-around: if two Boxes are stacked atop each other the player can
|
|
// get stuck if he jumps on top. He may not be Grounded but isn't changing
|
|
// effective Y position and a warp door may work as a good way out.
|
|
var yValue = e.Actor.Position().Y;
|
|
|
|
// Collect a sampling of last few Y values. If the player Y position
|
|
// is constant the last handful of frames, treat them as if they're
|
|
// grounded (or else they can't activate the warp door).
|
|
playerLastY.unshift(yValue);
|
|
if (playerLastY.length < 6) {
|
|
return;
|
|
}
|
|
|
|
// We have enough history.
|
|
playerLastY.pop();
|
|
|
|
// Hasn't moved?
|
|
var isGrounded = true;
|
|
for (var i = 0; i < playerLastY.length; i++) {
|
|
if (yValue !== playerLastY[i]) {
|
|
isGrounded = false;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!isGrounded) {
|
|
return;
|
|
}
|
|
|
|
// Player was effectively grounded! No change in Y position.
|
|
}
|
|
|
|
// Freeze the player.
|
|
e.Actor.Freeze()
|
|
|
|
// Play the open and close animation.
|
|
animating = true;
|
|
Self.PlayAnimation("open", function() {
|
|
e.Actor.Hide()
|
|
Self.PlayAnimation("close", function() {
|
|
Self.ShowLayerNamed(isStateDoor && !state ? spriteDisabled : spriteDefault);
|
|
animating = false;
|
|
|
|
// Teleport the player to the linked door. Inform the target
|
|
// door of the arrival of the player so it doesn't trigger
|
|
// to send the player back here again on a loop.
|
|
if (linkedDoor !== null) {
|
|
Message.Publish("warp-door:incoming", e.Actor);
|
|
e.Actor.MoveTo(linkedDoor.Position());
|
|
}
|
|
});
|
|
});
|
|
}
|
|
});
|
|
|
|
// Respond to incoming warp events.
|
|
Message.Subscribe("warp-door:incoming", function(player) {
|
|
animating = true;
|
|
player.Unfreeze();
|
|
Self.PlayAnimation("open", function() {
|
|
player.Show();
|
|
Self.PlayAnimation("close", function() {
|
|
animating = false;
|
|
|
|
// If the receiving door was a State Door, fix its state.
|
|
if (isStateDoor) {
|
|
Self.ShowLayerNamed(state ? spriteDefault : spriteDisabled);
|
|
}
|
|
});
|
|
});
|
|
});
|
|
}
|