mirror of
https://github.com/genxium/DelayNoMore
synced 2024-12-26 03:39:00 +00:00
Drafted backend handling of melee attack.
This commit is contained in:
parent
fdc296531a
commit
24d5ad9dc8
@ -62,6 +62,13 @@ const (
|
|||||||
MAGIC_LAST_SENT_INPUT_FRAME_ID_READDED = -2
|
MAGIC_LAST_SENT_INPUT_FRAME_ID_READDED = -2
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
ATK_CHARACTER_STATE_IDLE1 = 0
|
||||||
|
ATK_CHARACTER_STATE_WALKING = 1
|
||||||
|
ATK_CHARACTER_STATE_ATK1 = 2
|
||||||
|
ATK_CHARACTER_STATE_ATKED1 = 3
|
||||||
|
)
|
||||||
|
|
||||||
// These directions are chosen such that when speed is changed to "(speedX+delta, speedY+delta)" for any of them, the direction is unchanged.
|
// These directions are chosen such that when speed is changed to "(speedX+delta, speedY+delta)" for any of them, the direction is unchanged.
|
||||||
var DIRECTION_DECODER = [][]int32{
|
var DIRECTION_DECODER = [][]int32{
|
||||||
{0, 0},
|
{0, 0},
|
||||||
@ -166,7 +173,8 @@ type Room struct {
|
|||||||
LastRenderFrameIdTriggeredAt int64
|
LastRenderFrameIdTriggeredAt int64
|
||||||
PlayerDefaultSpeed int32
|
PlayerDefaultSpeed int32
|
||||||
|
|
||||||
BattleColliderInfo // Compositing to send centralized magic numbers
|
BulletBattleLocalIdCounter int32
|
||||||
|
BattleColliderInfo // Compositing to send centralized magic numbers
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pR *Room) updateScore() {
|
func (pR *Room) updateScore() {
|
||||||
@ -353,6 +361,7 @@ func (pR *Room) InputsBufferString(allDetails bool) string {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
f := tmp.(*InputFrameDownsync)
|
f := tmp.(*InputFrameDownsync)
|
||||||
|
//s = append(s, fmt.Sprintf("{inputFrameId: %v, inputList: %v, &inputList: %p, confirmedList: %v}", f.InputFrameId, f.InputList, &(f.InputList), f.ConfirmedList))
|
||||||
s = append(s, fmt.Sprintf("{inputFrameId: %v, inputList: %v, confirmedList: %v}", f.InputFrameId, f.InputList, f.ConfirmedList))
|
s = append(s, fmt.Sprintf("{inputFrameId: %v, inputList: %v, confirmedList: %v}", f.InputFrameId, f.InputList, f.ConfirmedList))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -618,7 +627,6 @@ func (pR *Room) OnBattleCmdReceived(pReq *WsReq) {
|
|||||||
Logger.Debug(fmt.Sprintf("Omitting obsolete inputFrameUpsync: roomId=%v, playerId=%v, clientInputFrameId=%v, InputsBuffer=%v", pR.Id, playerId, clientInputFrameId, pR.InputsBufferString(false)))
|
Logger.Debug(fmt.Sprintf("Omitting obsolete inputFrameUpsync: roomId=%v, playerId=%v, clientInputFrameId=%v, InputsBuffer=%v", pR.Id, playerId, clientInputFrameId, pR.InputsBufferString(false)))
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
bufIndex := pR.toDiscreteInputsBufferIndex(clientInputFrameId, pReq.JoinIndex)
|
bufIndex := pR.toDiscreteInputsBufferIndex(clientInputFrameId, pReq.JoinIndex)
|
||||||
pR.DiscreteInputsBuffer.Store(bufIndex, inputFrameUpsync)
|
pR.DiscreteInputsBuffer.Store(bufIndex, inputFrameUpsync)
|
||||||
|
|
||||||
@ -763,6 +771,7 @@ func (pR *Room) Dismiss() {
|
|||||||
func (pR *Room) OnDismissed() {
|
func (pR *Room) OnDismissed() {
|
||||||
|
|
||||||
// Always instantiates new HeapRAM blocks and let the old blocks die out due to not being retained by any root reference.
|
// Always instantiates new HeapRAM blocks and let the old blocks die out due to not being retained by any root reference.
|
||||||
|
pR.BulletBattleLocalIdCounter = 0
|
||||||
pR.WorldToVirtualGridRatio = float64(1000)
|
pR.WorldToVirtualGridRatio = float64(1000)
|
||||||
pR.VirtualGridToWorldRatio = float64(1.0) / pR.WorldToVirtualGridRatio // this is a one-off computation, should avoid division in iterations
|
pR.VirtualGridToWorldRatio = float64(1.0) / pR.WorldToVirtualGridRatio // this is a one-off computation, should avoid division in iterations
|
||||||
pR.SpAtkLookupFrames = 5
|
pR.SpAtkLookupFrames = 5
|
||||||
@ -774,7 +783,7 @@ func (pR *Room) OnDismissed() {
|
|||||||
pR.PlayerSignalToCloseDict = make(map[int32]SignalToCloseConnCbType)
|
pR.PlayerSignalToCloseDict = make(map[int32]SignalToCloseConnCbType)
|
||||||
pR.JoinIndexBooleanArr = make([]bool, pR.Capacity)
|
pR.JoinIndexBooleanArr = make([]bool, pR.Capacity)
|
||||||
pR.Barriers = make(map[int32]*Barrier)
|
pR.Barriers = make(map[int32]*Barrier)
|
||||||
pR.RenderCacheSize = 256
|
pR.RenderCacheSize = 512
|
||||||
pR.RenderFrameBuffer = NewRingBuffer(pR.RenderCacheSize)
|
pR.RenderFrameBuffer = NewRingBuffer(pR.RenderCacheSize)
|
||||||
pR.DiscreteInputsBuffer = sync.Map{}
|
pR.DiscreteInputsBuffer = sync.Map{}
|
||||||
pR.InputsBuffer = NewRingBuffer((pR.RenderCacheSize >> 2) + 1)
|
pR.InputsBuffer = NewRingBuffer((pR.RenderCacheSize >> 2) + 1)
|
||||||
@ -797,6 +806,34 @@ func (pR *Room) OnDismissed() {
|
|||||||
pR.MaxChasingRenderFramesPerUpdate = 8
|
pR.MaxChasingRenderFramesPerUpdate = 8
|
||||||
|
|
||||||
pR.BackendDynamicsEnabled = true // [WARNING] When "false", recovery upon reconnection wouldn't work!
|
pR.BackendDynamicsEnabled = true // [WARNING] When "false", recovery upon reconnection wouldn't work!
|
||||||
|
punchSkillId := int32(1)
|
||||||
|
if _, existent := pR.MeleeSkillConfig[punchSkillId]; !existent {
|
||||||
|
pR.MeleeSkillConfig = make(map[int32]*MeleeBullet, 0)
|
||||||
|
pR.MeleeSkillConfig[punchSkillId] = &MeleeBullet{
|
||||||
|
// for offender
|
||||||
|
StartupFrames: int32(18),
|
||||||
|
ActiveFrames: int32(42),
|
||||||
|
RecoveryFrames: int32(61), // usually but not always "startupFrames+activeFrames", I hereby set it to be 1 frame more than the actual animation to avoid critical transition, i.e. when the animation is 1 frame from ending but "rdfPlayer.framesToRecover" is already counted 0 and the player triggers an other same attack, making an effective bullet trigger but no animation is played due to same animName is still playing
|
||||||
|
RecoveryFramesOnBlock: int32(61),
|
||||||
|
RecoveryFramesOnHit: int32(61),
|
||||||
|
Moveforward: &Vec2D{
|
||||||
|
X: 0,
|
||||||
|
Y: 0,
|
||||||
|
},
|
||||||
|
HitboxOffset: float64(12.0), // should be about the radius of the PlayerCollider
|
||||||
|
HitboxSize: &Vec2D{
|
||||||
|
X: float64(45.0),
|
||||||
|
Y: float64(32.0),
|
||||||
|
},
|
||||||
|
|
||||||
|
// for defender
|
||||||
|
HitStunFrames: int32(18),
|
||||||
|
BlockStunFrames: int32(9),
|
||||||
|
Pushback: float64(22.0),
|
||||||
|
ReleaseTriggerType: int32(1), // 1: rising-edge, 2: falling-edge
|
||||||
|
Damage: int32(5),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pR.ChooseStage()
|
pR.ChooseStage()
|
||||||
pR.EffectivePlayerCount = 0
|
pR.EffectivePlayerCount = 0
|
||||||
@ -1039,7 +1076,10 @@ func (pR *Room) prefabInputFrameDownsync(inputFrameId int32) *InputFrameDownsync
|
|||||||
panic(fmt.Sprintf("Error prefabbing inputFrameDownsync: roomId=%v, InputsBuffer=%v", pR.Id, pR.InputsBufferString(false)))
|
panic(fmt.Sprintf("Error prefabbing inputFrameDownsync: roomId=%v, InputsBuffer=%v", pR.Id, pR.InputsBufferString(false)))
|
||||||
}
|
}
|
||||||
prevInputFrameDownsync := tmp.(*InputFrameDownsync)
|
prevInputFrameDownsync := tmp.(*InputFrameDownsync)
|
||||||
currInputList := prevInputFrameDownsync.InputList // Would be a clone of the values
|
currInputList := make([]uint64, pR.Capacity) // Would be a clone of the values
|
||||||
|
for i, _ := range currInputList {
|
||||||
|
currInputList[i] = (prevInputFrameDownsync.InputList[i] & uint64(15)) // Don't predict attack input
|
||||||
|
}
|
||||||
currInputFrameDownsync = &InputFrameDownsync{
|
currInputFrameDownsync = &InputFrameDownsync{
|
||||||
InputFrameId: inputFrameId,
|
InputFrameId: inputFrameId,
|
||||||
InputList: currInputList,
|
InputList: currInputList,
|
||||||
@ -1216,38 +1256,52 @@ func (pR *Room) applyInputFrameDownsyncDynamicsOnSingleRenderFrame(delayedInputF
|
|||||||
if 0 > offender.DirX {
|
if 0 > offender.DirX {
|
||||||
xfac = float64(-1.0)
|
xfac = float64(-1.0)
|
||||||
}
|
}
|
||||||
offenderWx, offenderWy := PolygonColliderAnchorToWorldPos(offenderCollider.X, offenderCollider.Y, offender.ColliderRadius, offender.ColliderRadius, pR.collisionSpaceOffsetX, pR.collisionSpaceOffsetY)
|
|
||||||
|
|
||||||
bulletWx, bulletWy := offenderWx+xfac*meleeBullet.HitboxOffset, offenderWy+yfac*meleeBullet.HitboxOffset
|
bulletCx, bulletCy := offenderCollider.X+xfac*meleeBullet.HitboxOffset, offenderCollider.Y+yfac*meleeBullet.HitboxOffset
|
||||||
|
|
||||||
newBulletCollider := GenerateRectCollider(bulletWx, bulletWy, xfac*meleeBullet.HitboxSize.X, meleeBullet.HitboxSize.Y, pR.collisionSpaceOffsetX, pR.collisionSpaceOffsetY, "MeleeBullet")
|
newBulletCollider := GenerateRectCollider(bulletCx, bulletCy, xfac*meleeBullet.HitboxSize.X, meleeBullet.HitboxSize.Y, pR.collisionSpaceOffsetX, pR.collisionSpaceOffsetY, "MeleeBullet")
|
||||||
// newBulletCollider.collisionBulletIndex = collisionBulletIndex
|
newBulletCollider.Data = meleeBullet
|
||||||
// newBulletCollider.offenderPlayerId = meleeBullet.offenderPlayerId
|
|
||||||
// newBulletCollider.pushback = meleeBullet.pushback
|
|
||||||
// newBulletCollider.hitStunFrames = meleeBullet.hitStunFrames
|
|
||||||
collisionSysMap[collisionBulletIndex] = newBulletCollider
|
collisionSysMap[collisionBulletIndex] = newBulletCollider
|
||||||
bulletColliders[collisionBulletIndex] = newBulletCollider
|
bulletColliders[collisionBulletIndex] = newBulletCollider
|
||||||
newBulletCollider.Update()
|
newBulletCollider.Update()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// for _, bulletCollider := range bulletColliders {
|
for _, bulletCollider := range bulletColliders {
|
||||||
// shouldRemove := false
|
shouldRemove := false
|
||||||
// if collision := bulletCollider.Check(0, 0); collision != nil {
|
meleeBullet := bulletCollider.Data.(*MeleeBullet)
|
||||||
// bulletShape := bulletCollider.Shape.(*resolv.ConvexPolygon)
|
collisionBulletIndex := COLLISION_BULLET_INDEX_PREFIX + meleeBullet.BattleLocalId
|
||||||
// for _, obj := range collision.Objects {
|
if collision := bulletCollider.Check(0, 0); collision != nil {
|
||||||
// bShape := obj.Shape.(*resolv.ConvexPolygon)
|
offender := currRenderFrame.Players[meleeBullet.OffenderPlayerId]
|
||||||
// if overlapped, pushbackX, pushbackY, overlapResult := CalcPushbacks(0, 0, bulletShape, bShape); overlapped {
|
bulletShape := bulletCollider.Shape.(*resolv.ConvexPolygon)
|
||||||
// bulletPushbacks[joinIndex-1].X += pushbackX
|
for _, obj := range collision.Objects {
|
||||||
// bulletPushbacks[joinIndex-1].Y += pushbackY
|
switch t := obj.Data.(type) {
|
||||||
// }
|
case Player:
|
||||||
// }
|
defenderShape := obj.Shape.(*resolv.ConvexPolygon)
|
||||||
// shouldRemove = true
|
if meleeBullet.OffenderPlayerId != t.Id {
|
||||||
// }
|
if overlapped, _, _, _ := CalcPushbacks(0, 0, bulletShape, defenderShape); overlapped {
|
||||||
// if shouldRemove {
|
xfac := float64(1.0) // By now, straight Punch offset doesn't respect "y-axis"
|
||||||
// removedBulletsAtCurrFrame[bulletCollider.CollisionBulletIndex] = 1
|
if 0 > offender.DirX {
|
||||||
// }
|
xfac = float64(-1.0)
|
||||||
// }
|
}
|
||||||
|
bulletPushbacks[t.JoinIndex-1].X += xfac * meleeBullet.Pushback
|
||||||
|
nextRenderFramePlayers[t.Id].CharacterState = ATK_CHARACTER_STATE_ATKED1
|
||||||
|
oldFramesToRecover := nextRenderFramePlayers[t.Id].FramesToRecover
|
||||||
|
if meleeBullet.HitStunFrames > oldFramesToRecover {
|
||||||
|
nextRenderFramePlayers[t.Id].FramesToRecover = meleeBullet.HitStunFrames
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
Logger.Debug(fmt.Sprintf("Bullet collided with non-player: roomId=%v, currRenderFrame.Id=%v, delayedInputFrame.Id=%v", pR.Id, currRenderFrame.Id, delayedInputFrame.InputFrameId))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
shouldRemove = true
|
||||||
|
}
|
||||||
|
if shouldRemove {
|
||||||
|
removedBulletsAtCurrFrame[collisionBulletIndex] = 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for _, meleeBullet := range currRenderFrame.MeleeBullets {
|
for _, meleeBullet := range currRenderFrame.MeleeBullets {
|
||||||
collisionBulletIndex := COLLISION_BULLET_INDEX_PREFIX + meleeBullet.BattleLocalId
|
collisionBulletIndex := COLLISION_BULLET_INDEX_PREFIX + meleeBullet.BattleLocalId
|
||||||
@ -1262,27 +1316,59 @@ func (pR *Room) applyInputFrameDownsyncDynamicsOnSingleRenderFrame(delayedInputF
|
|||||||
}
|
}
|
||||||
|
|
||||||
if nil != delayedInputFrame {
|
if nil != delayedInputFrame {
|
||||||
|
var delayedInputFrameForPrevRenderFrame *InputFrameDownsync = nil
|
||||||
|
tmp := pR.InputsBuffer.GetByFrameId(pR.ConvertToInputFrameId(currRenderFrame.Id-1, pR.InputDelayFrames))
|
||||||
|
if nil != tmp {
|
||||||
|
delayedInputFrameForPrevRenderFrame = tmp.(*InputFrameDownsync)
|
||||||
|
}
|
||||||
inputList := delayedInputFrame.InputList
|
inputList := delayedInputFrame.InputList
|
||||||
// Process player inputs
|
// Process player inputs
|
||||||
for playerId, player := range pR.Players {
|
for playerId, player := range pR.Players {
|
||||||
joinIndex := player.JoinIndex
|
joinIndex := player.JoinIndex
|
||||||
collisionPlayerIndex := COLLISION_PLAYER_INDEX_PREFIX + joinIndex
|
collisionPlayerIndex := COLLISION_PLAYER_INDEX_PREFIX + joinIndex
|
||||||
playerCollider := collisionSysMap[collisionPlayerIndex]
|
playerCollider := collisionSysMap[collisionPlayerIndex]
|
||||||
if 0 < nextRenderFramePlayers[playerId].FramesToRecover {
|
thatPlayerInNextFrame := nextRenderFramePlayers[playerId]
|
||||||
|
if 0 < thatPlayerInNextFrame.FramesToRecover {
|
||||||
// No need to process inputs for this player, but there might be bullet pushbacks on this player
|
// No need to process inputs for this player, but there might be bullet pushbacks on this player
|
||||||
playerCollider.X += bulletPushbacks[joinIndex-1].X
|
playerCollider.X += bulletPushbacks[joinIndex-1].X
|
||||||
playerCollider.Y += bulletPushbacks[joinIndex-1].Y
|
playerCollider.Y += bulletPushbacks[joinIndex-1].Y
|
||||||
|
// Update in the collision system
|
||||||
|
playerCollider.Update()
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
currPlayerDownsync := currRenderFrame.Players[playerId]
|
currPlayerDownsync := currRenderFrame.Players[playerId]
|
||||||
decodedInput := pR.decodeInput(inputList[joinIndex-1])
|
decodedInput := pR.decodeInput(inputList[joinIndex-1])
|
||||||
|
prevBtnALevel := int32(0)
|
||||||
|
if nil != delayedInputFrameForPrevRenderFrame {
|
||||||
|
prevDecodedInput := pR.decodeInput(delayedInputFrameForPrevRenderFrame.InputList[joinIndex-1])
|
||||||
|
prevBtnALevel = prevDecodedInput.BtnALevel
|
||||||
|
}
|
||||||
|
|
||||||
if 0 != decodedInput.Dx || 0 != decodedInput.Dy {
|
if decodedInput.BtnALevel > prevBtnALevel {
|
||||||
nextRenderFramePlayers[playerId].DirX = decodedInput.Dx
|
punchSkillId := int32(1)
|
||||||
nextRenderFramePlayers[playerId].DirY = decodedInput.Dy
|
punchConfig := pR.MeleeSkillConfig[punchSkillId]
|
||||||
nextRenderFramePlayers[playerId].CharacterState = 1
|
var newMeleeBullet MeleeBullet = *punchConfig
|
||||||
|
newMeleeBullet.BattleLocalId = pR.BulletBattleLocalIdCounter
|
||||||
|
pR.BulletBattleLocalIdCounter += 1
|
||||||
|
newMeleeBullet.OffenderJoinIndex = joinIndex
|
||||||
|
newMeleeBullet.OffenderPlayerId = playerId
|
||||||
|
newMeleeBullet.OriginatedRenderFrameId = currRenderFrame.Id
|
||||||
|
toRet.MeleeBullets = append(toRet.MeleeBullets, &newMeleeBullet)
|
||||||
|
thatPlayerInNextFrame.FramesToRecover = newMeleeBullet.RecoveryFrames
|
||||||
|
thatPlayerInNextFrame.CharacterState = ATK_CHARACTER_STATE_ATK1
|
||||||
|
Logger.Info(fmt.Sprintf("roomId=%v, playerId=%v triggered a rising-edge of btnA at currRenderFrame.id=%v, delayedInputFrame.id=%v", pR.Id, playerId, currRenderFrame.Id, delayedInputFrame.InputFrameId))
|
||||||
|
|
||||||
|
} else if decodedInput.BtnALevel < prevBtnALevel {
|
||||||
|
Logger.Info(fmt.Sprintf("roomId=%v, playerId=%v triggered a falling-edge of btnA at currRenderFrame.id=%v, delayedInputFrame.id=%v", pR.Id, playerId, currRenderFrame.Id, delayedInputFrame.InputFrameId))
|
||||||
} else {
|
} else {
|
||||||
nextRenderFramePlayers[playerId].CharacterState = 0
|
// No bullet trigger, process movement inputs
|
||||||
|
if 0 != decodedInput.Dx || 0 != decodedInput.Dy {
|
||||||
|
thatPlayerInNextFrame.DirX = decodedInput.Dx
|
||||||
|
thatPlayerInNextFrame.DirY = decodedInput.Dy
|
||||||
|
thatPlayerInNextFrame.CharacterState = ATK_CHARACTER_STATE_WALKING
|
||||||
|
} else {
|
||||||
|
thatPlayerInNextFrame.CharacterState = ATK_CHARACTER_STATE_IDLE1
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
movementX, movementY := VirtualGridToWorldPos(decodedInput.Dx+decodedInput.Dx*currPlayerDownsync.Speed, decodedInput.Dy+decodedInput.Dy*currPlayerDownsync.Speed, pR.VirtualGridToWorldRatio)
|
movementX, movementY := VirtualGridToWorldPos(decodedInput.Dx+decodedInput.Dx*currPlayerDownsync.Speed, decodedInput.Dy+decodedInput.Dy*currPlayerDownsync.Speed, pR.VirtualGridToWorldRatio)
|
||||||
@ -1320,8 +1406,8 @@ func (pR *Room) applyInputFrameDownsyncDynamicsOnSingleRenderFrame(delayedInputF
|
|||||||
|
|
||||||
// Update "virtual grid position"
|
// Update "virtual grid position"
|
||||||
newVx, newVy := PolygonColliderAnchorToVirtualGridPos(playerCollider.X-effPushbacks[joinIndex-1].X, playerCollider.Y-effPushbacks[joinIndex-1].Y, player.ColliderRadius, player.ColliderRadius, pR.collisionSpaceOffsetX, pR.collisionSpaceOffsetY, pR.WorldToVirtualGridRatio)
|
newVx, newVy := PolygonColliderAnchorToVirtualGridPos(playerCollider.X-effPushbacks[joinIndex-1].X, playerCollider.Y-effPushbacks[joinIndex-1].Y, player.ColliderRadius, player.ColliderRadius, pR.collisionSpaceOffsetX, pR.collisionSpaceOffsetY, pR.WorldToVirtualGridRatio)
|
||||||
nextRenderFramePlayers[playerId].VirtualGridX = newVx
|
thatPlayerInNextFrame := nextRenderFramePlayers[playerId]
|
||||||
nextRenderFramePlayers[playerId].VirtualGridY = newVy
|
thatPlayerInNextFrame.VirtualGridX, thatPlayerInNextFrame.VirtualGridY = newVx, newVy
|
||||||
}
|
}
|
||||||
|
|
||||||
Logger.Debug(fmt.Sprintf("After applyInputFrameDownsyncDynamicsOnSingleRenderFrame: currRenderFrame.Id=%v, inputList=%v, currRenderFrame.Players=%v, nextRenderFramePlayers=%v", currRenderFrame.Id, inputList, currRenderFrame.Players, nextRenderFramePlayers))
|
Logger.Debug(fmt.Sprintf("After applyInputFrameDownsyncDynamicsOnSingleRenderFrame: currRenderFrame.Id=%v, inputList=%v, currRenderFrame.Players=%v, nextRenderFramePlayers=%v", currRenderFrame.Id, inputList, currRenderFrame.Players, nextRenderFramePlayers))
|
||||||
@ -1352,6 +1438,7 @@ func (pR *Room) refreshColliders(spaceW, spaceH int32) {
|
|||||||
for _, player := range pR.Players {
|
for _, player := range pR.Players {
|
||||||
wx, wy := VirtualGridToWorldPos(player.VirtualGridX, player.VirtualGridY, pR.VirtualGridToWorldRatio)
|
wx, wy := VirtualGridToWorldPos(player.VirtualGridX, player.VirtualGridY, pR.VirtualGridToWorldRatio)
|
||||||
playerCollider := GenerateRectCollider(wx, wy, player.ColliderRadius*2, player.ColliderRadius*2, pR.collisionSpaceOffsetX, pR.collisionSpaceOffsetY, "Player")
|
playerCollider := GenerateRectCollider(wx, wy, player.ColliderRadius*2, player.ColliderRadius*2, pR.collisionSpaceOffsetX, pR.collisionSpaceOffsetY, "Player")
|
||||||
|
playerCollider.Data = player
|
||||||
space.Add(playerCollider)
|
space.Add(playerCollider)
|
||||||
// Keep track of the collider in "pR.CollisionSysMap"
|
// Keep track of the collider in "pR.CollisionSysMap"
|
||||||
joinIndex := player.JoinIndex
|
joinIndex := player.JoinIndex
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -20,6 +20,10 @@ func ConvexPolygonStr(body *resolv.ConvexPolygon) string {
|
|||||||
|
|
||||||
func GenerateRectCollider(origX, origY, w, h, spaceOffsetX, spaceOffsetY float64, tag string) *resolv.Object {
|
func GenerateRectCollider(origX, origY, w, h, spaceOffsetX, spaceOffsetY float64, tag string) *resolv.Object {
|
||||||
cx, cy := WorldToPolygonColliderAnchorPos(origX, origY, w*0.5, h*0.5, spaceOffsetX, spaceOffsetY)
|
cx, cy := WorldToPolygonColliderAnchorPos(origX, origY, w*0.5, h*0.5, spaceOffsetX, spaceOffsetY)
|
||||||
|
return GenerateRectColliderInCollisionSpace(cx, cy, w, h, tag)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GenerateRectColliderInCollisionSpace(cx, cy, w, h float64, tag string) *resolv.Object {
|
||||||
collider := resolv.NewObject(cx, cy, w, h, tag)
|
collider := resolv.NewObject(cx, cy, w, h, tag)
|
||||||
shape := resolv.NewRectangle(0, 0, w, h)
|
shape := resolv.NewRectangle(0, 0, w, h)
|
||||||
collider.SetShape(shape)
|
collider.SetShape(shape)
|
||||||
|
@ -4,36 +4,6 @@ option go_package = "battle_srv/protos"; // here "./" corresponds to the "--go_o
|
|||||||
package protos;
|
package protos;
|
||||||
import "geometry.proto"; // The import path here is only w.r.t. the proto file, not the Go package.
|
import "geometry.proto"; // The import path here is only w.r.t. the proto file, not the Go package.
|
||||||
|
|
||||||
message BattleColliderInfo {
|
|
||||||
string stageName = 1;
|
|
||||||
map<string, sharedprotos.Vec2DList> strToVec2DListMap = 2;
|
|
||||||
map<string, sharedprotos.Polygon2DList> strToPolygon2DListMap = 3;
|
|
||||||
int32 stageDiscreteW = 4;
|
|
||||||
int32 stageDiscreteH = 5;
|
|
||||||
int32 stageTileW = 6;
|
|
||||||
int32 stageTileH = 7;
|
|
||||||
|
|
||||||
int32 intervalToPing = 8;
|
|
||||||
int32 willKickIfInactiveFor = 9;
|
|
||||||
int32 boundRoomId = 10;
|
|
||||||
int64 battleDurationNanos = 11;
|
|
||||||
int32 serverFps = 12;
|
|
||||||
int32 inputDelayFrames = 13;
|
|
||||||
uint32 inputScaleFrames = 14;
|
|
||||||
int32 nstDelayFrames = 15;
|
|
||||||
int32 inputFrameUpsyncDelayTolerance = 16;
|
|
||||||
int32 maxChasingRenderFramesPerUpdate = 17;
|
|
||||||
int32 playerBattleState = 18;
|
|
||||||
double rollbackEstimatedDtMillis = 19;
|
|
||||||
int64 rollbackEstimatedDtNanos = 20;
|
|
||||||
|
|
||||||
double worldToVirtualGridRatio = 21;
|
|
||||||
double virtualGridToWorldRatio = 22;
|
|
||||||
|
|
||||||
int32 spAtkLookupFrames = 23;
|
|
||||||
int32 renderCacheSize = 24;
|
|
||||||
}
|
|
||||||
|
|
||||||
message PlayerDownsync {
|
message PlayerDownsync {
|
||||||
int32 id = 1;
|
int32 id = 1;
|
||||||
int32 virtualGridX = 2;
|
int32 virtualGridX = 2;
|
||||||
@ -126,6 +96,38 @@ message MeleeBullet {
|
|||||||
int32 offenderPlayerId = 17;
|
int32 offenderPlayerId = 17;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message BattleColliderInfo {
|
||||||
|
string stageName = 1;
|
||||||
|
map<string, sharedprotos.Vec2DList> strToVec2DListMap = 2;
|
||||||
|
map<string, sharedprotos.Polygon2DList> strToPolygon2DListMap = 3;
|
||||||
|
int32 stageDiscreteW = 4;
|
||||||
|
int32 stageDiscreteH = 5;
|
||||||
|
int32 stageTileW = 6;
|
||||||
|
int32 stageTileH = 7;
|
||||||
|
|
||||||
|
int32 intervalToPing = 8;
|
||||||
|
int32 willKickIfInactiveFor = 9;
|
||||||
|
int32 boundRoomId = 10;
|
||||||
|
int64 battleDurationNanos = 11;
|
||||||
|
int32 serverFps = 12;
|
||||||
|
int32 inputDelayFrames = 13;
|
||||||
|
uint32 inputScaleFrames = 14;
|
||||||
|
int32 nstDelayFrames = 15;
|
||||||
|
int32 inputFrameUpsyncDelayTolerance = 16;
|
||||||
|
int32 maxChasingRenderFramesPerUpdate = 17;
|
||||||
|
int32 playerBattleState = 18;
|
||||||
|
double rollbackEstimatedDtMillis = 19;
|
||||||
|
int64 rollbackEstimatedDtNanos = 20;
|
||||||
|
|
||||||
|
double worldToVirtualGridRatio = 21;
|
||||||
|
double virtualGridToWorldRatio = 22;
|
||||||
|
|
||||||
|
int32 spAtkLookupFrames = 23;
|
||||||
|
int32 renderCacheSize = 24;
|
||||||
|
|
||||||
|
map<int32, MeleeBullet> meleeSkillConfig = 25; // skillId -> skill
|
||||||
|
}
|
||||||
|
|
||||||
message RoomDownsyncFrame {
|
message RoomDownsyncFrame {
|
||||||
int32 id = 1;
|
int32 id = 1;
|
||||||
map<int32, PlayerDownsync> players = 2;
|
map<int32, PlayerDownsync> players = 2;
|
||||||
|
@ -343,6 +343,7 @@
|
|||||||
"forceBigEndianFloatingNumDecoding": false,
|
"forceBigEndianFloatingNumDecoding": false,
|
||||||
"renderFrameIdLagTolerance": 4,
|
"renderFrameIdLagTolerance": 4,
|
||||||
"jigglingEps1D": 0.001,
|
"jigglingEps1D": 0.001,
|
||||||
|
"bulletTriggerEnabled": true,
|
||||||
"_id": "d12gkAmppNlIzqcRDELa91"
|
"_id": "d12gkAmppNlIzqcRDELa91"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -522,7 +523,7 @@
|
|||||||
"array": [
|
"array": [
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
239.32248305180272,
|
210.23252687912068,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
@ -1482,7 +1483,6 @@
|
|||||||
"zoomingListenerNode": {
|
"zoomingListenerNode": {
|
||||||
"__id__": 5
|
"__id__": 5
|
||||||
},
|
},
|
||||||
"actionBtnListenerNode": null,
|
|
||||||
"stickhead": {
|
"stickhead": {
|
||||||
"__id__": 25
|
"__id__": 25
|
||||||
},
|
},
|
||||||
|
@ -440,7 +440,7 @@
|
|||||||
"array": [
|
"array": [
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
210.4441731196186,
|
210.23252687912068,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
|
@ -454,7 +454,7 @@
|
|||||||
"array": [
|
"array": [
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
210.4441731196186,
|
210.23252687912068,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
|
@ -1085,18 +1085,23 @@ cc.Class({
|
|||||||
|
|
||||||
bulletColliders.forEach((bulletCollider, collisionBulletIndex) => {
|
bulletColliders.forEach((bulletCollider, collisionBulletIndex) => {
|
||||||
const potentials = bulletCollider.potentials();
|
const potentials = bulletCollider.potentials();
|
||||||
|
const offender = currRenderFrame.players[bulletCollider.data.offenderPlayerId];
|
||||||
let shouldRemove = false;
|
let shouldRemove = false;
|
||||||
for (const potential of potentials) {
|
for (const potential of potentials) {
|
||||||
if (null != potential.data && potential.data.joinIndex == bulletCollider.data.offenderJoinIndex) continue;
|
if (null != potential.data && potential.data.joinIndex == bulletCollider.data.offenderJoinIndex) continue;
|
||||||
if (!bulletCollider.collides(potential, result1)) continue;
|
if (!bulletCollider.collides(potential, result1)) continue;
|
||||||
if (null != potential.data && null !== potential.data.joinIndex) {
|
if (null != potential.data && null !== potential.data.joinIndex) {
|
||||||
const joinIndex = potential.data.joinIndex;
|
const joinIndex = potential.data.joinIndex;
|
||||||
bulletPushbacks[joinIndex - 1][0] += bulletCollider.data.pushback; // Only for straight punch, there's no y-pushback
|
let xfac = 1;
|
||||||
|
if (0 > offender.dirX) {
|
||||||
|
xfac = -1;
|
||||||
|
}
|
||||||
|
bulletPushbacks[joinIndex - 1][0] += xfac * bulletCollider.data.pushback; // Only for straight punch, there's no y-pushback
|
||||||
bulletPushbacks[joinIndex - 1][1] += 0;
|
bulletPushbacks[joinIndex - 1][1] += 0;
|
||||||
const thatAckedPlayerInNextFrame = nextRenderFramePlayers[potential.data.id];
|
const thatAckedPlayerInNextFrame = nextRenderFramePlayers[potential.data.id];
|
||||||
thatAckedPlayerInNextFrame.characterState = window.ATK_CHARACTER_STATE.Atked1[0];
|
thatAckedPlayerInNextFrame.characterState = window.ATK_CHARACTER_STATE.Atked1[0];
|
||||||
const oldFrameToRecover = thatAckedPlayerInNextFrame.framesToRecover;
|
const oldFramesToRecover = thatAckedPlayerInNextFrame.framesToRecover;
|
||||||
thatAckedPlayerInNextFrame.framesToRecover = (oldFrameToRecover > bulletCollider.data.hitStunFrames ? oldFrameToRecover : bulletCollider.data.hitStunFrames); // In case the hit player is already stun, we extend it
|
thatAckedPlayerInNextFrame.framesToRecover = (oldFramesToRecover > bulletCollider.data.hitStunFrames ? oldFramesToRecover : bulletCollider.data.hitStunFrames); // In case the hit player is already stun, we extend it
|
||||||
}
|
}
|
||||||
shouldRemove = true;
|
shouldRemove = true;
|
||||||
}
|
}
|
||||||
@ -1156,14 +1161,14 @@ cc.Class({
|
|||||||
punch.offenderPlayerId = playerId;
|
punch.offenderPlayerId = playerId;
|
||||||
punch.originatedRenderFrameId = currRenderFrame.id;
|
punch.originatedRenderFrameId = currRenderFrame.id;
|
||||||
toRet.meleeBullets.push(punch);
|
toRet.meleeBullets.push(punch);
|
||||||
console.log(`A rising-edge of meleeBullet is created at renderFrame.id=${currRenderFrame.id}, delayedInputFrame.id=${delayedInputFrame.inputFrameId}: ${JSON.stringify(punch)}`);
|
console.log(`A rising-edge of meleeBullet is created at renderFrame.id=${currRenderFrame.id}, delayedInputFrame.id=${delayedInputFrame.inputFrameId}: ${self._stringifyRecentInputCache(true)}`);
|
||||||
|
|
||||||
thatPlayerInNextFrame.characterState = window.ATK_CHARACTER_STATE.Atk1[0];
|
thatPlayerInNextFrame.characterState = window.ATK_CHARACTER_STATE.Atk1[0];
|
||||||
}
|
}
|
||||||
} else if (0 == decodedInput.btnALevel && 1 == prevBtnALevel) {
|
} else if (0 == decodedInput.btnALevel && 1 == prevBtnALevel) {
|
||||||
// console.log(`playerId=${playerId} triggered a falling-edge of btnA at renderFrame.id=${currRenderFrame.id}, delayedInputFrame.id=${delayedInputFrame.inputFrameId}`);
|
// console.log(`playerId=${playerId} triggered a falling-edge of btnA at renderFrame.id=${currRenderFrame.id}, delayedInputFrame.id=${delayedInputFrame.inputFrameId}`);
|
||||||
} else {
|
} else {
|
||||||
// No trigger, process movement inputs
|
// No bullet trigger, process movement inputs
|
||||||
if (0 != decodedInput.dx || 0 != decodedInput.dy) {
|
if (0 != decodedInput.dx || 0 != decodedInput.dy) {
|
||||||
// Update directions and thus would eventually update moving animation accordingly
|
// Update directions and thus would eventually update moving animation accordingly
|
||||||
thatPlayerInNextFrame.dirX = decodedInput.dx;
|
thatPlayerInNextFrame.dirX = decodedInput.dx;
|
||||||
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user