mirror of
https://github.com/genxium/DelayNoMore
synced 2024-12-26 03:39:00 +00:00
Temp broken commit.
This commit is contained in:
parent
c171ebc211
commit
eedcf5c4dc
@ -435,24 +435,6 @@ func (pR *Room) StartBattle() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if 0 == pR.RenderFrameId {
|
|
||||||
for _, player := range pR.PlayersArr {
|
|
||||||
playerId := player.Id
|
|
||||||
thatPlayerBattleState := atomic.LoadInt32(&(player.BattleState)) // Might be changed in "OnPlayerDisconnected/OnPlayerLost" from other threads
|
|
||||||
// [WARNING] DON'T try to send any message to an inactive player!
|
|
||||||
switch thatPlayerBattleState {
|
|
||||||
case PlayerBattleStateIns.DISCONNECTED:
|
|
||||||
case PlayerBattleStateIns.LOST:
|
|
||||||
case PlayerBattleStateIns.EXPELLED_DURING_GAME:
|
|
||||||
case PlayerBattleStateIns.EXPELLED_IN_DISMISSAL:
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
kickoffFrame := pR.RenderFrameBuffer.GetByFrameId(0).(*RoomDownsyncFrame)
|
|
||||||
pR.sendSafely(kickoffFrame, nil, DOWNSYNC_MSG_ACT_BATTLE_START, playerId, true)
|
|
||||||
}
|
|
||||||
Logger.Info(fmt.Sprintf("In `battleMainLoop` for roomId=%v sent out kickoffFrame", pR.Id))
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
[WARNING]
|
[WARNING]
|
||||||
Golang "time.Sleep" is known to be taking longer than specified time to wake up at millisecond granularity, as discussed in https://github.com/golang/go/issues/44343
|
Golang "time.Sleep" is known to be taking longer than specified time to wake up at millisecond granularity, as discussed in https://github.com/golang/go/issues/44343
|
||||||
@ -462,6 +444,24 @@ func (pR *Room) StartBattle() {
|
|||||||
nextRenderFrameId := int32((totalElapsedNanos + pR.dilutedRollbackEstimatedDtNanos - 1) / pR.dilutedRollbackEstimatedDtNanos) // fast ceiling
|
nextRenderFrameId := int32((totalElapsedNanos + pR.dilutedRollbackEstimatedDtNanos - 1) / pR.dilutedRollbackEstimatedDtNanos) // fast ceiling
|
||||||
toSleepNanos := int64(0)
|
toSleepNanos := int64(0)
|
||||||
if nextRenderFrameId > pR.RenderFrameId {
|
if nextRenderFrameId > pR.RenderFrameId {
|
||||||
|
if 0 == pR.RenderFrameId {
|
||||||
|
// It's important to send kickoff frame iff "0 == pR.RenderFrameId && nextRenderFrameId > pR.RenderFrameId", otherwise it might send duplicate kickoff frames
|
||||||
|
for _, player := range pR.PlayersArr {
|
||||||
|
playerId := player.Id
|
||||||
|
thatPlayerBattleState := atomic.LoadInt32(&(player.BattleState)) // Might be changed in "OnPlayerDisconnected/OnPlayerLost" from other threads
|
||||||
|
// [WARNING] DON'T try to send any message to an inactive player!
|
||||||
|
switch thatPlayerBattleState {
|
||||||
|
case PlayerBattleStateIns.DISCONNECTED:
|
||||||
|
case PlayerBattleStateIns.LOST:
|
||||||
|
case PlayerBattleStateIns.EXPELLED_DURING_GAME:
|
||||||
|
case PlayerBattleStateIns.EXPELLED_IN_DISMISSAL:
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
kickoffFrame := pR.RenderFrameBuffer.GetByFrameId(0).(*RoomDownsyncFrame)
|
||||||
|
pR.sendSafely(kickoffFrame, nil, DOWNSYNC_MSG_ACT_BATTLE_START, playerId, true)
|
||||||
|
}
|
||||||
|
Logger.Info(fmt.Sprintf("In `battleMainLoop` for roomId=%v sent out kickoffFrame", pR.Id))
|
||||||
|
}
|
||||||
prevRenderFrameId := pR.RenderFrameId
|
prevRenderFrameId := pR.RenderFrameId
|
||||||
pR.RenderFrameId = nextRenderFrameId
|
pR.RenderFrameId = nextRenderFrameId
|
||||||
|
|
||||||
@ -754,7 +754,7 @@ func (pR *Room) OnDismissed() {
|
|||||||
pR.RollbackEstimatedDtNanos = 16666666 // A little smaller than the actual per frame time, just for logging FAST FRAME
|
pR.RollbackEstimatedDtNanos = 16666666 // A little smaller than the actual per frame time, just for logging FAST FRAME
|
||||||
dilutedServerFps := float64(55.0)
|
dilutedServerFps := float64(55.0)
|
||||||
pR.dilutedRollbackEstimatedDtNanos = int64(float64(pR.RollbackEstimatedDtNanos) * float64(pR.ServerFps) / dilutedServerFps)
|
pR.dilutedRollbackEstimatedDtNanos = int64(float64(pR.RollbackEstimatedDtNanos) * float64(pR.ServerFps) / dilutedServerFps)
|
||||||
pR.BattleDurationFrames = 30 * pR.ServerFps
|
pR.BattleDurationFrames = 60 * pR.ServerFps
|
||||||
pR.BattleDurationNanos = int64(pR.BattleDurationFrames) * (pR.RollbackEstimatedDtNanos + 1)
|
pR.BattleDurationNanos = int64(pR.BattleDurationFrames) * (pR.RollbackEstimatedDtNanos + 1)
|
||||||
pR.InputFrameUpsyncDelayTolerance = 2
|
pR.InputFrameUpsyncDelayTolerance = 2
|
||||||
pR.MaxChasingRenderFramesPerUpdate = 8
|
pR.MaxChasingRenderFramesPerUpdate = 8
|
||||||
@ -1307,8 +1307,6 @@ func (pR *Room) applyInputFrameDownsyncDynamicsOnSingleRenderFrame(delayedInputF
|
|||||||
}
|
}
|
||||||
|
|
||||||
nextRenderFrameMeleeBullets := make([]*MeleeBullet, 0, len(currRenderFrame.MeleeBullets)) // Is there any better way to reduce malloc/free impact, e.g. smart prediction for fixed memory allocation?
|
nextRenderFrameMeleeBullets := make([]*MeleeBullet, 0, len(currRenderFrame.MeleeBullets)) // Is there any better way to reduce malloc/free impact, e.g. smart prediction for fixed memory allocation?
|
||||||
|
|
||||||
// Guaranteed determinism regardless of traversal order
|
|
||||||
effPushbacks := make([]Vec2D, pR.Capacity)
|
effPushbacks := make([]Vec2D, pR.Capacity)
|
||||||
hardPushbackNorms := make([][]Vec2D, pR.Capacity)
|
hardPushbackNorms := make([][]Vec2D, pR.Capacity)
|
||||||
|
|
||||||
@ -1346,7 +1344,9 @@ func (pR *Room) applyInputFrameDownsyncDynamicsOnSingleRenderFrame(delayedInputF
|
|||||||
}
|
}
|
||||||
if !characStateAlreadyInAir && characStateIsInterruptWaivable {
|
if !characStateAlreadyInAir && characStateIsInterruptWaivable {
|
||||||
thatPlayerInNextFrame.VelY = pR.JumpingInitVelY
|
thatPlayerInNextFrame.VelY = pR.JumpingInitVelY
|
||||||
Logger.Info(fmt.Sprintf("playerId=%v, joinIndex=%v triggered a jump at renderFrame.id=%v, delayedInputFrame.id=%v, nextVelY=%v", playerId, joinIndex, currRenderFrame.Id, delayedInputFrame.InputFrameId, thatPlayerInNextFrame.VelY))
|
if 1 == currPlayerDownsync.JoinIndex {
|
||||||
|
Logger.Info(fmt.Sprintf("playerId=%v, joinIndex=%v jumped at {renderFrame.id: %d, virtualX: %d, virtualY: %d, nextVelX: %d, nextVelY: %d}, delayedInputFrame.id=%d", playerId, joinIndex, currRenderFrame.Id, currPlayerDownsync.VirtualGridX, currPlayerDownsync.VirtualGridY, thatPlayerInNextFrame.VelX, thatPlayerInNextFrame.VelY, delayedInputFrame.InputFrameId))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1375,8 +1375,8 @@ func (pR *Room) applyInputFrameDownsyncDynamicsOnSingleRenderFrame(delayedInputF
|
|||||||
if 0 != decodedInput.Dx || 0 != decodedInput.Dy {
|
if 0 != decodedInput.Dx || 0 != decodedInput.Dy {
|
||||||
thatPlayerInNextFrame.DirX = decodedInput.Dx
|
thatPlayerInNextFrame.DirX = decodedInput.Dx
|
||||||
thatPlayerInNextFrame.DirY = decodedInput.Dy
|
thatPlayerInNextFrame.DirY = decodedInput.Dy
|
||||||
thatPlayerInNextFrame.CharacterState = ATK_CHARACTER_STATE_WALKING
|
|
||||||
thatPlayerInNextFrame.VelX = decodedInput.Dx * currPlayerDownsync.Speed
|
thatPlayerInNextFrame.VelX = decodedInput.Dx * currPlayerDownsync.Speed
|
||||||
|
thatPlayerInNextFrame.CharacterState = ATK_CHARACTER_STATE_WALKING
|
||||||
} else {
|
} else {
|
||||||
thatPlayerInNextFrame.CharacterState = ATK_CHARACTER_STATE_IDLE1
|
thatPlayerInNextFrame.CharacterState = ATK_CHARACTER_STATE_IDLE1
|
||||||
thatPlayerInNextFrame.VelX = 0
|
thatPlayerInNextFrame.VelX = 0
|
||||||
@ -1389,6 +1389,7 @@ func (pR *Room) applyInputFrameDownsyncDynamicsOnSingleRenderFrame(delayedInputF
|
|||||||
for _, player := range pR.PlayersArr {
|
for _, player := range pR.PlayersArr {
|
||||||
playerId := player.Id
|
playerId := player.Id
|
||||||
joinIndex := player.JoinIndex
|
joinIndex := player.JoinIndex
|
||||||
|
effPushbacks[joinIndex-1].X, effPushbacks[joinIndex-1].Y = float64(0), float64(0)
|
||||||
collisionPlayerIndex := COLLISION_PLAYER_INDEX_PREFIX + joinIndex
|
collisionPlayerIndex := COLLISION_PLAYER_INDEX_PREFIX + joinIndex
|
||||||
playerCollider := collisionSysMap[collisionPlayerIndex]
|
playerCollider := collisionSysMap[collisionPlayerIndex]
|
||||||
currPlayerDownsync, thatPlayerInNextFrame := currRenderFrame.Players[playerId], nextRenderFramePlayers[playerId]
|
currPlayerDownsync, thatPlayerInNextFrame := currRenderFrame.Players[playerId], nextRenderFramePlayers[playerId]
|
||||||
@ -1448,67 +1449,77 @@ func (pR *Room) applyInputFrameDownsyncDynamicsOnSingleRenderFrame(delayedInputF
|
|||||||
currPlayerDownsync, thatPlayerInNextFrame := currRenderFrame.Players[playerId], nextRenderFramePlayers[playerId]
|
currPlayerDownsync, thatPlayerInNextFrame := currRenderFrame.Players[playerId], nextRenderFramePlayers[playerId]
|
||||||
fallStopping := false
|
fallStopping := false
|
||||||
possiblyFallStoppedOnAnotherPlayer := false
|
possiblyFallStoppedOnAnotherPlayer := false
|
||||||
if collision := playerCollider.Check(0, 0); collision != nil {
|
collision := playerCollider.Check(0, 0)
|
||||||
for _, obj := range collision.Objects {
|
if nil == collision {
|
||||||
isBarrier, isAnotherPlayer, isBullet := false, false, false
|
continue
|
||||||
switch obj.Data.(type) {
|
}
|
||||||
case *Barrier:
|
for _, obj := range collision.Objects {
|
||||||
isBarrier = true
|
isBarrier, isAnotherPlayer, isBullet := false, false, false
|
||||||
case *Player:
|
switch obj.Data.(type) {
|
||||||
isAnotherPlayer = true
|
case *Barrier:
|
||||||
case *MeleeBullet:
|
isBarrier = true
|
||||||
isBullet = true
|
case *Player:
|
||||||
}
|
isAnotherPlayer = true
|
||||||
if isBullet {
|
case *MeleeBullet:
|
||||||
// ignore bullets for this step
|
isBullet = true
|
||||||
continue
|
}
|
||||||
}
|
if isBullet {
|
||||||
bShape := obj.Shape.(*resolv.ConvexPolygon)
|
// ignore bullets for this step
|
||||||
if overlapped, pushbackX, pushbackY, overlapResult := CalcPushbacks(0, 0, playerShape, bShape); overlapped {
|
continue
|
||||||
normAlignmentWithGravity := (overlapResult.OverlapX*float64(0) + overlapResult.OverlapY*float64(-1.0))
|
}
|
||||||
landedOnGravityPushback := (pR.SnapIntoPlatformThreshold < normAlignmentWithGravity) // prevents false snapping on the lateral sides
|
bShape := obj.Shape.(*resolv.ConvexPolygon)
|
||||||
if landedOnGravityPushback {
|
overlapped, pushbackX, pushbackY, overlapResult := CalcPushbacks(0, 0, playerShape, bShape)
|
||||||
// kindly note that one player might land on top of another player, and snapping is also required in such case
|
if !overlapped {
|
||||||
pushbackX, pushbackY = (overlapResult.Overlap-pR.SnapIntoPlatformOverlap)*overlapResult.OverlapX, (overlapResult.Overlap-pR.SnapIntoPlatformOverlap)*overlapResult.OverlapY
|
continue
|
||||||
thatPlayerInNextFrame.InAir = false
|
}
|
||||||
}
|
normAlignmentWithGravity := (overlapResult.OverlapX*float64(0) + overlapResult.OverlapY*float64(-1.0))
|
||||||
for _, hardPushbackNorm := range hardPushbackNorms[joinIndex-1] {
|
landedOnGravityPushback := (pR.SnapIntoPlatformThreshold < normAlignmentWithGravity) // prevents false snapping on the lateral sides
|
||||||
projectedMagnitude := pushbackX*hardPushbackNorm.X + pushbackY*hardPushbackNorm.Y
|
if landedOnGravityPushback {
|
||||||
if isBarrier || (0 > projectedMagnitude && isAnotherPlayer) {
|
// kindly note that one player might land on top of another player, and snapping is also required in such case
|
||||||
pushbackX -= projectedMagnitude * hardPushbackNorm.X
|
pushbackX, pushbackY = (overlapResult.Overlap-pR.SnapIntoPlatformOverlap)*overlapResult.OverlapX, (overlapResult.Overlap-pR.SnapIntoPlatformOverlap)*overlapResult.OverlapY
|
||||||
pushbackY -= projectedMagnitude * hardPushbackNorm.Y
|
thatPlayerInNextFrame.InAir = false
|
||||||
}
|
}
|
||||||
}
|
for _, hardPushbackNorm := range hardPushbackNorms[joinIndex-1] {
|
||||||
if currPlayerDownsync.InAir && landedOnGravityPushback {
|
projectedMagnitude := pushbackX*hardPushbackNorm.X + pushbackY*hardPushbackNorm.Y
|
||||||
fallStopping = true
|
if isBarrier || (isAnotherPlayer && 0 > projectedMagnitude) {
|
||||||
if isAnotherPlayer {
|
pushbackX -= projectedMagnitude * hardPushbackNorm.X
|
||||||
possiblyFallStoppedOnAnotherPlayer = true
|
pushbackY -= projectedMagnitude * hardPushbackNorm.Y
|
||||||
}
|
|
||||||
}
|
|
||||||
effPushbacks[joinIndex-1].X += pushbackX
|
|
||||||
effPushbacks[joinIndex-1].Y += pushbackY
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if fallStopping {
|
effPushbacks[joinIndex-1].X += pushbackX
|
||||||
thatPlayerInNextFrame.VelX = 0
|
effPushbacks[joinIndex-1].Y += pushbackY
|
||||||
thatPlayerInNextFrame.VelY = 0
|
if currPlayerDownsync.InAir && landedOnGravityPushback {
|
||||||
thatPlayerInNextFrame.CharacterState = ATK_CHARACTER_STATE_IDLE1
|
fallStopping = true
|
||||||
thatPlayerInNextFrame.FramesToRecover = 0
|
if isAnotherPlayer {
|
||||||
if possiblyFallStoppedOnAnotherPlayer {
|
possiblyFallStoppedOnAnotherPlayer = true
|
||||||
Logger.Info(fmt.Sprintf("playerId=%d, joinIndex=%d possiblyFallStoppedOnAnotherPlayer with effPushback={%.2f, %.2f} at renderFrame.id=%d", playerId, joinIndex, effPushbacks[joinIndex-1].X, effPushbacks[joinIndex-1].Y, currRenderFrame.Id))
|
}
|
||||||
|
if 1 == thatPlayerInNextFrame.JoinIndex {
|
||||||
|
Logger.Info(fmt.Sprintf("playerId=%d, joinIndex=%d fallStopping#1 at {renderFrame.id: %d, virtualX: %d, virtualY: %d, velX: %d, velY: %d} with effPushback={%.3f, %.3f}, overlapMag=%.4f, possiblyFallStoppedOnAnotherPlayer=%v", playerId, joinIndex, currRenderFrame.Id, currPlayerDownsync.VirtualGridX, currPlayerDownsync.VirtualGridY, currPlayerDownsync.VelX, currPlayerDownsync.VelY, effPushbacks[joinIndex-1].X, effPushbacks[joinIndex-1].Y, overlapResult.Overlap, possiblyFallStoppedOnAnotherPlayer))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if currPlayerDownsync.InAir {
|
if 1 == joinIndex && currPlayerDownsync.InAir && isBarrier && !landedOnGravityPushback {
|
||||||
switch thatPlayerInNextFrame.CharacterState {
|
Logger.Warn(fmt.Sprintf("playerId=%d, joinIndex=%d inAir & pushed back by barrier & not landed at {renderFrame.id: %d, virtualX: %d, virtualY: %d, velX: %d, velY: %d} with effPushback={%.3f, %.3f}, playerColliderPos={%.3f, %.3f}, barrierPos={%.3f, %.3f}, overlapMag=%.4f, len(hardPushbackNorms)=%d", playerId, joinIndex, currRenderFrame.Id, currPlayerDownsync.VirtualGridX, currPlayerDownsync.VirtualGridY, currPlayerDownsync.VelX, currPlayerDownsync.VelY, effPushbacks[joinIndex-1].X, effPushbacks[joinIndex-1].Y, playerCollider.X-pR.collisionSpaceOffsetX, playerCollider.Y-pR.collisionSpaceOffsetY, bShape.X-pR.collisionSpaceOffsetX, bShape.Y-pR.collisionSpaceOffsetY, overlapResult.Overlap, len(hardPushbackNorms)))
|
||||||
case ATK_CHARACTER_STATE_IDLE1:
|
}
|
||||||
case ATK_CHARACTER_STATE_WALKING:
|
if 1 == joinIndex && currPlayerDownsync.InAir && isAnotherPlayer {
|
||||||
thatPlayerInNextFrame.CharacterState = ATK_CHARACTER_STATE_INAIR_IDLE1
|
Logger.Warn(fmt.Sprintf("playerId=%d, joinIndex=%d inAir & pushed back by another player at {renderFrame.id: %d, virtualX: %d, virtualY: %d, velX: %d, velY: %d} with effPushback={%.3f, %.3f}, landedOnGravityPushback=%v, fallStopping=%v, playerColliderPos={%.3f, %.3f}, anotherPlayerColliderPos={%.3f, %.3f}, overlapMag=%.4f, len(hardPushbackNorms)=%d", playerId, joinIndex, currRenderFrame.Id, currPlayerDownsync.VirtualGridX, currPlayerDownsync.VirtualGridY, currPlayerDownsync.VelX, currPlayerDownsync.VelY, effPushbacks[joinIndex-1].X, effPushbacks[joinIndex-1].Y, landedOnGravityPushback, fallStopping, playerCollider.X-pR.collisionSpaceOffsetX, playerCollider.Y-pR.collisionSpaceOffsetY, bShape.X-pR.collisionSpaceOffsetX, bShape.Y-pR.collisionSpaceOffsetY, overlapResult.Overlap, len(hardPushbackNorms)))
|
||||||
case ATK_CHARACTER_STATE_ATK1:
|
}
|
||||||
thatPlayerInNextFrame.CharacterState = ATK_CHARACTER_STATE_INAIR_ATK1
|
}
|
||||||
case ATK_CHARACTER_STATE_ATKED1:
|
if fallStopping {
|
||||||
thatPlayerInNextFrame.CharacterState = ATK_CHARACTER_STATE_INAIR_ATKED1
|
thatPlayerInNextFrame.VelX = 0
|
||||||
default:
|
thatPlayerInNextFrame.VelY = 0
|
||||||
}
|
thatPlayerInNextFrame.CharacterState = ATK_CHARACTER_STATE_IDLE1
|
||||||
|
thatPlayerInNextFrame.FramesToRecover = 0
|
||||||
|
}
|
||||||
|
if currPlayerDownsync.InAir {
|
||||||
|
switch thatPlayerInNextFrame.CharacterState {
|
||||||
|
case ATK_CHARACTER_STATE_IDLE1:
|
||||||
|
case ATK_CHARACTER_STATE_WALKING:
|
||||||
|
thatPlayerInNextFrame.CharacterState = ATK_CHARACTER_STATE_INAIR_IDLE1
|
||||||
|
case ATK_CHARACTER_STATE_ATK1:
|
||||||
|
thatPlayerInNextFrame.CharacterState = ATK_CHARACTER_STATE_INAIR_ATK1
|
||||||
|
case ATK_CHARACTER_STATE_ATKED1:
|
||||||
|
thatPlayerInNextFrame.CharacterState = ATK_CHARACTER_STATE_INAIR_ATKED1
|
||||||
|
default:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1537,7 +1548,7 @@ func (pR *Room) applyInputFrameDownsyncDynamicsOnSingleRenderFrame(delayedInputF
|
|||||||
for _, hardPushbackNorm := range hardPushbackNorms[joinIndex-1] {
|
for _, hardPushbackNorm := range hardPushbackNorms[joinIndex-1] {
|
||||||
projectedMagnitude := pushbackX*hardPushbackNorm.X + pushbackY*hardPushbackNorm.Y
|
projectedMagnitude := pushbackX*hardPushbackNorm.X + pushbackY*hardPushbackNorm.Y
|
||||||
if 0 > projectedMagnitude {
|
if 0 > projectedMagnitude {
|
||||||
Logger.Info(fmt.Sprintf("defenderPlayerId=%d, joinIndex=%d reducing bullet pushback={%.2f, %.2f} by {%.2f, %.2f} where hardPushbackNorm={%.2f, %.2f}, projectedMagnitude=%.2f at renderFrame.id=%d", t.Id, joinIndex, pushbackX, pushbackY, projectedMagnitude*hardPushbackNorm.X, projectedMagnitude*hardPushbackNorm.Y, hardPushbackNorm.X, hardPushbackNorm.Y, projectedMagnitude, currRenderFrame.Id))
|
Logger.Info(fmt.Sprintf("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
|
pushbackX -= projectedMagnitude * hardPushbackNorm.X
|
||||||
pushbackY -= projectedMagnitude * hardPushbackNorm.Y
|
pushbackY -= projectedMagnitude * hardPushbackNorm.Y
|
||||||
}
|
}
|
||||||
@ -1587,16 +1598,29 @@ func (pR *Room) applyInputFrameDownsyncDynamicsOnSingleRenderFrame(delayedInputF
|
|||||||
playerId := player.Id
|
playerId := player.Id
|
||||||
collisionPlayerIndex := COLLISION_PLAYER_INDEX_PREFIX + joinIndex
|
collisionPlayerIndex := COLLISION_PLAYER_INDEX_PREFIX + joinIndex
|
||||||
playerCollider := collisionSysMap[collisionPlayerIndex]
|
playerCollider := collisionSysMap[collisionPlayerIndex]
|
||||||
|
playerShape := playerCollider.Shape.(*resolv.ConvexPolygon)
|
||||||
// Update "virtual grid position"
|
// Update "virtual grid position"
|
||||||
thatPlayerInNextFrame := nextRenderFramePlayers[playerId]
|
currPlayerDownsync, thatPlayerInNextFrame := currRenderFrame.Players[playerId], nextRenderFramePlayers[playerId]
|
||||||
thatPlayerInNextFrame.VirtualGridX, thatPlayerInNextFrame.VirtualGridY = PolygonColliderAnchorToVirtualGridPos(playerCollider.X-effPushbacks[joinIndex-1].X, playerCollider.Y-effPushbacks[joinIndex-1].Y, player.ColliderRadius, player.ColliderRadius, pR.collisionSpaceOffsetX, pR.collisionSpaceOffsetY, pR.WorldToVirtualGridRatio)
|
thatPlayerInNextFrame.VirtualGridX, thatPlayerInNextFrame.VirtualGridY = PolygonColliderAnchorToVirtualGridPos(playerCollider.X-effPushbacks[joinIndex-1].X, playerCollider.Y-effPushbacks[joinIndex-1].Y, player.ColliderRadius, player.ColliderRadius, pR.collisionSpaceOffsetX, pR.collisionSpaceOffsetY, pR.WorldToVirtualGridRatio)
|
||||||
|
|
||||||
|
if 1 == thatPlayerInNextFrame.JoinIndex {
|
||||||
|
if thatPlayerInNextFrame.InAir && (0 != thatPlayerInNextFrame.VelY) {
|
||||||
|
Logger.Info(fmt.Sprintf("playerId=%d, joinIndex=%d inAir trajectory: {nextRenderFrame.id: %d, nextVirtualX: %d, nextVirtualY: %d, nextVelX: %d, nextVelX: %d}, with playerColliderPos={%.3f, %.3f}, effPushback={%.3f, %.3f}", playerId, joinIndex, currRenderFrame.Id+1, thatPlayerInNextFrame.VirtualGridX, thatPlayerInNextFrame.VirtualGridY, thatPlayerInNextFrame.VelX, thatPlayerInNextFrame.VelY, playerShape.X-pR.collisionSpaceOffsetX, playerShape.Y-pR.collisionSpaceOffsetY, effPushbacks[joinIndex-1].X, effPushbacks[joinIndex-1].Y))
|
||||||
|
}
|
||||||
|
if currPlayerDownsync.InAir && !thatPlayerInNextFrame.InAir {
|
||||||
|
Logger.Warn(fmt.Sprintf("playerId=%d, joinIndex=%d fallStopping#2 at {nextRenderFrame.id: %d, nextVirtualX: %d, nextVirtualY: %d, nextVelX: %d, nextVelX: %d}, with playerColliderPos={%.3f, %.3f}, effPushback={%.3f, %.3f}", playerId, joinIndex, currRenderFrame.Id+1, thatPlayerInNextFrame.VirtualGridX, thatPlayerInNextFrame.VirtualGridY, thatPlayerInNextFrame.VelX, thatPlayerInNextFrame.VelY, playerShape.X-pR.collisionSpaceOffsetX, playerShape.Y-pR.collisionSpaceOffsetY, effPushbacks[joinIndex-1].X, effPushbacks[joinIndex-1].Y))
|
||||||
|
}
|
||||||
|
if !currPlayerDownsync.InAir && thatPlayerInNextFrame.InAir {
|
||||||
|
Logger.Warn(fmt.Sprintf("playerId=%d, joinIndex=%d took off at {nextRenderFrame.id: %d, nextVirtualX: %d, nextVirtualY: %d, nextVelX: %d, nextVelX: %d}, with playerColliderPos={%.3f, %.3f}, effPushback={%.3f, %.3f}", playerId, joinIndex, currRenderFrame.Id+1, thatPlayerInNextFrame.VirtualGridX, thatPlayerInNextFrame.VirtualGridY, thatPlayerInNextFrame.VelX, thatPlayerInNextFrame.VelY, playerShape.X-pR.collisionSpaceOffsetX, playerShape.Y-pR.collisionSpaceOffsetY, effPushbacks[joinIndex-1].X, effPushbacks[joinIndex-1].Y))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return &RoomDownsyncFrame{
|
return &RoomDownsyncFrame{
|
||||||
Id: currRenderFrame.Id + 1,
|
Id: currRenderFrame.Id + 1,
|
||||||
Players: nextRenderFramePlayers,
|
Players: nextRenderFramePlayers,
|
||||||
CountdownNanos: (pR.BattleDurationNanos - int64(currRenderFrame.Id)*pR.RollbackEstimatedDtNanos),
|
|
||||||
MeleeBullets: nextRenderFrameMeleeBullets,
|
MeleeBullets: nextRenderFrameMeleeBullets,
|
||||||
|
CountdownNanos: (pR.BattleDurationNanos - int64(currRenderFrame.Id)*pR.RollbackEstimatedDtNanos),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1676,7 +1700,7 @@ func (pR *Room) doBattleMainLoopPerTickBackendDynamicsWithProperLocking(prevRend
|
|||||||
}
|
}
|
||||||
|
|
||||||
if nil != inputsBufferSnapshot {
|
if nil != inputsBufferSnapshot {
|
||||||
Logger.Warn(fmt.Sprintf("roomId=%v, room.RenderFrameId=%v, room.CurDynamicsRenderFrameId=%v, room.LastAllConfirmedInputFrameId=%v, unconfirmedMask=%v", pR.Id, pR.RenderFrameId, pR.CurDynamicsRenderFrameId, pR.LastAllConfirmedInputFrameId, inputsBufferSnapshot.UnconfirmedMask))
|
// Logger.Warn(fmt.Sprintf("roomId=%v, room.RenderFrameId=%v, room.CurDynamicsRenderFrameId=%v, room.LastAllConfirmedInputFrameId=%v, unconfirmedMask=%v", pR.Id, pR.RenderFrameId, pR.CurDynamicsRenderFrameId, pR.LastAllConfirmedInputFrameId, inputsBufferSnapshot.UnconfirmedMask))
|
||||||
pR.downsyncToAllPlayers(inputsBufferSnapshot)
|
pR.downsyncToAllPlayers(inputsBufferSnapshot)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1746,7 +1770,8 @@ func (pR *Room) downsyncToSinglePlayer(playerId int32, player *Player, refRender
|
|||||||
2. reconnection
|
2. reconnection
|
||||||
*/
|
*/
|
||||||
|
|
||||||
toSendInputFrameIdSt, toSendInputFrameIdEd := toSendInputFrameDownsyncsSnapshot[0].InputFrameId, toSendInputFrameDownsyncsSnapshot[len(toSendInputFrameDownsyncsSnapshot)-1].InputFrameId+1
|
//toSendInputFrameIdSt, toSendInputFrameIdEd := toSendInputFrameDownsyncsSnapshot[0].InputFrameId, toSendInputFrameDownsyncsSnapshot[len(toSendInputFrameDownsyncsSnapshot)-1].InputFrameId+1
|
||||||
|
_, toSendInputFrameIdEd := toSendInputFrameDownsyncsSnapshot[0].InputFrameId, toSendInputFrameDownsyncsSnapshot[len(toSendInputFrameDownsyncsSnapshot)-1].InputFrameId+1
|
||||||
if pR.BackendDynamicsEnabled && shouldResyncOverall {
|
if pR.BackendDynamicsEnabled && shouldResyncOverall {
|
||||||
tmp := pR.RenderFrameBuffer.GetByFrameId(refRenderFrameId)
|
tmp := pR.RenderFrameBuffer.GetByFrameId(refRenderFrameId)
|
||||||
if nil == tmp {
|
if nil == tmp {
|
||||||
@ -1759,7 +1784,7 @@ func (pR *Room) downsyncToSinglePlayer(playerId int32, player *Player, refRender
|
|||||||
}
|
}
|
||||||
refRenderFrame.BackendUnconfirmedMask = unconfirmedMask
|
refRenderFrame.BackendUnconfirmedMask = unconfirmedMask
|
||||||
pR.sendSafely(refRenderFrame, toSendInputFrameDownsyncsSnapshot, DOWNSYNC_MSG_ACT_FORCED_RESYNC, playerId, false)
|
pR.sendSafely(refRenderFrame, toSendInputFrameDownsyncsSnapshot, DOWNSYNC_MSG_ACT_FORCED_RESYNC, playerId, false)
|
||||||
Logger.Warn(fmt.Sprintf("Sent refRenderFrameId=%v & inputFrameIds [%d, %d), for roomId=%v, playerId=%d, playerJoinIndex=%d, renderFrameId=%d, curDynamicsRenderFrameId=%d, playerLastSentInputFrameId=%d: InputsBuffer=%v", refRenderFrameId, toSendInputFrameIdSt, toSendInputFrameIdEd, pR.Id, playerId, player.JoinIndex, pR.RenderFrameId, pR.CurDynamicsRenderFrameId, player.LastSentInputFrameId, pR.InputsBufferString(false)))
|
// Logger.Warn(fmt.Sprintf("Sent refRenderFrameId=%v & inputFrameIds [%d, %d), for roomId=%v, playerId=%d, playerJoinIndex=%d, renderFrameId=%d, curDynamicsRenderFrameId=%d, playerLastSentInputFrameId=%d: InputsBuffer=%v", refRenderFrameId, toSendInputFrameIdSt, toSendInputFrameIdEd, pR.Id, playerId, player.JoinIndex, pR.RenderFrameId, pR.CurDynamicsRenderFrameId, player.LastSentInputFrameId, pR.InputsBufferString(false)))
|
||||||
} else {
|
} else {
|
||||||
pR.sendSafely(nil, toSendInputFrameDownsyncsSnapshot, DOWNSYNC_MSG_ACT_INPUT_BATCH, playerId, false)
|
pR.sendSafely(nil, toSendInputFrameDownsyncsSnapshot, DOWNSYNC_MSG_ACT_INPUT_BATCH, playerId, false)
|
||||||
}
|
}
|
||||||
@ -1804,21 +1829,25 @@ func (pR *Room) cloneInputsBuffer(stFrameId, edFrameId int32) []*InputFrameDowns
|
|||||||
|
|
||||||
func (pR *Room) calcHardPushbacksNorms(playerCollider *resolv.Object, playerShape *resolv.ConvexPolygon, snapIntoPlatformOverlap float64, pEffPushback *Vec2D) []Vec2D {
|
func (pR *Room) calcHardPushbacksNorms(playerCollider *resolv.Object, playerShape *resolv.ConvexPolygon, snapIntoPlatformOverlap float64, pEffPushback *Vec2D) []Vec2D {
|
||||||
ret := make([]Vec2D, 0, 10) // no one would simultaneously have more than 5 hardPushbacks
|
ret := make([]Vec2D, 0, 10) // no one would simultaneously have more than 5 hardPushbacks
|
||||||
if collision := playerCollider.Check(0, 0); collision != nil {
|
collision := playerCollider.Check(0, 0)
|
||||||
for _, obj := range collision.Objects {
|
if nil == collision {
|
||||||
switch obj.Data.(type) {
|
return ret
|
||||||
case *Barrier:
|
}
|
||||||
barrierShape := obj.Shape.(*resolv.ConvexPolygon)
|
for _, obj := range collision.Objects {
|
||||||
if overlapped, pushbackX, pushbackY, overlapResult := CalcPushbacks(0, 0, playerShape, barrierShape); overlapped {
|
switch obj.Data.(type) {
|
||||||
// ALWAY snap into hardPushbacks!
|
case *Barrier:
|
||||||
// [OverlapX, OverlapY] is the unit vector that points into the platform
|
barrierShape := obj.Shape.(*resolv.ConvexPolygon)
|
||||||
pushbackX, pushbackY = (overlapResult.Overlap-snapIntoPlatformOverlap)*overlapResult.OverlapX, (overlapResult.Overlap-snapIntoPlatformOverlap)*overlapResult.OverlapY
|
overlapped, pushbackX, pushbackY, overlapResult := CalcPushbacks(0, 0, playerShape, barrierShape)
|
||||||
ret = append(ret, Vec2D{X: overlapResult.OverlapX, Y: overlapResult.OverlapY})
|
if !overlapped {
|
||||||
pEffPushback.X += pushbackX
|
continue
|
||||||
pEffPushback.Y += pushbackY
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
// ALWAY snap into hardPushbacks!
|
||||||
|
// [OverlapX, OverlapY] is the unit vector that points into the platform
|
||||||
|
pushbackX, pushbackY = (overlapResult.Overlap-snapIntoPlatformOverlap)*overlapResult.OverlapX, (overlapResult.Overlap-snapIntoPlatformOverlap)*overlapResult.OverlapY
|
||||||
|
ret = append(ret, Vec2D{X: overlapResult.OverlapX, Y: overlapResult.OverlapY})
|
||||||
|
pEffPushback.X += pushbackX
|
||||||
|
pEffPushback.Y += pushbackY
|
||||||
|
default:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ret
|
return ret
|
||||||
|
@ -34,14 +34,15 @@ func NewWorldColliderDisplay(game *Game, stageDiscreteW, stageDiscreteH, stageTi
|
|||||||
spaceOffsetX := float64(spaceW) * 0.5
|
spaceOffsetX := float64(spaceW) * 0.5
|
||||||
spaceOffsetY := float64(spaceH) * 0.5
|
spaceOffsetY := float64(spaceH) * 0.5
|
||||||
|
|
||||||
virtualGridToWorldRatio := 0.1
|
worldToVirtualGridRatio := float64(1000)
|
||||||
playerDefaultSpeed := 20
|
virtualGridToWorldRatio := float64(1)/worldToVirtualGridRatio
|
||||||
|
playerDefaultSpeed := 1 * worldToVirtualGridRatio
|
||||||
minStep := (int(float64(playerDefaultSpeed)*virtualGridToWorldRatio) << 2)
|
minStep := (int(float64(playerDefaultSpeed)*virtualGridToWorldRatio) << 2)
|
||||||
playerColliderRadius := float64(24)
|
playerColliderRadius := float64(12)
|
||||||
playerColliders := make([]*resolv.Object, len(playerPosList.Eles))
|
playerColliders := make([]*resolv.Object, len(playerPosList.Eles))
|
||||||
space := resolv.NewSpace(int(spaceW), int(spaceH), minStep, minStep)
|
space := resolv.NewSpace(int(spaceW), int(spaceH), minStep, minStep)
|
||||||
for i, playerPos := range playerPosList.Eles {
|
for i, playerPos := range playerPosList.Eles {
|
||||||
playerCollider := GenerateRectCollider(playerPos.X, playerPos.Y, playerColliderRadius*2, playerColliderRadius*2, spaceOffsetX, spaceOffsetY, "Player") // [WARNING] Deliberately not using a circle because "resolv v0.5.1" doesn't yet align circle center with space cell center, regardless of the "specified within-object offset"
|
playerCollider := GenerateRectCollider(playerPos.X, playerPos.Y, playerColliderRadius*2, playerColliderRadius*4, spaceOffsetX, spaceOffsetY, "Player") // [WARNING] Deliberately not using a circle because "resolv v0.5.1" doesn't yet align circle center with space cell center, regardless of the "specified within-object offset"
|
||||||
Logger.Info(fmt.Sprintf("Player Collider#%d: player world pos =(%.2f, %.2f), shape=%v", i, playerPos.X, playerPos.Y, ConvexPolygonStr(playerCollider.Shape.(*resolv.ConvexPolygon))))
|
Logger.Info(fmt.Sprintf("Player Collider#%d: player world pos =(%.2f, %.2f), shape=%v", i, playerPos.X, playerPos.Y, ConvexPolygonStr(playerCollider.Shape.(*resolv.ConvexPolygon))))
|
||||||
playerColliders[i] = playerCollider
|
playerColliders[i] = playerCollider
|
||||||
space.Add(playerCollider)
|
space.Add(playerCollider)
|
||||||
@ -50,33 +51,34 @@ func NewWorldColliderDisplay(game *Game, stageDiscreteW, stageDiscreteH, stageTi
|
|||||||
barrierLocalId := 0
|
barrierLocalId := 0
|
||||||
for _, barrierUnaligned := range barrierList.Eles {
|
for _, barrierUnaligned := range barrierList.Eles {
|
||||||
barrierCollider := GenerateConvexPolygonCollider(barrierUnaligned, spaceOffsetX, spaceOffsetY, "Barrier")
|
barrierCollider := GenerateConvexPolygonCollider(barrierUnaligned, spaceOffsetX, spaceOffsetY, "Barrier")
|
||||||
Logger.Info(fmt.Sprintf("Added barrier: shape=%v", ConvexPolygonStr(barrierCollider.Shape.(*resolv.ConvexPolygon))))
|
Logger.Debug(fmt.Sprintf("Added barrier: shape=%v", ConvexPolygonStr(barrierCollider.Shape.(*resolv.ConvexPolygon))))
|
||||||
space.Add(barrierCollider)
|
space.Add(barrierCollider)
|
||||||
barrierLocalId++
|
barrierLocalId++
|
||||||
}
|
}
|
||||||
|
|
||||||
world.Space = space
|
world.Space = space
|
||||||
|
|
||||||
moveToCollide := false
|
moveToCollide := true
|
||||||
if moveToCollide {
|
if moveToCollide {
|
||||||
newVx, newVy := int32(-2959), int32(-2261)
|
|
||||||
effPushback := Vec2D{X: float64(0), Y: float64(0)}
|
effPushback := Vec2D{X: float64(0), Y: float64(0)}
|
||||||
toTestPlayerCollider := playerColliders[0]
|
toTestPlayerCollider := playerColliders[0]
|
||||||
|
newVx, newVy := int32(43900), int32(-451350)
|
||||||
toTestPlayerCollider.X, toTestPlayerCollider.Y = VirtualGridToPolygonColliderAnchorPos(newVx, newVy, playerColliderRadius, playerColliderRadius, spaceOffsetX, spaceOffsetY, virtualGridToWorldRatio)
|
toTestPlayerCollider.X, toTestPlayerCollider.Y = VirtualGridToPolygonColliderAnchorPos(newVx, newVy, playerColliderRadius, playerColliderRadius, spaceOffsetX, spaceOffsetY, virtualGridToWorldRatio)
|
||||||
|
|
||||||
Logger.Info(fmt.Sprintf("Checking collision for virtual (%d, %d), now playerShape=%v", newVx, newVy, ConvexPolygonStr(toTestPlayerCollider.Shape.(*resolv.ConvexPolygon))))
|
Logger.Info(fmt.Sprintf("Checking collision for playerShape=%v", ConvexPolygonStr(toTestPlayerCollider.Shape.(*resolv.ConvexPolygon))))
|
||||||
|
|
||||||
toTestPlayerCollider.Update()
|
toTestPlayerCollider.Update()
|
||||||
if collision := toTestPlayerCollider.Check(0, 0); collision != nil {
|
if collision := toTestPlayerCollider.Check(0, 0); collision != nil {
|
||||||
playerShape := toTestPlayerCollider.Shape.(*resolv.ConvexPolygon)
|
playerShape := toTestPlayerCollider.Shape.(*resolv.ConvexPolygon)
|
||||||
for _, obj := range collision.Objects {
|
for _, obj := range collision.Objects {
|
||||||
barrierShape := obj.Shape.(*resolv.ConvexPolygon)
|
bShape := obj.Shape.(*resolv.ConvexPolygon)
|
||||||
if overlapped, pushbackX, pushbackY, overlapResult := CalcPushbacks(0, 0, playerShape, barrierShape); overlapped {
|
Logger.Warn(fmt.Sprintf("Checking potential: a=%v, b=%v", ConvexPolygonStr(playerShape), ConvexPolygonStr(bShape)))
|
||||||
Logger.Warn(fmt.Sprintf("Overlapped: a=%v, b=%v, pushbackX=%v, pushbackY=%v", ConvexPolygonStr(playerShape), ConvexPolygonStr(barrierShape), pushbackX, pushbackY))
|
if overlapped, pushbackX, pushbackY, overlapResult := CalcPushbacks(0, 0, playerShape, bShape); overlapped {
|
||||||
|
Logger.Warn(fmt.Sprintf("Overlapped: a=%v, b=%v, pushbackX=%v, pushbackY=%v", ConvexPolygonStr(playerShape), ConvexPolygonStr(bShape), pushbackX, pushbackY))
|
||||||
effPushback.X += pushbackX
|
effPushback.X += pushbackX
|
||||||
effPushback.Y += pushbackY
|
effPushback.Y += pushbackY
|
||||||
} else {
|
} else {
|
||||||
Logger.Warn(fmt.Sprintf("Collided BUT not overlapped: a=%v, b=%v, overlapResult=%v", ConvexPolygonStr(playerShape), ConvexPolygonStr(barrierShape), overlapResult))
|
Logger.Warn(fmt.Sprintf("Collided BUT not overlapped: a=%v, b=%v, overlapResult=%v", ConvexPolygonStr(playerShape), ConvexPolygonStr(bShape), overlapResult))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
toTestPlayerCollider.X -= effPushback.X
|
toTestPlayerCollider.X -= effPushback.X
|
||||||
@ -109,7 +111,7 @@ func NewWorldColliderDisplay(game *Game, stageDiscreteW, stageDiscreteH, stageTi
|
|||||||
ReleaseTriggerType: int32(1), // 1: rising-edge, 2: falling-edge
|
ReleaseTriggerType: int32(1), // 1: rising-edge, 2: falling-edge
|
||||||
Damage: int32(5),
|
Damage: int32(5),
|
||||||
}
|
}
|
||||||
bulletLeftToRight := true
|
bulletLeftToRight := false
|
||||||
if bulletLeftToRight {
|
if bulletLeftToRight {
|
||||||
xfac := float64(1.0)
|
xfac := float64(1.0)
|
||||||
offenderWx, offenderWy := playerPosList.Eles[0].X, playerPosList.Eles[0].Y
|
offenderWx, offenderWy := playerPosList.Eles[0].X, playerPosList.Eles[0].Y
|
||||||
@ -132,7 +134,7 @@ func NewWorldColliderDisplay(game *Game, stageDiscreteW, stageDiscreteH, stageTi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bulletRightToLeft := true
|
bulletRightToLeft := false
|
||||||
if bulletRightToLeft {
|
if bulletRightToLeft {
|
||||||
xfac := float64(-1.0)
|
xfac := float64(-1.0)
|
||||||
offenderWx, offenderWy := playerPosList.Eles[1].X, playerPosList.Eles[1].Y
|
offenderWx, offenderWy := playerPosList.Eles[1].X, playerPosList.Eles[1].Y
|
||||||
@ -177,7 +179,7 @@ func (world *WorldColliderDisplay) Draw(screen *ebiten.Image) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
world.Game.DebugDraw(screen, world.Space)
|
//world.Game.DebugDraw(screen, world.Space)
|
||||||
|
|
||||||
if world.Game.ShowHelpText {
|
if world.Game.ShowHelpText {
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ import (
|
|||||||
func ConvexPolygonStr(body *resolv.ConvexPolygon) string {
|
func ConvexPolygonStr(body *resolv.ConvexPolygon) string {
|
||||||
var s []string = make([]string, len(body.Points))
|
var s []string = make([]string, len(body.Points))
|
||||||
for i, p := range body.Points {
|
for i, p := range body.Points {
|
||||||
s[i] = fmt.Sprintf("[%.2f, %.2f]", p[0]+body.X, p[1]+body.Y)
|
s[i] = fmt.Sprintf("[%.3f, %.3f]", p[0]+body.X, p[1]+body.Y)
|
||||||
}
|
}
|
||||||
|
|
||||||
return fmt.Sprintf("{\n%s\n}", strings.Join(s, ",\n"))
|
return fmt.Sprintf("{\n%s\n}", strings.Join(s, ",\n"))
|
||||||
@ -66,6 +66,7 @@ func CalcPushbacks(oldDx, oldDy float64, playerShape, barrierShape *resolv.Conve
|
|||||||
playerShape.SetPosition(origX, origY)
|
playerShape.SetPosition(origX, origY)
|
||||||
}()
|
}()
|
||||||
playerShape.SetPosition(origX+oldDx, origY+oldDy)
|
playerShape.SetPosition(origX+oldDx, origY+oldDy)
|
||||||
|
|
||||||
overlapResult := &SatResult{
|
overlapResult := &SatResult{
|
||||||
Overlap: 0,
|
Overlap: 0,
|
||||||
OverlapX: 0,
|
OverlapX: 0,
|
||||||
@ -74,7 +75,7 @@ func CalcPushbacks(oldDx, oldDy float64, playerShape, barrierShape *resolv.Conve
|
|||||||
BContainedInA: true,
|
BContainedInA: true,
|
||||||
Axis: vector.Vector{0, 0},
|
Axis: vector.Vector{0, 0},
|
||||||
}
|
}
|
||||||
if overlapped := IsPolygonPairOverlapped(playerShape, barrierShape, overlapResult); overlapped {
|
if overlapped := isPolygonPairOverlapped(playerShape, barrierShape, overlapResult); overlapped {
|
||||||
pushbackX, pushbackY := overlapResult.Overlap*overlapResult.OverlapX, overlapResult.Overlap*overlapResult.OverlapY
|
pushbackX, pushbackY := overlapResult.Overlap*overlapResult.OverlapX, overlapResult.Overlap*overlapResult.OverlapY
|
||||||
return true, pushbackX, pushbackY, overlapResult
|
return true, pushbackX, pushbackY, overlapResult
|
||||||
} else {
|
} else {
|
||||||
@ -91,16 +92,17 @@ type SatResult struct {
|
|||||||
Axis vector.Vector
|
Axis vector.Vector
|
||||||
}
|
}
|
||||||
|
|
||||||
func IsPolygonPairOverlapped(a, b *resolv.ConvexPolygon, result *SatResult) bool {
|
func isPolygonPairOverlapped(a, b *resolv.ConvexPolygon, result *SatResult) bool {
|
||||||
aCnt, bCnt := len(a.Points), len(b.Points)
|
aCnt, bCnt := len(a.Points), len(b.Points)
|
||||||
// Single point case
|
// Single point case
|
||||||
if 1 == aCnt && 1 == bCnt {
|
if 1 == aCnt && 1 == bCnt {
|
||||||
if nil != result {
|
if nil != result {
|
||||||
result.Overlap = 0
|
result.Overlap = 0
|
||||||
}
|
}
|
||||||
return a.Points[0].X() == b.Points[0].X() && a.Points[0].Y() == b.Points[0].Y()
|
return a.Points[0][0] == b.Points[0][0] && a.Points[0][1] == b.Points[0][1]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Logger.Info(fmt.Sprintf("Checking collision between a=%v, b=%v", ConvexPolygonStr(a), ConvexPolygonStr(b)))
|
||||||
if 1 < aCnt {
|
if 1 < aCnt {
|
||||||
for _, axis := range a.SATAxes() {
|
for _, axis := range a.SATAxes() {
|
||||||
if isPolygonPairSeparatedByDir(a, b, axis.Unit(), result) {
|
if isPolygonPairSeparatedByDir(a, b, axis.Unit(), result) {
|
||||||
@ -116,6 +118,7 @@ func IsPolygonPairOverlapped(a, b *resolv.ConvexPolygon, result *SatResult) bool
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
//Logger.Info(fmt.Sprintf("a=%v and b=%v are overlapped", ConvexPolygonStr(a), ConvexPolygonStr(b)))
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@ -137,9 +140,10 @@ func isPolygonPairSeparatedByDir(a, b *resolv.ConvexPolygon, e vector.Vector, re
|
|||||||
e = (-2.98, 1.49).Unit()
|
e = (-2.98, 1.49).Unit()
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
//Logger.Info(fmt.Sprintf("Checking separation between a=%v, b=%v along axis e={%.3f, %.3f}#1", ConvexPolygonStr(a), ConvexPolygonStr(b), e[0], e[1]))
|
||||||
var aStart, aEnd, bStart, bEnd float64 = math.MaxFloat64, -math.MaxFloat64, math.MaxFloat64, -math.MaxFloat64
|
var aStart, aEnd, bStart, bEnd float64 = math.MaxFloat64, -math.MaxFloat64, math.MaxFloat64, -math.MaxFloat64
|
||||||
for _, p := range a.Points {
|
for _, p := range a.Points {
|
||||||
dot := (p.X()+a.X)*e.X() + (p.Y()+a.Y)*e.Y()
|
dot := (p[0]+a.X)*e[0] + (p[1]+a.Y)*e[1]
|
||||||
|
|
||||||
if aStart > dot {
|
if aStart > dot {
|
||||||
aStart = dot
|
aStart = dot
|
||||||
@ -151,7 +155,7 @@ func isPolygonPairSeparatedByDir(a, b *resolv.ConvexPolygon, e vector.Vector, re
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, p := range b.Points {
|
for _, p := range b.Points {
|
||||||
dot := (p.X()+b.X)*e.X() + (p.Y()+b.Y)*e.Y()
|
dot := (p[0]+b.X)*e[0] + (p[1]+b.Y)*e[1]
|
||||||
|
|
||||||
if bStart > dot {
|
if bStart > dot {
|
||||||
bStart = dot
|
bStart = dot
|
||||||
@ -168,7 +172,6 @@ func isPolygonPairSeparatedByDir(a, b *resolv.ConvexPolygon, e vector.Vector, re
|
|||||||
}
|
}
|
||||||
|
|
||||||
if nil != result {
|
if nil != result {
|
||||||
result.Axis = e
|
|
||||||
overlap := float64(0)
|
overlap := float64(0)
|
||||||
|
|
||||||
if aStart < bStart {
|
if aStart < bStart {
|
||||||
@ -209,16 +212,19 @@ func isPolygonPairSeparatedByDir(a, b *resolv.ConvexPolygon, e vector.Vector, re
|
|||||||
absoluteOverlap = -overlap
|
absoluteOverlap = -overlap
|
||||||
}
|
}
|
||||||
|
|
||||||
if 0 == currentOverlap || currentOverlap > absoluteOverlap {
|
if (0 == result.Axis[0] && 0 == result.Axis[1]) || currentOverlap > absoluteOverlap {
|
||||||
var sign float64 = 1
|
var sign float64 = 1
|
||||||
if overlap < 0 {
|
if overlap < 0 {
|
||||||
sign = -1
|
sign = -1
|
||||||
}
|
}
|
||||||
|
|
||||||
result.Overlap = absoluteOverlap
|
result.Overlap = absoluteOverlap
|
||||||
result.OverlapX = e.X() * sign
|
result.OverlapX = e[0] * sign
|
||||||
result.OverlapY = e.Y() * sign
|
result.OverlapY = e[1] * sign
|
||||||
}
|
}
|
||||||
|
|
||||||
|
result.Axis = e
|
||||||
|
//Logger.Info(fmt.Sprintf("Checking separation between a=%v, b=%v along axis e={%.3f, %.3f}#2: aStart=%.3f, aEnd=%.3f, bStart=%.3f, bEnd=%.3f, overlap=%.3f, currentOverlap=%.3f, absoluteOverlap=%.3f, result=%v", ConvexPolygonStr(a), ConvexPolygonStr(b), e[0], e[1], aStart, aEnd, bStart, bEnd, overlap, currentOverlap, absoluteOverlap, result))
|
||||||
}
|
}
|
||||||
|
|
||||||
// the specified unit vector "e" doesn't separate "a" and "b", overlap result is generated
|
// the specified unit vector "e" doesn't separate "a" and "b", overlap result is generated
|
||||||
|
@ -5,14 +5,14 @@
|
|||||||
<tileset firstgid="129" source="tiles2.tsx"/>
|
<tileset firstgid="129" source="tiles2.tsx"/>
|
||||||
<layer id="2" name="Ground" width="128" height="128">
|
<layer id="2" name="Ground" width="128" height="128">
|
||||||
<data encoding="base64" compression="zlib">
|
<data encoding="base64" compression="zlib">
|
||||||
eJzt3DFv00AYgGErFUuHigqBVGYGJP4ECxLqgDrRjak/BImdkZGJ/k8cNUbBSmLnavu75HuGR5WaDum9Z+fi5HzRNM0FAAAAAAAAAAAAAAAAAAAUuNyIfh4s52FL1/8hoegOkf1XG13/b63bPVZnSP//+++j//nZ7n870P+yglb6z9d/F/3P2/p/f72xa2z654ToVvov2z8D/fWP7hDZ/0WB6Gb666+//vrH9K+B/vrrr7/++ut/Wv1/jvy76w39z6v/n9bvPY+tP39+bH3RP7x/6Zh21xR/PJP++uuv//q53PTof/79b3r9Hf/66x/f/+WAKftv0z+2/1D3Xf1/tb4eqetv/VdP/7Ht7xrr/1Mxtv/Y9iv9T8pQ/12NP7Su9rTv9++7O5L+cf13tb/a0u8+R/83rXf6V9P/0Hl/u//U9K+3f8ka8Vj6L99/zBzoj+WUfYdM2X9VQYsa+081xoeUtNf/fPpH0z/3HNBff/31j24R1T96/KNlf/8XPf7R9M9N/9z0z03/3PTPTf/c9M9N/9z0z03/3PTPTf/c9M9N/9z0z03/cq96olvqf9r9rwfM8R01/evp7/ivu3+/t/6nzfpP/6XHe99re2T/VQUtau5/v/G5ab5/evr573f3ge30X6Z/172vmwfRDfWfr/+hvUFD79ciz+vH9I/uUGv/rvP7Z6h9D5n+86p9H2H2/nPv+ax9L2n2/ksd/53arhPpv2z/bg4cS//l+k+5ni+5t4/+9Rz/z50Hpfd3Wup1Qv9xSufB28L+j83T9SX96+hfqu3/sbR/Z855kL0/8R0AAAAAAAAAAAAAAACA5f0FyTyU0g==
|
eJzt3DFv00AYgOEoFUuHigqBVGYGJP4EI+qAOsHG1H/CzsjIRP8njhRLwUpi52L7O/t7hmdpOiT33tmXtJebzWZzAwAAAAAAAAAAAAAAAAAABW73op8H83k+0PZ/Tii6Q2T/7V7b/0fj8YTtCun/f/9T9F+fw/6PPf1vK2il/3T9j9F/3Xav/e3esbHpXhOiW+k/b/8M9Nc/ukNk/1cFopvpr7/++usf078G+uuvv/7666//svr/Gvh793v6r6v/38afE4/t/v780viqf3j/0jFtP1P8eSX99ddf/91zeejQf/39Hzr9rX/99Y/v/7rHmP0P6R/bv6/7sf6/G98u1Pa3/6un/9D2Txv7/6UY2n9o+63+i9LX/1jjT427E+27/bueLqR/XP9j7e8OdLtP0f9d44P+1fQ/d90/7D82/evtX7JHvJT+8/cfMge6Yzlm3z5j9t9W0KLG/mON8Tkl7fVfT/9o+ueeA/rrr7/+0S2i+kePf7Ts7/+ixz+a/rnpn5v+uemfm/656Z+b/rnpn5v+uemfm/656Z+b/rnpn5v+uelf7k1HdEv9l93/vscU/6Omfz39rf+6+3d7679s9n/6zz3ep+7tkf23FbSouf/3ve71vv159BrWf9r+5+75+i/XkP7nzgb1vV+LvK5f0j+6Q639284fr1D7GTL9p1X7OcLs/ac+81n7WdLs/eda/63aPifSf97+7Ry4lP7z9R9zP1/y3T7617P+r50Hpd/vNNd9Qv9hSufB+8L+L40v+lfTv1TT/3Np/9aU8yB7f+I7AAAAAAAAAAAAAAAAAPP7B3wkkY4=
|
||||||
</data>
|
</data>
|
||||||
</layer>
|
</layer>
|
||||||
<objectgroup id="1" name="PlayerStartingPos">
|
<objectgroup id="1" name="PlayerStartingPos">
|
||||||
<object id="135" x="1170" y="1539.67">
|
<object id="135" x="1010" y="1451">
|
||||||
<point/>
|
<point/>
|
||||||
</object>
|
</object>
|
||||||
<object id="137" x="1254" y="1332">
|
<object id="137" x="951" y="1452">
|
||||||
<point/>
|
<point/>
|
||||||
</object>
|
</object>
|
||||||
</objectgroup>
|
</objectgroup>
|
||||||
@ -164,11 +164,6 @@
|
|||||||
</properties>
|
</properties>
|
||||||
<polyline points="0,0 -97.3334,0 -97,17.3333 0,16.6667"/>
|
<polyline points="0,0 -97.3334,0 -97,17.3333 0,16.6667"/>
|
||||||
</object>
|
</object>
|
||||||
<object id="53" x="847.333" y="1423.67" width="15" height="34.3333">
|
|
||||||
<properties>
|
|
||||||
<property name="boundary_type" value="barrier"/>
|
|
||||||
</properties>
|
|
||||||
</object>
|
|
||||||
<object id="54" x="656" y="1503.5" width="80.5" height="15.5">
|
<object id="54" x="656" y="1503.5" width="80.5" height="15.5">
|
||||||
<properties>
|
<properties>
|
||||||
<property name="boundary_type" value="barrier"/>
|
<property name="boundary_type" value="barrier"/>
|
||||||
@ -229,35 +224,6 @@
|
|||||||
<property name="boundary_type" value="barrier"/>
|
<property name="boundary_type" value="barrier"/>
|
||||||
</properties>
|
</properties>
|
||||||
</object>
|
</object>
|
||||||
<object id="68" x="815.833" y="1438.83" width="79.6667" height="17">
|
|
||||||
<properties>
|
|
||||||
<property name="boundary_type" value="barrier"/>
|
|
||||||
</properties>
|
|
||||||
</object>
|
|
||||||
<object id="69" x="863" y="1424">
|
|
||||||
<properties>
|
|
||||||
<property name="boundary_type" value="barrier"/>
|
|
||||||
</properties>
|
|
||||||
<polyline points="0,0 -0.333333,14.3089 15,14.6667"/>
|
|
||||||
</object>
|
|
||||||
<object id="70" x="847.333" y="1424.33">
|
|
||||||
<properties>
|
|
||||||
<property name="boundary_type" value="barrier"/>
|
|
||||||
</properties>
|
|
||||||
<polyline points="0,0 0,14.3333 -15.6667,14.3333"/>
|
|
||||||
</object>
|
|
||||||
<object id="71" x="815.667" y="1439.33">
|
|
||||||
<properties>
|
|
||||||
<property name="boundary_type" value="barrier"/>
|
|
||||||
</properties>
|
|
||||||
<polyline points="0,0 0,17 -15.6667,17"/>
|
|
||||||
</object>
|
|
||||||
<object id="72" x="896.333" y="1439">
|
|
||||||
<properties>
|
|
||||||
<property name="boundary_type" value="barrier"/>
|
|
||||||
</properties>
|
|
||||||
<polyline points="0,0 -0.333333,16.9105 15,17.3334"/>
|
|
||||||
</object>
|
|
||||||
<object id="73" x="783.75" y="1567.5" width="96.25" height="15.5">
|
<object id="73" x="783.75" y="1567.5" width="96.25" height="15.5">
|
||||||
<properties>
|
<properties>
|
||||||
<property name="boundary_type" value="barrier"/>
|
<property name="boundary_type" value="barrier"/>
|
||||||
|
@ -440,7 +440,7 @@
|
|||||||
"array": [
|
"array": [
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
216.67520680312998,
|
216.19964242526865,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
|
@ -454,7 +454,7 @@
|
|||||||
"array": [
|
"array": [
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
216.67520680312998,
|
215.64032554232523,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
|
@ -331,7 +331,7 @@ cc.Class({
|
|||||||
window.mapIns = self;
|
window.mapIns = self;
|
||||||
window.forceBigEndianFloatingNumDecoding = self.forceBigEndianFloatingNumDecoding;
|
window.forceBigEndianFloatingNumDecoding = self.forceBigEndianFloatingNumDecoding;
|
||||||
|
|
||||||
self.showCriticalCoordinateLabels = false;
|
self.showCriticalCoordinateLabels = true;
|
||||||
|
|
||||||
console.warn("+++++++ Map onLoad()");
|
console.warn("+++++++ Map onLoad()");
|
||||||
window.handleClientSessionError = function() {
|
window.handleClientSessionError = function() {
|
||||||
@ -427,6 +427,16 @@ cc.Class({
|
|||||||
mapNode.removeAllChildren();
|
mapNode.removeAllChildren();
|
||||||
self._resetCurrentMatch();
|
self._resetCurrentMatch();
|
||||||
|
|
||||||
|
if (self.showCriticalCoordinateLabels) {
|
||||||
|
const drawer = new cc.Node();
|
||||||
|
drawer.setPosition(cc.v2(0, 0))
|
||||||
|
safelyAddChild(self.node, drawer);
|
||||||
|
setLocalZOrder(drawer, 999);
|
||||||
|
const g = drawer.addComponent(cc.Graphics);
|
||||||
|
g.lineWidth = 2;
|
||||||
|
self.g = g;
|
||||||
|
}
|
||||||
|
|
||||||
tiledMapIns.tmxAsset = tmxAsset;
|
tiledMapIns.tmxAsset = tmxAsset;
|
||||||
const newMapSize = tiledMapIns.getMapSize();
|
const newMapSize = tiledMapIns.getMapSize();
|
||||||
const newTileSize = tiledMapIns.getTileSize();
|
const newTileSize = tiledMapIns.getTileSize();
|
||||||
@ -443,12 +453,14 @@ cc.Class({
|
|||||||
}
|
}
|
||||||
|
|
||||||
let barrierIdCounter = 0;
|
let barrierIdCounter = 0;
|
||||||
const boundaryObjs = tileCollisionManager.extractBoundaryObjects(self.node);
|
const refBoundaryObjs = tileCollisionManager.extractBoundaryObjects(self.node).barriers;
|
||||||
for (let boundaryObj of boundaryObjs.barriers) {
|
const boundaryObjs = parsedBattleColliderInfo.strToPolygon2DListMap;
|
||||||
const x0 = boundaryObj.anchor.x,
|
for (let k = 0; k < boundaryObjs["Barrier"].eles.length; k++) {
|
||||||
y0 = boundaryObj.anchor.y;
|
let boundaryObj = boundaryObjs["Barrier"].eles[k];
|
||||||
|
const refBoundaryObj = refBoundaryObjs[k];
|
||||||
const newBarrierCollider = self.collisionSys.createPolygon(x0, y0, Array.from(boundaryObj, p => {
|
// boundaryObj = refBoundaryObj;
|
||||||
|
const [x0, y0] = [boundaryObj.anchor.x, boundaryObj.anchor.y];
|
||||||
|
const newBarrierCollider = self.collisionSys.createPolygon(x0, y0, Array.from(boundaryObj.points, p => {
|
||||||
return [p.x, p.y];
|
return [p.x, p.y];
|
||||||
}));
|
}));
|
||||||
newBarrierCollider.data = {
|
newBarrierCollider.data = {
|
||||||
@ -967,13 +979,13 @@ cc.Class({
|
|||||||
applyRoomDownsyncFrameDynamics(rdf, prevRdf) {
|
applyRoomDownsyncFrameDynamics(rdf, prevRdf) {
|
||||||
const self = this;
|
const self = this;
|
||||||
for (let [playerId, playerRichInfo] of self.playerRichInfoDict.entries()) {
|
for (let [playerId, playerRichInfo] of self.playerRichInfoDict.entries()) {
|
||||||
const immediatePlayerInfo = rdf.players[playerId];
|
const currPlayerDownsync = rdf.players[playerId];
|
||||||
const prevRdfPlayer = (null == prevRdf ? null : prevRdf.players[playerId]);
|
const prevRdfPlayer = (null == prevRdf ? null : prevRdf.players[playerId]);
|
||||||
const [wx, wy] = self.virtualGridToWorldPos(immediatePlayerInfo.virtualGridX, immediatePlayerInfo.virtualGridY);
|
const [wx, wy] = self.virtualGridToWorldPos(currPlayerDownsync.virtualGridX, currPlayerDownsync.virtualGridY);
|
||||||
//const justJiggling = (self.jigglingEps1D >= Math.abs(wx - playerRichInfo.node.x) && self.jigglingEps1D >= Math.abs(wy - playerRichInfo.node.y));
|
//const justJiggling = (self.jigglingEps1D >= Math.abs(wx - playerRichInfo.node.x) && self.jigglingEps1D >= Math.abs(wy - playerRichInfo.node.y));
|
||||||
playerRichInfo.node.setPosition(wx, wy);
|
playerRichInfo.node.setPosition(wx, wy);
|
||||||
playerRichInfo.scriptIns.updateSpeed(immediatePlayerInfo.speed);
|
playerRichInfo.scriptIns.updateSpeed(currPlayerDownsync.speed);
|
||||||
playerRichInfo.scriptIns.updateCharacterAnim(immediatePlayerInfo, prevRdfPlayer, false);
|
playerRichInfo.scriptIns.updateCharacterAnim(currPlayerDownsync, prevRdfPlayer, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update countdown
|
// Update countdown
|
||||||
@ -1125,7 +1137,9 @@ cc.Class({
|
|||||||
characStateIsInterruptWaivable
|
characStateIsInterruptWaivable
|
||||||
) {
|
) {
|
||||||
thatPlayerInNextFrame.velY = self.jumpingInitVelY;
|
thatPlayerInNextFrame.velY = self.jumpingInitVelY;
|
||||||
console.log(`playerId=${playerId}, joinIndex=${joinIndex} triggered a rising-edge of btnB at renderFrame.id=${currRenderFrame.id}, delayedInputFrame.id=${delayedInputFrame.inputFrameId}, nextVelY=${thatPlayerInNextFrame.velY}, characStateAlreadyInAir=${characStateAlreadyInAir}, characStateIsInterruptWaivable=${characStateIsInterruptWaivable}`);
|
if (1 == joinIndex) {
|
||||||
|
console.log(`playerId=${playerId}, joinIndex=${joinIndex} jumped at {renderFrame.id: ${currRenderFrame.id}, virtualX: ${currPlayerDownsync.virtualGridX}, virtualY: ${currPlayerDownsync.virtualGridY}, nextVelX: ${thatPlayerInNextFrame.velX}, nextVelY: ${thatPlayerInNextFrame.velY}}, delayedInputFrame.id=${delayedInputFrame.inputFrameId}`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1258,15 +1272,26 @@ cc.Class({
|
|||||||
pushback[1] -= projectedMagnitude * hardPushbackNorm[1];
|
pushback[1] -= projectedMagnitude * hardPushbackNorm[1];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
effPushbacks[joinIndex - 1][0] += pushback[0];
|
||||||
|
effPushbacks[joinIndex - 1][1] += pushback[1];
|
||||||
if (currPlayerDownsync.inAir && landedOnGravityPushback) {
|
if (currPlayerDownsync.inAir && landedOnGravityPushback) {
|
||||||
fallStopping = true;
|
fallStopping = true;
|
||||||
if (isAnotherPlayer) {
|
if (isAnotherPlayer) {
|
||||||
possiblyFallStoppedOnAnotherPlayer = true;
|
possiblyFallStoppedOnAnotherPlayer = true;
|
||||||
}
|
}
|
||||||
|
if (1 == thatPlayerInNextFrame.joinIndex) {
|
||||||
|
console.log(`playerId=${playerId}, joinIndex=${currPlayerDownsync.joinIndex} fallStopping#1 at {renderFrame.id: ${currRenderFrame.id}, virtualX: ${currPlayerDownsync.virtualGridX}, virtualY: ${currPlayerDownsync.virtualGridY}, velX: ${currPlayerDownsync.velX}, velY: ${currPlayerDownsync.velY}} with effPushback={${effPushbacks[joinIndex - 1][0].toFixed(3)}, ${effPushbacks[joinIndex - 1][1].toFixed(3)}}, overlayMag=${result.overlap.toFixed(4)}, possiblyFallStoppedOnAnotherPlayer=${possiblyFallStoppedOnAnotherPlayer}`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
effPushbacks[joinIndex - 1][0] += pushback[0];
|
if (1 == joinIndex && currPlayerDownsync.inAir && isBarrier && !landedOnGravityPushback) {
|
||||||
effPushbacks[joinIndex - 1][1] += pushback[1];
|
console.warn(`playerId=${playerId}, joinIndex=${currPlayerDownsync.joinIndex} inAir & pushed back by barrier & not landed at {renderFrame.id: ${currRenderFrame.id}, virtualX: ${currPlayerDownsync.virtualGridX}, virtualY: ${currPlayerDownsync.virtualGridY}, velX: ${currPlayerDownsync.velX}, velY: ${currPlayerDownsync.velY}} with effPushback={${effPushbacks[joinIndex - 1][0].toFixed(3)}, ${effPushbacks[joinIndex - 1][1].toFixed(3)}}, playerColliderPos={${playerCollider.x.toFixed(3)}, ${playerCollider.y.toFixed(3)}}, barrierPos={${potential.x.toFixed(3)}, ${potential.y.toFixed(3)}}, overlayMag=${result.overlap.toFixed(4)}, len(hardPushbackNorms)=${hardPushbackNorms.length}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (1 == joinIndex && currPlayerDownsync.inAir && isAnotherPlayer) {
|
||||||
|
console.warn(`playerId=${playerId}, joinIndex=${currPlayerDownsync.joinIndex} inAir and pushed back by another player at {renderFrame.id: ${currRenderFrame.id}, virtualX: ${currPlayerDownsync.virtualGridX}, virtualY: ${currPlayerDownsync.virtualGridY}, velX: ${currPlayerDownsync.velX}, velY: ${currPlayerDownsync.velY}} with effPushback={${effPushbacks[joinIndex - 1][0].toFixed(3)}, ${effPushbacks[joinIndex - 1][1].toFixed(3)}}, landedOnGravityPushback=${landedOnGravityPushback}, fallStopping=${fallStopping}, playerColliderPos={${playerCollider.x.toFixed(3)}, ${playerCollider.y.toFixed(3)}}, anotherPlayerColliderPos={${potential.x.toFixed(3)}, ${potential.y.toFixed(3)}}, overlayMag=${result.overlap.toFixed(4)}, len(hardPushbackNorms)=${hardPushbackNorms.length}`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fallStopping) {
|
if (fallStopping) {
|
||||||
@ -1274,9 +1299,6 @@ cc.Class({
|
|||||||
thatPlayerInNextFrame.velY = 0;
|
thatPlayerInNextFrame.velY = 0;
|
||||||
thatPlayerInNextFrame.characterState = window.ATK_CHARACTER_STATE.Idle1[0];
|
thatPlayerInNextFrame.characterState = window.ATK_CHARACTER_STATE.Idle1[0];
|
||||||
thatPlayerInNextFrame.framesToRecover = 0;
|
thatPlayerInNextFrame.framesToRecover = 0;
|
||||||
if (possiblyFallStoppedOnAnotherPlayer) {
|
|
||||||
console.log(`playerId=${playerId}, joinIndex=${joinIndex} possiblyFallStoppedOnAnotherPlayer with effPushback=${effPushbacks[joinIndex - 1]} at renderFrame.id=${currRenderFrame.id}`);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (currPlayerDownsync.inAir) {
|
if (currPlayerDownsync.inAir) {
|
||||||
thatPlayerInNextFrame.characterState = window.toInAirConjugate(thatPlayerInNextFrame.characterState);
|
thatPlayerInNextFrame.characterState = window.toInAirConjugate(thatPlayerInNextFrame.characterState);
|
||||||
@ -1307,7 +1329,7 @@ cc.Class({
|
|||||||
// Otherwise when smashing into a wall the atked player would be pushed into the wall first and only got back in the next renderFrame, not what I want here
|
// Otherwise when smashing into a wall the atked player would be pushed into the wall first and only got back in the next renderFrame, not what I want here
|
||||||
bulletPushback[0] -= (projectedMagnitude * hardPushbackNorm[0]);
|
bulletPushback[0] -= (projectedMagnitude * hardPushbackNorm[0]);
|
||||||
bulletPushback[1] -= (projectedMagnitude * hardPushbackNorm[1]);
|
bulletPushback[1] -= (projectedMagnitude * hardPushbackNorm[1]);
|
||||||
// console.log(`playerId=${playerId}, joinIndex=${joinIndex} reducing bulletPushback=${JSON.stringify(bulletPushback)} by ${JSON.stringify([projectedMagnitude * hardPushbackNorm[0], projectedMagnitude * hardPushbackNorm[1]])} where hardPushbackNorm=${JSON.stringify(hardPushbackNorm)}, projectedMagnitude=${projectedMagnitude} at renderFrame.id=${currRenderFrame.id}`);
|
// console.log(`playerId=${playerId}, joinIndex=${joinIndex} reducing bulletPushback=${JSON.stringify(bulletPushback)} by ${JSON.stringify([projectedMagnitude * hardPushbackNorm[0], projectedMagnitude * hardPushbackNorm[1]])} where hardPushbackNorm=${JSON.stringify(hardPushbackNorm)}, projectedMagnitude=${projectedMagnitude} at renderFrame.id=${currRenderFrame.id}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// console.log(`playerId=${playerId}, joinIndex=${joinIndex} is actually pushed back by meleeBullet for bulletPushback=${JSON.stringify(bulletPushback)} at renderFrame.id=${currRenderFrame.id}`);
|
// console.log(`playerId=${playerId}, joinIndex=${joinIndex} is actually pushed back by meleeBullet for bulletPushback=${JSON.stringify(bulletPushback)} at renderFrame.id=${currRenderFrame.id}`);
|
||||||
@ -1348,8 +1370,20 @@ cc.Class({
|
|||||||
const collisionPlayerIndex = self.collisionPlayerIndexPrefix + joinIndex;
|
const collisionPlayerIndex = self.collisionPlayerIndexPrefix + joinIndex;
|
||||||
const playerCollider = collisionSysMap.get(collisionPlayerIndex);
|
const playerCollider = collisionSysMap.get(collisionPlayerIndex);
|
||||||
// Update "virtual grid position"
|
// Update "virtual grid position"
|
||||||
const thatPlayerInNextFrame = nextRenderFramePlayers[playerId];
|
const [currPlayerDownsync, thatPlayerInNextFrame] = [currRenderFrame.players[playerId], nextRenderFramePlayers[playerId]];
|
||||||
[thatPlayerInNextFrame.virtualGridX, thatPlayerInNextFrame.virtualGridY] = self.polygonColliderAnchorToVirtualGridPos(playerCollider.x - effPushbacks[joinIndex - 1][0], playerCollider.y - effPushbacks[joinIndex - 1][1], self.playerRichInfoArr[j].colliderRadius, self.playerRichInfoArr[j].colliderRadius);
|
[thatPlayerInNextFrame.virtualGridX, thatPlayerInNextFrame.virtualGridY] = self.polygonColliderAnchorToVirtualGridPos(playerCollider.x - effPushbacks[joinIndex - 1][0], playerCollider.y - effPushbacks[joinIndex - 1][1], self.playerRichInfoArr[j].colliderRadius, self.playerRichInfoArr[j].colliderRadius);
|
||||||
|
|
||||||
|
if (1 == thatPlayerInNextFrame.joinIndex) {
|
||||||
|
if (thatPlayerInNextFrame.inAir && 0 != thatPlayerInNextFrame.velY) {
|
||||||
|
console.log(`playerId=${playerId}, joinIndex=${thatPlayerInNextFrame.joinIndex} inAir trajectory: {nextRenderFrame.id: ${currRenderFrame.id + 1}, nextVirtualX: ${thatPlayerInNextFrame.virtualGridX}, nextVirtualY: ${thatPlayerInNextFrame.virtualGridY}, nextVelX: ${thatPlayerInNextFrame.velX}, nextVelY: ${thatPlayerInNextFrame.velY}}, with playerColliderPos={${playerCollider.x.toFixed(3)}, ${playerCollider.y.toFixed(3)}}, effPushback={${effPushbacks[joinIndex - 1][0].toFixed(3)}, ${effPushbacks[joinIndex - 1][1].toFixed(3)}}`);
|
||||||
|
}
|
||||||
|
if (currPlayerDownsync.inAir && !thatPlayerInNextFrame.inAir) {
|
||||||
|
console.warn(`playerId=${playerId}, joinIndex=${thatPlayerInNextFrame.joinIndex} fallStopping#2 at {nextRenderFrame.id: ${currRenderFrame.id + 1}, nextVirtualX: ${thatPlayerInNextFrame.virtualGridX}, nextVirtualY: ${thatPlayerInNextFrame.virtualGridY}, nextVelX: ${thatPlayerInNextFrame.velX}, nextVelY: ${thatPlayerInNextFrame.velY}}, with playerColliderPos={${playerCollider.x.toFixed(3)}, ${playerCollider.y.toFixed(3)}}, effPushback={${effPushbacks[joinIndex - 1][0].toFixed(3)}, ${effPushbacks[joinIndex - 1][1].toFixed(3)}}`);
|
||||||
|
}
|
||||||
|
if (!currPlayerDownsync.inAir && thatPlayerInNextFrame.inAir) {
|
||||||
|
console.warn(`playerId=${playerId}, joinIndex=${thatPlayerInNextFrame.joinIndex} took off at {nextRenderFrame.id: ${currRenderFrame.id + 1}, nextVirtualX: ${thatPlayerInNextFrame.virtualGridX}, nextVirtualY: ${thatPlayerInNextFrame.virtualGridY}, nextVelX: ${thatPlayerInNextFrame.velX}, nextVelY: ${thatPlayerInNextFrame.velY}}, with playerColliderPos={${playerCollider.x.toFixed(3)}, ${playerCollider.y.toFixed(3)}}, effPushback={${effPushbacks[joinIndex - 1][0].toFixed(3)}, ${effPushbacks[joinIndex - 1][1].toFixed(3)}}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return window.pb.protos.RoomDownsyncFrame.create({
|
return window.pb.protos.RoomDownsyncFrame.create({
|
||||||
@ -1364,11 +1398,10 @@ cc.Class({
|
|||||||
This function eventually calculates a "RoomDownsyncFrame" where "RoomDownsyncFrame.id == renderFrameIdEd" if not interruptted.
|
This function eventually calculates a "RoomDownsyncFrame" where "RoomDownsyncFrame.id == renderFrameIdEd" if not interruptted.
|
||||||
*/
|
*/
|
||||||
const self = this;
|
const self = this;
|
||||||
let i = renderFrameIdSt,
|
let prevLatestRdf = null,
|
||||||
prevLatestRdf = null,
|
|
||||||
latestRdf = null;
|
latestRdf = null;
|
||||||
|
|
||||||
do {
|
for (let i = renderFrameIdSt; i < renderFrameIdEd; i++) {
|
||||||
latestRdf = self.recentRenderCache.getByFrameId(i); // typed "RoomDownsyncFrame"; [WARNING] When "true == isChasing", this function can be interruptted by "onRoomDownsyncFrame(rdf)" asynchronously anytime, making this line return "null"!
|
latestRdf = self.recentRenderCache.getByFrameId(i); // typed "RoomDownsyncFrame"; [WARNING] When "true == isChasing", this function can be interruptted by "onRoomDownsyncFrame(rdf)" asynchronously anytime, making this line return "null"!
|
||||||
if (null == latestRdf) {
|
if (null == latestRdf) {
|
||||||
console.warn(`Couldn't find renderFrame for i=${i} to rollback, self.renderFrameId=${self.renderFrameId}, lastAllConfirmedRenderFrameId=${self.lastAllConfirmedRenderFrameId}, lastAllConfirmedInputFrameId=${self.lastAllConfirmedInputFrameId}, might've been interruptted by onRoomDownsyncFrame`);
|
console.warn(`Couldn't find renderFrame for i=${i} to rollback, self.renderFrameId=${self.renderFrameId}, lastAllConfirmedRenderFrameId=${self.lastAllConfirmedRenderFrameId}, lastAllConfirmedInputFrameId=${self.lastAllConfirmedInputFrameId}, might've been interruptted by onRoomDownsyncFrame`);
|
||||||
@ -1400,8 +1433,7 @@ cc.Class({
|
|||||||
self.chaserRenderFrameId = latestRdf.id;
|
self.chaserRenderFrameId = latestRdf.id;
|
||||||
}
|
}
|
||||||
self.recentRenderCache.setByFrameId(latestRdf, latestRdf.id);
|
self.recentRenderCache.setByFrameId(latestRdf, latestRdf.id);
|
||||||
++i;
|
}
|
||||||
} while (i < renderFrameIdEd);
|
|
||||||
|
|
||||||
return [prevLatestRdf, latestRdf];
|
return [prevLatestRdf, latestRdf];
|
||||||
},
|
},
|
||||||
@ -1496,6 +1528,7 @@ cc.Class({
|
|||||||
},
|
},
|
||||||
|
|
||||||
calcHardPushbacksNorms(collider, potentials, result, snapIntoPlatformOverlap, effPushback) {
|
calcHardPushbacksNorms(collider, potentials, result, snapIntoPlatformOverlap, effPushback) {
|
||||||
|
const self = this;
|
||||||
let ret = [];
|
let ret = [];
|
||||||
for (const potential of potentials) {
|
for (const potential of potentials) {
|
||||||
if (null == potential.data || !(true == potential.data.hardPushback)) continue;
|
if (null == potential.data || !(true == potential.data.hardPushback)) continue;
|
||||||
|
@ -11,24 +11,28 @@ function polygonStr(body) {
|
|||||||
return JSON.stringify(coords);
|
return JSON.stringify(coords);
|
||||||
}
|
}
|
||||||
|
|
||||||
const playerCollider = collisionSys.createPolygon(1269.665, 1353.335, [[0, 0], [64, 0], [64, 64], [0, 64]]);
|
const playerCollider1 = collisionSys.createPolygon(944.000, 676.000, [[0, 0], [24, 0], [24, 48], [0, 48]]);
|
||||||
|
playerCollider1.data = {isPlayer: true};
|
||||||
|
const playerCollider2 = collisionSys.createPolygon(958.000, 724.000, [[0, 0], [24, 0], [24, 48], [0, 48]]);
|
||||||
|
playerCollider2.data = {isPlayer: true};
|
||||||
|
|
||||||
const barrierCollider1 = collisionSys.createPolygon(1277.7159000000001, 1570.5575, [[642.5696, 319.159], [0, 319.15680000000003], [5.7286, 0], [643.7451, 0.9014999999999986]]);
|
const barrierCollider1 = collisionSys.createPolygon(1277.7159000000001, 1570.5575, [[642.5696, 319.159], [0, 319.15680000000003], [5.7286, 0], [643.7451, 0.9014999999999986]]);
|
||||||
const barrierCollider2 = collisionSys.createPolygon(1289.039, 1318.0805, [[628.626, 54.254500000000064], [0, 56.03250000000003], [0.42449999999999477, 1.1229999999999905], [625.9715000000001, 0]]);
|
const barrierCollider2 = collisionSys.createPolygon(1289.039, 1318.0805, [[628.626, 54.254500000000064], [0, 56.03250000000003], [0.42449999999999477, 1.1229999999999905], [625.9715000000001, 0]]);
|
||||||
const barrierCollider3 = collisionSys.createPolygon(1207, 1310, [[69, 581], [0, 579], [8, 3], [79, 0]]);
|
const barrierCollider3 = collisionSys.createPolygon(1207, 1310, [[69, 581], [0, 579], [8, 3], [79, 0]]);
|
||||||
|
|
||||||
playerCollider.x += -2.98;
|
|
||||||
playerCollider.y += -50.0;
|
|
||||||
collisionSys.update();
|
collisionSys.update();
|
||||||
|
|
||||||
const effPushback = [0.0, 0.0];
|
const effPushback = [0.0, 0.0];
|
||||||
|
|
||||||
const result = collisionSys.createResult();
|
const result = collisionSys.createResult();
|
||||||
|
|
||||||
const potentials = playerCollider.potentials();
|
// Check collision for player1
|
||||||
|
const potentials = playerCollider1.potentials();
|
||||||
for (const barrier of potentials) {
|
for (const potential of potentials) {
|
||||||
if (!playerCollider.collides(barrier, result)) continue;
|
if (null == potential.data || true != potential.data.isPlayer) continue;
|
||||||
|
console.log(`Collided player potential of a=${polygonStr(playerCollider1)}: b=${polygonStr(potential)}`);
|
||||||
|
if (!playerCollider1.collides(potential, result)) continue;
|
||||||
|
console.log(`Collided player of a=${polygonStr(playerCollider1)}: b=${polygonStr(potential)}`);
|
||||||
const pushbackX = result.overlap * result.overlap_x;
|
const pushbackX = result.overlap * result.overlap_x;
|
||||||
const pushbackY = result.overlap * result.overlap_y;
|
const pushbackY = result.overlap * result.overlap_y;
|
||||||
console.log(`Overlapped: a=${polygonStr(result.a)}, b=${polygonStr(result.b)}, pushbackX=${pushbackX}, pushbackY=${pushbackY}`);
|
console.log(`Overlapped: a=${polygonStr(result.a)}, b=${polygonStr(result.b)}, pushbackX=${pushbackX}, pushbackY=${pushbackY}`);
|
||||||
|
Loading…
Reference in New Issue
Block a user