mirror of
https://github.com/genxium/DelayNoMore
synced 2024-12-25 03:08:57 +00:00
A temp dirty commit having mysterious left moving players.
This commit is contained in:
parent
c6b98855af
commit
2b304eaa75
@ -518,7 +518,7 @@
|
||||
"array": [
|
||||
0,
|
||||
0,
|
||||
216.50635094610968,
|
||||
210.4441731196186,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
|
@ -380,6 +380,8 @@ cc.Class({
|
||||
}
|
||||
self.pJumpedOrNotList = [];
|
||||
for (let i = 0; i < window.boundRoomCapacity; i++) self.pJumpedOrNotList.push(false);
|
||||
self.dynamicRectangleColliders = gopkgs.NewDynamicRectangleColliders(64);
|
||||
|
||||
self.recentRenderCache = gopkgs.NewRingBufferJs(self.renderCacheSize);
|
||||
|
||||
self.recentInputCache = gopkgs.NewRingBufferJs((self.renderCacheSize >> 1) + 1);
|
||||
@ -1401,7 +1403,7 @@ othersForcedDownsyncRenderFrame=${JSON.stringify(othersForcedDownsyncRenderFrame
|
||||
};
|
||||
self.rdfIdToActuallyUsedInput.set(i, inputFrameDownsyncClone);
|
||||
}
|
||||
const renderRes = gopkgs.ApplyInputFrameDownsyncDynamicsOnSingleRenderFrameJs(self.recentInputCache, i, collisionSys, collisionSysMap, self.spaceOffsetX, self.spaceOffsetY, self.chConfigsOrderedByJoinIndex, self.recentRenderCache, self.collisionHolder, self.pEffPushbacks, self.pHardPushbackNormsArr, self.pJumpedOrNotList);
|
||||
const renderRes = gopkgs.ApplyInputFrameDownsyncDynamicsOnSingleRenderFrameJs(self.recentInputCache, i, collisionSys, collisionSysMap, self.spaceOffsetX, self.spaceOffsetY, self.chConfigsOrderedByJoinIndex, self.recentRenderCache, self.collisionHolder, self.pEffPushbacks, self.pHardPushbackNormsArr, self.pJumpedOrNotList, self.dynamicRectangleColliders);
|
||||
const nextRdf = gopkgs.GetRoomDownsyncFrame(self.recentRenderCache, self.renderFrameId + 1);
|
||||
|
||||
if (true == isChasing) {
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -217,21 +217,23 @@ func calcPushbacks(oldDx, oldDy float64, playerShape, barrierShape *resolv.Conve
|
||||
}
|
||||
|
||||
func isPolygonPairOverlapped(a, b *resolv.ConvexPolygon, result *SatResult) bool {
|
||||
aCnt, bCnt := len(a.Points), len(b.Points)
|
||||
aCnt, bCnt := a.Points.Cnt, b.Points.Cnt
|
||||
// Single point case
|
||||
if 1 == aCnt && 1 == bCnt {
|
||||
if nil != result {
|
||||
result.Overlap = 0
|
||||
}
|
||||
return a.Points[0][0] == b.Points[0][0] && a.Points[0][1] == b.Points[0][1]
|
||||
aPoint := a.GetPointByOffset(0)
|
||||
bPoint := b.GetPointByOffset(0)
|
||||
return aPoint[0] == bPoint[0] && aPoint[1] == bPoint[1]
|
||||
}
|
||||
|
||||
if 1 < aCnt {
|
||||
// Deliberately using "Points" instead of "SATAxes" to avoid unnecessary heap memory alloc
|
||||
for i, _ := range a.Points {
|
||||
u, v := a.Points[i], a.Points[0]
|
||||
if i != len(a.Points)-1 {
|
||||
v = a.Points[i+1]
|
||||
for i := int32(0); i < a.Points.Cnt; i++ {
|
||||
u, v := a.GetPointByOffset(i), a.GetPointByOffset(0)
|
||||
if i != a.Points.Cnt-1 {
|
||||
v = a.GetPointByOffset(i + 1)
|
||||
}
|
||||
dy := v[1] - u[1]
|
||||
dx := v[0] - u[0]
|
||||
@ -243,10 +245,10 @@ func isPolygonPairOverlapped(a, b *resolv.ConvexPolygon, result *SatResult) bool
|
||||
}
|
||||
|
||||
if 1 < bCnt {
|
||||
for i, _ := range b.Points {
|
||||
u, v := b.Points[i], b.Points[0]
|
||||
if i != len(b.Points)-1 {
|
||||
v = b.Points[i+1]
|
||||
for i := int32(0); i < b.Points.Cnt; i++ {
|
||||
u, v := b.GetPointByOffset(i), b.GetPointByOffset(0)
|
||||
if i != b.Points.Cnt-1 {
|
||||
v = b.GetPointByOffset(i + 1)
|
||||
}
|
||||
dy := v[1] - u[1]
|
||||
dx := v[0] - u[0]
|
||||
@ -307,7 +309,8 @@ func isPolygonPairSeparatedByDir(a, b *resolv.ConvexPolygon, e resolv.Vector, re
|
||||
*/
|
||||
|
||||
var aStart, aEnd, bStart, bEnd float64 = MAX_FLOAT64, -MAX_FLOAT64, MAX_FLOAT64, -MAX_FLOAT64
|
||||
for _, p := range a.Points {
|
||||
for i := int32(0); i < a.Points.Cnt; i++ {
|
||||
p := a.GetPointByOffset(i)
|
||||
dot := (p[0]+a.X)*e[0] + (p[1]+a.Y)*e[1]
|
||||
|
||||
if aStart > dot {
|
||||
@ -319,7 +322,8 @@ func isPolygonPairSeparatedByDir(a, b *resolv.ConvexPolygon, e resolv.Vector, re
|
||||
}
|
||||
}
|
||||
|
||||
for _, p := range b.Points {
|
||||
for i := int32(0); i < b.Points.Cnt; i++ {
|
||||
p := b.GetPointByOffset(i)
|
||||
dot := (p[0]+b.X)*e[0] + (p[1]+b.Y)*e[1]
|
||||
|
||||
if bStart > dot {
|
||||
@ -454,7 +458,7 @@ func calcHardPushbacksNorms(joinIndex int32, currPlayerDownsync, thatPlayerInNex
|
||||
//playerColliderCenterX, playerColliderCenterY := playerCollider.Center()
|
||||
//fmt.Printf("joinIndex=%d calcHardPushbacksNorms has non-empty collision;playerColliderPos=(%.2f,%.2f)\n", joinIndex, playerColliderCenterX, playerColliderCenterY)
|
||||
for true {
|
||||
obj := collision.FirstCollidedObject()
|
||||
obj := collision.PopFirstCollidedObject()
|
||||
if nil == obj {
|
||||
break
|
||||
}
|
||||
@ -558,11 +562,9 @@ func deriveOpPattern(currPlayerDownsync, thatPlayerInNextFrame *PlayerDownsync,
|
||||
/*
|
||||
[LONG TERM PERFORMANCE ENHANCEMENT PLAN]
|
||||
|
||||
The function "ApplyInputFrameDownsyncDynamicsOnSingleRenderFrame" is creating new heap-memory blocks at 60fps, e.g. nextRenderFramePlayers & nextRenderFrameMeleeBullets & nextRenderFrameFireballBullets & effPushbacks & hardPushbackNorms & jumpedOrNotList & playerColliders & bulletColliders, which would induce "possibly performance impacting garbage collections" when many rooms are running simultaneously.
|
||||
|
||||
It's not easy to remove all of the dynamic heap-memory blocks allocation/deallocation, but we can reduce them to some extent.
|
||||
The function "ApplyInputFrameDownsyncDynamicsOnSingleRenderFrame" is creating new heap-memory blocks at 60fps, e.g. nextRenderFramePlayers & nextRenderFrameMeleeBullets & nextRenderFrameFireballBullets & effPushbacks & hardPushbackNorms & jumpedOrNotList & dynamicRectangleColliders("player" & "bullet"), which would induce "possibly performance impacting garbage collections" when many rooms are running simultaneously.
|
||||
*/
|
||||
func ApplyInputFrameDownsyncDynamicsOnSingleRenderFrame(inputsBuffer *resolv.RingBuffer, currRenderFrameId int32, collisionSys *resolv.Space, collisionSysMap map[int32]*resolv.Object, collisionSpaceOffsetX, collisionSpaceOffsetY float64, chConfigsOrderedByJoinIndex []*CharacterConfig, renderFrameBuffer *resolv.RingBuffer, collision *resolv.Collision, effPushbacks []*Vec2D, hardPushbackNormsArr [][]*Vec2D, jumpedOrNotList []bool) bool {
|
||||
func ApplyInputFrameDownsyncDynamicsOnSingleRenderFrame(inputsBuffer *resolv.RingBuffer, currRenderFrameId int32, collisionSys *resolv.Space, collisionSysMap map[int32]*resolv.Object, collisionSpaceOffsetX, collisionSpaceOffsetY float64, chConfigsOrderedByJoinIndex []*CharacterConfig, renderFrameBuffer *resolv.RingBuffer, collision *resolv.Collision, effPushbacks []*Vec2D, hardPushbackNormsArr [][]*Vec2D, jumpedOrNotList []bool, dynamicRectangleColliders []*resolv.Object) bool {
|
||||
currRenderFrame := renderFrameBuffer.GetByFrameId(currRenderFrameId).(*RoomDownsyncFrame)
|
||||
nextRenderFrameId := currRenderFrameId + 1
|
||||
roomCapacity := len(currRenderFrame.PlayersArr)
|
||||
@ -759,8 +761,14 @@ func ApplyInputFrameDownsyncDynamicsOnSingleRenderFrame(inputsBuffer *resolv.Rin
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
[WARNING]
|
||||
1. The dynamic colliders will all be removed from "Space" at the end of this function due to the need for being rollback-compatible.
|
||||
2. To achieve "zero gc" in "ApplyInputFrameDownsyncDynamicsOnSingleRenderFrame", I deliberately chose a collision system that doesn't use dynamic tree node alloc.
|
||||
*/
|
||||
colliderCnt := 0
|
||||
|
||||
// 2. Process player movement
|
||||
playerColliders := make([]*resolv.Object, len(currRenderFrame.PlayersArr), len(currRenderFrame.PlayersArr)) // Will all be removed at the end of this function due to the need for being rollback-compatible
|
||||
for i, currPlayerDownsync := range currRenderFrame.PlayersArr {
|
||||
joinIndex := currPlayerDownsync.JoinIndex
|
||||
effPushbacks[joinIndex-1].X, effPushbacks[joinIndex-1].Y = float64(0), float64(0)
|
||||
@ -819,8 +827,9 @@ func ApplyInputFrameDownsyncDynamicsOnSingleRenderFrame(inputsBuffer *resolv.Rin
|
||||
|
||||
colliderWorldWidth, colliderWorldHeight := VirtualGridToWorldPos(colliderWidth, colliderHeight)
|
||||
|
||||
playerCollider := GenerateRectCollider(wx, wy, colliderWorldWidth, colliderWorldHeight, SNAP_INTO_PLATFORM_OVERLAP, SNAP_INTO_PLATFORM_OVERLAP, SNAP_INTO_PLATFORM_OVERLAP, SNAP_INTO_PLATFORM_OVERLAP, collisionSpaceOffsetX, collisionSpaceOffsetY, currPlayerDownsync, "Player") // the coords of all barrier boundaries are multiples of tileWidth(i.e. 16), by adding snapping y-padding when "landedOnGravityPushback" all "playerCollider.Y" would be a multiple of 1.0
|
||||
playerColliders[i] = playerCollider
|
||||
playerCollider := dynamicRectangleColliders[colliderCnt]
|
||||
UpdateRectCollider(playerCollider, wx, wy, colliderWorldWidth, colliderWorldHeight, SNAP_INTO_PLATFORM_OVERLAP, SNAP_INTO_PLATFORM_OVERLAP, SNAP_INTO_PLATFORM_OVERLAP, SNAP_INTO_PLATFORM_OVERLAP, collisionSpaceOffsetX, collisionSpaceOffsetY, currPlayerDownsync, "Player") // the coords of all barrier boundaries are multiples of tileWidth(i.e. 16), by adding snapping y-padding when "landedOnGravityPushback" all "playerCollider.Y" would be a multiple of 1.0
|
||||
colliderCnt++
|
||||
|
||||
// Add to collision system
|
||||
collisionSys.AddSingle(playerCollider)
|
||||
@ -838,9 +847,8 @@ func ApplyInputFrameDownsyncDynamicsOnSingleRenderFrame(inputsBuffer *resolv.Rin
|
||||
}
|
||||
}
|
||||
|
||||
// 3. Add bullet colliders into collision system
|
||||
// 3. Add bullet colliders into collision system; [DIRTY TRICK] Players always precede bullets in "dynamicRectangleColliders".
|
||||
// [WARNING] For rollback compatibility, static data of "BulletConfig" & "BattleAttr(static since instantiated)" can just be copies of the pointers in "RenderFrameBuffer", however, FireballBullets movement data as well as bullet animation data must be copies of instances for each RenderFrame!
|
||||
bulletColliders := make([]*resolv.Object, 0, ((len(currRenderFrame.MeleeBullets) + len(currRenderFrame.FireballBullets)) << 1)) // Will all be removed at the end of this function due to the need for being rollback-compatible
|
||||
for _, prevFireball := range currRenderFrame.FireballBullets {
|
||||
if TERMINATING_BULLET_LOCAL_ID == prevFireball.BattleAttr.BulletLocalId {
|
||||
break
|
||||
@ -862,9 +870,12 @@ func ApplyInputFrameDownsyncDynamicsOnSingleRenderFrame(inputsBuffer *resolv.Rin
|
||||
if IsFireballBulletActive(fireballBullet, currRenderFrame) {
|
||||
bulletWx, bulletWy := VirtualGridToWorldPos(fireballBullet.VirtualGridX, fireballBullet.VirtualGridY)
|
||||
hitboxSizeWx, hitboxSizeWy := VirtualGridToWorldPos(fireballBullet.Bullet.HitboxSizeX, fireballBullet.Bullet.HitboxSizeY)
|
||||
newBulletCollider := GenerateRectCollider(bulletWx, bulletWy, hitboxSizeWx, hitboxSizeWy, SNAP_INTO_PLATFORM_OVERLAP, SNAP_INTO_PLATFORM_OVERLAP, SNAP_INTO_PLATFORM_OVERLAP, SNAP_INTO_PLATFORM_OVERLAP, collisionSpaceOffsetX, collisionSpaceOffsetY, fireballBullet, "FireballBullet")
|
||||
|
||||
newBulletCollider := dynamicRectangleColliders[colliderCnt]
|
||||
UpdateRectCollider(newBulletCollider, bulletWx, bulletWy, hitboxSizeWx, hitboxSizeWy, SNAP_INTO_PLATFORM_OVERLAP, SNAP_INTO_PLATFORM_OVERLAP, SNAP_INTO_PLATFORM_OVERLAP, SNAP_INTO_PLATFORM_OVERLAP, collisionSpaceOffsetX, collisionSpaceOffsetY, fireballBullet, "FireballBullet")
|
||||
colliderCnt++
|
||||
|
||||
collisionSys.AddSingle(newBulletCollider)
|
||||
bulletColliders = append(bulletColliders, newBulletCollider)
|
||||
fireballBullet.BlState = BULLET_ACTIVE
|
||||
if fireballBullet.BlState != prevFireball.BlState {
|
||||
fireballBullet.FramesInBlState = 0
|
||||
@ -906,9 +917,12 @@ func ApplyInputFrameDownsyncDynamicsOnSingleRenderFrame(inputsBuffer *resolv.Rin
|
||||
}
|
||||
bulletWx, bulletWy := VirtualGridToWorldPos(offender.VirtualGridX+xfac*meleeBullet.Bullet.HitboxOffsetX, offender.VirtualGridY)
|
||||
hitboxSizeWx, hitboxSizeWy := VirtualGridToWorldPos(meleeBullet.Bullet.HitboxSizeX, meleeBullet.Bullet.HitboxSizeY)
|
||||
newBulletCollider := GenerateRectCollider(bulletWx, bulletWy, hitboxSizeWx, hitboxSizeWy, SNAP_INTO_PLATFORM_OVERLAP, SNAP_INTO_PLATFORM_OVERLAP, SNAP_INTO_PLATFORM_OVERLAP, SNAP_INTO_PLATFORM_OVERLAP, collisionSpaceOffsetX, collisionSpaceOffsetY, meleeBullet, "MeleeBullet")
|
||||
|
||||
newBulletCollider := dynamicRectangleColliders[colliderCnt]
|
||||
UpdateRectCollider(newBulletCollider, bulletWx, bulletWy, hitboxSizeWx, hitboxSizeWy, SNAP_INTO_PLATFORM_OVERLAP, SNAP_INTO_PLATFORM_OVERLAP, SNAP_INTO_PLATFORM_OVERLAP, SNAP_INTO_PLATFORM_OVERLAP, collisionSpaceOffsetX, collisionSpaceOffsetY, meleeBullet, "MeleeBullet")
|
||||
colliderCnt++
|
||||
|
||||
collisionSys.AddSingle(newBulletCollider)
|
||||
bulletColliders = append(bulletColliders, newBulletCollider)
|
||||
meleeBullet.BlState = BULLET_ACTIVE
|
||||
if meleeBullet.BlState != prevMelee.BlState {
|
||||
meleeBullet.FramesInBlState = 0
|
||||
@ -921,7 +935,7 @@ func ApplyInputFrameDownsyncDynamicsOnSingleRenderFrame(inputsBuffer *resolv.Rin
|
||||
// 4. Calc pushbacks for each player (after its movement) w/o bullets
|
||||
for i, currPlayerDownsync := range currRenderFrame.PlayersArr {
|
||||
joinIndex := currPlayerDownsync.JoinIndex
|
||||
playerCollider := playerColliders[i]
|
||||
playerCollider := dynamicRectangleColliders[i]
|
||||
playerShape := playerCollider.Shape.(*resolv.ConvexPolygon)
|
||||
thatPlayerInNextFrame := nextRenderFramePlayers[i]
|
||||
hardPushbackCnt := calcHardPushbacksNorms(joinIndex, currPlayerDownsync, thatPlayerInNextFrame, playerCollider, playerShape, SNAP_INTO_PLATFORM_OVERLAP, effPushbacks[joinIndex-1], hardPushbackNormsArr[joinIndex-1], collision)
|
||||
@ -930,7 +944,7 @@ func ApplyInputFrameDownsyncDynamicsOnSingleRenderFrame(inputsBuffer *resolv.Rin
|
||||
|
||||
if collided := playerCollider.CheckAllWithHolder(0, 0, collision); collided {
|
||||
for true {
|
||||
obj := collision.FirstCollidedObject()
|
||||
obj := collision.PopFirstCollidedObject()
|
||||
if nil == obj {
|
||||
break
|
||||
}
|
||||
@ -963,14 +977,12 @@ func ApplyInputFrameDownsyncDynamicsOnSingleRenderFrame(inputsBuffer *resolv.Rin
|
||||
// [WARNING] The "zero overlap collision" might be randomly detected/missed on either frontend or backend, to have deterministic result we added paddings to all sides of a playerCollider. As each velocity component of (velX, velY) being a multiple of 0.5 at any renderFrame, each position component of (x, y) can only be a multiple of 0.5 too, thus whenever a 1-dimensional collision happens between players from [player#1: i*0.5, player#2: j*0.5, not collided yet] to [player#1: (i+k)*0.5, player#2: j*0.5, collided], the overlap becomes (i+k-j)*0.5+2*s, and after snapping subtraction the effPushback magnitude for each player is (i+k-j)*0.5, resulting in 0.5-multiples-position for the next renderFrame.
|
||||
pushbackX, pushbackY = (overlapResult.Overlap-SNAP_INTO_PLATFORM_OVERLAP*2)*overlapResult.OverlapX, (overlapResult.Overlap-SNAP_INTO_PLATFORM_OVERLAP*2)*overlapResult.OverlapY
|
||||
}
|
||||
if 0 < hardPushbackCnt {
|
||||
for i := 0; i < hardPushbackCnt; i++ {
|
||||
hardPushbackNorm := hardPushbackNormsArr[joinIndex-1][i]
|
||||
projectedMagnitude := pushbackX*hardPushbackNorm.X + pushbackY*hardPushbackNorm.Y
|
||||
if isBarrier || (isAnotherPlayer && 0 > projectedMagnitude) {
|
||||
pushbackX -= projectedMagnitude * hardPushbackNorm.X
|
||||
pushbackY -= projectedMagnitude * hardPushbackNorm.Y
|
||||
}
|
||||
for i := 0; i < hardPushbackCnt; i++ {
|
||||
hardPushbackNorm := hardPushbackNormsArr[joinIndex-1][i]
|
||||
projectedMagnitude := pushbackX*hardPushbackNorm.X + pushbackY*hardPushbackNorm.Y
|
||||
if isBarrier || (isAnotherPlayer && 0 > projectedMagnitude) {
|
||||
pushbackX -= projectedMagnitude * hardPushbackNorm.X
|
||||
pushbackY -= projectedMagnitude * hardPushbackNorm.Y
|
||||
}
|
||||
}
|
||||
effPushbacks[joinIndex-1].X += pushbackX
|
||||
@ -1028,7 +1040,7 @@ func ApplyInputFrameDownsyncDynamicsOnSingleRenderFrame(inputsBuffer *resolv.Rin
|
||||
if chConfig.OnWallEnabled {
|
||||
if thatPlayerInNextFrame.InAir {
|
||||
// [WARNING] Sticking to wall MUST BE based on "InAir", otherwise we would get gravity reduction from ground up incorrectly!
|
||||
if _, existent := noOpSet[currPlayerDownsync.CharacterState]; !existent && 0 < hardPushbackCnt {
|
||||
if _, existent := noOpSet[currPlayerDownsync.CharacterState]; !existent {
|
||||
// [WARNING] Sticking to wall could only be triggered by proactive player input
|
||||
for i := 0; i < hardPushbackCnt; i++ {
|
||||
hardPushbackNorm := hardPushbackNormsArr[joinIndex-1][i]
|
||||
@ -1051,13 +1063,12 @@ func ApplyInputFrameDownsyncDynamicsOnSingleRenderFrame(inputsBuffer *resolv.Rin
|
||||
thatPlayerInNextFrame.OnWallNormX, thatPlayerInNextFrame.OnWallNormY = 0, 0
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 5. Check bullet-anything collisions
|
||||
for _, bulletCollider := range bulletColliders {
|
||||
for i := len(nextRenderFramePlayers); i < colliderCnt; i++ {
|
||||
bulletCollider := dynamicRectangleColliders[i]
|
||||
collided := bulletCollider.CheckAllWithHolder(0, 0, collision)
|
||||
bulletCollider.Space.RemoveSingle(bulletCollider) // Make sure that the bulletCollider is always removed for each renderFrame
|
||||
if !collided {
|
||||
continue
|
||||
}
|
||||
@ -1079,7 +1090,7 @@ func ApplyInputFrameDownsyncDynamicsOnSingleRenderFrame(inputsBuffer *resolv.Rin
|
||||
bulletShape := bulletCollider.Shape.(*resolv.ConvexPolygon)
|
||||
offender := currRenderFrame.PlayersArr[bulletBattleAttr.OffenderJoinIndex-1]
|
||||
for true {
|
||||
obj := collision.FirstCollidedObject()
|
||||
obj := collision.PopFirstCollidedObject()
|
||||
if nil == obj {
|
||||
break
|
||||
}
|
||||
@ -1153,7 +1164,7 @@ func ApplyInputFrameDownsyncDynamicsOnSingleRenderFrame(inputsBuffer *resolv.Rin
|
||||
// 6. Get players out of stuck barriers if there's any
|
||||
for i, currPlayerDownsync := range currRenderFrame.PlayersArr {
|
||||
joinIndex := currPlayerDownsync.JoinIndex
|
||||
playerCollider := playerColliders[i]
|
||||
playerCollider := dynamicRectangleColliders[i]
|
||||
// Update "virtual grid position"
|
||||
thatPlayerInNextFrame := nextRenderFramePlayers[i]
|
||||
thatPlayerInNextFrame.VirtualGridX, thatPlayerInNextFrame.VirtualGridY = PolygonColliderBLToVirtualGridPos(playerCollider.X-effPushbacks[joinIndex-1].X, playerCollider.Y-effPushbacks[joinIndex-1].Y, playerCollider.W*0.5, playerCollider.H*0.5, 0, 0, 0, 0, collisionSpaceOffsetX, collisionSpaceOffsetY)
|
||||
@ -1199,9 +1210,10 @@ func ApplyInputFrameDownsyncDynamicsOnSingleRenderFrame(inputsBuffer *resolv.Rin
|
||||
}
|
||||
}
|
||||
|
||||
for _, playerCollider := range playerColliders {
|
||||
playerCollider.Space.RemoveSingle(playerCollider)
|
||||
}
|
||||
for i := 0; i < colliderCnt; i++ {
|
||||
dynamicCollider := dynamicRectangleColliders[i]
|
||||
dynamicCollider.Space.RemoveSingle(dynamicCollider)
|
||||
}
|
||||
|
||||
ret.Id = nextRenderFrameId
|
||||
ret.BulletLocalIdCounter = bulletLocalId
|
||||
@ -1222,6 +1234,15 @@ func generateRectColliderInCollisionSpace(blX, blY, w, h float64, data interface
|
||||
return collider
|
||||
}
|
||||
|
||||
func UpdateRectCollider(collider *resolv.Object, wx, wy, w, h, topPadding, bottomPadding, leftPadding, rightPadding, spaceOffsetX, spaceOffsetY float64, data interface{}, tag string) {
|
||||
blX, blY := WorldToPolygonColliderBLPos(wx, wy, w*0.5, h*0.5, topPadding, bottomPadding, leftPadding, rightPadding, spaceOffsetX, spaceOffsetY)
|
||||
collider.X, collider.Y, collider.W, collider.H = blX, blY, w, h
|
||||
rectShape := collider.Shape.(*resolv.ConvexPolygon)
|
||||
rectShape.UpdateAsRectangle(0, 0, w, h)
|
||||
collider.Data = data
|
||||
// Ignore "tag" for now
|
||||
}
|
||||
|
||||
func GenerateConvexPolygonCollider(unalignedSrc *Polygon2D, spaceOffsetX, spaceOffsetY float64, data interface{}, tag string) *resolv.Object {
|
||||
aligned := AlignPolygon2DToBoundingBox(unalignedSrc)
|
||||
var w, h float64 = 0, 0
|
||||
|
@ -9,6 +9,14 @@ import (
|
||||
/*
|
||||
[WARNING] Should avoid using "MakeFullWrapper" as much as possible, and completely remove its usage in 60fps calls like "update(dt)" on frontend!
|
||||
*/
|
||||
func NewDynamicRectangleColliders(cnt int) []*js.Object {
|
||||
ret := make([]*js.Object, cnt)
|
||||
for i := 0; i < cnt; i++ {
|
||||
ret[i] = js.MakeWrapper(GenerateRectCollider(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, nil, ""))
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func NewCollisionHolder() *js.Object {
|
||||
return js.MakeWrapper(resolv.NewCollision())
|
||||
}
|
||||
@ -103,9 +111,9 @@ func GetCharacterConfigsOrderedByJoinIndex(speciesIdList []int) []*js.Object {
|
||||
return ret
|
||||
}
|
||||
|
||||
func ApplyInputFrameDownsyncDynamicsOnSingleRenderFrameJs(inputsBuffer *resolv.RingBuffer, currRenderFrameId int32, collisionSys *resolv.Space, collisionSysMap map[int32]*resolv.Object, collisionSpaceOffsetX, collisionSpaceOffsetY float64, chConfigsOrderedByJoinIndex []*CharacterConfig, renderFrameBuffer *resolv.RingBuffer, collision *resolv.Collision, effPushbacks []*Vec2D, hardPushbackNormsArr [][]*Vec2D, jumpedOrNotList []bool) bool {
|
||||
func ApplyInputFrameDownsyncDynamicsOnSingleRenderFrameJs(inputsBuffer *resolv.RingBuffer, currRenderFrameId int32, collisionSys *resolv.Space, collisionSysMap map[int32]*resolv.Object, collisionSpaceOffsetX, collisionSpaceOffsetY float64, chConfigsOrderedByJoinIndex []*CharacterConfig, renderFrameBuffer *resolv.RingBuffer, collision *resolv.Collision, effPushbacks []*Vec2D, hardPushbackNormsArr [][]*Vec2D, jumpedOrNotList []bool, dynamicRectangleColliders []*resolv.Object) bool {
|
||||
// We need access to all fields of RoomDownsyncFrame for displaying in frontend
|
||||
return ApplyInputFrameDownsyncDynamicsOnSingleRenderFrame(inputsBuffer, currRenderFrameId, collisionSys, collisionSysMap, collisionSpaceOffsetX, collisionSpaceOffsetY, chConfigsOrderedByJoinIndex, renderFrameBuffer, collision, effPushbacks, hardPushbackNormsArr, jumpedOrNotList)
|
||||
return ApplyInputFrameDownsyncDynamicsOnSingleRenderFrame(inputsBuffer, currRenderFrameId, collisionSys, collisionSysMap, collisionSpaceOffsetX, collisionSpaceOffsetY, chConfigsOrderedByJoinIndex, renderFrameBuffer, collision, effPushbacks, hardPushbackNormsArr, jumpedOrNotList, dynamicRectangleColliders)
|
||||
}
|
||||
|
||||
func GetRoomDownsyncFrame(renderFrameBuffer *resolv.RingBuffer, frameId int32) *js.Object {
|
||||
@ -183,5 +191,6 @@ func main() {
|
||||
"GetMeleeBullet": GetMeleeBullet,
|
||||
"GetFireballBullet": GetFireballBullet,
|
||||
"GetInput": GetInput,
|
||||
"NewDynamicRectangleColliders": NewDynamicRectangleColliders,
|
||||
})
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ func (cc *Collision) Clear() {
|
||||
cc.Cells.Clear()
|
||||
}
|
||||
|
||||
func (cc *Collision) FirstCollidedObject() *Object {
|
||||
func (cc *Collision) PopFirstCollidedObject() *Object {
|
||||
if 0 >= cc.Objects.Cnt {
|
||||
return nil
|
||||
}
|
||||
|
@ -254,7 +254,7 @@ func (obj *Object) CheckAllWithHolder(dx, dy float64, cc *Collision) bool {
|
||||
if obj.Space == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
cc.Clear()
|
||||
cc.checkingObject = obj
|
||||
|
||||
if dx < 0 {
|
||||
|
@ -125,7 +125,7 @@ func (line *Line) IntersectionPointsCircle(circle *Circle) []Vector {
|
||||
}
|
||||
|
||||
type ConvexPolygon struct {
|
||||
Points []Vector
|
||||
Points *RingBuffer
|
||||
X, Y float64
|
||||
Closed bool
|
||||
}
|
||||
@ -135,46 +135,72 @@ type ConvexPolygon struct {
|
||||
// polygon square, with the vertices at {0,0}, {10,0}, {10, 10}, and {0, 10}.
|
||||
func NewConvexPolygon(points ...float64) *ConvexPolygon {
|
||||
|
||||
// if len(points)/2 < 2 {
|
||||
// return nil
|
||||
// }
|
||||
|
||||
cp := &ConvexPolygon{Points: []Vector{}, Closed: true}
|
||||
cp := &ConvexPolygon{
|
||||
Points: NewRingBuffer(6), // I don't expected more points to be coped with in this particular game
|
||||
Closed: true,
|
||||
}
|
||||
|
||||
cp.AddPoints(points...)
|
||||
|
||||
return cp
|
||||
}
|
||||
|
||||
func (cp *ConvexPolygon) Clone() Shape {
|
||||
|
||||
points := []Vector{}
|
||||
|
||||
for _, point := range cp.Points {
|
||||
points = append(points, point.Clone())
|
||||
func (cp *ConvexPolygon) GetPointByOffset(offset int32) Vector {
|
||||
if cp.Points.Cnt <= offset {
|
||||
return nil
|
||||
}
|
||||
return cp.Points.GetByFrameId(cp.Points.StFrameId + offset).(Vector)
|
||||
}
|
||||
|
||||
func (cp *ConvexPolygon) Clone() Shape {
|
||||
|
||||
newPoly := NewConvexPolygon()
|
||||
newPoly.X = cp.X
|
||||
newPoly.Y = cp.Y
|
||||
newPoly.AddPointsVec(points...)
|
||||
for i := int32(0); i < cp.Points.Cnt; i++ {
|
||||
newPoly.Points.Put(cp.GetPointByOffset(i))
|
||||
}
|
||||
newPoly.Closed = cp.Closed
|
||||
return newPoly
|
||||
}
|
||||
|
||||
// AddPointsVec allows you to add points to the ConvexPolygon with a slice of Vectors, each indicating a point / vertex.
|
||||
func (cp *ConvexPolygon) AddPointsVec(points ...Vector) {
|
||||
cp.Points = append(cp.Points, points...)
|
||||
}
|
||||
|
||||
// AddPoints allows you to add points to the ConvexPolygon with a slice or selection of float64s, with each pair indicating an X or Y value for
|
||||
// a point / vertex (i.e. AddPoints(0, 1, 2, 3) would add two points - one at {0, 1}, and another at {2, 3}).
|
||||
func (cp *ConvexPolygon) AddPoints(vertexPositions ...float64) {
|
||||
for v := 0; v < len(vertexPositions); v += 2 {
|
||||
cp.Points = append(cp.Points, Vector{vertexPositions[v], vertexPositions[v+1]})
|
||||
// "resolv.Vector" is an alias of "[]float64", thus already a pointer type
|
||||
cp.Points.Put(Vector{vertexPositions[v], vertexPositions[v+1]})
|
||||
}
|
||||
}
|
||||
|
||||
func (cp *ConvexPolygon) UpdateAsRectangle(x, y, w, h float64) bool {
|
||||
// This function might look ugly but it's a fast in-place update!
|
||||
if 4 != cp.Points.Cnt {
|
||||
panic("ConvexPolygon not having exactly 4 vertices to form a rectangle#1!")
|
||||
}
|
||||
for i := int32(0); i < cp.Points.Cnt; i++ {
|
||||
thatVec := cp.GetPointByOffset(i)
|
||||
if nil == thatVec {
|
||||
panic("ConvexPolygon not having exactly 4 vertices to form a rectangle#2!")
|
||||
}
|
||||
switch i {
|
||||
case 0:
|
||||
thatVec[0] = x
|
||||
thatVec[1] = y
|
||||
case 1:
|
||||
thatVec[0] = x + w
|
||||
thatVec[1] = y
|
||||
case 2:
|
||||
thatVec[0] = x + w
|
||||
thatVec[1] = y + h
|
||||
case 3:
|
||||
thatVec[0] = x
|
||||
thatVec[1] = y + h
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// Lines returns a slice of transformed Lines composing the ConvexPolygon.
|
||||
func (cp *ConvexPolygon) Lines() []*Line {
|
||||
|
||||
@ -200,8 +226,9 @@ func (cp *ConvexPolygon) Lines() []*Line {
|
||||
|
||||
// Transformed returns the ConvexPolygon's points / vertices, transformed according to the ConvexPolygon's position.
|
||||
func (cp *ConvexPolygon) Transformed() []Vector {
|
||||
transformed := make([]Vector, len(cp.Points))
|
||||
for i, point := range cp.Points {
|
||||
transformed := make([]Vector, cp.Points.Cnt)
|
||||
for i := int32(0); i < cp.Points.Cnt; i++ {
|
||||
point := cp.GetPointByOffset(i)
|
||||
transformed[i] = Vector{point[0] + cp.X, point[1] + cp.Y}
|
||||
}
|
||||
return transformed
|
||||
@ -331,10 +358,6 @@ func (polygon *ConvexPolygon) PointInside(point Vector) bool {
|
||||
return contactCount == 1
|
||||
}
|
||||
|
||||
func (polygon *ConvexPolygon) GetPoints() []Vector {
|
||||
return polygon.Points
|
||||
}
|
||||
|
||||
type ContactSet struct {
|
||||
Points []Vector // Slice of Points indicating contact between the two Shapes.
|
||||
MTV Vector // Minimum Translation Vector; this is the vector to move a Shape on to move it outside of its contacting Shape.
|
||||
@ -553,42 +576,6 @@ func (cp *ConvexPolygon) ContainedBy(otherShape Shape) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// FlipH flips the ConvexPolygon's vertices horizontally according to their initial offset when adding the points.
|
||||
func (cp *ConvexPolygon) FlipH() {
|
||||
|
||||
for _, v := range cp.Points {
|
||||
v[0] = -v[0]
|
||||
}
|
||||
// We have to reverse vertex order after flipping the vertices to ensure the winding order is consistent between Objects (so that the normals are consistently outside or inside, which is important
|
||||
// when doing Intersection tests). If we assume that the normal of a line, going from vertex A to vertex B, is one direction, then the normal would be inverted if the vertices were flipped in position,
|
||||
// but not in order. This would make Intersection tests drive objects into each other, instead of giving the delta to move away.
|
||||
cp.ReverseVertexOrder()
|
||||
|
||||
}
|
||||
|
||||
// FlipV flips the ConvexPolygon's vertices vertically according to their initial offset when adding the points.
|
||||
func (cp *ConvexPolygon) FlipV() {
|
||||
|
||||
for _, v := range cp.Points {
|
||||
v[1] = -v[1]
|
||||
}
|
||||
cp.ReverseVertexOrder()
|
||||
|
||||
}
|
||||
|
||||
// ReverseVertexOrder reverses the vertex ordering of the ConvexPolygon.
|
||||
func (cp *ConvexPolygon) ReverseVertexOrder() {
|
||||
|
||||
verts := []Vector{cp.Points[0]}
|
||||
|
||||
for i := len(cp.Points) - 1; i >= 1; i-- {
|
||||
verts = append(verts, cp.Points[i])
|
||||
}
|
||||
|
||||
cp.Points = verts
|
||||
|
||||
}
|
||||
|
||||
// NewRectangle returns a rectangular ConvexPolygon with the vertices in clockwise order. In actuality, an AABBRectangle should be its own
|
||||
// "thing" with its own optimized Intersection code check.
|
||||
func NewRectangle(x, y, w, h float64) *ConvexPolygon {
|
||||
|
Loading…
Reference in New Issue
Block a user