Fixed collider visualizer.

This commit is contained in:
genxium 2022-12-26 20:37:40 +08:00
parent ac5217611d
commit bb6055f48c
6 changed files with 63 additions and 38 deletions

View File

@ -13,13 +13,13 @@ import (
"io/ioutil" "io/ioutil"
"jsexport/battle" "jsexport/battle"
"math/rand" "math/rand"
"os"
"path/filepath" "path/filepath"
"resolv" "resolv"
"strings" "strings"
"sync" "sync"
"sync/atomic" "sync/atomic"
"time" "time"
"os"
) )
const ( 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 { func (pR *Room) inputFrameDownsyncStr(inputFrameDownsync *pb.InputFrameDownsync) string {
if nil == inputFrameDownsync { if nil == inputFrameDownsync {
return "" 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. // 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) s := make([]string, 0)
for rdfId := pR.RenderFrameBuffer.StFrameId; rdfId < pR.RenderFrameBuffer.EdFrameId; rdfId++ { 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") 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)) Logger.Error("battleMainLoop, recovery spot#1, recovered from: ", zap.Any("roomId", pR.Id), zap.Any("panic", r))
} }
pR.StopBattleForSettlement() 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 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() pR.onBattleStoppedForSettlement()
}() }()

View File

@ -2,8 +2,8 @@ package main
import ( import (
"github.com/hajimehoshi/ebiten/v2" "github.com/hajimehoshi/ebiten/v2"
"github.com/solarlune/resolv"
"image/color" "image/color"
"resolv"
) )
var ( var (

View File

@ -5,9 +5,9 @@ go 1.18
require ( require (
jsexport v0.0.0 jsexport v0.0.0
dnmshared v0.0.0 dnmshared v0.0.0
resolv v0.0.0
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0
github.com/hajimehoshi/ebiten/v2 v2.4.7 github.com/hajimehoshi/ebiten/v2 v2.4.7
github.com/solarlune/resolv v0.5.1
golang.org/x/image v0.0.0-20220902085622-e7cb96979f69 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/hajimehoshi/file2byteslice v0.0.0-20210813153925-5340248a8f41 // indirect
github.com/inconshreveable/mousetrap v1.0.0 // indirect github.com/inconshreveable/mousetrap v1.0.0 // indirect
github.com/jezek/xgb v1.0.1 // 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/astrewrite v0.0.0-20160511093645-99348263ae86 // indirect
github.com/neelance/sourcemap v0.0.0-20200213170602-2833bce08e4c // indirect github.com/neelance/sourcemap v0.0.0-20200213170602-2833bce08e4c // indirect
github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749 // indirect github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749 // indirect
@ -41,4 +40,5 @@ require (
replace ( replace (
dnmshared => ../dnmshared dnmshared => ../dnmshared
jsexport => ../jsexport jsexport => ../jsexport
resolv => ../resolv_tailored
) )

View File

@ -11,13 +11,13 @@ import (
"github.com/hajimehoshi/ebiten/v2" "github.com/hajimehoshi/ebiten/v2"
"github.com/hajimehoshi/ebiten/v2/ebitenutil" "github.com/hajimehoshi/ebiten/v2/ebitenutil"
"github.com/hajimehoshi/ebiten/v2/text" "github.com/hajimehoshi/ebiten/v2/text"
"github.com/solarlune/resolv"
"golang.org/x/image/font" "golang.org/x/image/font"
"encoding/xml" "encoding/xml"
"io/ioutil" "io/ioutil"
"os" "os"
"path/filepath" "path/filepath"
"resolv"
. "dnmshared" . "dnmshared"
) )

View File

@ -1,14 +1,13 @@
package main package main
import ( import (
. "jsexport/protos"
. "dnmshared" . "dnmshared"
. "dnmshared/sharedprotos"
"fmt" "fmt"
"github.com/hajimehoshi/ebiten/v2" "github.com/hajimehoshi/ebiten/v2"
"github.com/solarlune/resolv"
"go.uber.org/zap" "go.uber.org/zap"
"image/color" "image/color"
. "jsexport/battle"
"resolv"
) )
type WorldColliderDisplay struct { type WorldColliderDisplay struct {
@ -39,20 +38,20 @@ func NewWorldColliderDisplay(game *Game, stageDiscreteW, stageDiscreteH, stageTi
playerDefaultSpeed := 1 * worldToVirtualGridRatio playerDefaultSpeed := 1 * worldToVirtualGridRatio
minStep := (int(float64(playerDefaultSpeed)*virtualGridToWorldRatio) << 3) minStep := (int(float64(playerDefaultSpeed)*virtualGridToWorldRatio) << 3)
playerColliderRadius := float64(12) playerColliderRadius := float64(12)
playerColliders := make([]*resolv.Object, len(playerPosList.Eles)) playerColliders := make([]*resolv.Object, len(playerPosList))
snapIntoPlatformOverlap := float64(0.1) snapIntoPlatformOverlap := float64(0.1)
space := resolv.NewSpace(int(spaceW), int(spaceH), minStep, minStep) space := resolv.NewSpace(int(spaceW), int(spaceH), minStep, minStep)
topPadding, bottomPadding, leftPadding, rightPadding := snapIntoPlatformOverlap, snapIntoPlatformOverlap, snapIntoPlatformOverlap, snapIntoPlatformOverlap 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 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)))) 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 playerColliders[i] = playerCollider
space.Add(playerCollider) space.Add(playerCollider)
} }
barrierLocalId := 0 barrierLocalId := 0
for _, barrierUnaligned := range barrierList.Eles { for _, barrierUnaligned := range barrierList {
barrierCollider := GenerateConvexPolygonCollider(barrierUnaligned, spaceOffsetX, spaceOffsetY, nil, "Barrier") barrierCollider := GenerateConvexPolygonCollider(barrierUnaligned, spaceOffsetX, spaceOffsetY, nil, "Barrier")
Logger.Debug(fmt.Sprintf("Added barrier: shape=%v", ConvexPolygonStr(barrierCollider.Shape.(*resolv.ConvexPolygon)))) Logger.Debug(fmt.Sprintf("Added barrier: shape=%v", ConvexPolygonStr(barrierCollider.Shape.(*resolv.ConvexPolygon))))
space.Add(barrierCollider) space.Add(barrierCollider)
@ -64,16 +63,14 @@ func NewWorldColliderDisplay(game *Game, stageDiscreteW, stageDiscreteH, stageTi
moveToCollide := true moveToCollide := true
if moveToCollide { if moveToCollide {
effPushback := Vec2D{X: float64(0), Y: float64(0)} effPushback := Vec2D{X: float64(0), Y: float64(0)}
toTestPlayerCollider := playerColliders[0]
colliderWidth, colliderHeight := playerColliderRadius*2, playerColliderRadius*4 colliderWidth, colliderHeight := playerColliderRadius*2, playerColliderRadius*4
newVx, newVy := int32(-189000), int32(-497000) playerColliders[0].X, playerColliders[0].Y = VirtualGridToPolygonColliderBLPos(int32(-139000-2000), int32(-474500+2000), colliderWidth, colliderHeight, topPadding, bottomPadding, leftPadding, rightPadding, spaceOffsetX, spaceOffsetY, virtualGridToWorldRatio)
toTestPlayerCollider.X, toTestPlayerCollider.Y = VirtualGridToPolygonColliderBLPos(newVx, newVy, colliderWidth, colliderHeight, topPadding, bottomPadding, leftPadding, rightPadding, spaceOffsetX, spaceOffsetY, virtualGridToWorldRatio) playerColliders[0].Update()
playerColliders[1].X, playerColliders[1].Y = VirtualGridToPolygonColliderBLPos(int32(-165000), int32(-504000), colliderWidth, colliderHeight, topPadding, bottomPadding, leftPadding, rightPadding, spaceOffsetX, spaceOffsetY, virtualGridToWorldRatio)
playerColliders[1].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 { if collision := toTestPlayerCollider.Check(0, 0); collision != nil {
playerShape := toTestPlayerCollider.Shape.(*resolv.ConvexPolygon) playerShape := toTestPlayerCollider.Shape.(*resolv.ConvexPolygon)
for _, obj := range collision.Objects { for _, obj := range collision.Objects {
@ -100,15 +97,11 @@ func NewWorldColliderDisplay(game *Game, stageDiscreteW, stageDiscreteH, stageTi
RecoveryFrames: int32(61), RecoveryFrames: int32(61),
RecoveryFramesOnBlock: int32(61), RecoveryFramesOnBlock: int32(61),
RecoveryFramesOnHit: int32(61), RecoveryFramesOnHit: int32(61),
Moveforward: &Vec2D{ SelfMoveforwardX: 0,
X: 0, SelfMoveforwardY: 0,
Y: 0, HitboxOffset: float64(24.0),
}, HitboxSizeX: float64(45.0),
HitboxOffset: float64(24.0), HitboxSizeY: float64(32.0),
HitboxSize: &Vec2D{
X: float64(45.0),
Y: float64(32.0),
},
// for defender // for defender
HitStunFrames: int32(18), HitStunFrames: int32(18),
@ -120,9 +113,9 @@ func NewWorldColliderDisplay(game *Game, stageDiscreteW, stageDiscreteH, stageTi
bulletLeftToRight := false bulletLeftToRight := false
if bulletLeftToRight { if bulletLeftToRight {
xfac := float64(1.0) 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 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) space.Add(newBulletCollider)
bulletShape := newBulletCollider.Shape.(*resolv.ConvexPolygon) bulletShape := newBulletCollider.Shape.(*resolv.ConvexPolygon)
Logger.Warn(fmt.Sprintf("bullet ->: Added bullet collider to space: a=%v", ConvexPolygonStr(bulletShape))) 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 bulletRightToLeft := false
if bulletRightToLeft { if bulletRightToLeft {
xfac := float64(-1.0) 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 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) space.Add(newBulletCollider)
bulletShape := newBulletCollider.Shape.(*resolv.ConvexPolygon) bulletShape := newBulletCollider.Shape.(*resolv.ConvexPolygon)
Logger.Warn(fmt.Sprintf("bullet <-: Added bullet collider to space: a=%v", ConvexPolygonStr(bulletShape))) 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) { func (world *WorldColliderDisplay) Draw(screen *ebiten.Image) {
for _, o := range world.Space.Objects() { for _, o := range world.Space.Objects() {
if o.HasTags("Player") { if o.HasTags("Player1") {
drawColor := color.RGBA{0, 255, 0, 255} 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) DrawPolygon(screen, o.Shape.(*resolv.ConvexPolygon), drawColor)
} else if o.HasTags("MeleeBullet") { } 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) DrawPolygon(screen, o.Shape.(*resolv.ConvexPolygon), drawColor)
} else { } else {
drawColor := color.RGBA{60, 60, 60, 255} drawColor := color.RGBA{60, 60, 60, 255}

View File

@ -1206,6 +1206,11 @@ ${self._stringifyRdfIdToActuallyUsedInput()}`);
return `[stRenderFrameId=${self.recentRenderCache.stFrameId}, edRenderFrameId=${self.recentRenderCache.edFrameId})`; 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) { inputFrameDownsyncStr(inputFrameDownsync) {
if (null == inputFrameDownsync) return ""; if (null == inputFrameDownsync) return "";
const self = this; const self = this;
@ -1227,7 +1232,13 @@ ${self._stringifyRdfIdToActuallyUsedInput()}`);
let s = []; let s = [];
for (let i = self.recentRenderCache.stFrameId; i < self.recentRenderCache.edFrameId; i++) { for (let i = self.recentRenderCache.stFrameId; i < self.recentRenderCache.edFrameId; i++) {
const actuallyUsedInputClone = self.rdfIdToActuallyUsedInput.get(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} s.push(`rdfId:${i}
players:[${playersStrBldr.join(',')}]
actuallyUsedinputList:{${self.inputFrameDownsyncStr(actuallyUsedInputClone)}}`); actuallyUsedinputList:{${self.inputFrameDownsyncStr(actuallyUsedInputClone)}}`);
} }