diff --git a/battle_srv/models/room.go b/battle_srv/models/room.go index d72c0c7..4422fcf 100644 --- a/battle_srv/models/room.go +++ b/battle_srv/models/room.go @@ -13,13 +13,13 @@ import ( "io/ioutil" "jsexport/battle" "math/rand" + "os" "path/filepath" "resolv" "strings" "sync" "sync/atomic" "time" - "os" ) const ( @@ -344,6 +344,19 @@ func (pR *Room) InputsBufferString(allDetails bool) string { } } +func (pR *Room) playerDownsyncStr(player *battle.PlayerDownsync) string { + if nil == player { + return "" + } + inAirInt := 0 + if player.InAir { + inAirInt = 1 + } + s := fmt.Sprintf("{%d,%d,%d,%d,%d,%d}", player.JoinIndex, player.VirtualGridX, player.VirtualGridY, player.VelX, player.VelY, inAirInt) + + return s +} + func (pR *Room) inputFrameDownsyncStr(inputFrameDownsync *pb.InputFrameDownsync) string { if nil == inputFrameDownsync { return "" @@ -364,7 +377,12 @@ func (pR *Room) rdfIdToActuallyUsedInputString() string { // Appending of the array of strings can be very SLOW due to on-demand heap allocation! Use this printing with caution. s := make([]string, 0) for rdfId := pR.RenderFrameBuffer.StFrameId; rdfId < pR.RenderFrameBuffer.EdFrameId; rdfId++ { - s = append(s, fmt.Sprintf("rdfId:%d\nactuallyUsedinputList:{%v}", rdfId, pR.inputFrameDownsyncStr(pR.rdfIdToActuallyUsedInput[rdfId]))) + rdf := pR.RenderFrameBuffer.GetByFrameId(rdfId).(*battle.RoomDownsyncFrame) + playersStrBldr := make([]string, 0, len(rdf.PlayersArr)) + for _, player := range rdf.PlayersArr { + playersStrBldr = append(playersStrBldr, pR.playerDownsyncStr(player)) + } + s = append(s, fmt.Sprintf("rdfId:%d\nplayers:[%v]\nactuallyUsedinputList:{%v}", rdfId, strings.Join(playersStrBldr, ","), pR.inputFrameDownsyncStr(pR.rdfIdToActuallyUsedInput[rdfId]))) } return strings.Join(s, "\n") @@ -406,9 +424,9 @@ func (pR *Room) StartBattle() { Logger.Error("battleMainLoop, recovery spot#1, recovered from: ", zap.Any("roomId", pR.Id), zap.Any("panic", r)) } pR.StopBattleForSettlement() - rdfIdToActuallyUsedInputDump := pR.rdfIdToActuallyUsedInputString() + rdfIdToActuallyUsedInputDump := pR.rdfIdToActuallyUsedInputString() Logger.Info(fmt.Sprintf("The `battleMainLoop` for roomId=%v is stopped@renderFrameId=%v, with battleDurationFrames=%v:\n%v", pR.Id, pR.RenderFrameId, pR.BattleDurationFrames, pR.InputsBufferString(false))) // This takes sometime to print - os.WriteFile(fmt.Sprintf("room_%d.txt", pR.Id), []byte(rdfIdToActuallyUsedInputDump), 0644) // DEBUG ONLY + os.WriteFile(fmt.Sprintf("room_%d.txt", pR.Id), []byte(rdfIdToActuallyUsedInputDump), 0644) // DEBUG ONLY pR.onBattleStoppedForSettlement() }() diff --git a/collider_visualizer/common.go b/collider_visualizer/common.go index feab531..c054be3 100644 --- a/collider_visualizer/common.go +++ b/collider_visualizer/common.go @@ -2,8 +2,8 @@ package main import ( "github.com/hajimehoshi/ebiten/v2" - "github.com/solarlune/resolv" "image/color" + "resolv" ) var ( diff --git a/collider_visualizer/go.mod b/collider_visualizer/go.mod index adb6118..2bb4dcf 100644 --- a/collider_visualizer/go.mod +++ b/collider_visualizer/go.mod @@ -5,9 +5,9 @@ go 1.18 require ( jsexport v0.0.0 dnmshared v0.0.0 + resolv 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 golang.org/x/image v0.0.0-20220902085622-e7cb96979f69 ) @@ -18,7 +18,6 @@ require ( github.com/hajimehoshi/file2byteslice v0.0.0-20210813153925-5340248a8f41 // indirect github.com/inconshreveable/mousetrap v1.0.0 // indirect github.com/jezek/xgb v1.0.1 // indirect - github.com/kvartborg/vector v0.0.0-20200419093813-2cba0cabb4f0 // indirect github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86 // indirect github.com/neelance/sourcemap v0.0.0-20200213170602-2833bce08e4c // indirect github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749 // indirect @@ -41,4 +40,5 @@ require ( replace ( dnmshared => ../dnmshared jsexport => ../jsexport + resolv => ../resolv_tailored ) diff --git a/collider_visualizer/main.go b/collider_visualizer/main.go index d972b7e..fef8009 100644 --- a/collider_visualizer/main.go +++ b/collider_visualizer/main.go @@ -11,13 +11,13 @@ import ( "github.com/hajimehoshi/ebiten/v2" "github.com/hajimehoshi/ebiten/v2/ebitenutil" "github.com/hajimehoshi/ebiten/v2/text" - "github.com/solarlune/resolv" "golang.org/x/image/font" "encoding/xml" "io/ioutil" "os" "path/filepath" + "resolv" . "dnmshared" ) diff --git a/collider_visualizer/worldColliderDisplay.go b/collider_visualizer/worldColliderDisplay.go index 1ac60fb..c25281a 100644 --- a/collider_visualizer/worldColliderDisplay.go +++ b/collider_visualizer/worldColliderDisplay.go @@ -1,14 +1,13 @@ package main import ( - . "jsexport/protos" . "dnmshared" - . "dnmshared/sharedprotos" "fmt" "github.com/hajimehoshi/ebiten/v2" - "github.com/solarlune/resolv" "go.uber.org/zap" "image/color" + . "jsexport/battle" + "resolv" ) type WorldColliderDisplay struct { @@ -39,20 +38,20 @@ func NewWorldColliderDisplay(game *Game, stageDiscreteW, stageDiscreteH, stageTi playerDefaultSpeed := 1 * worldToVirtualGridRatio minStep := (int(float64(playerDefaultSpeed)*virtualGridToWorldRatio) << 3) playerColliderRadius := float64(12) - playerColliders := make([]*resolv.Object, len(playerPosList.Eles)) + playerColliders := make([]*resolv.Object, len(playerPosList)) snapIntoPlatformOverlap := float64(0.1) space := resolv.NewSpace(int(spaceW), int(spaceH), minStep, minStep) topPadding, bottomPadding, leftPadding, rightPadding := snapIntoPlatformOverlap, snapIntoPlatformOverlap, snapIntoPlatformOverlap, snapIntoPlatformOverlap - for i, playerPos := range playerPosList.Eles { + for i, playerPos := range playerPosList { colliderWidth, colliderHeight := playerColliderRadius*2, playerColliderRadius*4 - playerCollider := GenerateRectCollider(playerPos.X, playerPos.Y, colliderWidth, colliderHeight, topPadding, bottomPadding, leftPadding, rightPadding, spaceOffsetX, spaceOffsetY, nil, "Player") // [WARNING] Deliberately not using a circle because "resolv v0.5.1" doesn't yet align circle center with space cell center, regardless of the "specified within-object offset" + playerCollider := GenerateRectCollider(playerPos.X, playerPos.Y, colliderWidth, colliderHeight, topPadding, bottomPadding, leftPadding, rightPadding, spaceOffsetX, spaceOffsetY, nil, fmt.Sprintf("Player%d", i+1)) // [WARNING] Deliberately not using a circle because "resolv v0.5.1" doesn't yet align circle center with space cell center, regardless of the "specified within-object offset" Logger.Info(fmt.Sprintf("Player Collider#%d: player world pos=(%.2f, %.2f), shape=%v", i, playerPos.X, playerPos.Y, ConvexPolygonStr(playerCollider.Shape.(*resolv.ConvexPolygon)))) playerColliders[i] = playerCollider space.Add(playerCollider) } barrierLocalId := 0 - for _, barrierUnaligned := range barrierList.Eles { + for _, barrierUnaligned := range barrierList { barrierCollider := GenerateConvexPolygonCollider(barrierUnaligned, spaceOffsetX, spaceOffsetY, nil, "Barrier") Logger.Debug(fmt.Sprintf("Added barrier: shape=%v", ConvexPolygonStr(barrierCollider.Shape.(*resolv.ConvexPolygon)))) space.Add(barrierCollider) @@ -64,16 +63,14 @@ func NewWorldColliderDisplay(game *Game, stageDiscreteW, stageDiscreteH, stageTi moveToCollide := true if moveToCollide { effPushback := Vec2D{X: float64(0), Y: float64(0)} - toTestPlayerCollider := playerColliders[0] colliderWidth, colliderHeight := playerColliderRadius*2, playerColliderRadius*4 - newVx, newVy := int32(-189000), int32(-497000) - toTestPlayerCollider.X, toTestPlayerCollider.Y = VirtualGridToPolygonColliderBLPos(newVx, newVy, colliderWidth, colliderHeight, topPadding, bottomPadding, leftPadding, rightPadding, spaceOffsetX, spaceOffsetY, virtualGridToWorldRatio) - playerColliders[1].X, playerColliders[1].Y = VirtualGridToPolygonColliderBLPos(int32(-165000), int32(-504000), colliderWidth, colliderHeight, topPadding, bottomPadding, leftPadding, rightPadding, spaceOffsetX, spaceOffsetY, virtualGridToWorldRatio) - playerColliders[1].Update() + playerColliders[0].X, playerColliders[0].Y = VirtualGridToPolygonColliderBLPos(int32(-139000-2000), int32(-474500+2000), colliderWidth, colliderHeight, topPadding, bottomPadding, leftPadding, rightPadding, spaceOffsetX, spaceOffsetY, virtualGridToWorldRatio) + playerColliders[0].Update() - Logger.Info(fmt.Sprintf("Checking collision for playerShape=%v", ConvexPolygonStr(toTestPlayerCollider.Shape.(*resolv.ConvexPolygon)))) + playerColliders[1].X, playerColliders[1].Y = VirtualGridToPolygonColliderBLPos(int32(-163000), int32(-520000), colliderWidth, colliderHeight, topPadding, bottomPadding, leftPadding, rightPadding, spaceOffsetX, spaceOffsetY, virtualGridToWorldRatio) + playerColliders[1].Update() - toTestPlayerCollider.Update() + toTestPlayerCollider := playerColliders[1] if collision := toTestPlayerCollider.Check(0, 0); collision != nil { playerShape := toTestPlayerCollider.Shape.(*resolv.ConvexPolygon) for _, obj := range collision.Objects { @@ -100,15 +97,11 @@ func NewWorldColliderDisplay(game *Game, stageDiscreteW, stageDiscreteH, stageTi 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), - }, + SelfMoveforwardX: 0, + SelfMoveforwardY: 0, + HitboxOffset: float64(24.0), + HitboxSizeX: float64(45.0), + HitboxSizeY: float64(32.0), // for defender HitStunFrames: int32(18), @@ -120,9 +113,9 @@ func NewWorldColliderDisplay(game *Game, stageDiscreteW, stageDiscreteH, stageTi bulletLeftToRight := false if bulletLeftToRight { xfac := float64(1.0) - offenderWx, offenderWy := playerPosList.Eles[0].X, playerPosList.Eles[0].Y + offenderWx, offenderWy := playerPosList[0].X, playerPosList[0].Y bulletWx, bulletWy := offenderWx+xfac*meleeBullet.HitboxOffset, offenderWy - newBulletCollider := GenerateRectCollider(bulletWx, bulletWy, meleeBullet.HitboxSize.X, meleeBullet.HitboxSize.Y, topPadding, bottomPadding, leftPadding, rightPadding, spaceOffsetX, spaceOffsetY, nil, "MeleeBullet") + newBulletCollider := GenerateRectCollider(bulletWx, bulletWy, meleeBullet.HitboxSizeX, meleeBullet.HitboxSizeY, topPadding, bottomPadding, leftPadding, rightPadding, spaceOffsetX, spaceOffsetY, nil, "MeleeBullet") space.Add(newBulletCollider) bulletShape := newBulletCollider.Shape.(*resolv.ConvexPolygon) Logger.Warn(fmt.Sprintf("bullet ->: Added bullet collider to space: a=%v", ConvexPolygonStr(bulletShape))) @@ -142,10 +135,10 @@ func NewWorldColliderDisplay(game *Game, stageDiscreteW, stageDiscreteH, stageTi bulletRightToLeft := false if bulletRightToLeft { xfac := float64(-1.0) - offenderWx, offenderWy := playerPosList.Eles[1].X, playerPosList.Eles[1].Y + offenderWx, offenderWy := playerPosList[1].X, playerPosList[1].Y bulletWx, bulletWy := offenderWx+xfac*meleeBullet.HitboxOffset, offenderWy - newBulletCollider := GenerateRectCollider(bulletWx, bulletWy, meleeBullet.HitboxSize.X, meleeBullet.HitboxSize.Y, topPadding, bottomPadding, leftPadding, rightPadding, spaceOffsetX, spaceOffsetY, nil, "MeleeBullet") + newBulletCollider := GenerateRectCollider(bulletWx, bulletWy, meleeBullet.HitboxSizeX, meleeBullet.HitboxSizeY, topPadding, bottomPadding, leftPadding, rightPadding, spaceOffsetX, spaceOffsetY, nil, "MeleeBullet") space.Add(newBulletCollider) bulletShape := newBulletCollider.Shape.(*resolv.ConvexPolygon) Logger.Warn(fmt.Sprintf("bullet <-: Added bullet collider to space: a=%v", ConvexPolygonStr(bulletShape))) @@ -172,11 +165,14 @@ func (world *WorldColliderDisplay) Update() { func (world *WorldColliderDisplay) Draw(screen *ebiten.Image) { for _, o := range world.Space.Objects() { - if o.HasTags("Player") { - drawColor := color.RGBA{0, 255, 0, 255} + if o.HasTags("Player1") { + drawColor := color.RGBA{255, 0, 0, 255} + DrawPolygon(screen, o.Shape.(*resolv.ConvexPolygon), drawColor) + } else if o.HasTags("Player2") { + drawColor := color.RGBA{0, 0, 255, 255} DrawPolygon(screen, o.Shape.(*resolv.ConvexPolygon), drawColor) } else if o.HasTags("MeleeBullet") { - drawColor := color.RGBA{0, 0, 255, 255} + drawColor := color.RGBA{78, 255, 112, 255} DrawPolygon(screen, o.Shape.(*resolv.ConvexPolygon), drawColor) } else { drawColor := color.RGBA{60, 60, 60, 255} diff --git a/frontend/assets/scripts/Map.js b/frontend/assets/scripts/Map.js index 8c29b44..f98c3a8 100644 --- a/frontend/assets/scripts/Map.js +++ b/frontend/assets/scripts/Map.js @@ -1206,6 +1206,11 @@ ${self._stringifyRdfIdToActuallyUsedInput()}`); return `[stRenderFrameId=${self.recentRenderCache.stFrameId}, edRenderFrameId=${self.recentRenderCache.edFrameId})`; }, + playerDownsyncStr(playerDownsync) { + if (null == playerDownsync) return ""; + return `{${playerDownsync.JoinIndex},${playerDownsync.VirtualGridX},${playerDownsync.VirtualGridY},${playerDownsync.VelX},${playerDownsync.VelY},${playerDownsync.InAir ? 1 : 0}}`; + }, + inputFrameDownsyncStr(inputFrameDownsync) { if (null == inputFrameDownsync) return ""; const self = this; @@ -1227,7 +1232,13 @@ ${self._stringifyRdfIdToActuallyUsedInput()}`); let s = []; for (let i = self.recentRenderCache.stFrameId; i < self.recentRenderCache.edFrameId; i++) { const actuallyUsedInputClone = self.rdfIdToActuallyUsedInput.get(i); + const rdf = self.recentRenderCache.getByFrameId(i); + const playersStrBldr = []; + for (let k in rdf.PlayersArr) { + playersStrBldr.push(self.playerDownsyncStr(rdf.PlayersArr[k])); + } s.push(`rdfId:${i} +players:[${playersStrBldr.join(',')}] actuallyUsedinputList:{${self.inputFrameDownsyncStr(actuallyUsedInputClone)}}`); }