mirror of
https://github.com/genxium/DelayNoMore
synced 2024-12-26 19:58:56 +00:00
A temp broken commit except for OfflineMap - refactoring character/skill/bullet config hierarchy.
This commit is contained in:
parent
c7fc377a2b
commit
8b80117d3d
File diff suppressed because one or more lines are too long
@ -97,9 +97,9 @@ message MeleeBullet {
|
|||||||
// for defender
|
// for defender
|
||||||
int32 hitStunFrames = 9;
|
int32 hitStunFrames = 9;
|
||||||
int32 blockStunFrames = 10;
|
int32 blockStunFrames = 10;
|
||||||
double pushback = 11;
|
double pushbackX = 11;
|
||||||
|
double pushbackY = 12;
|
||||||
|
|
||||||
int32 releaseTriggerType = 12; // 1: rising-edge, 2: falling-edge
|
|
||||||
int32 damage = 13;
|
int32 damage = 13;
|
||||||
|
|
||||||
int32 offenderJoinIndex = 14;
|
int32 offenderJoinIndex = 14;
|
||||||
@ -108,44 +108,28 @@ message MeleeBullet {
|
|||||||
double hitboxSizeX = 16;
|
double hitboxSizeX = 16;
|
||||||
double hitboxSizeY = 17;
|
double hitboxSizeY = 17;
|
||||||
|
|
||||||
double selfMoveforwardX = 18;
|
double selfLockVelX = 18;
|
||||||
double selfMoveforwardY = 19;
|
double selfLockVelY = 19;
|
||||||
|
|
||||||
|
int32 releaseTriggerType = 999; // 1: rising-edge, 2: falling-edge
|
||||||
}
|
}
|
||||||
|
|
||||||
message BattleColliderInfo {
|
message BattleColliderInfo {
|
||||||
string stageName = 1;
|
string stageName = 1;
|
||||||
int32 stageDiscreteW = 2;
|
|
||||||
int32 stageDiscreteH = 3;
|
|
||||||
int32 stageTileW = 4;
|
|
||||||
int32 stageTileH = 5;
|
|
||||||
|
|
||||||
int32 intervalToPing = 6;
|
int32 intervalToPing = 2;
|
||||||
int32 willKickIfInactiveFor = 7;
|
int32 willKickIfInactiveFor = 3;
|
||||||
int32 boundRoomId = 8;
|
int32 boundRoomId = 4;
|
||||||
int32 battleDurationFrames = 9;
|
int64 battleDurationNanos = 5;
|
||||||
int64 battleDurationNanos = 10;
|
int32 inputFrameUpsyncDelayTolerance = 6;
|
||||||
int32 serverFps = 11;
|
int32 maxChasingRenderFramesPerUpdate = 7;
|
||||||
int32 inputDelayFrames = 12; // in the count of render frames
|
double rollbackEstimatedDtMillis = 8;
|
||||||
uint32 inputScaleFrames = 13; // inputDelayedAndScaledFrameId = ((originalFrameId - InputDelayFrames) >> InputScaleFrames)
|
int64 rollbackEstimatedDtNanos = 9;
|
||||||
int32 nstDelayFrames = 14; // network-single-trip delay in the count of render frames, proposed to be (InputDelayFrames >> 1) because we expect a round-trip delay to be exactly "InputDelayFrames"
|
|
||||||
int32 inputFrameUpsyncDelayTolerance = 15;
|
|
||||||
int32 maxChasingRenderFramesPerUpdate = 16;
|
|
||||||
int32 playerBattleState = 17;
|
|
||||||
double rollbackEstimatedDtMillis = 18;
|
|
||||||
int64 rollbackEstimatedDtNanos = 19;
|
|
||||||
|
|
||||||
double worldToVirtualGridRatio = 20;
|
int32 renderCacheSize = 10;
|
||||||
double virtualGridToWorldRatio = 21;
|
int32 spaceOffsetX = 11;
|
||||||
|
int32 spaceOffsetY = 12;
|
||||||
int32 spAtkLookupFrames = 22;
|
int32 collisionMinStep = 13;
|
||||||
int32 renderCacheSize = 23;
|
|
||||||
|
|
||||||
double snapIntoPlatformOverlap = 24;
|
|
||||||
double snapIntoPlatformThreshold = 25;
|
|
||||||
int32 jumpingInitVelY = 26;
|
|
||||||
int32 gravityX = 27;
|
|
||||||
int32 gravityY = 28;
|
|
||||||
int32 collisionMinStep = 29;
|
|
||||||
|
|
||||||
bool frameDataLoggingEnabled = 999;
|
bool frameDataLoggingEnabled = 999;
|
||||||
}
|
}
|
||||||
|
@ -315,11 +315,7 @@ cc.Class({
|
|||||||
self.selfPlayerInfo = null; // This field is kept for distinguishing "self" and "others".
|
self.selfPlayerInfo = null; // This field is kept for distinguishing "self" and "others".
|
||||||
self.recentInputCache = gopkgs.NewRingBufferJs((self.renderCacheSize >> 1) + 1);
|
self.recentInputCache = gopkgs.NewRingBufferJs((self.renderCacheSize >> 1) + 1);
|
||||||
|
|
||||||
const spaceW = self.stageDiscreteW * self.stageTileW;
|
self.gopkgsCollisionSys = gopkgs.NewCollisionSpaceJs((self.spaceOffsetX << 1), (self.spaceOffsetY << 1), self.collisionMinStep, self.collisionMinStep);
|
||||||
const spaceH = self.stageDiscreteH * self.stageTileH;
|
|
||||||
self.spaceOffsetX = (spaceW >> 1);
|
|
||||||
self.spaceOffsetY = (spaceH >> 1);
|
|
||||||
self.gopkgsCollisionSys = gopkgs.NewCollisionSpaceJs(spaceW, spaceH, self.collisionMinStep, self.collisionMinStep);
|
|
||||||
self.gopkgsCollisionSysMap = {}; // [WARNING] Don't use "JavaScript Map" which could cause loss of type information when passing through Golang transpiled functions!
|
self.gopkgsCollisionSysMap = {}; // [WARNING] Don't use "JavaScript Map" which could cause loss of type information when passing through Golang transpiled functions!
|
||||||
|
|
||||||
self.collisionBarrierIndexPrefix = (1 << 16); // For tracking the movements of barriers, though not yet actually used
|
self.collisionBarrierIndexPrefix = (1 << 16); // For tracking the movements of barriers, though not yet actually used
|
||||||
@ -596,7 +592,7 @@ cc.Class({
|
|||||||
const jsMeleeBulletsArr = [];
|
const jsMeleeBulletsArr = [];
|
||||||
for (let k in pbRdf.meleeBullets) {
|
for (let k in pbRdf.meleeBullets) {
|
||||||
const pbBullet = pbRdf.meleeBullets[k];
|
const pbBullet = pbRdf.meleeBullets[k];
|
||||||
const jsBullet = gopkgs.NewMeleeBulletJs(pbBullet.battleLocalId, pbBullet.startupFrames, pbBullet.activeFrames, pbBullet.recoveryFrames, pbBullet.recoveryFramesOnBlock, pbBullet.recoveryFramesOnHit, pbBullet.hitStunFrames, pbBullet.blockStunFrames, pbBullet.releaseTriggerType, pbBullet.damage, pbBullet.offenderJoinIndex, pbBullet.offenderPlayerId, pbBullet.pushback, pbBullet.hitboxOffset, pbBullet.selfMoveforwardX, pbBullet.selfMoveforwardY, pbBullet.hitboxSizeX, pbBullet.hitboxSizeY);
|
const jsBullet = gopkgs.NewMeleeBulletJs(pbBullet.originatedRenderFrameId, pbBullet.offenderJoinIndex, pbBullet.startupFrames, pbBullet.cancellableStFrame, pbBullet.cancellableEdFrame, pbBullet.activeFrames, pbBullet.hitStunFrames, pbBullet.blockStunFrames, pbBullet.pushbackX, pbBullet.pushbackY, pbBullet.damage, pbBullet.selfLockVelX, pbBullet.selfLockVelY, pbBullet.hitboxOffsetX, pbBullet.hitboxOffsetY, pbBullet.hitboxSizeX, pbBullet.hitboxSizeY, pbBullet.blowUp);
|
||||||
jsMeleeBulletsArr.push(jsBullet);
|
jsMeleeBulletsArr.push(jsBullet);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -638,8 +634,10 @@ cc.Class({
|
|||||||
}
|
}
|
||||||
|
|
||||||
// The logic below applies to (window.MAGIC_ROOM_DOWNSYNC_FRAME_ID.BATTLE_START == rdf.id || window.RING_BUFF_NON_CONSECUTIVE_SET == dumpRenderCacheRet)
|
// The logic below applies to (window.MAGIC_ROOM_DOWNSYNC_FRAME_ID.BATTLE_START == rdf.id || window.RING_BUFF_NON_CONSECUTIVE_SET == dumpRenderCacheRet)
|
||||||
|
if (null == pbRdf.speciesIdList) {
|
||||||
|
console.error(`pbRdf.speciesIdList is required for starting or resyncing battle!`);
|
||||||
|
}
|
||||||
self.chConfigsOrderedByJoinIndex = gopkgs.GetCharacterConfigsOrderedByJoinIndex(pbRdf.speciesIdList);
|
self.chConfigsOrderedByJoinIndex = gopkgs.GetCharacterConfigsOrderedByJoinIndex(pbRdf.speciesIdList);
|
||||||
self.playerOpPatternToSkillId = pbRdf.playerOpPatternToSkillId;
|
|
||||||
self._initPlayerRichInfoDict(rdf.PlayersArr);
|
self._initPlayerRichInfoDict(rdf.PlayersArr);
|
||||||
|
|
||||||
// Show the top status indicators for IN_BATTLE
|
// Show the top status indicators for IN_BATTLE
|
||||||
@ -831,13 +829,10 @@ batchInputFrameIdRange=[${batch[0].inputFrameId}, ${batch[batch.length - 1].inpu
|
|||||||
const self = this;
|
const self = this;
|
||||||
const newPlayerNode = cc.instantiate(self.controlledCharacterPrefab)
|
const newPlayerNode = cc.instantiate(self.controlledCharacterPrefab)
|
||||||
const playerScriptIns = newPlayerNode.getComponent("ControlledCharacter");
|
const playerScriptIns = newPlayerNode.getComponent("ControlledCharacter");
|
||||||
if (1 == joinIndex) {
|
const chConfig = self.chConfigsOrderedByJoinIndex[joinIndex - 1];
|
||||||
playerScriptIns.setSpecies("SoldierWaterGhost");
|
playerScriptIns.setSpecies(chConfig.SpeciesName);
|
||||||
} else if (2 == joinIndex) {
|
|
||||||
playerScriptIns.setSpecies("UltramanTiga");
|
|
||||||
}
|
|
||||||
|
|
||||||
const [wx, wy] = self.virtualGridToWorldPos(vx, vy);
|
const [wx, wy] = gopkgs.VirtualGridToWorldPos(vx, vy);
|
||||||
newPlayerNode.setPosition(wx, wy);
|
newPlayerNode.setPosition(wx, wy);
|
||||||
playerScriptIns.mapNode = self.node;
|
playerScriptIns.mapNode = self.node;
|
||||||
const colliderRadius = playerDownsyncInfo.ColliderRadius;
|
const colliderRadius = playerDownsyncInfo.ColliderRadius;
|
||||||
@ -846,17 +841,7 @@ batchInputFrameIdRange=[${batch[0].inputFrameId}, ${batch[batch.length - 1].inpu
|
|||||||
const colliderWidth = halfColliderWidth + halfColliderWidth,
|
const colliderWidth = halfColliderWidth + halfColliderWidth,
|
||||||
colliderHeight = halfColliderHeight + halfColliderHeight; // avoid multiplying
|
colliderHeight = halfColliderHeight + halfColliderHeight; // avoid multiplying
|
||||||
|
|
||||||
const [cx, cy] = gopkgs.WorldToPolygonColliderBLPos(wx, wy, halfColliderWidth, halfColliderHeight, self.snapIntoPlatformOverlap, self.snapIntoPlatformOverlap, self.snapIntoPlatformOverlap, self.snapIntoPlatformOverlap, self.spaceOffsetX, self.spaceOffsetY);
|
const newPlayerCollider = gopkgs.GenerateRectColliderJs(wx, wy, colliderWidth, colliderHeight, self.spaceOffsetX, self.spaceOffsetY, playerDownsyncInfo, "Player");
|
||||||
const gopkgsBoundaryAnchor = gopkgs.NewVec2DJs(cx, cy);
|
|
||||||
const gopkgsBoundaryPts = [
|
|
||||||
gopkgs.NewVec2DJs(0, 0),
|
|
||||||
gopkgs.NewVec2DJs(self.snapIntoPlatformOverlap + colliderWidth + self.snapIntoPlatformOverlap, 0),
|
|
||||||
gopkgs.NewVec2DJs(self.snapIntoPlatformOverlap + colliderWidth + self.snapIntoPlatformOverlap, self.snapIntoPlatformOverlap + colliderHeight + self.snapIntoPlatformOverlap),
|
|
||||||
gopkgs.NewVec2DJs(0, self.snapIntoPlatformOverlap + colliderHeight + self.snapIntoPlatformOverlap)
|
|
||||||
];
|
|
||||||
const gopkgsBoundary = gopkgs.NewPolygon2DJs(gopkgsBoundaryAnchor, gopkgsBoundaryPts);
|
|
||||||
const newPlayerCollider = gopkgs.GenerateConvexPolygonColliderJs(gopkgsBoundary, self.spaceOffsetX, self.spaceOffsetY, playerDownsyncInfo, "Player");
|
|
||||||
//const newPlayerCollider = gopkgs.GenerateRectColliderJs(wx, wy, colliderWidth, colliderHeight, self.snapIntoPlatformOverlap, self.snapIntoPlatformOverlap, self.snapIntoPlatformOverlap, self.snapIntoPlatformOverlap, self.spaceOffsetX, self.spaceOffsetY, playerDownsyncInfo, "Player");
|
|
||||||
self.gopkgsCollisionSys.Add(newPlayerCollider);
|
self.gopkgsCollisionSys.Add(newPlayerCollider);
|
||||||
const collisionPlayerIndex = self.collisionPlayerIndexPrefix + joinIndex;
|
const collisionPlayerIndex = self.collisionPlayerIndexPrefix + joinIndex;
|
||||||
self.gopkgsCollisionSysMap[collisionPlayerIndex] = newPlayerCollider;
|
self.gopkgsCollisionSysMap[collisionPlayerIndex] = newPlayerCollider;
|
||||||
@ -1067,7 +1052,7 @@ othersForcedDownsyncRenderFrame=${JSON.stringify(othersForcedDownsyncRenderFrame
|
|||||||
const currPlayerDownsync = playersArr[k];
|
const currPlayerDownsync = playersArr[k];
|
||||||
const chConfig = self.chConfigsOrderedByJoinIndex[k];
|
const chConfig = self.chConfigsOrderedByJoinIndex[k];
|
||||||
const prevRdfPlayer = (null == prevRdf ? null : prevRdf.PlayersArr[k]);
|
const prevRdfPlayer = (null == prevRdf ? null : prevRdf.PlayersArr[k]);
|
||||||
const [wx, wy] = self.virtualGridToWorldPos(currPlayerDownsync.VirtualGridX, currPlayerDownsync.VirtualGridY);
|
const [wx, wy] = gopkgs.VirtualGridToWorldPos(currPlayerDownsync.VirtualGridX, currPlayerDownsync.VirtualGridY);
|
||||||
const playerRichInfo = self.playerRichInfoArr[k];
|
const playerRichInfo = self.playerRichInfoArr[k];
|
||||||
playerRichInfo.node.setPosition(wx, wy);
|
playerRichInfo.node.setPosition(wx, wy);
|
||||||
playerRichInfo.scriptIns.updateSpeed(currPlayerDownsync.Speed);
|
playerRichInfo.scriptIns.updateSpeed(currPlayerDownsync.Speed);
|
||||||
@ -1107,7 +1092,7 @@ othersForcedDownsyncRenderFrame=${JSON.stringify(othersForcedDownsyncRenderFrame
|
|||||||
};
|
};
|
||||||
self.rdfIdToActuallyUsedInput.set(currRdf.Id, inputFrameDownsyncClone);
|
self.rdfIdToActuallyUsedInput.set(currRdf.Id, inputFrameDownsyncClone);
|
||||||
}
|
}
|
||||||
const nextRdf = gopkgs.ApplyInputFrameDownsyncDynamicsOnSingleRenderFrameJs(self.recentInputCache, currRdf, collisionSys, collisionSysMap, self.spaceOffsetX, self.spaceOffsetY, self.playerOpPatternToSkillId, self.chConfigsOrderedByJoinIndex);
|
const nextRdf = gopkgs.ApplyInputFrameDownsyncDynamicsOnSingleRenderFrameJs(self.recentInputCache, currRdf, collisionSys, collisionSysMap, self.spaceOffsetX, self.spaceOffsetY, self.chConfigsOrderedByJoinIndex);
|
||||||
|
|
||||||
if (true == isChasing) {
|
if (true == isChasing) {
|
||||||
// [WARNING] Move the cursor "self.chaserRenderFrameId" when "true == isChasing", keep in mind that "self.chaserRenderFrameId" is not monotonic!
|
// [WARNING] Move the cursor "self.chaserRenderFrameId" when "true == isChasing", keep in mind that "self.chaserRenderFrameId" is not monotonic!
|
||||||
@ -1236,12 +1221,6 @@ actuallyUsedinputList:{${self.inputFrameDownsyncStr(actuallyUsedInputClone)}}`);
|
|||||||
return `{${(playerCollider.x + leftPadding + halfBoundingW).toFixed(2)}, ${(playerCollider.y + bottomPadding + halfBoundingH).toFixed(2)}}`;
|
return `{${(playerCollider.x + leftPadding + halfBoundingW).toFixed(2)}, ${(playerCollider.y + bottomPadding + halfBoundingH).toFixed(2)}}`;
|
||||||
},
|
},
|
||||||
|
|
||||||
virtualGridToWorldPos(vx, vy) {
|
|
||||||
// No loss of precision
|
|
||||||
const self = this;
|
|
||||||
return [vx * self.virtualGridToWorldRatio, vy * self.virtualGridToWorldRatio];
|
|
||||||
},
|
|
||||||
|
|
||||||
showDebugBoundaries(rdf) {
|
showDebugBoundaries(rdf) {
|
||||||
const self = this;
|
const self = this;
|
||||||
const leftPadding = self.snapIntoPlatformOverlap,
|
const leftPadding = self.snapIntoPlatformOverlap,
|
||||||
|
@ -40,24 +40,6 @@ cc.Class({
|
|||||||
self.rollbackEstimatedDtNanos = 16666666;
|
self.rollbackEstimatedDtNanos = 16666666;
|
||||||
self.tooFastDtIntervalMillis = 0.5 * self.rollbackEstimatedDtMillis;
|
self.tooFastDtIntervalMillis = 0.5 * self.rollbackEstimatedDtMillis;
|
||||||
|
|
||||||
self.worldToVirtualGridRatio = 100;
|
|
||||||
self.virtualGridToWorldRatio = 1.0 / self.worldToVirtualGridRatio;
|
|
||||||
|
|
||||||
const opJoinIndexPrefix1 = (1 << 8);
|
|
||||||
const playerOpPatternToSkillId = {};
|
|
||||||
playerOpPatternToSkillId[opJoinIndexPrefix1 + 0] = 1;
|
|
||||||
playerOpPatternToSkillId[opJoinIndexPrefix1 + 1] = 2;
|
|
||||||
|
|
||||||
/*
|
|
||||||
[WARNING] As when a character is standing on a barrier, if not carefully curated there MIGHT BE a bouncing sequence of "[(inAir -> dropIntoBarrier ->), (notInAir -> pushedOutOfBarrier ->)], [(inAir -> ..."
|
|
||||||
|
|
||||||
Moreover, "snapIntoPlatformOverlap" should be small enough such that the walking "velX" or jumping initial "velY" can escape from it by 1 renderFrame (when jumping is triggered, the character is waived from snappig for 1 renderFrame).
|
|
||||||
*/
|
|
||||||
self.snapIntoPlatformOverlap = 0.1;
|
|
||||||
self.snapIntoPlatformThreshold = 0.5; // a platform must be "horizontal enough" for a character to "stand on"
|
|
||||||
self.jumpingInitVelY = 7 * self.worldToVirtualGridRatio; // unit: (virtual grid length/renderFrame)
|
|
||||||
[self.gravityX, self.gravityY] = [0, -0.5 * self.worldToVirtualGridRatio]; // unit: (virtual grid length/renderFrame^2)
|
|
||||||
|
|
||||||
const tiledMapIns = self.node.getComponent(cc.TiledMap);
|
const tiledMapIns = self.node.getComponent(cc.TiledMap);
|
||||||
|
|
||||||
const fullPathOfTmxFile = cc.js.formatStr("map/%s/map", "dungeon");
|
const fullPathOfTmxFile = cc.js.formatStr("map/%s/map", "dungeon");
|
||||||
@ -86,10 +68,8 @@ cc.Class({
|
|||||||
self.node.setContentSize(newMapSize.width * newTileSize.width, newMapSize.height * newTileSize.height);
|
self.node.setContentSize(newMapSize.width * newTileSize.width, newMapSize.height * newTileSize.height);
|
||||||
self.node.setPosition(cc.v2(0, 0));
|
self.node.setPosition(cc.v2(0, 0));
|
||||||
|
|
||||||
self.stageDiscreteW = newMapSize.width;
|
self.spaceOffsetX = ((newMapSize.width * newTileSize.width) >> 1);
|
||||||
self.stageDiscreteH = newMapSize.height;
|
self.spaceOffsetY = ((newMapSize.height * newTileSize.height) >> 1);
|
||||||
self.stageTileW = newTileSize.width;
|
|
||||||
self.stageTileH = newTileSize.height;
|
|
||||||
|
|
||||||
self._resetCurrentMatch();
|
self._resetCurrentMatch();
|
||||||
let barrierIdCounter = 0;
|
let barrierIdCounter = 0;
|
||||||
@ -142,15 +122,18 @@ cc.Class({
|
|||||||
self.gopkgsCollisionSysMap[collisionBarrierIndex] = newBarrierCollider;
|
self.gopkgsCollisionSysMap[collisionBarrierIndex] = newBarrierCollider;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const p1Vpos = gopkgs.WorldToVirtualGridPos(boundaryObjs.playerStartingPositions[0].x, boundaryObjs.playerStartingPositions[0].y);
|
||||||
|
const speedV = gopkgs.WorldToVirtualGridPos(1.0, 0);
|
||||||
|
|
||||||
const startRdf = window.pb.protos.RoomDownsyncFrame.create({
|
const startRdf = window.pb.protos.RoomDownsyncFrame.create({
|
||||||
id: window.MAGIC_ROOM_DOWNSYNC_FRAME_ID.BATTLE_START,
|
id: window.MAGIC_ROOM_DOWNSYNC_FRAME_ID.BATTLE_START,
|
||||||
playersArr: [
|
playersArr: [
|
||||||
window.pb.protos.PlayerDownsync.create({
|
window.pb.protos.PlayerDownsync.create({
|
||||||
id: 10,
|
id: 10,
|
||||||
joinIndex: 1,
|
joinIndex: 1,
|
||||||
virtualGridX: boundaryObjs.playerStartingPositions[0].x * self.worldToVirtualGridRatio,
|
virtualGridX: p1Vpos[0],
|
||||||
virtualGridY: boundaryObjs.playerStartingPositions[0].y * self.worldToVirtualGridRatio,
|
virtualGridY: p1Vpos[1],
|
||||||
speed: 1 * self.worldToVirtualGridRatio,
|
speed: speedV[0],
|
||||||
colliderRadius: 12,
|
colliderRadius: 12,
|
||||||
characterState: window.ATK_CHARACTER_STATE.InAirIdle1NoJump[0],
|
characterState: window.ATK_CHARACTER_STATE.InAirIdle1NoJump[0],
|
||||||
framesToRecover: 0,
|
framesToRecover: 0,
|
||||||
@ -162,7 +145,6 @@ cc.Class({
|
|||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
speciesIdList: [0],
|
speciesIdList: [0],
|
||||||
playerOpPatternToSkillId: playerOpPatternToSkillId,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
self.selfPlayerInfo = {
|
self.selfPlayerInfo = {
|
||||||
@ -208,48 +190,4 @@ cc.Class({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
spawnPlayerNode(joinIndex, vx, vy, playerDownsyncInfo) {
|
|
||||||
const self = this;
|
|
||||||
const newPlayerNode = cc.instantiate(self.controlledCharacterPrefab)
|
|
||||||
const playerScriptIns = newPlayerNode.getComponent("ControlledCharacter");
|
|
||||||
if (1 == joinIndex) {
|
|
||||||
playerScriptIns.setSpecies("MonkGirl");
|
|
||||||
} else if (2 == joinIndex) {
|
|
||||||
playerScriptIns.setSpecies("UltramanTiga");
|
|
||||||
}
|
|
||||||
|
|
||||||
const [wx, wy] = self.virtualGridToWorldPos(vx, vy);
|
|
||||||
newPlayerNode.setPosition(wx, wy);
|
|
||||||
playerScriptIns.mapNode = self.node;
|
|
||||||
const colliderRadius = playerDownsyncInfo.ColliderRadius;
|
|
||||||
const halfColliderWidth = colliderRadius,
|
|
||||||
halfColliderHeight = colliderRadius + colliderRadius; // avoid multiplying
|
|
||||||
const colliderWidth = halfColliderWidth + halfColliderWidth,
|
|
||||||
colliderHeight = halfColliderHeight + halfColliderHeight; // avoid multiplying
|
|
||||||
|
|
||||||
const [cx, cy] = gopkgs.WorldToPolygonColliderBLPos(wx, wy, halfColliderWidth, halfColliderHeight, self.snapIntoPlatformOverlap, self.snapIntoPlatformOverlap, self.snapIntoPlatformOverlap, self.snapIntoPlatformOverlap, self.spaceOffsetX, self.spaceOffsetY);
|
|
||||||
const gopkgsBoundaryAnchor = gopkgs.NewVec2DJs(cx, cy);
|
|
||||||
const gopkgsBoundaryPts = [
|
|
||||||
gopkgs.NewVec2DJs(0, 0),
|
|
||||||
gopkgs.NewVec2DJs(self.snapIntoPlatformOverlap + colliderWidth + self.snapIntoPlatformOverlap, 0),
|
|
||||||
gopkgs.NewVec2DJs(self.snapIntoPlatformOverlap + colliderWidth + self.snapIntoPlatformOverlap, self.snapIntoPlatformOverlap + colliderHeight + self.snapIntoPlatformOverlap),
|
|
||||||
gopkgs.NewVec2DJs(0, self.snapIntoPlatformOverlap + colliderHeight + self.snapIntoPlatformOverlap)
|
|
||||||
];
|
|
||||||
const gopkgsBoundary = gopkgs.NewPolygon2DJs(gopkgsBoundaryAnchor, gopkgsBoundaryPts);
|
|
||||||
const newPlayerCollider = gopkgs.GenerateConvexPolygonColliderJs(gopkgsBoundary, self.spaceOffsetX, self.spaceOffsetY, playerDownsyncInfo, "Player");
|
|
||||||
//const newPlayerCollider = gopkgs.GenerateRectColliderJs(wx, wy, colliderWidth, colliderHeight, self.snapIntoPlatformOverlap, self.snapIntoPlatformOverlap, self.snapIntoPlatformOverlap, self.snapIntoPlatformOverlap, self.spaceOffsetX, self.spaceOffsetY, playerDownsyncInfo, "Player");
|
|
||||||
self.gopkgsCollisionSys.Add(newPlayerCollider);
|
|
||||||
const collisionPlayerIndex = self.collisionPlayerIndexPrefix + joinIndex;
|
|
||||||
self.gopkgsCollisionSysMap[collisionPlayerIndex] = newPlayerCollider;
|
|
||||||
|
|
||||||
console.log(`Created new player collider: joinIndex=${joinIndex}, colliderRadius=${playerDownsyncInfo.ColliderRadius}`);
|
|
||||||
|
|
||||||
safelyAddChild(self.node, newPlayerNode);
|
|
||||||
setLocalZOrder(newPlayerNode, 5);
|
|
||||||
|
|
||||||
newPlayerNode.active = true;
|
|
||||||
playerScriptIns.updateCharacterAnim(playerDownsyncInfo, null, true);
|
|
||||||
|
|
||||||
return [newPlayerNode, playerScriptIns];
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
@ -20,9 +20,9 @@ const (
|
|||||||
GRAVITY_X = int32(0)
|
GRAVITY_X = int32(0)
|
||||||
GRAVITY_Y = -int32(float64(0.5) * WORLD_TO_VIRTUAL_GRID_RATIO) // makes all "playerCollider.Y" a multiple of 0.5 in all cases
|
GRAVITY_Y = -int32(float64(0.5) * WORLD_TO_VIRTUAL_GRID_RATIO) // makes all "playerCollider.Y" a multiple of 0.5 in all cases
|
||||||
|
|
||||||
INPUT_DELAY_FRAMES = int32(8)
|
INPUT_DELAY_FRAMES = int32(8) // in the count of render frames
|
||||||
NST_DELAY_FRAMES = int32(16)
|
INPUT_SCALE_FRAMES = uint32(2) // inputDelayedAndScaledFrameId = ((originalFrameId - InputDelayFrames) >> InputScaleFrames)
|
||||||
INPUT_SCALE_FRAMES = uint32(2)
|
NST_DELAY_FRAMES = int32(16) // network-single-trip delay in the count of render frames, proposed to be (InputDelayFrames >> 1) because we expect a round-trip delay to be exactly "InputDelayFrames"
|
||||||
|
|
||||||
SNAP_INTO_PLATFORM_OVERLAP = float64(0.1)
|
SNAP_INTO_PLATFORM_OVERLAP = float64(0.1)
|
||||||
SNAP_INTO_PLATFORM_THRESHOLD = float64(0.5)
|
SNAP_INTO_PLATFORM_THRESHOLD = float64(0.5)
|
||||||
@ -249,18 +249,18 @@ func isPolygonPairSeparatedByDir(a, b *resolv.ConvexPolygon, e resolv.Vector, re
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func WorldToVirtualGridPos(wx, wy, worldToVirtualGridRatio float64) (int32, int32) {
|
func WorldToVirtualGridPos(wx, wy float64) (int32, int32) {
|
||||||
// [WARNING] Introduces loss of precision!
|
// [WARNING] Introduces loss of precision!
|
||||||
// In JavaScript floating numbers suffer from seemingly non-deterministic arithmetics, and even if certain libs solved this issue by approaches such as fixed-point-number, they might not be used in other libs -- e.g. the "collision libs" we're interested in -- thus couldn't kill all pains.
|
// In JavaScript floating numbers suffer from seemingly non-deterministic arithmetics, and even if certain libs solved this issue by approaches such as fixed-point-number, they might not be used in other libs -- e.g. the "collision libs" we're interested in -- thus couldn't kill all pains.
|
||||||
var virtualGridX int32 = int32(math.Floor(wx * worldToVirtualGridRatio))
|
var virtualGridX int32 = int32(math.Floor(wx * WORLD_TO_VIRTUAL_GRID_RATIO))
|
||||||
var virtualGridY int32 = int32(math.Floor(wy * worldToVirtualGridRatio))
|
var virtualGridY int32 = int32(math.Floor(wy * WORLD_TO_VIRTUAL_GRID_RATIO))
|
||||||
return virtualGridX, virtualGridY
|
return virtualGridX, virtualGridY
|
||||||
}
|
}
|
||||||
|
|
||||||
func VirtualGridToWorldPos(vx, vy int32, virtualGridToWorldRatio float64) (float64, float64) {
|
func VirtualGridToWorldPos(vx, vy int32) (float64, float64) {
|
||||||
// No loss of precision
|
// No loss of precision
|
||||||
var wx float64 = float64(vx) * virtualGridToWorldRatio
|
var wx float64 = float64(vx) * VIRTUAL_GRID_TO_WORLD_RATIO
|
||||||
var wy float64 = float64(vy) * virtualGridToWorldRatio
|
var wy float64 = float64(vy) * VIRTUAL_GRID_TO_WORLD_RATIO
|
||||||
return wx, wy
|
return wx, wy
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -272,13 +272,13 @@ func PolygonColliderBLToWorldPos(cx, cy, halfBoundingW, halfBoundingH, topPaddin
|
|||||||
return cx + halfBoundingW + leftPadding - collisionSpaceOffsetX, cy + halfBoundingH + bottomPadding - collisionSpaceOffsetY
|
return cx + halfBoundingW + leftPadding - collisionSpaceOffsetX, cy + halfBoundingH + bottomPadding - collisionSpaceOffsetY
|
||||||
}
|
}
|
||||||
|
|
||||||
func PolygonColliderBLToVirtualGridPos(cx, cy, halfBoundingW, halfBoundingH, topPadding, bottomPadding, leftPadding, rightPadding, collisionSpaceOffsetX, collisionSpaceOffsetY float64, worldToVirtualGridRatio float64) (int32, int32) {
|
func PolygonColliderBLToVirtualGridPos(cx, cy, halfBoundingW, halfBoundingH, topPadding, bottomPadding, leftPadding, rightPadding, collisionSpaceOffsetX, collisionSpaceOffsetY float64) (int32, int32) {
|
||||||
wx, wy := PolygonColliderBLToWorldPos(cx, cy, halfBoundingW, halfBoundingH, topPadding, bottomPadding, leftPadding, rightPadding, collisionSpaceOffsetX, collisionSpaceOffsetY)
|
wx, wy := PolygonColliderBLToWorldPos(cx, cy, halfBoundingW, halfBoundingH, topPadding, bottomPadding, leftPadding, rightPadding, collisionSpaceOffsetX, collisionSpaceOffsetY)
|
||||||
return WorldToVirtualGridPos(wx, wy, worldToVirtualGridRatio)
|
return WorldToVirtualGridPos(wx, wy)
|
||||||
}
|
}
|
||||||
|
|
||||||
func VirtualGridToPolygonColliderBLPos(vx, vy int32, halfBoundingW, halfBoundingH, topPadding, bottomPadding, leftPadding, rightPadding, collisionSpaceOffsetX, collisionSpaceOffsetY float64, virtualGridToWorldRatio float64) (float64, float64) {
|
func VirtualGridToPolygonColliderBLPos(vx, vy int32, halfBoundingW, halfBoundingH, topPadding, bottomPadding, leftPadding, rightPadding, collisionSpaceOffsetX, collisionSpaceOffsetY float64) (float64, float64) {
|
||||||
wx, wy := VirtualGridToWorldPos(vx, vy, virtualGridToWorldRatio)
|
wx, wy := VirtualGridToWorldPos(vx, vy)
|
||||||
return WorldToPolygonColliderBLPos(wx, wy, halfBoundingW, halfBoundingH, topPadding, bottomPadding, leftPadding, rightPadding, collisionSpaceOffsetX, collisionSpaceOffsetY)
|
return WorldToPolygonColliderBLPos(wx, wy, halfBoundingW, halfBoundingH, topPadding, bottomPadding, leftPadding, rightPadding, collisionSpaceOffsetX, collisionSpaceOffsetY)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -369,7 +369,7 @@ func deriveOpPattern(currPlayerDownsync, thatPlayerInNextFrame *PlayerDownsync,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// [WARNING] The params of this method is carefully tuned such that only "battle.RoomDownsyncFrame" is a necessary custom struct.
|
// [WARNING] The params of this method is carefully tuned such that only "battle.RoomDownsyncFrame" is a necessary custom struct.
|
||||||
func ApplyInputFrameDownsyncDynamicsOnSingleRenderFrame(inputsBuffer *RingBuffer, currRenderFrame *RoomDownsyncFrame, collisionSys *resolv.Space, collisionSysMap map[int32]*resolv.Object, collisionSpaceOffsetX, collisionSpaceOffsetY float64, playerOpPatternToSkillId map[int]int, chConfigsOrderedByJoinIndex []*CharacterConfig) *RoomDownsyncFrame {
|
func ApplyInputFrameDownsyncDynamicsOnSingleRenderFrame(inputsBuffer *RingBuffer, currRenderFrame *RoomDownsyncFrame, collisionSys *resolv.Space, collisionSysMap map[int32]*resolv.Object, collisionSpaceOffsetX, collisionSpaceOffsetY float64, chConfigsOrderedByJoinIndex []*CharacterConfig) *RoomDownsyncFrame {
|
||||||
// [WARNING] On backend this function MUST BE called while "InputsBufferLock" is locked!
|
// [WARNING] On backend this function MUST BE called while "InputsBufferLock" is locked!
|
||||||
roomCapacity := len(currRenderFrame.PlayersArr)
|
roomCapacity := len(currRenderFrame.PlayersArr)
|
||||||
nextRenderFramePlayers := make([]*PlayerDownsync, roomCapacity)
|
nextRenderFramePlayers := make([]*PlayerDownsync, roomCapacity)
|
||||||
@ -408,6 +408,7 @@ func ApplyInputFrameDownsyncDynamicsOnSingleRenderFrame(inputsBuffer *RingBuffer
|
|||||||
// 1. Process player inputs
|
// 1. Process player inputs
|
||||||
for i, currPlayerDownsync := range currRenderFrame.PlayersArr {
|
for i, currPlayerDownsync := range currRenderFrame.PlayersArr {
|
||||||
jumpedOrNotList[i] = false
|
jumpedOrNotList[i] = false
|
||||||
|
chConfig := chConfigsOrderedByJoinIndex[i]
|
||||||
thatPlayerInNextFrame := nextRenderFramePlayers[i]
|
thatPlayerInNextFrame := nextRenderFramePlayers[i]
|
||||||
patternId, jumpedOrNot, effDx, effDy := deriveOpPattern(currPlayerDownsync, thatPlayerInNextFrame, currRenderFrame, inputsBuffer, INPUT_DELAY_FRAMES, INPUT_SCALE_FRAMES)
|
patternId, jumpedOrNot, effDx, effDy := deriveOpPattern(currPlayerDownsync, thatPlayerInNextFrame, currRenderFrame, inputsBuffer, INPUT_DELAY_FRAMES, INPUT_SCALE_FRAMES)
|
||||||
if PATTERN_ID_UNABLE_TO_OP == patternId {
|
if PATTERN_ID_UNABLE_TO_OP == patternId {
|
||||||
@ -415,19 +416,22 @@ func ApplyInputFrameDownsyncDynamicsOnSingleRenderFrame(inputsBuffer *RingBuffer
|
|||||||
}
|
}
|
||||||
|
|
||||||
if jumpedOrNot {
|
if jumpedOrNot {
|
||||||
thatPlayerInNextFrame.VelY = int32(chConfigsOrderedByJoinIndex[i].JumpingInitVelY)
|
thatPlayerInNextFrame.VelY = int32(chConfig.JumpingInitVelY)
|
||||||
jumpedOrNotList[i] = true
|
jumpedOrNotList[i] = true
|
||||||
}
|
}
|
||||||
joinIndex := currPlayerDownsync.JoinIndex
|
joinIndex := currPlayerDownsync.JoinIndex
|
||||||
if PATTERN_ID_NO_OP != patternId {
|
if PATTERN_ID_NO_OP != patternId {
|
||||||
if skillId, existent := playerOpPatternToSkillId[(int(joinIndex)<<uint(8))+patternId]; existent {
|
if skillId, existent := chConfig.PatternIdToSkillId[patternId]; existent {
|
||||||
skillConfig := skillIdToBullet[skillId].(*MeleeBullet) // Hardcoded type "MeleeBullet" for now
|
skillConfig := skills[skillId]
|
||||||
var newMeleeBullet MeleeBullet = *skillConfig
|
// Hardcoded to use only the first hit for now
|
||||||
newMeleeBullet.OffenderJoinIndex = joinIndex
|
switch v := skillConfig.Hits[0].(type) {
|
||||||
newMeleeBullet.OffenderPlayerId = currPlayerDownsync.Id
|
case *MeleeBullet:
|
||||||
newMeleeBullet.OriginatedRenderFrameId = currRenderFrame.Id
|
var newBullet MeleeBullet = *v // Copied primitive fields into an onstack variable
|
||||||
nextRenderFrameMeleeBullets = append(nextRenderFrameMeleeBullets, &newMeleeBullet)
|
newBullet.OriginatedRenderFrameId = currRenderFrame.Id
|
||||||
thatPlayerInNextFrame.FramesToRecover = newMeleeBullet.RecoveryFrames
|
newBullet.OffenderJoinIndex = joinIndex
|
||||||
|
nextRenderFrameMeleeBullets = append(nextRenderFrameMeleeBullets, &newBullet)
|
||||||
|
thatPlayerInNextFrame.FramesToRecover = skillConfig.RecoveryFrames
|
||||||
|
}
|
||||||
thatPlayerInNextFrame.CharacterState = ATK_CHARACTER_STATE_ATK1
|
thatPlayerInNextFrame.CharacterState = ATK_CHARACTER_STATE_ATK1
|
||||||
if false == currPlayerDownsync.InAir {
|
if false == currPlayerDownsync.InAir {
|
||||||
thatPlayerInNextFrame.VelX = 0
|
thatPlayerInNextFrame.VelX = 0
|
||||||
@ -453,13 +457,14 @@ func ApplyInputFrameDownsyncDynamicsOnSingleRenderFrame(inputsBuffer *RingBuffer
|
|||||||
collisionPlayerIndex := COLLISION_PLAYER_INDEX_PREFIX + joinIndex
|
collisionPlayerIndex := COLLISION_PLAYER_INDEX_PREFIX + joinIndex
|
||||||
playerCollider := collisionSysMap[collisionPlayerIndex]
|
playerCollider := collisionSysMap[collisionPlayerIndex]
|
||||||
thatPlayerInNextFrame := nextRenderFramePlayers[i]
|
thatPlayerInNextFrame := nextRenderFramePlayers[i]
|
||||||
|
chConfig := chConfigsOrderedByJoinIndex[i]
|
||||||
// Reset playerCollider position from the "virtual grid position"
|
// Reset playerCollider position from the "virtual grid position"
|
||||||
newVx, newVy := currPlayerDownsync.VirtualGridX+currPlayerDownsync.VelX, currPlayerDownsync.VirtualGridY+currPlayerDownsync.VelY
|
newVx, newVy := currPlayerDownsync.VirtualGridX+currPlayerDownsync.VelX, currPlayerDownsync.VirtualGridY+currPlayerDownsync.VelY
|
||||||
if jumpedOrNotList[i] {
|
if jumpedOrNotList[i] {
|
||||||
newVy += int32(chConfigsOrderedByJoinIndex[i].JumpingInitVelY) // Immediately gets out of any snapping
|
newVy += chConfig.JumpingInitVelY // Immediately gets out of any snapping
|
||||||
}
|
}
|
||||||
|
|
||||||
playerCollider.X, playerCollider.Y = VirtualGridToPolygonColliderBLPos(newVx, newVy, playerCollider.W*0.5, playerCollider.H*0.5, 0, 0, 0, 0, collisionSpaceOffsetX, collisionSpaceOffsetY, VIRTUAL_GRID_TO_WORLD_RATIO)
|
playerCollider.X, playerCollider.Y = VirtualGridToPolygonColliderBLPos(newVx, newVy, playerCollider.W*0.5, playerCollider.H*0.5, 0, 0, 0, 0, collisionSpaceOffsetX, collisionSpaceOffsetY)
|
||||||
// Update in the collision system
|
// Update in the collision system
|
||||||
playerCollider.Update()
|
playerCollider.Update()
|
||||||
|
|
||||||
@ -475,13 +480,13 @@ func ApplyInputFrameDownsyncDynamicsOnSingleRenderFrame(inputsBuffer *RingBuffer
|
|||||||
if (meleeBullet.OriginatedRenderFrameId+meleeBullet.StartupFrames <= currRenderFrame.Id) && (meleeBullet.OriginatedRenderFrameId+meleeBullet.StartupFrames+meleeBullet.ActiveFrames > currRenderFrame.Id) {
|
if (meleeBullet.OriginatedRenderFrameId+meleeBullet.StartupFrames <= currRenderFrame.Id) && (meleeBullet.OriginatedRenderFrameId+meleeBullet.StartupFrames+meleeBullet.ActiveFrames > currRenderFrame.Id) {
|
||||||
offender := currRenderFrame.PlayersArr[meleeBullet.OffenderJoinIndex-1]
|
offender := currRenderFrame.PlayersArr[meleeBullet.OffenderJoinIndex-1]
|
||||||
|
|
||||||
xfac := float64(1.0) // By now, straight Punch offset doesn't respect "y-axis"
|
xfac := int32(1) // By now, straight Punch offset doesn't respect "y-axis"
|
||||||
if 0 > offender.DirX {
|
if 0 > offender.DirX {
|
||||||
xfac = float64(-1.0)
|
xfac = -xfac
|
||||||
}
|
}
|
||||||
offenderWx, offenderWy := VirtualGridToWorldPos(offender.VirtualGridX, offender.VirtualGridY, VIRTUAL_GRID_TO_WORLD_RATIO)
|
bulletWx, bulletWy := VirtualGridToWorldPos(offender.VirtualGridX+xfac*meleeBullet.HitboxOffsetX, offender.VirtualGridY)
|
||||||
bulletWx, bulletWy := offenderWx+xfac*meleeBullet.HitboxOffset, offenderWy
|
hitboxSizeWx, hitboxSizeWy := VirtualGridToWorldPos(meleeBullet.HitboxSizeX, meleeBullet.HitboxSizeY)
|
||||||
newBulletCollider := GenerateRectCollider(bulletWx, bulletWy, meleeBullet.HitboxSizeX, meleeBullet.HitboxSizeY, SNAP_INTO_PLATFORM_OVERLAP, SNAP_INTO_PLATFORM_OVERLAP, SNAP_INTO_PLATFORM_OVERLAP, SNAP_INTO_PLATFORM_OVERLAP, collisionSpaceOffsetX, collisionSpaceOffsetY, meleeBullet, "MeleeBullet")
|
newBulletCollider := GenerateRectCollider(bulletWx, bulletWy, hitboxSizeWx, hitboxSizeWy, SNAP_INTO_PLATFORM_OVERLAP, SNAP_INTO_PLATFORM_OVERLAP, SNAP_INTO_PLATFORM_OVERLAP, SNAP_INTO_PLATFORM_OVERLAP, collisionSpaceOffsetX, collisionSpaceOffsetY, meleeBullet, "MeleeBullet")
|
||||||
collisionSys.Add(newBulletCollider)
|
collisionSys.Add(newBulletCollider)
|
||||||
bulletColliders = append(bulletColliders, newBulletCollider)
|
bulletColliders = append(bulletColliders, newBulletCollider)
|
||||||
} else {
|
} else {
|
||||||
@ -497,7 +502,9 @@ func ApplyInputFrameDownsyncDynamicsOnSingleRenderFrame(inputsBuffer *RingBuffer
|
|||||||
playerShape := playerCollider.Shape.(*resolv.ConvexPolygon)
|
playerShape := playerCollider.Shape.(*resolv.ConvexPolygon)
|
||||||
hardPushbackNorms[joinIndex-1] = calcHardPushbacksNorms(joinIndex, playerCollider, playerShape, SNAP_INTO_PLATFORM_OVERLAP, &(effPushbacks[joinIndex-1]))
|
hardPushbackNorms[joinIndex-1] = calcHardPushbacksNorms(joinIndex, playerCollider, playerShape, SNAP_INTO_PLATFORM_OVERLAP, &(effPushbacks[joinIndex-1]))
|
||||||
thatPlayerInNextFrame := nextRenderFramePlayers[i]
|
thatPlayerInNextFrame := nextRenderFramePlayers[i]
|
||||||
|
chConfig := chConfigsOrderedByJoinIndex[i]
|
||||||
landedOnGravityPushback := false
|
landedOnGravityPushback := false
|
||||||
|
|
||||||
if collision := playerCollider.Check(0, 0); nil != collision {
|
if collision := playerCollider.Check(0, 0); nil != collision {
|
||||||
for _, obj := range collision.Objects {
|
for _, obj := range collision.Objects {
|
||||||
isBarrier, isAnotherPlayer, isBullet := false, false, false
|
isBarrier, isAnotherPlayer, isBullet := false, false, false
|
||||||
@ -547,10 +554,97 @@ func ApplyInputFrameDownsyncDynamicsOnSingleRenderFrame(inputsBuffer *RingBuffer
|
|||||||
// fallStopping
|
// fallStopping
|
||||||
thatPlayerInNextFrame.VelX = 0
|
thatPlayerInNextFrame.VelX = 0
|
||||||
thatPlayerInNextFrame.VelY = 0
|
thatPlayerInNextFrame.VelY = 0
|
||||||
|
if ATK_CHARACTER_STATE_BLOWN_UP1 == thatPlayerInNextFrame.CharacterState {
|
||||||
|
thatPlayerInNextFrame.CharacterState = ATK_CHARACTER_STATE_LAY_DOWN1
|
||||||
|
thatPlayerInNextFrame.FramesToRecover = chConfig.LayDownFramesToRecover
|
||||||
|
} else {
|
||||||
thatPlayerInNextFrame.CharacterState = ATK_CHARACTER_STATE_IDLE1
|
thatPlayerInNextFrame.CharacterState = ATK_CHARACTER_STATE_IDLE1
|
||||||
thatPlayerInNextFrame.FramesToRecover = 0
|
thatPlayerInNextFrame.FramesToRecover = 0
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
// not fallStopping, could be in LayDown or GetUp
|
||||||
|
if ATK_CHARACTER_STATE_LAY_DOWN1 == thatPlayerInNextFrame.CharacterState {
|
||||||
|
if 0 == thatPlayerInNextFrame.FramesToRecover {
|
||||||
|
thatPlayerInNextFrame.CharacterState = ATK_CHARACTER_STATE_GET_UP1
|
||||||
|
thatPlayerInNextFrame.FramesToRecover = chConfig.GetUpFramesToRecover
|
||||||
}
|
}
|
||||||
|
} else if ATK_CHARACTER_STATE_GET_UP1 == thatPlayerInNextFrame.CharacterState {
|
||||||
|
if thatPlayerInNextFrame.FramesInChState == chConfig.GetUpFrames {
|
||||||
|
// [WARNING] Before reaching here, the player had 3 invinsible frames to either attack or jump, if it ever took any action then this condition wouldn't have been met, thus we hereby only transit it back to IDLE as it took no action
|
||||||
|
thatPlayerInNextFrame.CharacterState = ATK_CHARACTER_STATE_IDLE1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 5. Check bullet-anything collisions
|
||||||
|
for _, bulletCollider := range bulletColliders {
|
||||||
|
collision := bulletCollider.Check(0, 0)
|
||||||
|
bulletCollider.Space.Remove(bulletCollider) // Make sure that the bulletCollider is always removed for each renderFrame
|
||||||
|
switch v := bulletCollider.Data.(type) {
|
||||||
|
case *MeleeBullet:
|
||||||
|
if nil == collision {
|
||||||
|
nextRenderFrameMeleeBullets = append(nextRenderFrameMeleeBullets, v)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
bulletShape := bulletCollider.Shape.(*resolv.ConvexPolygon)
|
||||||
|
offender := currRenderFrame.PlayersArr[v.OffenderJoinIndex-1]
|
||||||
|
for _, obj := range collision.Objects {
|
||||||
|
defenderShape := obj.Shape.(*resolv.ConvexPolygon)
|
||||||
|
switch t := obj.Data.(type) {
|
||||||
|
case *PlayerDownsync:
|
||||||
|
if v.OffenderJoinIndex == t.JoinIndex {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
overlapped, _, _, _ := CalcPushbacks(0, 0, bulletShape, defenderShape)
|
||||||
|
if !overlapped {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
joinIndex := t.JoinIndex
|
||||||
|
xfac := int32(1) // By now, straight Punch offset doesn't respect "y-axis"
|
||||||
|
if 0 > offender.DirX {
|
||||||
|
xfac = -xfac
|
||||||
|
}
|
||||||
|
pushbackX, pushbackY := VirtualGridToWorldPos(-xfac*v.PushbackX, v.PushbackY)
|
||||||
|
|
||||||
|
for _, hardPushbackNorm := range *hardPushbackNorms[joinIndex-1] {
|
||||||
|
projectedMagnitude := pushbackX*hardPushbackNorm.X + pushbackY*hardPushbackNorm.Y
|
||||||
|
if 0 > projectedMagnitude {
|
||||||
|
//fmt.Printf("defenderPlayerId=%d, joinIndex=%d reducing bullet pushback={%.3f, %.3f} by {%.3f, %.3f} where hardPushbackNorm={%.3f, %.3f}, projectedMagnitude=%.3f at renderFrame.id=%d", t.Id, joinIndex, pushbackX, pushbackY, projectedMagnitude*hardPushbackNorm.X, projectedMagnitude*hardPushbackNorm.Y, hardPushbackNorm.X, hardPushbackNorm.Y, projectedMagnitude, currRenderFrame.Id)
|
||||||
|
pushbackX -= projectedMagnitude * hardPushbackNorm.X
|
||||||
|
pushbackY -= projectedMagnitude * hardPushbackNorm.Y
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
effPushbacks[joinIndex-1].X += pushbackX
|
||||||
|
effPushbacks[joinIndex-1].Y += pushbackY
|
||||||
|
atkedPlayerInNextFrame := nextRenderFramePlayers[t.JoinIndex-1]
|
||||||
|
if v.BlowUp {
|
||||||
|
atkedPlayerInNextFrame.CharacterState = ATK_CHARACTER_STATE_BLOWN_UP1
|
||||||
|
} else {
|
||||||
|
atkedPlayerInNextFrame.CharacterState = ATK_CHARACTER_STATE_ATKED1
|
||||||
|
}
|
||||||
|
oldFramesToRecover := nextRenderFramePlayers[t.JoinIndex-1].FramesToRecover
|
||||||
|
if v.HitStunFrames > oldFramesToRecover {
|
||||||
|
atkedPlayerInNextFrame.FramesToRecover = v.HitStunFrames
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 6. Get players out of stuck barriers if there's any
|
||||||
|
for i, currPlayerDownsync := range currRenderFrame.PlayersArr {
|
||||||
|
joinIndex := currPlayerDownsync.JoinIndex
|
||||||
|
collisionPlayerIndex := COLLISION_PLAYER_INDEX_PREFIX + joinIndex
|
||||||
|
playerCollider := collisionSysMap[collisionPlayerIndex]
|
||||||
|
// Update "virtual grid position"
|
||||||
|
thatPlayerInNextFrame := nextRenderFramePlayers[i]
|
||||||
|
thatPlayerInNextFrame.VirtualGridX, thatPlayerInNextFrame.VirtualGridY = PolygonColliderBLToVirtualGridPos(playerCollider.X-effPushbacks[joinIndex-1].X, playerCollider.Y-effPushbacks[joinIndex-1].Y, playerCollider.W*0.5, playerCollider.H*0.5, 0, 0, 0, 0, collisionSpaceOffsetX, collisionSpaceOffsetY)
|
||||||
|
|
||||||
|
// Update "CharacterState"
|
||||||
if thatPlayerInNextFrame.InAir {
|
if thatPlayerInNextFrame.InAir {
|
||||||
oldNextCharacterState := thatPlayerInNextFrame.CharacterState
|
oldNextCharacterState := thatPlayerInNextFrame.CharacterState
|
||||||
switch oldNextCharacterState {
|
switch oldNextCharacterState {
|
||||||
@ -566,70 +660,6 @@ func ApplyInputFrameDownsyncDynamicsOnSingleRenderFrame(inputsBuffer *RingBuffer
|
|||||||
thatPlayerInNextFrame.CharacterState = ATK_CHARACTER_STATE_INAIR_ATKED1
|
thatPlayerInNextFrame.CharacterState = ATK_CHARACTER_STATE_INAIR_ATKED1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// 5. Check bullet-anything collisions
|
|
||||||
for _, bulletCollider := range bulletColliders {
|
|
||||||
meleeBullet := bulletCollider.Data.(*MeleeBullet)
|
|
||||||
bulletShape := bulletCollider.Shape.(*resolv.ConvexPolygon)
|
|
||||||
collision := bulletCollider.Check(0, 0)
|
|
||||||
bulletCollider.Space.Remove(bulletCollider) // Make sure that the bulletCollider is always removed for each renderFrame
|
|
||||||
if nil == collision {
|
|
||||||
nextRenderFrameMeleeBullets = append(nextRenderFrameMeleeBullets, meleeBullet)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
offender := currRenderFrame.PlayersArr[meleeBullet.OffenderJoinIndex-1]
|
|
||||||
for _, obj := range collision.Objects {
|
|
||||||
defenderShape := obj.Shape.(*resolv.ConvexPolygon)
|
|
||||||
switch t := obj.Data.(type) {
|
|
||||||
case *PlayerDownsync:
|
|
||||||
if meleeBullet.OffenderPlayerId == t.Id {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
overlapped, _, _, _ := CalcPushbacks(0, 0, bulletShape, defenderShape)
|
|
||||||
if !overlapped {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
joinIndex := t.JoinIndex
|
|
||||||
xfac := float64(1.0) // By now, straight Punch offset doesn't respect "y-axis"
|
|
||||||
if 0 > offender.DirX {
|
|
||||||
xfac = float64(-1.0)
|
|
||||||
}
|
|
||||||
pushbackX, pushbackY := -xfac*meleeBullet.Pushback, float64(0)
|
|
||||||
|
|
||||||
for _, hardPushbackNorm := range *hardPushbackNorms[joinIndex-1] {
|
|
||||||
projectedMagnitude := pushbackX*hardPushbackNorm.X + pushbackY*hardPushbackNorm.Y
|
|
||||||
if 0 > projectedMagnitude {
|
|
||||||
//fmt.Printf("defenderPlayerId=%d, joinIndex=%d reducing bullet pushback={%.3f, %.3f} by {%.3f, %.3f} where hardPushbackNorm={%.3f, %.3f}, projectedMagnitude=%.3f at renderFrame.id=%d", t.Id, joinIndex, pushbackX, pushbackY, projectedMagnitude*hardPushbackNorm.X, projectedMagnitude*hardPushbackNorm.Y, hardPushbackNorm.X, hardPushbackNorm.Y, projectedMagnitude, currRenderFrame.Id)
|
|
||||||
pushbackX -= projectedMagnitude * hardPushbackNorm.X
|
|
||||||
pushbackY -= projectedMagnitude * hardPushbackNorm.Y
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
effPushbacks[joinIndex-1].X += pushbackX
|
|
||||||
effPushbacks[joinIndex-1].Y += pushbackY
|
|
||||||
atkedPlayerInCurFrame, atkedPlayerInNextFrame := currRenderFrame.PlayersArr[t.JoinIndex-1], nextRenderFramePlayers[t.JoinIndex-1]
|
|
||||||
atkedPlayerInNextFrame.CharacterState = ATK_CHARACTER_STATE_ATKED1
|
|
||||||
if atkedPlayerInCurFrame.InAir {
|
|
||||||
atkedPlayerInNextFrame.CharacterState = ATK_CHARACTER_STATE_INAIR_ATKED1
|
|
||||||
}
|
|
||||||
oldFramesToRecover := nextRenderFramePlayers[t.JoinIndex-1].FramesToRecover
|
|
||||||
if meleeBullet.HitStunFrames > oldFramesToRecover {
|
|
||||||
atkedPlayerInNextFrame.FramesToRecover = meleeBullet.HitStunFrames
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 6. Get players out of stuck barriers if there's any
|
|
||||||
for i, currPlayerDownsync := range currRenderFrame.PlayersArr {
|
|
||||||
joinIndex := currPlayerDownsync.JoinIndex
|
|
||||||
collisionPlayerIndex := COLLISION_PLAYER_INDEX_PREFIX + joinIndex
|
|
||||||
playerCollider := collisionSysMap[collisionPlayerIndex]
|
|
||||||
// Update "virtual grid position"
|
|
||||||
thatPlayerInNextFrame := nextRenderFramePlayers[i]
|
|
||||||
thatPlayerInNextFrame.VirtualGridX, thatPlayerInNextFrame.VirtualGridY = PolygonColliderBLToVirtualGridPos(playerCollider.X-effPushbacks[joinIndex-1].X, playerCollider.Y-effPushbacks[joinIndex-1].Y, playerCollider.W*0.5, playerCollider.H*0.5, 0, 0, 0, 0, collisionSpaceOffsetX, collisionSpaceOffsetY, WORLD_TO_VIRTUAL_GRID_RATIO)
|
|
||||||
if thatPlayerInNextFrame.CharacterState != currPlayerDownsync.CharacterState {
|
if thatPlayerInNextFrame.CharacterState != currPlayerDownsync.CharacterState {
|
||||||
thatPlayerInNextFrame.FramesInChState = 0
|
thatPlayerInNextFrame.FramesInChState = 0
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,23 @@
|
|||||||
package battle
|
package battle
|
||||||
|
|
||||||
|
type CharacterConfig struct {
|
||||||
|
SpeciesId int
|
||||||
|
SpeciesName string
|
||||||
|
|
||||||
|
InAirIdleFrameIdxTurningPoint int
|
||||||
|
InAirIdleFrameIdxTurnedCycle int
|
||||||
|
|
||||||
|
LayDownFrames int32
|
||||||
|
LayDownFramesToRecover int32
|
||||||
|
|
||||||
|
GetUpFrames int32
|
||||||
|
GetUpFramesToRecover int32
|
||||||
|
|
||||||
|
JumpingInitVelY int32
|
||||||
|
|
||||||
|
PatternIdToSkillId map[int]int
|
||||||
|
}
|
||||||
|
|
||||||
var Characters = map[int]*CharacterConfig{
|
var Characters = map[int]*CharacterConfig{
|
||||||
0: &CharacterConfig{
|
0: &CharacterConfig{
|
||||||
SpeciesId: 0,
|
SpeciesId: 0,
|
||||||
@ -8,13 +26,13 @@ var Characters = map[int]*CharacterConfig{
|
|||||||
InAirIdleFrameIdxTurningPoint: 11,
|
InAirIdleFrameIdxTurningPoint: 11,
|
||||||
InAirIdleFrameIdxTurnedCycle: 1,
|
InAirIdleFrameIdxTurnedCycle: 1,
|
||||||
|
|
||||||
LayDownFrames: 16,
|
LayDownFrames: int32(16),
|
||||||
LayDownFramesToRecover: 16,
|
LayDownFramesToRecover: int32(16),
|
||||||
|
|
||||||
GetUpFrames: 33,
|
GetUpFrames: int32(33),
|
||||||
GetUpFramesToRecover: 30, // 3 invinsible frames for just-blown-up character to make a comeback
|
GetUpFramesToRecover: int32(30), // 3 invinsible frames for just-blown-up character to make a comeback
|
||||||
|
|
||||||
JumpingInitVelY: int(float64(8) * WORLD_TO_VIRTUAL_GRID_RATIO),
|
JumpingInitVelY: int32(float64(8) * WORLD_TO_VIRTUAL_GRID_RATIO),
|
||||||
|
|
||||||
PatternIdToSkillId: map[int]int{
|
PatternIdToSkillId: map[int]int{
|
||||||
0: 1, // Atk1
|
0: 1, // Atk1
|
||||||
@ -23,52 +41,51 @@ var Characters = map[int]*CharacterConfig{
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
var skillIdToBullet = map[int]interface{}{
|
var skills = map[int]*Skill{
|
||||||
1: &MeleeBullet{
|
1: &Skill{
|
||||||
|
RecoveryFrames: int32(34),
|
||||||
|
RecoveryFramesOnBlock: int32(34),
|
||||||
|
RecoveryFramesOnHit: int32(34),
|
||||||
|
ReleaseTriggerType: int32(1),
|
||||||
|
Hits: []interface{}{
|
||||||
|
&MeleeBullet{
|
||||||
Bullet: Bullet{
|
Bullet: Bullet{
|
||||||
// for offender
|
|
||||||
StartupFrames: int32(5),
|
StartupFrames: int32(5),
|
||||||
ActiveFrames: int32(10),
|
ActiveFrames: int32(10),
|
||||||
|
HitStunFrames: int32(18),
|
||||||
|
BlockStunFrames: int32(9),
|
||||||
|
Damage: int32(5),
|
||||||
|
PushbackX: int32(float64(8) * WORLD_TO_VIRTUAL_GRID_RATIO),
|
||||||
|
PushbackY: int32(0),
|
||||||
|
HitboxOffsetX: int32(float64(12) * WORLD_TO_VIRTUAL_GRID_RATIO),
|
||||||
|
HitboxOffsetY: int32(0),
|
||||||
|
HitboxSizeX: int32(float64(24) * WORLD_TO_VIRTUAL_GRID_RATIO),
|
||||||
|
HitboxSizeY: int32(float64(32) * WORLD_TO_VIRTUAL_GRID_RATIO),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
2: &Skill{
|
||||||
RecoveryFrames: int32(34),
|
RecoveryFrames: int32(34),
|
||||||
RecoveryFramesOnBlock: int32(34),
|
RecoveryFramesOnBlock: int32(34),
|
||||||
RecoveryFramesOnHit: int32(34),
|
RecoveryFramesOnHit: int32(34),
|
||||||
HitboxOffset: float64(12.0), // should be about the radius of the PlayerCollider
|
ReleaseTriggerType: int32(1),
|
||||||
|
Hits: []interface{}{
|
||||||
// for defender
|
&MeleeBullet{
|
||||||
HitStunFrames: int32(18),
|
|
||||||
BlockStunFrames: int32(9),
|
|
||||||
Pushback: float64(8.0),
|
|
||||||
ReleaseTriggerType: int32(1), // 1: rising-edge, 2: falling-edge
|
|
||||||
Damage: int32(5),
|
|
||||||
|
|
||||||
SelfMoveforwardX: 0,
|
|
||||||
SelfMoveforwardY: 0,
|
|
||||||
HitboxSizeX: 24.0,
|
|
||||||
HitboxSizeY: 32.0,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
2: &MeleeBullet{
|
|
||||||
Bullet: Bullet{
|
Bullet: Bullet{
|
||||||
// for offender
|
|
||||||
StartupFrames: int32(3),
|
StartupFrames: int32(3),
|
||||||
ActiveFrames: int32(20),
|
ActiveFrames: int32(20),
|
||||||
RecoveryFrames: int32(34),
|
|
||||||
RecoveryFramesOnBlock: int32(34),
|
|
||||||
RecoveryFramesOnHit: int32(34),
|
|
||||||
HitboxOffset: float64(16.0), // should be about the radius of the PlayerCollider
|
|
||||||
|
|
||||||
// for defender
|
|
||||||
HitStunFrames: int32(18),
|
HitStunFrames: int32(18),
|
||||||
BlockStunFrames: int32(9),
|
BlockStunFrames: int32(9),
|
||||||
Pushback: float64(6.0),
|
|
||||||
BlowUpVelY: int32(float64(3) * WORLD_TO_VIRTUAL_GRID_RATIO),
|
|
||||||
ReleaseTriggerType: int32(1), // 1: rising-edge, 2: falling-edge
|
|
||||||
Damage: int32(5),
|
Damage: int32(5),
|
||||||
|
PushbackX: int32(float64(6) * WORLD_TO_VIRTUAL_GRID_RATIO),
|
||||||
SelfMoveforwardX: 0,
|
PushbackY: int32(0),
|
||||||
SelfMoveforwardY: 0,
|
HitboxOffsetX: int32(float64(12) * WORLD_TO_VIRTUAL_GRID_RATIO),
|
||||||
HitboxSizeX: 32.0,
|
HitboxOffsetY: int32(0),
|
||||||
HitboxSizeY: 24.0,
|
HitboxSizeX: int32(float64(32) * WORLD_TO_VIRTUAL_GRID_RATIO),
|
||||||
|
HitboxSizeY: int32(float64(24) * WORLD_TO_VIRTUAL_GRID_RATIO),
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -53,30 +53,29 @@ type Barrier struct {
|
|||||||
|
|
||||||
type Bullet struct {
|
type Bullet struct {
|
||||||
// for offender
|
// for offender
|
||||||
BattleLocalId int32
|
OriginatedRenderFrameId int32 // Copied from the first bullet for all subsequent bullets
|
||||||
StartupFrames int32
|
OffenderJoinIndex int32 // Copied to favor collision handling of the dispatched bullet
|
||||||
|
StartupFrames int32 // from "OriginatedRenderFrameId"
|
||||||
|
CancellableStFrame int32 // from "OriginatedRenderFrameId"
|
||||||
|
CancellableEdFrame int32 // from "OriginatedRenderFrameId"
|
||||||
ActiveFrames int32
|
ActiveFrames int32
|
||||||
RecoveryFrames int32
|
|
||||||
RecoveryFramesOnBlock int32
|
|
||||||
RecoveryFramesOnHit int32
|
|
||||||
HitboxOffset float64
|
|
||||||
OriginatedRenderFrameId int32
|
|
||||||
|
|
||||||
// for defender
|
// for defender
|
||||||
HitStunFrames int32
|
HitStunFrames int32
|
||||||
BlockStunFrames int32
|
BlockStunFrames int32
|
||||||
Pushback float64
|
PushbackX int32
|
||||||
ReleaseTriggerType int32
|
PushbackY int32
|
||||||
Damage int32
|
Damage int32
|
||||||
OffenderJoinIndex int32
|
|
||||||
OffenderPlayerId int32
|
|
||||||
|
|
||||||
SelfMoveforwardX float64
|
SelfLockVelX int32
|
||||||
SelfMoveforwardY float64
|
SelfLockVelY int32
|
||||||
HitboxSizeX float64
|
|
||||||
HitboxSizeY float64
|
|
||||||
|
|
||||||
BlowUpVelY int32
|
HitboxOffsetX int32
|
||||||
|
HitboxOffsetY int32
|
||||||
|
HitboxSizeX int32
|
||||||
|
HitboxSizeY int32
|
||||||
|
|
||||||
|
BlowUp bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type MeleeBullet struct {
|
type MeleeBullet struct {
|
||||||
@ -95,7 +94,12 @@ type FireballBullet struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Skill struct {
|
type Skill struct {
|
||||||
Hits []Bullet // Hits within a "Skill" are automatically triggered
|
BattleLocalId int32
|
||||||
|
RecoveryFrames int32
|
||||||
|
RecoveryFramesOnBlock int32
|
||||||
|
RecoveryFramesOnHit int32
|
||||||
|
ReleaseTriggerType int32 // 1: rising-edge, 2: falling-edge
|
||||||
|
Hits []interface{} // Hits within a "Skill" are automatically triggered
|
||||||
}
|
}
|
||||||
|
|
||||||
type RoomDownsyncFrame struct {
|
type RoomDownsyncFrame struct {
|
||||||
@ -114,21 +118,3 @@ type InputFrameDownsync struct {
|
|||||||
InputList []uint64
|
InputList []uint64
|
||||||
ConfirmedList uint64
|
ConfirmedList uint64
|
||||||
}
|
}
|
||||||
|
|
||||||
type CharacterConfig struct {
|
|
||||||
SpeciesId int
|
|
||||||
SpeciesName string
|
|
||||||
|
|
||||||
InAirIdleFrameIdxTurningPoint int
|
|
||||||
InAirIdleFrameIdxTurnedCycle int
|
|
||||||
|
|
||||||
LayDownFrames int
|
|
||||||
LayDownFramesToRecover int
|
|
||||||
|
|
||||||
GetUpFrames int
|
|
||||||
GetUpFramesToRecover int
|
|
||||||
|
|
||||||
JumpingInitVelY int
|
|
||||||
|
|
||||||
PatternIdToSkillId map[int]int
|
|
||||||
}
|
|
||||||
|
@ -64,29 +64,32 @@ func NewPlayerDownsyncJs(id, virtualGridX, virtualGridY, dirX, dirY, velX, velY,
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewMeleeBulletJs(battleLocalId, startupFrames, activeFrames, recoveryFrames, recoveryFramesOnBlock, recoveryFramesOnHit, hitStunFrames, blockStunFrames, releaseTriggerType, damage, offenderJoinIndex, offenderPlayerId int32, pushback, hitboxOffset, selfMoveforwardX, selfMoveforwardY, hitboxSizeX, hitboxSizeY float64) *js.Object {
|
func NewMeleeBulletJs(originatedRenderFrameId, offenderJoinIndex, startupFrames, cancellableStFrame, cancellableEdFrame, activeFrames, hitStunFrames, blockStunFrames, pushbackX, pushbackY, damage, selfLockVelX, selfLockVelY, hitboxOffsetX, hitboxOffsetY, hitboxSizeX, hitboxSizeY int32, blowUp bool) *js.Object {
|
||||||
return js.MakeWrapper(&MeleeBullet{
|
return js.MakeWrapper(&MeleeBullet{
|
||||||
Bullet: Bullet{
|
Bullet: Bullet{
|
||||||
BattleLocalId: battleLocalId,
|
OriginatedRenderFrameId: originatedRenderFrameId,
|
||||||
|
OffenderJoinIndex: offenderJoinIndex,
|
||||||
|
|
||||||
StartupFrames: startupFrames,
|
StartupFrames: startupFrames,
|
||||||
|
CancellableStFrame: cancellableStFrame,
|
||||||
|
CancellableEdFrame: cancellableEdFrame,
|
||||||
ActiveFrames: activeFrames,
|
ActiveFrames: activeFrames,
|
||||||
RecoveryFrames: recoveryFrames,
|
|
||||||
RecoveryFramesOnBlock: recoveryFramesOnBlock,
|
|
||||||
RecoveryFramesOnHit: recoveryFramesOnHit,
|
|
||||||
HitboxOffset: hitboxOffset,
|
|
||||||
HitStunFrames: hitStunFrames,
|
HitStunFrames: hitStunFrames,
|
||||||
BlockStunFrames: blockStunFrames,
|
BlockStunFrames: blockStunFrames,
|
||||||
Pushback: pushback,
|
PushbackX: pushbackX,
|
||||||
ReleaseTriggerType: releaseTriggerType,
|
PushbackY: pushbackY,
|
||||||
Damage: damage,
|
Damage: damage,
|
||||||
|
|
||||||
SelfMoveforwardX: selfMoveforwardX,
|
SelfLockVelX: selfLockVelX,
|
||||||
SelfMoveforwardY: selfMoveforwardY,
|
SelfLockVelY: selfLockVelY,
|
||||||
|
|
||||||
|
HitboxOffsetX: hitboxOffsetX,
|
||||||
|
HitboxOffsetY: hitboxOffsetY,
|
||||||
HitboxSizeX: hitboxSizeX,
|
HitboxSizeX: hitboxSizeX,
|
||||||
HitboxSizeY: hitboxSizeY,
|
HitboxSizeY: hitboxSizeY,
|
||||||
|
|
||||||
OffenderJoinIndex: offenderJoinIndex,
|
BlowUp: blowUp,
|
||||||
OffenderPlayerId: offenderPlayerId,
|
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -110,18 +113,19 @@ func GetCollisionSpaceObjsJs(space *resolv.Space) []*js.Object {
|
|||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
func GenerateRectColliderJs(wx, wy, w, h, topPadding, bottomPadding, leftPadding, rightPadding, spaceOffsetX, spaceOffsetY float64, data interface{}, tag string) *js.Object {
|
func GenerateRectColliderJs(wx, wy, w, h, spaceOffsetX, spaceOffsetY float64, data interface{}, tag string) *js.Object {
|
||||||
/*
|
/*
|
||||||
[WARNING] It's important to note that we don't need "js.MakeFullWrapper" for a call sequence as follows.
|
[WARNING] It's important to note that we don't need "js.MakeFullWrapper" for a call sequence as follows.
|
||||||
```
|
```
|
||||||
var space = gopkgs.NewCollisionSpaceJs(2048, 2048, 8, 8);
|
var space = gopkgs.NewCollisionSpaceJs(2048, 2048, 8, 8);
|
||||||
var a = gopkgs.GenerateRectColliderJs(189, 497, 48, 48, snapIntoPlatformOverlap, snapIntoPlatformOverlap, snapIntoPlatformOverlap, snapIntoPlatformOverlap, spaceOffsetX, spaceOffsetY, "Player");
|
var a = gopkgs.GenerateRectColliderJs(189, 497, 48, 48, spaceOffsetX, spaceOffsetY, "Player");
|
||||||
space.Add(a);
|
space.Add(a);
|
||||||
```
|
```
|
||||||
The "space" variable doesn't need access to the field of "a" in JavaScript level to run "space.Add(...)" method, which is good.
|
The "space" variable doesn't need access to the field of "a" in JavaScript level to run "space.Add(...)" method, which is good.
|
||||||
|
|
||||||
However, the full wrapper access here is used for updating "collider.X/collider.Y" at JavaScript runtime.
|
However, the full wrapper access here is used for updating "collider.X/collider.Y" at JavaScript runtime.
|
||||||
*/
|
*/
|
||||||
|
topPadding, bottomPadding, leftPadding, rightPadding := SNAP_INTO_PLATFORM_OVERLAP, SNAP_INTO_PLATFORM_OVERLAP, SNAP_INTO_PLATFORM_OVERLAP, SNAP_INTO_PLATFORM_OVERLAP
|
||||||
return js.MakeFullWrapper(GenerateRectCollider(wx, wy, w, h, topPadding, bottomPadding, leftPadding, rightPadding, spaceOffsetX, spaceOffsetY, data, tag))
|
return js.MakeFullWrapper(GenerateRectCollider(wx, wy, w, h, topPadding, bottomPadding, leftPadding, rightPadding, spaceOffsetX, spaceOffsetY, data, tag))
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -138,9 +142,9 @@ func GetCharacterConfigsOrderedByJoinIndex(speciesIdList []int) []*js.Object {
|
|||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
func ApplyInputFrameDownsyncDynamicsOnSingleRenderFrameJs(inputsBuffer *RingBuffer, currRenderFrame *RoomDownsyncFrame, collisionSys *resolv.Space, collisionSysMap map[int32]*resolv.Object, collisionSpaceOffsetX, collisionSpaceOffsetY float64, playerOpPatternToSkillId map[int]int, chConfigsOrderedByJoinIndex []*CharacterConfig) *js.Object {
|
func ApplyInputFrameDownsyncDynamicsOnSingleRenderFrameJs(inputsBuffer *RingBuffer, currRenderFrame *RoomDownsyncFrame, collisionSys *resolv.Space, collisionSysMap map[int32]*resolv.Object, collisionSpaceOffsetX, collisionSpaceOffsetY float64, chConfigsOrderedByJoinIndex []*CharacterConfig) *js.Object {
|
||||||
// We need access to all fields of RoomDownsyncFrame for displaying in frontend
|
// We need access to all fields of RoomDownsyncFrame for displaying in frontend
|
||||||
return js.MakeFullWrapper(ApplyInputFrameDownsyncDynamicsOnSingleRenderFrame(inputsBuffer, currRenderFrame, collisionSys, collisionSysMap, collisionSpaceOffsetX, collisionSpaceOffsetY, playerOpPatternToSkillId, chConfigsOrderedByJoinIndex))
|
return js.MakeFullWrapper(ApplyInputFrameDownsyncDynamicsOnSingleRenderFrame(inputsBuffer, currRenderFrame, collisionSys, collisionSysMap, collisionSpaceOffsetX, collisionSpaceOffsetY, chConfigsOrderedByJoinIndex))
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@ -157,9 +161,11 @@ func main() {
|
|||||||
"GenerateRectColliderJs": GenerateRectColliderJs,
|
"GenerateRectColliderJs": GenerateRectColliderJs,
|
||||||
"GenerateConvexPolygonColliderJs": GenerateConvexPolygonColliderJs,
|
"GenerateConvexPolygonColliderJs": GenerateConvexPolygonColliderJs,
|
||||||
"GetCollisionSpaceObjsJs": GetCollisionSpaceObjsJs,
|
"GetCollisionSpaceObjsJs": GetCollisionSpaceObjsJs,
|
||||||
"GetCharacterConfigsOrderedByJoinIndex": GetCharacterConfigsOrderedByJoinIndex,
|
|
||||||
"ApplyInputFrameDownsyncDynamicsOnSingleRenderFrameJs": ApplyInputFrameDownsyncDynamicsOnSingleRenderFrameJs,
|
|
||||||
"WorldToPolygonColliderBLPos": WorldToPolygonColliderBLPos, // No need to wrap primitive return types
|
"WorldToPolygonColliderBLPos": WorldToPolygonColliderBLPos, // No need to wrap primitive return types
|
||||||
"PolygonColliderBLToWorldPos": PolygonColliderBLToWorldPos,
|
"PolygonColliderBLToWorldPos": PolygonColliderBLToWorldPos,
|
||||||
|
"WorldToVirtualGridPos": WorldToVirtualGridPos,
|
||||||
|
"VirtualGridToWorldPos": VirtualGridToWorldPos,
|
||||||
|
"GetCharacterConfigsOrderedByJoinIndex": GetCharacterConfigsOrderedByJoinIndex,
|
||||||
|
"ApplyInputFrameDownsyncDynamicsOnSingleRenderFrameJs": ApplyInputFrameDownsyncDynamicsOnSingleRenderFrameJs,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user