mirror of
https://github.com/genxium/DelayNoMore
synced 2024-12-25 19:28:55 +00:00
Fixed backend bullet collision handling.
This commit is contained in:
parent
2a1105efa4
commit
1593965950
@ -193,7 +193,7 @@ func (pR *Room) AddPlayerIfPossible(pPlayerFromDbInit *Player, session *websocke
|
||||
pPlayerFromDbInit.LastSentInputFrameId = MAGIC_LAST_SENT_INPUT_FRAME_ID_NORMAL_ADDED
|
||||
pPlayerFromDbInit.BattleState = PlayerBattleStateIns.ADDED_PENDING_BATTLE_COLLIDER_ACK
|
||||
pPlayerFromDbInit.Speed = pR.PlayerDefaultSpeed // Hardcoded
|
||||
pPlayerFromDbInit.ColliderRadius = float64(24) // Hardcoded
|
||||
pPlayerFromDbInit.ColliderRadius = float64(12) // Hardcoded
|
||||
|
||||
pR.Players[playerId] = pPlayerFromDbInit
|
||||
pR.PlayerDownsyncSessionDict[playerId] = session
|
||||
@ -787,26 +787,26 @@ func (pR *Room) OnDismissed() {
|
||||
pR.RenderFrameId = 0
|
||||
pR.CurDynamicsRenderFrameId = 0
|
||||
pR.InputDelayFrames = 8
|
||||
pR.NstDelayFrames = 8
|
||||
pR.NstDelayFrames = 4
|
||||
pR.InputScaleFrames = uint32(2)
|
||||
pR.ServerFps = 60
|
||||
pR.RollbackEstimatedDtMillis = 16.667 // Use fixed-and-low-precision to mitigate the inconsistent floating-point-number issue between Golang and JavaScript
|
||||
pR.RollbackEstimatedDtNanos = 16666666 // A little smaller than the actual per frame time, just for preventing FAST FRAME
|
||||
dilutionFactor := 8
|
||||
dilutionFactor := 12
|
||||
pR.dilutedRollbackEstimatedDtNanos = int64(16666666 * (dilutionFactor) / (dilutionFactor - 1)) // [WARNING] Only used in controlling "battleMainLoop" to be keep a frame rate lower than that of the frontends, such that upon resync(i.e. BackendDynamicsEnabled=true), the frontends would have bigger chances to keep up with or even surpass the backend calculation
|
||||
pR.BattleDurationFrames = 30 * pR.ServerFps
|
||||
pR.BattleDurationNanos = int64(pR.BattleDurationFrames) * (pR.RollbackEstimatedDtNanos + 1)
|
||||
pR.InputFrameUpsyncDelayTolerance = 2
|
||||
pR.MaxChasingRenderFramesPerUpdate = 8
|
||||
pR.MaxChasingRenderFramesPerUpdate = 5
|
||||
|
||||
pR.BackendDynamicsEnabled = true // [WARNING] When "false", recovery upon reconnection wouldn't work!
|
||||
punchSkillId := int32(1)
|
||||
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
|
||||
StartupFrames: int32(23),
|
||||
ActiveFrames: int32(3),
|
||||
RecoveryFrames: int32(61), // 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{
|
||||
@ -822,7 +822,7 @@ func (pR *Room) OnDismissed() {
|
||||
// for defender
|
||||
HitStunFrames: int32(18),
|
||||
BlockStunFrames: int32(9),
|
||||
Pushback: float64(22.0),
|
||||
Pushback: float64(11.0),
|
||||
ReleaseTriggerType: int32(1), // 1: rising-edge, 2: falling-edge
|
||||
Damage: int32(5),
|
||||
}
|
||||
@ -1244,20 +1244,20 @@ func (pR *Room) applyInputFrameDownsyncDynamicsOnSingleRenderFrame(delayedInputF
|
||||
offenderCollider := collisionSysMap[collisionOffenderIndex]
|
||||
offender := currRenderFrame.Players[meleeBullet.OffenderPlayerId]
|
||||
|
||||
xfac, yfac := float64(1.0), float64(0) // By now, straight Punch offset doesn't respect "y-axis"
|
||||
xfac := float64(1.0) // By now, straight Punch offset doesn't respect "y-axis"
|
||||
if 0 > offender.DirX {
|
||||
xfac = float64(-1.0)
|
||||
}
|
||||
offenderWx, offenderWy := VirtualGridToWorldPos(offender.VirtualGridX, offender.VirtualGridY, pR.VirtualGridToWorldRatio)
|
||||
bulletWx, bulletWy := offenderWx+xfac*meleeBullet.HitboxOffset, offenderWy
|
||||
|
||||
bulletCx, bulletCy := offenderCollider.X+xfac*meleeBullet.HitboxOffset, offenderCollider.Y+yfac*meleeBullet.HitboxOffset
|
||||
|
||||
newBulletCollider := GenerateRectColliderInCollisionSpace(bulletCx, bulletCy, xfac*meleeBullet.HitboxSize.X, meleeBullet.HitboxSize.Y, "MeleeBullet")
|
||||
newBulletCollider := GenerateRectCollider(bulletWx, bulletWy, meleeBullet.HitboxSize.X, meleeBullet.HitboxSize.Y, pR.collisionSpaceOffsetX, pR.collisionSpaceOffsetY, "MeleeBullet")
|
||||
newBulletCollider.Data = meleeBullet
|
||||
pR.Space.Add(newBulletCollider)
|
||||
collisionSysMap[collisionBulletIndex] = newBulletCollider
|
||||
bulletColliders[collisionBulletIndex] = newBulletCollider
|
||||
|
||||
Logger.Debug(fmt.Sprintf("roomId=%v, a meleeBullet is added to collisionSys at currRenderFrame.id=%v as start-up frames ended and active frame is not yet ended: %v, from offenderCollider=%v", pR.Id, currRenderFrame.Id, ConvexPolygonStr(newBulletCollider.Shape.(*resolv.ConvexPolygon)), ConvexPolygonStr(offenderCollider.Shape.(*resolv.ConvexPolygon))))
|
||||
Logger.Debug(fmt.Sprintf("roomId=%v, a meleeBullet is added to collisionSys at currRenderFrame.id=%v as start-up frames ended and active frame is not yet ended: %v, from offenderCollider=%v, xfac=%v", pR.Id, currRenderFrame.Id, ConvexPolygonStr(newBulletCollider.Shape.(*resolv.ConvexPolygon)), ConvexPolygonStr(offenderCollider.Shape.(*resolv.ConvexPolygon)), xfac))
|
||||
}
|
||||
}
|
||||
|
||||
@ -1267,13 +1267,11 @@ func (pR *Room) applyInputFrameDownsyncDynamicsOnSingleRenderFrame(delayedInputF
|
||||
collisionBulletIndex := COLLISION_BULLET_INDEX_PREFIX + meleeBullet.BattleLocalId
|
||||
bulletShape := bulletCollider.Shape.(*resolv.ConvexPolygon)
|
||||
if collision := bulletCollider.Check(0, 0); collision != nil {
|
||||
// FIXME: A bullet going to the "right" can hit a wall or a player (though couldn't identify the player), but if it goes to the "left" then it couldn't hit anything, why?
|
||||
offender := currRenderFrame.Players[meleeBullet.OffenderPlayerId]
|
||||
Logger.Info(fmt.Sprintf("roomId=%v, a meleeBullet collides w/ sth at currRenderFrame.id=%v: %v", pR.Id, currRenderFrame.Id, ConvexPolygonStr(bulletShape)))
|
||||
for _, obj := range collision.Objects {
|
||||
defenderShape := obj.Shape.(*resolv.ConvexPolygon)
|
||||
switch t := obj.Data.(type) {
|
||||
case Player:
|
||||
defenderShape := obj.Shape.(*resolv.ConvexPolygon)
|
||||
case *Player:
|
||||
if meleeBullet.OffenderPlayerId != t.Id {
|
||||
if overlapped, _, _, _ := CalcPushbacks(0, 0, bulletShape, defenderShape); overlapped {
|
||||
xfac := float64(1.0) // By now, straight Punch offset doesn't respect "y-axis"
|
||||
@ -1286,15 +1284,14 @@ func (pR *Room) applyInputFrameDownsyncDynamicsOnSingleRenderFrame(delayedInputF
|
||||
if meleeBullet.HitStunFrames > oldFramesToRecover {
|
||||
nextRenderFramePlayers[t.Id].FramesToRecover = meleeBullet.HitStunFrames
|
||||
}
|
||||
Logger.Debug(fmt.Sprintf("roomId=%v, a meleeBullet collides w/ player at currRenderFrame.id=%v: b=%v, p=%v", pR.Id, currRenderFrame.Id, ConvexPolygonStr(bulletShape), ConvexPolygonStr(defenderShape)))
|
||||
}
|
||||
}
|
||||
default:
|
||||
Logger.Debug(fmt.Sprintf("Bullet %v collided with non-player: roomId=%v, currRenderFrame.Id=%v, delayedInputFrame.Id=%v", bulletShape, pR.Id, currRenderFrame.Id, delayedInputFrame.InputFrameId))
|
||||
Logger.Debug(fmt.Sprintf("Bullet %v collided with non-player %v: roomId=%v, currRenderFrame.Id=%v, delayedInputFrame.Id=%v, objDataType=%t, objData=%v", ConvexPolygonStr(bulletShape), ConvexPolygonStr(defenderShape), pR.Id, currRenderFrame.Id, delayedInputFrame.InputFrameId, obj.Data, obj.Data))
|
||||
}
|
||||
}
|
||||
shouldRemove = true
|
||||
} else {
|
||||
Logger.Info(fmt.Sprintf("roomId=%v, meleeBullet doesn't collider w/ anything at currRenderFrame.id=%v: %v; p1=%v, p2=%v; bulletSpace=%p, p1Space=%p, p2Space=%p", pR.Id, currRenderFrame.Id, ConvexPolygonStr(bulletShape), ConvexPolygonStr(collisionSysMap[COLLISION_PLAYER_INDEX_PREFIX+1].Shape.(*resolv.ConvexPolygon)), ConvexPolygonStr(collisionSysMap[COLLISION_PLAYER_INDEX_PREFIX+2].Shape.(*resolv.ConvexPolygon)), bulletCollider.Space, collisionSysMap[COLLISION_PLAYER_INDEX_PREFIX+1].Space, collisionSysMap[COLLISION_PLAYER_INDEX_PREFIX+2].Space))
|
||||
}
|
||||
if shouldRemove {
|
||||
removedBulletsAtCurrFrame[collisionBulletIndex] = 1
|
||||
@ -1360,7 +1357,7 @@ func (pR *Room) applyInputFrameDownsyncDynamicsOnSingleRenderFrame(delayedInputF
|
||||
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))
|
||||
Logger.Debug(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 {
|
||||
// No bullet trigger, process movement inputs
|
||||
if 0 != decodedInput.Dx || 0 != decodedInput.Dy {
|
||||
@ -1434,7 +1431,7 @@ func (pR *Room) inputFrameIdDebuggable(inputFrameId int32) bool {
|
||||
func (pR *Room) refreshColliders(spaceW, spaceH int32) {
|
||||
// Kindly note that by now, we've already got all the shapes in the tmx file into "pR.(Players | Barriers)" from "ParseTmxLayersAndGroups"
|
||||
|
||||
minStep := (int(float64(pR.PlayerDefaultSpeed)*pR.VirtualGridToWorldRatio) >> 1) // the approx minimum distance a player can move per frame in world coordinate
|
||||
minStep := (int(float64(pR.PlayerDefaultSpeed)*pR.VirtualGridToWorldRatio) << 1) // the approx minimum distance a player can move per frame in world coordinate
|
||||
pR.Space = resolv.NewSpace(int(spaceW), int(spaceH), minStep, minStep) // allocate a new collision space everytime after a battle is settled
|
||||
for _, player := range pR.Players {
|
||||
wx, wy := VirtualGridToWorldPos(player.VirtualGridX, player.VirtualGridY, pR.VirtualGridToWorldRatio)
|
||||
|
@ -4,6 +4,7 @@ go 1.19
|
||||
|
||||
require (
|
||||
dnmshared v0.0.0
|
||||
battle_srv v0.0.0
|
||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0
|
||||
github.com/hajimehoshi/ebiten/v2 v2.4.7
|
||||
github.com/solarlune/resolv v0.5.1
|
||||
@ -26,3 +27,4 @@ require (
|
||||
)
|
||||
|
||||
replace dnmshared => ../dnmshared
|
||||
replace battle_srv => ../battle_srv
|
||||
|
@ -1,6 +1,7 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
. "battle_srv/protos"
|
||||
. "dnmshared"
|
||||
. "dnmshared/sharedprotos"
|
||||
"fmt"
|
||||
@ -36,7 +37,7 @@ func NewWorldColliderDisplay(game *Game, stageDiscreteW, stageDiscreteH, stageTi
|
||||
virtualGridToWorldRatio := 0.1
|
||||
playerDefaultSpeed := 20
|
||||
minStep := (int(float64(playerDefaultSpeed)*virtualGridToWorldRatio) << 2)
|
||||
playerColliderRadius := float64(16)
|
||||
playerColliderRadius := float64(24)
|
||||
playerColliders := make([]*resolv.Object, len(playerPosList.Eles))
|
||||
space := resolv.NewSpace(int(spaceW), int(spaceH), minStep, minStep)
|
||||
for i, playerPos := range playerPosList.Eles {
|
||||
@ -84,6 +85,75 @@ func NewWorldColliderDisplay(game *Game, stageDiscreteW, stageDiscreteH, stageTi
|
||||
Logger.Info(fmt.Sprintf("effPushback={%v, %v}", effPushback.X, effPushback.Y))
|
||||
}
|
||||
}
|
||||
meleeBullet := &MeleeBullet{
|
||||
// for offender
|
||||
StartupFrames: int32(18),
|
||||
ActiveFrames: int32(1),
|
||||
RecoveryFrames: int32(61),
|
||||
RecoveryFramesOnBlock: int32(61),
|
||||
RecoveryFramesOnHit: int32(61),
|
||||
Moveforward: &Vec2D{
|
||||
X: 0,
|
||||
Y: 0,
|
||||
},
|
||||
HitboxOffset: float64(24.0),
|
||||
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),
|
||||
}
|
||||
bulletLeftToRight := true
|
||||
if bulletLeftToRight {
|
||||
xfac := float64(1.0)
|
||||
offenderWx, offenderWy := playerPosList.Eles[0].X, playerPosList.Eles[0].Y
|
||||
bulletWx, bulletWy := offenderWx+xfac*meleeBullet.HitboxOffset, offenderWy
|
||||
|
||||
newBulletCollider := GenerateRectCollider(bulletWx, bulletWy, meleeBullet.HitboxSize.X, meleeBullet.HitboxSize.Y, spaceOffsetX, spaceOffsetY, "MeleeBullet")
|
||||
space.Add(newBulletCollider)
|
||||
bulletShape := newBulletCollider.Shape.(*resolv.ConvexPolygon)
|
||||
Logger.Warn(fmt.Sprintf("bullet ->: Added bullet collider to space: a=%v", ConvexPolygonStr(bulletShape)))
|
||||
|
||||
if collision := newBulletCollider.Check(0, 0); collision != nil {
|
||||
for _, obj := range collision.Objects {
|
||||
objShape := obj.Shape.(*resolv.ConvexPolygon)
|
||||
if overlapped, pushbackX, pushbackY, overlapResult := CalcPushbacks(0, 0, bulletShape, objShape); overlapped {
|
||||
Logger.Warn(fmt.Sprintf("bullet ->: Overlapped: a=%v, b=%v, pushbackX=%v, pushbackY=%v", ConvexPolygonStr(bulletShape), ConvexPolygonStr(objShape), pushbackX, pushbackY))
|
||||
} else {
|
||||
Logger.Warn(fmt.Sprintf("bullet ->: Collided BUT not overlapped: a=%v, b=%v, overlapResult=%v", ConvexPolygonStr(bulletShape), ConvexPolygonStr(objShape), overlapResult))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bulletRightToLeft := true
|
||||
if bulletRightToLeft {
|
||||
xfac := float64(-1.0)
|
||||
offenderWx, offenderWy := playerPosList.Eles[1].X, playerPosList.Eles[1].Y
|
||||
bulletWx, bulletWy := offenderWx+xfac*meleeBullet.HitboxOffset, offenderWy
|
||||
|
||||
newBulletCollider := GenerateRectCollider(bulletWx, bulletWy, meleeBullet.HitboxSize.X, meleeBullet.HitboxSize.Y, spaceOffsetX, spaceOffsetY, "MeleeBullet")
|
||||
space.Add(newBulletCollider)
|
||||
bulletShape := newBulletCollider.Shape.(*resolv.ConvexPolygon)
|
||||
Logger.Warn(fmt.Sprintf("bullet <-: Added bullet collider to space: a=%v", ConvexPolygonStr(bulletShape)))
|
||||
|
||||
if collision := newBulletCollider.Check(0, 0); collision != nil {
|
||||
for _, obj := range collision.Objects {
|
||||
objShape := obj.Shape.(*resolv.ConvexPolygon)
|
||||
if overlapped, pushbackX, pushbackY, overlapResult := CalcPushbacks(0, 0, bulletShape, objShape); overlapped {
|
||||
Logger.Warn(fmt.Sprintf("bullet <-: Overlapped: a=%v, b=%v, pushbackX=%v, pushbackY=%v", ConvexPolygonStr(bulletShape), ConvexPolygonStr(objShape), pushbackX, pushbackY))
|
||||
} else {
|
||||
Logger.Warn(fmt.Sprintf("bullet <-: Collided BUT not overlapped: a=%v, b=%v, overlapResult=%v", ConvexPolygonStr(bulletShape), ConvexPolygonStr(objShape), overlapResult))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return world
|
||||
}
|
||||
@ -98,6 +168,9 @@ func (world *WorldColliderDisplay) Draw(screen *ebiten.Image) {
|
||||
if o.HasTags("Player") {
|
||||
drawColor := color.RGBA{0, 255, 0, 255}
|
||||
DrawPolygon(screen, o.Shape.(*resolv.ConvexPolygon), drawColor)
|
||||
} else if o.HasTags("MeleeBullet") {
|
||||
drawColor := color.RGBA{0, 0, 255, 255}
|
||||
DrawPolygon(screen, o.Shape.(*resolv.ConvexPolygon), drawColor)
|
||||
} else {
|
||||
drawColor := color.RGBA{60, 60, 60, 255}
|
||||
DrawPolygon(screen, o.Shape.(*resolv.ConvexPolygon), drawColor)
|
||||
|
@ -529,8 +529,8 @@
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
0.5,
|
||||
0.5,
|
||||
1
|
||||
]
|
||||
},
|
||||
@ -648,7 +648,7 @@
|
||||
"_N$_defaultCacheMode": 0,
|
||||
"_N$timeScale": 1,
|
||||
"_N$debugBones": false,
|
||||
"_N$enableBatch": false,
|
||||
"_N$enableBatch": true,
|
||||
"_id": ""
|
||||
},
|
||||
{
|
||||
@ -763,7 +763,7 @@
|
||||
"_N$_defaultCacheMode": 0,
|
||||
"_N$timeScale": 1,
|
||||
"_N$debugBones": false,
|
||||
"_N$enableBatch": false,
|
||||
"_N$enableBatch": true,
|
||||
"_id": ""
|
||||
},
|
||||
{
|
||||
@ -878,7 +878,7 @@
|
||||
"_N$_defaultCacheMode": 0,
|
||||
"_N$timeScale": 1,
|
||||
"_N$debugBones": false,
|
||||
"_N$enableBatch": false,
|
||||
"_N$enableBatch": true,
|
||||
"_id": ""
|
||||
},
|
||||
{
|
||||
|
@ -761,7 +761,7 @@ cc.Class({
|
||||
|
||||
newPlayerNode.setPosition(cc.v2(wpos[0], wpos[1]));
|
||||
playerScriptIns.mapNode = self.node;
|
||||
const cpos = self.virtualGridToPlayerColliderPos(vx, vy, playerDownsyncInfo);
|
||||
const cpos = self.virtualGridToPolygonColliderAnchorPos(vx, vy, playerDownsyncInfo.colliderRadius, playerDownsyncInfo.colliderRadius);
|
||||
const d = playerDownsyncInfo.colliderRadius * 2,
|
||||
x0 = cpos[0],
|
||||
y0 = cpos[1];
|
||||
@ -1044,7 +1044,7 @@ cc.Class({
|
||||
|
||||
const newVx = currPlayerDownsync.virtualGridX;
|
||||
const newVy = currPlayerDownsync.virtualGridY;
|
||||
const newCpos = self.virtualGridToPlayerColliderPos(newVx, newVy, self.playerRichInfoArr[joinIndex - 1]);
|
||||
const newCpos = self.virtualGridToPolygonColliderAnchorPos(newVx, newVy, self.playerRichInfoArr[joinIndex - 1].colliderRadius, self.playerRichInfoArr[joinIndex - 1].colliderRadius);
|
||||
playerCollider.x = newCpos[0];
|
||||
playerCollider.y = newCpos[1];
|
||||
}
|
||||
@ -1064,15 +1064,16 @@ cc.Class({
|
||||
const offenderCollider = collisionSysMap.get(collisionOffenderIndex);
|
||||
const offender = currRenderFrame.players[meleeBullet.offenderPlayerId];
|
||||
|
||||
let xfac = 1,
|
||||
yfac = 0; // By now, straight Punch offset doesn't respect "y-axis"
|
||||
let xfac = 1; // By now, straight Punch offset doesn't respect "y-axis"
|
||||
if (0 > offender.dirX) {
|
||||
xfac = -1;
|
||||
}
|
||||
const x0 = offenderCollider.x + xfac * meleeBullet.hitboxOffset,
|
||||
y0 = offenderCollider.y + yfac * meleeBullet.hitboxOffset;
|
||||
const pts = [[0, 0], [xfac * meleeBullet.hitboxSize.x, 0], [xfac * meleeBullet.hitboxSize.x, meleeBullet.hitboxSize.y], [0, meleeBullet.hitboxSize.y]];
|
||||
const newBulletCollider = collisionSys.createPolygon(x0, y0, pts);
|
||||
const offenderWpos = self.virtualGridToWorldPos(offender.virtualGridX, offender.virtualGridY);
|
||||
const bulletWx = offenderWpos[0] + xfac * meleeBullet.hitboxOffset;
|
||||
const bulletWy = offenderWpos[1];
|
||||
const bulletCpos = self.worldToPolygonColliderAnchorPos(bulletWx, bulletWy, meleeBullet.hitboxSize.x * 0.5, meleeBullet.hitboxSize.y * 0.5);
|
||||
const pts = [[0, 0], [meleeBullet.hitboxSize.x, 0], [meleeBullet.hitboxSize.x, meleeBullet.hitboxSize.y], [0, meleeBullet.hitboxSize.y]];
|
||||
const newBulletCollider = collisionSys.createPolygon(bulletCpos[0], bulletCpos[1], pts);
|
||||
newBulletCollider.data = meleeBullet;
|
||||
collisionSysMap.set(collisionBulletIndex, newBulletCollider);
|
||||
bulletColliders.set(collisionBulletIndex, newBulletCollider);
|
||||
@ -1208,7 +1209,7 @@ cc.Class({
|
||||
const playerId = self.playerRichInfoArr[j].id;
|
||||
const collisionPlayerIndex = self.collisionPlayerIndexPrefix + joinIndex;
|
||||
const playerCollider = collisionSysMap.get(collisionPlayerIndex);
|
||||
const newVpos = self.playerColliderAnchorToVirtualGridPos(playerCollider.x - effPushbacks[joinIndex - 1][0], playerCollider.y - effPushbacks[joinIndex - 1][1], self.playerRichInfoArr[j]);
|
||||
const newVpos = self.polygonColliderAnchorToVirtualGridPos(playerCollider.x - effPushbacks[joinIndex - 1][0], playerCollider.y - effPushbacks[joinIndex - 1][1], self.playerRichInfoArr[j].colliderRadius, self.playerRichInfoArr[j].colliderRadius);
|
||||
const thatPlayerInNextFrame = nextRenderFramePlayers[playerId];
|
||||
thatPlayerInNextFrame.virtualGridX = newVpos[0];
|
||||
thatPlayerInNextFrame.virtualGridY = newVpos[1];
|
||||
@ -1340,23 +1341,23 @@ cc.Class({
|
||||
return [wx, wy];
|
||||
},
|
||||
|
||||
playerWorldToCollisionPos(wx, wy, playerRichInfo) {
|
||||
return [wx - playerRichInfo.colliderRadius, wy - playerRichInfo.colliderRadius];
|
||||
worldToPolygonColliderAnchorPos(wx, wy, halfBoundingW, halfBoundingH) {
|
||||
return [wx - halfBoundingW, wy - halfBoundingH];
|
||||
},
|
||||
|
||||
playerColliderAnchorToWorldPos(cx, cy, playerRichInfo) {
|
||||
return [cx + playerRichInfo.colliderRadius, cy + playerRichInfo.colliderRadius];
|
||||
polygonColliderAnchorToWorldPos(cx, cy, halfBoundingW, halfBoundingH) {
|
||||
return [cx + halfBoundingW, cy + halfBoundingH];
|
||||
},
|
||||
|
||||
playerColliderAnchorToVirtualGridPos(cx, cy, playerRichInfo) {
|
||||
polygonColliderAnchorToVirtualGridPos(cx, cy, halfBoundingW, halfBoundingH) {
|
||||
const self = this;
|
||||
const wpos = self.playerColliderAnchorToWorldPos(cx, cy, playerRichInfo);
|
||||
const wpos = self.polygonColliderAnchorToWorldPos(cx, cy, halfBoundingW, halfBoundingH);
|
||||
return self.worldToVirtualGridPos(wpos[0], wpos[1])
|
||||
},
|
||||
|
||||
virtualGridToPlayerColliderPos(vx, vy, playerRichInfo) {
|
||||
virtualGridToPolygonColliderAnchorPos(vx, vy, halfBoundingW, halfBoundingH) {
|
||||
const self = this;
|
||||
const wpos = self.virtualGridToWorldPos(vx, vy);
|
||||
return self.playerWorldToCollisionPos(wpos[0], wpos[1], playerRichInfo)
|
||||
return self.worldToPolygonColliderAnchorPos(wpos[0], wpos[1], halfBoundingW, halfBoundingH)
|
||||
},
|
||||
});
|
||||
|
@ -42,8 +42,8 @@ cc.Class({
|
||||
self.meleeSkillConfig = {
|
||||
1: {
|
||||
// for offender
|
||||
startupFrames: 18,
|
||||
activeFrames: 42,
|
||||
startupFrames: 23,
|
||||
activeFrames: 3,
|
||||
recoveryFrames: 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: 61,
|
||||
recoveryFramesOnHit: 61,
|
||||
@ -60,7 +60,7 @@ cc.Class({
|
||||
// for defender
|
||||
hitStunFrames: 18,
|
||||
blockStunFrames: 9,
|
||||
pushback: 22.0,
|
||||
pushback: 11.0,
|
||||
releaseTriggerType: 1, // 1: rising-edge, 2: falling-edge
|
||||
damage: 5
|
||||
}
|
||||
@ -140,7 +140,7 @@ cc.Class({
|
||||
joinIndex: 1,
|
||||
virtualGridX: 0,
|
||||
virtualGridY: 0,
|
||||
speed: 2 * self.worldToVirtualGridRatio,
|
||||
speed: 1 * self.worldToVirtualGridRatio,
|
||||
colliderRadius: 12,
|
||||
characterState: window.ATK_CHARACTER_STATE.Idle1[0],
|
||||
framesToRecover: 0,
|
||||
@ -152,7 +152,7 @@ cc.Class({
|
||||
joinIndex: 2,
|
||||
virtualGridX: 80 * self.worldToVirtualGridRatio,
|
||||
virtualGridY: 40 * self.worldToVirtualGridRatio,
|
||||
speed: 2 * self.worldToVirtualGridRatio,
|
||||
speed: 1 * self.worldToVirtualGridRatio,
|
||||
colliderRadius: 12,
|
||||
characterState: window.ATK_CHARACTER_STATE.Idle1[0],
|
||||
framesToRecover: 0,
|
||||
|
Loading…
Reference in New Issue
Block a user