mirror of
https://github.com/genxium/DelayNoMore
synced 2024-12-28 04:28:04 +00:00
338 lines
15 KiB
JavaScript
338 lines
15 KiB
JavaScript
const COLLISION_WITH_PLAYER_STATE = {
|
|
WALKING_COLLIDABLE: 0,
|
|
STILL_NEAR_SELF_PLAYER_ONLY_PLAYING_ANIM: 1,
|
|
STILL_NEAR_SELF_PLAYER_ONLY_PLAYED_ANIM: 2,
|
|
STILL_NEAR_OTHER_PLAYER_ONLY_PLAYING_ANIM: 3,
|
|
STILL_NEAR_OTHER_PLAYER_ONLY_PLAYED_ANIM: 4,
|
|
STILL_NEAR_SELF_PLAYER_NEAR_OTHER_PLAYER_PLAYING_ANIM: 5,
|
|
STILL_NEAR_SELF_PLAYER_NEAR_OTHER_PLAYER_PLAYED_ANIM: 6,
|
|
WALKING_COLLIDABLE_WITH_SELF_PLAYER_BUT_NOT_OTHER_PLAYER: 7,
|
|
STILL_NEAR_NOBODY_PLAYING_ANIM: 8,
|
|
};
|
|
|
|
const STILL_NEAR_SELF_PLAYER_STATE_SET = new Set();
|
|
STILL_NEAR_SELF_PLAYER_STATE_SET.add(COLLISION_WITH_PLAYER_STATE.STILL_NEAR_SELF_PLAYER_ONLY_PLAYING_ANIM);
|
|
STILL_NEAR_SELF_PLAYER_STATE_SET.add(COLLISION_WITH_PLAYER_STATE.STILL_NEAR_SELF_PLAYER_ONLY_PLAYED_ANIM);
|
|
STILL_NEAR_SELF_PLAYER_STATE_SET.add(COLLISION_WITH_PLAYER_STATE.STILL_NEAR_SELF_PLAYER_NEAR_OTHER_PLAYER_PLAYING_ANIM);
|
|
STILL_NEAR_SELF_PLAYER_STATE_SET.add(COLLISION_WITH_PLAYER_STATE.STILL_NEAR_SELF_PLAYER_NEAR_OTHER_PLAYER_PLAYED_ANIM);
|
|
|
|
const STILL_NEAR_OTHER_PLAYER_STATE_SET = new Set();
|
|
STILL_NEAR_OTHER_PLAYER_STATE_SET.add(COLLISION_WITH_PLAYER_STATE.STILL_NEAR_OTHER_PLAYER_ONLY_PLAYING_ANIM);
|
|
STILL_NEAR_OTHER_PLAYER_STATE_SET.add(COLLISION_WITH_PLAYER_STATE.STILL_NEAR_OTHER_PLAYER_ONLY_PLAYED_ANIM);
|
|
STILL_NEAR_OTHER_PLAYER_STATE_SET.add(COLLISION_WITH_PLAYER_STATE.STILL_NEAR_SELF_PLAYER_NEAR_OTHER_PLAYER_PLAYING_ANIM);
|
|
STILL_NEAR_OTHER_PLAYER_STATE_SET.add(COLLISION_WITH_PLAYER_STATE.STILL_NEAR_SELF_PLAYER_NEAR_OTHER_PLAYER_PLAYED_ANIM);
|
|
|
|
const STILL_SHOULD_NOT_PLAY_STUNNED_ANIM_SET = new Set();
|
|
STILL_SHOULD_NOT_PLAY_STUNNED_ANIM_SET.add(COLLISION_WITH_PLAYER_STATE.STILL_NEAR_SELF_PLAYER_ONLY_PLAYING_ANIM);
|
|
STILL_SHOULD_NOT_PLAY_STUNNED_ANIM_SET.add(COLLISION_WITH_PLAYER_STATE.STILL_NEAR_SELF_PLAYER_ONLY_PLAYED_ANIM);
|
|
STILL_SHOULD_NOT_PLAY_STUNNED_ANIM_SET.add(COLLISION_WITH_PLAYER_STATE.STILL_NEAR_OTHER_PLAYER_ONLY_PLAYING_ANIM);
|
|
STILL_SHOULD_NOT_PLAY_STUNNED_ANIM_SET.add(COLLISION_WITH_PLAYER_STATE.STILL_NEAR_OTHER_PLAYER_ONLY_PLAYED_ANIM);
|
|
STILL_SHOULD_NOT_PLAY_STUNNED_ANIM_SET.add(COLLISION_WITH_PLAYER_STATE.STILL_NEAR_SELF_PLAYER_NEAR_OTHER_PLAYER_PLAYING_ANIM);
|
|
STILL_SHOULD_NOT_PLAY_STUNNED_ANIM_SET.add(COLLISION_WITH_PLAYER_STATE.STILL_NEAR_SELF_PLAYER_NEAR_OTHER_PLAYER_PLAYED_ANIM);
|
|
STILL_SHOULD_NOT_PLAY_STUNNED_ANIM_SET.add(COLLISION_WITH_PLAYER_STATE.STILL_NEAR_NOBODY_PLAYING_ANIM);
|
|
|
|
function transitWalkingConditionallyCollidableToUnconditionallyCollidable(currentCollisionWithPlayerState) {
|
|
switch (currentCollisionWithPlayerState) {
|
|
case COLLISION_WITH_PLAYER_STATE.WALKING_COLLIDABLE_WITH_SELF_PLAYER_BUT_NOT_OTHER_PLAYER:
|
|
return COLLISION_WITH_PLAYER_STATE.WALKING_COLLIDABLE;
|
|
}
|
|
|
|
return currentCollisionWithPlayerState;
|
|
}
|
|
|
|
function transitUponSelfPlayerLeftProximityArea(currentCollisionWithPlayerState) {
|
|
switch (currentCollisionWithPlayerState) {
|
|
case COLLISION_WITH_PLAYER_STATE.STILL_NEAR_SELF_PLAYER_ONLY_PLAYING_ANIM:
|
|
return COLLISION_WITH_PLAYER_STATE.STILL_NEAR_NOBODY_PLAYING_ANIM;
|
|
|
|
case COLLISION_WITH_PLAYER_STATE.STILL_NEAR_SELF_PLAYER_ONLY_PLAYED_ANIM:
|
|
return COLLISION_WITH_PLAYER_STATE.WALKING_COLLIDABLE;
|
|
|
|
case COLLISION_WITH_PLAYER_STATE.STILL_NEAR_SELF_PLAYER_NEAR_OTHER_PLAYER_PLAYING_ANIM:
|
|
return COLLISION_WITH_PLAYER_STATE.STILL_NEAR_OTHER_PLAYER_ONLY_PLAYING_ANIM;
|
|
|
|
case COLLISION_WITH_PLAYER_STATE.STILL_NEAR_SELF_PLAYER_NEAR_OTHER_PLAYER_PLAYED_ANIM:
|
|
return COLLISION_WITH_PLAYER_STATE.WALKING_COLLIDABLE_WITH_SELF_PLAYER_BUT_NOT_OTHER_PLAYER;
|
|
}
|
|
return currentCollisionWithPlayerState;
|
|
}
|
|
|
|
function transitDueToNoBodyInProximityArea(currentCollisionWithPlayerState) {
|
|
switch (currentCollisionWithPlayerState) {
|
|
case COLLISION_WITH_PLAYER_STATE.STILL_NEAR_SELF_PLAYER_ONLY_PLAYING_ANIM:
|
|
case COLLISION_WITH_PLAYER_STATE.STILL_NEAR_OTHER_PLAYER_ONLY_PLAYING_ANIM:
|
|
case COLLISION_WITH_PLAYER_STATE.STILL_NEAR_SELF_PLAYER_NEAR_OTHER_PLAYER_PLAYING_ANIM:
|
|
return COLLISION_WITH_PLAYER_STATE.STILL_NEAR_NOBODY_PLAYING_ANIM;
|
|
|
|
case COLLISION_WITH_PLAYER_STATE.STILL_NEAR_SELF_PLAYER_ONLY_PLAYED_ANIM:
|
|
case COLLISION_WITH_PLAYER_STATE.STILL_NEAR_OTHER_PLAYER_ONLY_PLAYED_ANIM:
|
|
case COLLISION_WITH_PLAYER_STATE.STILL_NEAR_SELF_PLAYER_NEAR_OTHER_PLAYER_PLAYED_ANIM:
|
|
return COLLISION_WITH_PLAYER_STATE.WALKING_COLLIDABLE_WITH_SELF_PLAYER_BUT_NOT_OTHER_PLAYER;
|
|
}
|
|
return currentCollisionWithPlayerState;
|
|
}
|
|
|
|
function transitToPlayingStunnedAnim(currentCollisionWithPlayerState, dueToSelfPlayer, dueToOtherPlayer) {
|
|
if (dueToSelfPlayer) {
|
|
switch (currentCollisionWithPlayerState) {
|
|
case COLLISION_WITH_PLAYER_STATE.WALKING_COLLIDABLE:
|
|
case COLLISION_WITH_PLAYER_STATE.WALKING_COLLIDABLE_WITH_SELF_PLAYER_BUT_NOT_OTHER_PLAYER:
|
|
return COLLISION_WITH_PLAYER_STATE.STILL_NEAR_SELF_PLAYER_ONLY_PLAYING_ANIM;
|
|
}
|
|
}
|
|
|
|
if (dueToOtherPlayer) {
|
|
switch (currentCollisionWithPlayerState) {
|
|
case COLLISION_WITH_PLAYER_STATE.WALKING_COLLIDABLE:
|
|
return COLLISION_WITH_PLAYER_STATE.STILL_NEAR_OTHER_PLAYER_ONLY_PLAYING_ANIM;
|
|
}
|
|
}
|
|
// TODO: Any error to throw?
|
|
return currentCollisionWithPlayerState;
|
|
}
|
|
|
|
function transitDuringPlayingStunnedAnim(currentCollisionWithPlayerState, dueToSelfPlayerComesIntoProximity, dueToOtherPlayerComesIntoProximity) {
|
|
if (dueToSelfPlayerComesIntoProximity) {
|
|
switch (currentCollisionWithPlayerState) {
|
|
case COLLISION_WITH_PLAYER_STATE.STILL_NEAR_OTHER_PLAYER_ONLY_PLAYING_ANIM:
|
|
return COLLISION_WITH_PLAYER_STATE.STILL_NEAR_SELF_PLAYER_NEAR_OTHER_PLAYER_PLAYING_ANIM;
|
|
|
|
case COLLISION_WITH_PLAYER_STATE.STILL_NEAR_NOBODY_PLAYING_ANIM:
|
|
return COLLISION_WITH_PLAYER_STATE.STILL_NEAR_SELF_PLAYER_ONLY_PLAYING_ANIM;
|
|
}
|
|
}
|
|
|
|
if (dueToOtherPlayerComesIntoProximity) {
|
|
switch (currentCollisionWithPlayerState) {
|
|
case COLLISION_WITH_PLAYER_STATE.STILL_NEAR_SELF_PLAYER_ONLY_PLAYING_ANIM:
|
|
return COLLISION_WITH_PLAYER_STATE.STILL_NEAR_SELF_PLAYER_NEAR_OTHER_PLAYER_PLAYING_ANIM;
|
|
|
|
case COLLISION_WITH_PLAYER_STATE.STILL_NEAR_NOBODY_PLAYING_ANIM:
|
|
return COLLISION_WITH_PLAYER_STATE.STILL_NEAR_OTHER_PLAYER_ONLY_PLAYING_ANIM;
|
|
}
|
|
}
|
|
// TODO: Any error to throw?
|
|
return currentCollisionWithPlayerState;
|
|
}
|
|
|
|
function transitStunnedAnimPlayingToPlayed(currentCollisionWithPlayerState, forceNotCollidableWithOtherPlayer) {
|
|
switch (currentCollisionWithPlayerState) {
|
|
case COLLISION_WITH_PLAYER_STATE.STILL_NEAR_SELF_PLAYER_ONLY_PLAYING_ANIM:
|
|
return COLLISION_WITH_PLAYER_STATE.STILL_NEAR_SELF_PLAYER_ONLY_PLAYED_ANIM;
|
|
|
|
case COLLISION_WITH_PLAYER_STATE.STILL_NEAR_OTHER_PLAYER_ONLY_PLAYING_ANIM:
|
|
return COLLISION_WITH_PLAYER_STATE.STILL_NEAR_OTHER_PLAYER_ONLY_PLAYED_ANIM;
|
|
|
|
case COLLISION_WITH_PLAYER_STATE.STILL_NEAR_SELF_PLAYER_NEAR_OTHER_PLAYER_PLAYING_ANIM:
|
|
return COLLISION_WITH_PLAYER_STATE.STILL_NEAR_SELF_PLAYER_NEAR_OTHER_PLAYER_PLAYED_ANIM;
|
|
|
|
case COLLISION_WITH_PLAYER_STATE.STILL_NEAR_NOBODY_PLAYING_ANIM:
|
|
return (true == forceNotCollidableWithOtherPlayer ? COLLISION_WITH_PLAYER_STATE.WALKING_COLLIDABLE_WITH_SELF_PLAYER_BUT_NOT_OTHER_PLAYER : COLLISION_WITH_PLAYER_STATE.WALKING_COLLIDABLE);
|
|
}
|
|
// TODO: Any error to throw?
|
|
return currentCollisionWithPlayerState;
|
|
}
|
|
|
|
function transitStunnedAnimPlayedToWalking(currentCollisionWithPlayerState) {
|
|
/*
|
|
* Intentionally NOT transiting for
|
|
*
|
|
* - STILL_NEAR_SELF_PLAYER_NEAR_OTHER_PLAYER_PLAYED_ANIM, or
|
|
* - STILL_NEAR_SELF_PLAYER_ONLY_PLAYED_ANIM,
|
|
*
|
|
* which should be transited upon leaving of "SelfPlayer".
|
|
*/
|
|
switch (currentCollisionWithPlayerState) {
|
|
case COLLISION_WITH_PLAYER_STATE.STILL_NEAR_OTHER_PLAYER_ONLY_PLAYED_ANIM:
|
|
return COLLISION_WITH_PLAYER_STATE.WALKING_COLLIDABLE_WITH_SELF_PLAYER_BUT_NOT_OTHER_PLAYER;
|
|
}
|
|
// TODO: Any error to throw?
|
|
return currentCollisionWithPlayerState;
|
|
}
|
|
|
|
const BasePlayer = require("./BasePlayer");
|
|
|
|
cc.Class({
|
|
extends: BasePlayer,
|
|
|
|
// LIFE-CYCLE CALLBACKS:
|
|
start() {
|
|
BasePlayer.prototype.start.call(this);
|
|
|
|
this.scheduleNewDirection(this._generateRandomDirectionExcluding(0, 0));
|
|
},
|
|
|
|
onLoad() {
|
|
BasePlayer.prototype.onLoad.call(this);
|
|
const self = this;
|
|
|
|
this.collisionWithPlayerState = COLLISION_WITH_PLAYER_STATE.WALKING_COLLIDABLE;
|
|
|
|
this.clips = {
|
|
'01': 'FlatHeadSisterRunTop',
|
|
'0-1': 'FlatHeadSisterRunBottom',
|
|
'-20': 'FlatHeadSisterRunLeft',
|
|
'20': 'FlatHeadSisterRunRight',
|
|
'-21': 'FlatHeadSisterRunTopLeft',
|
|
'21': 'FlatHeadSisterRunTopRight',
|
|
'-2-1': 'FlatHeadSisterRunBottomLeft',
|
|
'2-1': 'FlatHeadSisterRunBottomRight'
|
|
};
|
|
|
|
|
|
self.onStunnedAnimPlayedSafe = () => {
|
|
const oldCollisionWithPlayerState = self.collisionWithPlayerState;
|
|
self.collisionWithPlayerState = transitStunnedAnimPlayingToPlayed(this.collisionWithPlayerState, true);
|
|
if (oldCollisionWithPlayerState == self.collisionWithPlayerState || !self.node) return;
|
|
|
|
// TODO: Be more specific with "toExcludeDx" and "toExcludeDy".
|
|
self.scheduleNewDirection(self._generateRandomDirectionExcluding(0, 0));
|
|
self.collisionWithPlayerState = transitStunnedAnimPlayedToWalking(self.collisionWithPlayerState);
|
|
setTimeout(() => {
|
|
self.collisionWithPlayerState = transitWalkingConditionallyCollidableToUnconditionallyCollidable(self.collisionWithPlayerState);
|
|
}, 5000);
|
|
};
|
|
|
|
self.onStunnedAnimPlayedSafeAction = cc.callFunc(self.onStunnedAnimPlayedSafe, self);
|
|
|
|
self.playStunnedAnim = () => {
|
|
let colliededAction1 = cc.rotateTo(0.2, -15);
|
|
let colliededAction2 = cc.rotateTo(0.3, 15);
|
|
let colliededAction3 = cc.rotateTo(0.2, 0);
|
|
|
|
self.node.runAction(cc.sequence(
|
|
cc.callFunc(() => {
|
|
self.player.pause()
|
|
}, self),
|
|
colliededAction1,
|
|
colliededAction2,
|
|
colliededAction3,
|
|
cc.callFunc(() => {
|
|
self.player.resume()
|
|
}, self),
|
|
self.onStunnedAnimPlayedSafeAction
|
|
));
|
|
|
|
// NOTE: Use <cc.Animation>.on('stop', self.onStunnedAnimPlayedSafe) if necessary.
|
|
}
|
|
},
|
|
|
|
_canMoveBy(vecToMoveBy) {
|
|
if (COLLISION_WITH_PLAYER_STATE.WALKING_COLLIDABLE_WITH_SELF_PLAYER_BUT_NOT_OTHER_PLAYER != this.collisionWithPlayerState && COLLISION_WITH_PLAYER_STATE.WALKING_COLLIDABLE != this.collisionWithPlayerState) {
|
|
return false;
|
|
}
|
|
|
|
const superRet = BasePlayer.prototype._canMoveBy.call(this, vecToMoveBy);
|
|
const self = this;
|
|
|
|
const computedNewDifferentPosLocalToParentWithinCurrentFrame = self.node.position.add(vecToMoveBy);
|
|
|
|
const currentSelfColliderCircle = self.node.getComponent("cc.CircleCollider");
|
|
let nextSelfColliderCircle = null;
|
|
if (0 < self.contactedBarriers.length || 0 < self.contactedNPCPlayers.length || 0 < self.contactedControlledPlayers) {
|
|
/* To avoid unexpected buckling. */
|
|
const mutatedVecToMoveBy = vecToMoveBy.mul(2);
|
|
nextSelfColliderCircle = {
|
|
position: self.node.position.add(vecToMoveBy.mul(2)).add(currentSelfColliderCircle.offset),
|
|
radius: currentSelfColliderCircle.radius,
|
|
};
|
|
} else {
|
|
nextSelfColliderCircle = {
|
|
position: computedNewDifferentPosLocalToParentWithinCurrentFrame.add(currentSelfColliderCircle.offset),
|
|
radius: currentSelfColliderCircle.radius,
|
|
};
|
|
}
|
|
|
|
for (let aCircleCollider of self.contactedControlledPlayers) {
|
|
let contactedCircleLocalToParentWithinCurrentFrame = {
|
|
position: aCircleCollider.node.position.add(aCircleCollider.offset),
|
|
radius: aCircleCollider.radius,
|
|
};
|
|
if (cc.Intersection.circleCircle(contactedCircleLocalToParentWithinCurrentFrame, nextSelfColliderCircle)) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return superRet;
|
|
},
|
|
|
|
update(dt) {
|
|
const self = this;
|
|
|
|
BasePlayer.prototype.update.call(this, dt);
|
|
|
|
if (0 < self.contactedBarriers.length) {
|
|
self.scheduleNewDirection(self._generateRandomDirectionExcluding(self.scheduledDirection.dx, self.scheduledDirection.dy));
|
|
}
|
|
|
|
if (tileCollisionManager.isOutOfMapNode(self.mapNode, self.computedNewDifferentPosLocalToParentWithinCurrentFrame)) {
|
|
self.scheduleNewDirection(self._generateRandomDirectionExcluding(self.scheduledDirection.dx, self.scheduledDirection.dy));
|
|
}
|
|
},
|
|
|
|
onCollisionEnter(other, self) {
|
|
BasePlayer.prototype.onCollisionEnter.call(this, other, self);
|
|
const playerScriptIns = self.getComponent(self.node.name);
|
|
switch (other.node.name) {
|
|
case "SelfPlayer":
|
|
playerScriptIns._addContactedControlledPlayers(other);
|
|
if (1 == playerScriptIns.contactedControlledPlayers.length) {
|
|
// When "SelfPlayer" comes into proximity area.
|
|
if (!STILL_SHOULD_NOT_PLAY_STUNNED_ANIM_SET.has(playerScriptIns.collisionWithPlayerState)) {
|
|
playerScriptIns.collisionWithPlayerState = transitToPlayingStunnedAnim(playerScriptIns.collisionWithPlayerState, true, false);
|
|
playerScriptIns.playStunnedAnim();
|
|
} else {
|
|
playerScriptIns.collisionWithPlayerState = transitDuringPlayingStunnedAnim(playerScriptIns.collisionWithPlayerState, true, false);
|
|
}
|
|
}
|
|
break;
|
|
case "NPCPlayer":
|
|
if (1 == playerScriptIns.contactedNPCPlayers.length) {
|
|
// When one of the other "OtherPlayer"s comes into proximity area.
|
|
if (!STILL_SHOULD_NOT_PLAY_STUNNED_ANIM_SET.has(playerScriptIns.collisionWithPlayerState)) {
|
|
const oldState = playerScriptIns.collisionWithPlayerState;
|
|
playerScriptIns.collisionWithPlayerState = transitToPlayingStunnedAnim(oldState, false, true);
|
|
if (playerScriptIns.collisionWithPlayerState != oldState) {
|
|
playerScriptIns.playStunnedAnim();
|
|
}
|
|
} else {
|
|
playerScriptIns.collisionWithPlayerState = transitDuringPlayingStunnedAnim(playerScriptIns.collisionWithPlayerState, false, true);
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
},
|
|
|
|
onCollisionStay(other, self) {
|
|
// TBD.
|
|
},
|
|
|
|
onCollisionExit(other, self) {
|
|
BasePlayer.prototype.onCollisionExit.call(this, other, self);
|
|
const playerScriptIns = self.getComponent(self.node.name);
|
|
switch (other.node.name) {
|
|
case "SelfPlayer":
|
|
playerScriptIns._removeContactedControlledPlayer(other);
|
|
if (0 == playerScriptIns.contactedControlledPlayers.length) {
|
|
// Special release step.
|
|
if (STILL_NEAR_SELF_PLAYER_STATE_SET.has(playerScriptIns.collisionWithPlayerState)) {
|
|
playerScriptIns.collisionWithPlayerState = transitUponSelfPlayerLeftProximityArea(playerScriptIns.collisionWithPlayerState);
|
|
}
|
|
}
|
|
if (0 == playerScriptIns.contactedControlledPlayers.length && 0 == playerScriptIns.contactedNPCPlayers.length) {
|
|
transitDueToNoBodyInProximityArea(playerScriptIns.collisionWithPlayerState);
|
|
}
|
|
break;
|
|
case "NPCPlayer":
|
|
if (0 == playerScriptIns.contactedControlledPlayers.length && 0 == playerScriptIns.contactedNPCPlayers.length) {
|
|
transitDueToNoBodyInProximityArea(playerScriptIns.collisionWithPlayerState);
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
},
|
|
});
|