Updated collider utility encapsulation for visualization subproject.

This commit is contained in:
genxium
2022-10-19 15:10:11 +08:00
parent 62f10e0877
commit 3baaf1d52c
2 changed files with 113 additions and 49 deletions

View File

@@ -7,8 +7,6 @@ import (
"github.com/solarlune/resolv"
"go.uber.org/zap"
"image/color"
"math"
)
type WorldColliderDisplay struct {
@@ -34,14 +32,11 @@ func NewWorldColliderDisplay(game *Game, stageDiscreteW, stageDiscreteH, stageTi
spaceOffsetX := float64(spaceW) * 0.5
spaceOffsetY := float64(spaceH) * 0.5
// TODO: Move collider y-axis transformation to a "dnmshared"
playerColliderRadius := float64(32)
playerColliders := make([]*resolv.Object, len(playerList))
space := resolv.NewSpace(int(spaceW), int(spaceH), 16, 16)
for i, player := range playerList {
playerCollider := resolv.NewObject(player.X-playerColliderRadius+spaceOffsetX, player.Y-playerColliderRadius+spaceOffsetY, playerColliderRadius*2, playerColliderRadius*2, "Player")
playerColliderShape := resolv.NewRectangle(0, 0, playerColliderRadius*2, playerColliderRadius*2) // [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.SetShape(playerColliderShape)
playerCollider := GenerateRectCollider(player.X, player.Y, playerColliderRadius*2, playerColliderRadius*2, spaceOffsetX, spaceOffsetY, "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"
Logger.Info(fmt.Sprintf("Player Collider#%d: player.X=%v, player.Y=%v, radius=%v, spaceOffsetX=%v, spaceOffsetY=%v, shape=%v; calibrationCheckX=player.X-radius+spaceOffsetX=%v", i, player.X, player.Y, playerColliderRadius, spaceOffsetX, spaceOffsetY, playerCollider.Shape, player.X-playerColliderRadius+spaceOffsetX))
playerColliders[i] = playerCollider
space.Add(playerCollider)
@@ -49,56 +44,43 @@ func NewWorldColliderDisplay(game *Game, stageDiscreteW, stageDiscreteH, stageTi
barrierLocalId := 0
for _, barrierUnaligned := range barrierList {
barrier := AlignPolygon2DToBoundingBox(barrierUnaligned)
var w float64 = 0
var h float64 = 0
for i, pi := range barrier.Points {
for j, pj := range barrier.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 i := 0; i < len(barrier.Points); i++ {
p := barrier.Points[i]
barrierColliderShape.AddPoints(p.X, p.Y)
}
barrierCollider := resolv.NewObject(barrier.Anchor.X+spaceOffsetX, barrier.Anchor.Y+spaceOffsetY, w, h, "Barrier")
barrierCollider.SetShape(barrierColliderShape)
space.Add(barrierCollider)
barrierCollider := GenerateConvexPolygonCollider(barrierUnaligned, spaceOffsetX, spaceOffsetY, "Barrier")
Logger.Info(fmt.Sprintf("Added barrier: shape=%v", barrierCollider.Shape))
space.Add(barrierCollider)
barrierLocalId++
}
world.Space = space
toTestPlayerCollider := playerColliders[0]
oldDx := 0.0
oldDy := 180.0
if collision := toTestPlayerCollider.Check(oldDx, oldDy, "Barrier"); collision != nil {
toCheckBarrier := collision.Objects[0].Shape
if intersection := toTestPlayerCollider.Shape.Intersection(oldDx, oldDy, toCheckBarrier); nil != intersection {
Logger.Info(fmt.Sprintf("Collided: shape=%v, oldDx=%v, oldDy=%v, intersection.MTV=%v", toTestPlayerCollider.Shape, oldDx, oldDy, intersection.MTV))
} else {
Logger.Info(fmt.Sprintf("Collided: shape=%v, oldDx=%v, oldDy=%v, toCheckBarrier=%v, no intersecting points", toTestPlayerCollider.Shape, oldDx, oldDy, toCheckBarrier))
}
} else {
Logger.Info(fmt.Sprintf("Collision Test: shape=%v, oldDx=%v, oldDy=%v, not colliding with any Barrier", toTestPlayerCollider.Shape, oldDx, oldDy))
}
moveToCollide := true
if moveToCollide {
toTestPlayerCollider := playerColliders[0]
oldDx := 0.0
oldDy := 180.0
dx := oldDx
dy := oldDy
if collision := toTestPlayerCollider.Check(oldDx, oldDy, "Barrier"); collision != nil {
playerShape := toTestPlayerCollider.Shape.(*resolv.ConvexPolygon)
barrierShape := collision.Objects[0].Shape.(*resolv.ConvexPolygon)
origX, origY := playerShape.Position()
playerShape.SetPosition(origX+oldDx, origY+oldDy)
if mtv := CalculateMTVForConvexPolygon(playerShape, barrierShape); mtv != nil {
Logger.Info(fmt.Sprintf("Collided: shape=%v, oldDx=%v, oldDy=%v, MTV=%v", toTestPlayerCollider.Shape, oldDx, oldDy, mtv))
//dx, dy = mtv[0], mtv[1]
} else {
Logger.Info(fmt.Sprintf("Collided: shape=%v, oldDx=%v, oldDy=%v, toCheckBarrier=%v, not intersecting", toTestPlayerCollider.Shape, oldDx, oldDy, barrierShape))
}
toTestPlayerCollider.Update()
playerShape.SetPosition(origX, origY)
toTestPlayerCollider.X += dx
toTestPlayerCollider.Y += dy
} else {
Logger.Info(fmt.Sprintf("Collision Test: shape=%v, oldDx=%v, oldDy=%v, not colliding with any Barrier", toTestPlayerCollider.Shape, oldDx, oldDy))
}
toTestPlayerCollider.Update()
}
return world
}