mirror of
https://github.com/genxium/DelayNoMore
synced 2024-12-25 19:28:55 +00:00
Drafted backend collision with pushback calculations.
This commit is contained in:
parent
bc8989a0e6
commit
150e30db2a
@ -5,9 +5,9 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"github.com/golang/protobuf/proto"
|
"github.com/golang/protobuf/proto"
|
||||||
"github.com/gorilla/websocket"
|
"github.com/gorilla/websocket"
|
||||||
|
"github.com/kvartborg/vector"
|
||||||
"github.com/solarlune/resolv"
|
"github.com/solarlune/resolv"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
"math"
|
|
||||||
"math/rand"
|
"math/rand"
|
||||||
. "server/common"
|
. "server/common"
|
||||||
"server/common/utils"
|
"server/common/utils"
|
||||||
@ -1151,19 +1151,35 @@ func (pR *Room) applyInputFrameDownsyncDynamics(fromRenderFrameId int32, toRende
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
baseChange := player.Speed * pR.RollbackEstimatedDt * decodedInputSpeedFactor
|
baseChange := player.Speed * pR.RollbackEstimatedDt * decodedInputSpeedFactor
|
||||||
dx := baseChange * float64(decodedInput[0])
|
oldDx, oldDy := baseChange * float64(decodedInput[0]), baseChange * float64(decodedInput[1])
|
||||||
dy := baseChange * float64(decodedInput[1])
|
dx, dy := oldDx, oldDy
|
||||||
|
|
||||||
collisionPlayerIndex := COLLISION_PLAYER_INDEX_PREFIX + joinIndex
|
collisionPlayerIndex := COLLISION_PLAYER_INDEX_PREFIX + joinIndex
|
||||||
playerCollider := pR.CollisionSysMap[collisionPlayerIndex]
|
playerCollider := pR.CollisionSysMap[collisionPlayerIndex]
|
||||||
if collision := playerCollider.Check(dx, dy, "Barrier"); collision != nil {
|
if collision := playerCollider.Check(oldDx, oldDy, "Barrier"); collision != nil {
|
||||||
changeWithCollision := collision.ContactWithObject(collision.Objects[0])
|
playerShape := playerCollider.Shape.(*resolv.ConvexPolygon)
|
||||||
Logger.Info(fmt.Sprintf("Collided: roomId=%v, playerId=%v, orig dx=%v, orig dy=%v, proposed new dx =%v, proposed new dy=%v", pR.Id, player.Id, dx, dy, changeWithCollision.X(), changeWithCollision.Y()))
|
barrierShape := collision.Objects[0].Shape.(*resolv.ConvexPolygon)
|
||||||
// FIXME: Use a mechanism equivalent to that of the frontend!
|
origX, origY := playerShape.Position()
|
||||||
// dx = changeWithCollision.X()
|
playerShape.SetPosition(origX+oldDx, origY+oldDy)
|
||||||
// dy = changeWithCollision.Y()
|
if colliding := IsPolygonPairColliding(playerShape, barrierShape, nil); colliding {
|
||||||
dx = 0
|
Logger.Info(fmt.Sprintf("Collided: playerShape=%v, oldDx=%v, oldDy=%v", playerShape, oldDx, oldDy))
|
||||||
dy = 0
|
overlapResult := &SatResult{
|
||||||
|
Overlap: 0,
|
||||||
|
OverlapX: 0,
|
||||||
|
OverlapY: 0,
|
||||||
|
AContainedInB: true,
|
||||||
|
BContainedInA: true,
|
||||||
|
Axis: vector.Vector{0, 0},
|
||||||
|
}
|
||||||
|
e := vector.Vector{oldDx, oldDy}.Unit()
|
||||||
|
if separatableAlongMovement := IsPolygonPairSeparatedByDir(playerShape, barrierShape, e, overlapResult); !separatableAlongMovement {
|
||||||
|
pushbackX, pushbackY := overlapResult.Overlap*overlapResult.OverlapX, overlapResult.Overlap*overlapResult.OverlapY
|
||||||
|
Logger.Info(fmt.Sprintf("Collided: playerShape=%v, oldDx=%v, oldDy=%v, toCheckBarrier=%v, pushbackX=%v, pushbackY=%v", playerShape, oldDx, oldDy, barrierShape, pushbackX, pushbackY))
|
||||||
|
dx, dy = oldDx-pushbackX, oldDy-pushbackY
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
playerShape.SetPosition(origX, origY)
|
||||||
}
|
}
|
||||||
playerCollider.X += dx
|
playerCollider.X += dx
|
||||||
playerCollider.Y += dy
|
playerCollider.Y += dy
|
||||||
@ -1203,9 +1219,7 @@ func (pR *Room) refreshColliders() {
|
|||||||
minStep := int(3) // the approx minimum distance a player can move per frame
|
minStep := int(3) // the approx minimum distance a player can move per frame
|
||||||
space := resolv.NewSpace(int(spaceW), int(spaceH), minStep, minStep) // allocate a new collision space everytime after a battle is settled
|
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 {
|
for _, player := range pR.Players {
|
||||||
playerCollider := resolv.NewObject(player.X-playerColliderRadius+spaceOffsetX, player.Y-playerColliderRadius+spaceOffsetY, playerColliderRadius*2, playerColliderRadius*2)
|
playerCollider := GenerateRectCollider(player.X, player.Y, playerColliderRadius*2, playerColliderRadius*2, spaceOffsetX, spaceOffsetY, "Player")
|
||||||
playerColliderShape := resolv.NewCircle(+playerColliderRadius, +playerColliderRadius, playerColliderRadius)
|
|
||||||
playerCollider.SetShape(playerColliderShape)
|
|
||||||
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
|
||||||
@ -1215,31 +1229,8 @@ func (pR *Room) refreshColliders() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, barrier := range pR.Barriers {
|
for _, barrier := range pR.Barriers {
|
||||||
|
boundaryUnaligned := barrier.Boundary
|
||||||
var w float64 = 0
|
barrierCollider := GenerateConvexPolygonCollider(boundaryUnaligned, spaceOffsetX, spaceOffsetY, "Barrier")
|
||||||
var h float64 = 0
|
|
||||||
|
|
||||||
for i, pi := range barrier.Boundary.Points {
|
|
||||||
for j, pj := range barrier.Boundary.Points {
|
|
||||||
if i == j {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if math.Abs(pj.X-pi.X) > w {
|
|
||||||
w = math.Abs(pj.X - pi.X)
|
|
||||||
}
|
|
||||||
if math.Abs(pj.Y-pi.Y) > h {
|
|
||||||
h = math.Abs(pj.Y - pi.Y)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
barrierColliderShape := resolv.NewConvexPolygon()
|
|
||||||
for _, p := range barrier.Boundary.Points {
|
|
||||||
barrierColliderShape.AddPoints(p.X, p.Y)
|
|
||||||
}
|
|
||||||
|
|
||||||
barrierCollider := resolv.NewObject(barrier.Boundary.Anchor.X+spaceOffsetX, barrier.Boundary.Anchor.Y+spaceOffsetY, w, h, "Barrier")
|
|
||||||
barrierCollider.SetShape(barrierColliderShape)
|
|
||||||
space.Add(barrierCollider)
|
space.Add(barrierCollider)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -56,10 +56,8 @@ func NewWorldColliderDisplay(game *Game, stageDiscreteW, stageDiscreteH, stageTi
|
|||||||
moveToCollide := true
|
moveToCollide := true
|
||||||
if moveToCollide {
|
if moveToCollide {
|
||||||
toTestPlayerCollider := playerColliders[0]
|
toTestPlayerCollider := playerColliders[0]
|
||||||
oldDx := 135.0
|
oldDx, oldDy := 135.0, 135.0
|
||||||
oldDy := 135.0
|
dx, dy := oldDx, oldDy
|
||||||
dx := oldDx
|
|
||||||
dy := oldDy
|
|
||||||
if collision := toTestPlayerCollider.Check(oldDx, oldDy, "Barrier"); collision != nil {
|
if collision := toTestPlayerCollider.Check(oldDx, oldDy, "Barrier"); collision != nil {
|
||||||
playerShape := toTestPlayerCollider.Shape.(*resolv.ConvexPolygon)
|
playerShape := toTestPlayerCollider.Shape.(*resolv.ConvexPolygon)
|
||||||
barrierShape := collision.Objects[0].Shape.(*resolv.ConvexPolygon)
|
barrierShape := collision.Objects[0].Shape.(*resolv.ConvexPolygon)
|
||||||
|
@ -440,7 +440,7 @@
|
|||||||
"array": [
|
"array": [
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
209.73151519075364,
|
342.9460598986377,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
|
@ -740,9 +740,13 @@ cc.Class({
|
|||||||
newPlayerNode.setPosition(cc.v2(x, y));
|
newPlayerNode.setPosition(cc.v2(x, y));
|
||||||
newPlayerNode.getComponent("SelfPlayer").mapNode = self.node;
|
newPlayerNode.getComponent("SelfPlayer").mapNode = self.node;
|
||||||
const currentSelfColliderCircle = newPlayerNode.getComponent(cc.CircleCollider);
|
const currentSelfColliderCircle = newPlayerNode.getComponent(cc.CircleCollider);
|
||||||
|
const r = currentSelfColliderCircle.radius, d = 2*r;
|
||||||
|
// The collision box of an individual player is a polygon instead of a circle, because the backend collision engine doesn't handle circle alignment well.
|
||||||
|
const x0 = x-r, y0 = y-r;
|
||||||
|
let pts = [[0, 0], [d, 0], [d, d], [0, d]];
|
||||||
|
|
||||||
const newPlayerColliderLatest = self.latestCollisionSys.createCircle(x, y, currentSelfColliderCircle.radius);
|
const newPlayerColliderLatest = self.latestCollisionSys.createPolygon(x0, y0, pts);
|
||||||
const newPlayerColliderChaser = self.chaserCollisionSys.createCircle(x, y, currentSelfColliderCircle.radius);
|
const newPlayerColliderChaser = self.chaserCollisionSys.createPolygon(x0, y0, pts);
|
||||||
const collisionPlayerIndex = self.collisionPlayerIndexPrefix + joinIndex;
|
const collisionPlayerIndex = self.collisionPlayerIndexPrefix + joinIndex;
|
||||||
self.latestCollisionSysMap.set(collisionPlayerIndex, newPlayerColliderLatest);
|
self.latestCollisionSysMap.set(collisionPlayerIndex, newPlayerColliderLatest);
|
||||||
self.chaserCollisionSysMap.set(collisionPlayerIndex, newPlayerColliderChaser);
|
self.chaserCollisionSysMap.set(collisionPlayerIndex, newPlayerColliderChaser);
|
||||||
@ -952,10 +956,12 @@ cc.Class({
|
|||||||
const joinIndex = playerRichInfo.joinIndex;
|
const joinIndex = playerRichInfo.joinIndex;
|
||||||
const collisionPlayerIndex = self.collisionPlayerIndexPrefix + joinIndex;
|
const collisionPlayerIndex = self.collisionPlayerIndexPrefix + joinIndex;
|
||||||
const playerCollider = collisionSysMap.get(collisionPlayerIndex);
|
const playerCollider = collisionSysMap.get(collisionPlayerIndex);
|
||||||
|
const currentSelfColliderCircle = playerRichInfo.node.getComponent(cc.CircleCollider);
|
||||||
|
const r = currentSelfColliderCircle.radius;
|
||||||
rdf.players[playerRichInfo.id] = {
|
rdf.players[playerRichInfo.id] = {
|
||||||
id: playerRichInfo.id,
|
id: playerRichInfo.id,
|
||||||
x: playerCollider.x,
|
x: playerCollider.x + r, // [WARNING] the (x, y) of "playerCollider" is offset to the anchor (i.e. first point of all points) of the polygon shape
|
||||||
y: playerCollider.y,
|
y: playerCollider.y + r,
|
||||||
dir: self.ctrl.decodeDirection(null == inputFrameAppliedOnPrevRenderFrame ? 0 : inputFrameAppliedOnPrevRenderFrame.inputList[joinIndex - 1]),
|
dir: self.ctrl.decodeDirection(null == inputFrameAppliedOnPrevRenderFrame ? 0 : inputFrameAppliedOnPrevRenderFrame.inputList[joinIndex - 1]),
|
||||||
speed: (null == speedRefRenderFrame ? playerRichInfo.speed : speedRefRenderFrame.players[playerRichInfo.id].speed),
|
speed: (null == speedRefRenderFrame ? playerRichInfo.speed : speedRefRenderFrame.players[playerRichInfo.id].speed),
|
||||||
joinIndex: joinIndex
|
joinIndex: joinIndex
|
||||||
@ -1025,8 +1031,11 @@ cc.Class({
|
|||||||
const collisionPlayerIndex = self.collisionPlayerIndexPrefix + joinIndex;
|
const collisionPlayerIndex = self.collisionPlayerIndexPrefix + joinIndex;
|
||||||
const playerCollider = collisionSysMap.get(collisionPlayerIndex);
|
const playerCollider = collisionSysMap.get(collisionPlayerIndex);
|
||||||
const player = latestRdf.players[playerId];
|
const player = latestRdf.players[playerId];
|
||||||
playerCollider.x = player.x;
|
|
||||||
playerCollider.y = player.y;
|
const currentSelfColliderCircle = playerRichInfo.node.getComponent(cc.CircleCollider);
|
||||||
|
const r = currentSelfColliderCircle.radius;
|
||||||
|
playerCollider.x = player.x - r;
|
||||||
|
playerCollider.y = player.y - r;
|
||||||
});
|
});
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Loading…
Reference in New Issue
Block a user