2022-10-14 10:02:03 +00:00
package main
import (
2022-10-15 08:51:38 +00:00
. "dnmshared"
2022-10-14 10:02:03 +00:00
"fmt"
"github.com/hajimehoshi/ebiten/v2"
2022-10-19 09:32:18 +00:00
"github.com/kvartborg/vector"
2022-10-14 10:02:03 +00:00
"github.com/solarlune/resolv"
2022-10-15 08:51:38 +00:00
"go.uber.org/zap"
"image/color"
2022-10-14 10:02:03 +00:00
)
type WorldColliderDisplay struct {
2022-10-15 08:51:38 +00:00
Game * Game
Space * resolv . Space
2022-10-14 10:02:03 +00:00
}
func ( world * WorldColliderDisplay ) Init ( ) {
}
func NewWorldColliderDisplay ( game * Game , stageDiscreteW , stageDiscreteH , stageTileW , stageTileH int32 , playerPosMap StrToVec2DListMap , barrierMap StrToPolygon2DListMap ) * WorldColliderDisplay {
2022-10-14 10:47:09 +00:00
2022-10-15 08:51:38 +00:00
playerList := * ( playerPosMap [ "PlayerStartingPos" ] )
2022-10-14 10:47:09 +00:00
barrierList := * ( barrierMap [ "Barrier" ] )
world := & WorldColliderDisplay { Game : game }
Logger . Info ( "Parsed variables" , zap . Any ( "stageDiscreteW" , stageDiscreteW ) , zap . Any ( "stageDiscreteH" , stageDiscreteH ) , zap . Any ( "stageTileW" , stageTileW ) , zap . Any ( "stageTileH" , stageTileH ) )
2022-10-14 10:02:03 +00:00
spaceW := stageDiscreteW * stageTileW
spaceH := stageDiscreteH * stageTileH
spaceOffsetX := float64 ( spaceW ) * 0.5
spaceOffsetY := float64 ( spaceH ) * 0.5
2022-10-19 00:32:20 +00:00
playerColliderRadius := float64 ( 32 )
playerColliders := make ( [ ] * resolv . Object , len ( playerList ) )
2022-10-15 08:51:38 +00:00
space := resolv . NewSpace ( int ( spaceW ) , int ( spaceH ) , 16 , 16 )
2022-10-19 00:32:20 +00:00
for i , player := range playerList {
2022-10-19 07:10:11 +00:00
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"
2022-10-19 00:32:20 +00:00
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
2022-10-15 08:51:38 +00:00
space . Add ( playerCollider )
}
barrierLocalId := 0
2022-10-15 13:39:22 +00:00
for _ , barrierUnaligned := range barrierList {
2022-10-19 07:10:11 +00:00
barrierCollider := GenerateConvexPolygonCollider ( barrierUnaligned , spaceOffsetX , spaceOffsetY , "Barrier" )
2022-10-19 00:32:20 +00:00
Logger . Info ( fmt . Sprintf ( "Added barrier: shape=%v" , barrierCollider . Shape ) )
2022-10-19 07:10:11 +00:00
space . Add ( barrierCollider )
2022-10-15 08:51:38 +00:00
barrierLocalId ++
}
2022-10-14 10:02:03 +00:00
2022-10-14 10:47:09 +00:00
world . Space = space
2022-10-19 00:32:20 +00:00
2022-10-19 07:10:11 +00:00
moveToCollide := true
if moveToCollide {
toTestPlayerCollider := playerColliders [ 0 ]
2022-10-19 09:56:52 +00:00
oldDx := 135.0
2022-10-19 09:32:18 +00:00
oldDy := 135.0
2022-10-19 07:10:11 +00:00
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 )
2022-10-19 09:32:18 +00:00
if colliding := IsPolygonPairColliding ( playerShape , barrierShape , nil ) ; colliding {
Logger . Info ( fmt . Sprintf ( "Collided: playerShape=%v, oldDx=%v, oldDy=%v" , playerShape , oldDx , oldDy ) )
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
} else {
Logger . Info ( fmt . Sprintf ( "Not Collided: playerShape=%v, oldDx=%v, oldDy=%v, toCheckBarrier=%v, e=%v" , playerShape , oldDx , oldDy , barrierShape , e ) )
}
2022-10-19 07:10:11 +00:00
} else {
2022-10-19 09:32:18 +00:00
Logger . Info ( fmt . Sprintf ( "Not collided: playerShape=%v, oldDx=%v, oldDy=%v, toCheckBarrier=%v" , playerShape , oldDx , oldDy , barrierShape ) )
2022-10-19 07:10:11 +00:00
}
playerShape . SetPosition ( origX , origY )
toTestPlayerCollider . X += dx
toTestPlayerCollider . Y += dy
2022-10-19 00:32:20 +00:00
} else {
2022-10-19 07:10:11 +00:00
Logger . Info ( fmt . Sprintf ( "Collision Test: shape=%v, oldDx=%v, oldDy=%v, not colliding with any Barrier" , toTestPlayerCollider . Shape , oldDx , oldDy ) )
}
2022-10-19 00:32:20 +00:00
2022-10-19 07:10:11 +00:00
toTestPlayerCollider . Update ( )
}
2022-10-19 00:32:20 +00:00
2022-10-15 08:51:38 +00:00
return world
2022-10-14 10:02:03 +00:00
}
func ( world * WorldColliderDisplay ) Update ( ) {
}
func ( world * WorldColliderDisplay ) Draw ( screen * ebiten . Image ) {
for _ , o := range world . Space . Objects ( ) {
if o . HasTags ( "Player" ) {
2022-10-15 08:51:38 +00:00
drawColor := color . RGBA { 0 , 255 , 0 , 255 }
2022-10-19 00:32:20 +00:00
DrawPolygon ( screen , o . Shape . ( * resolv . ConvexPolygon ) , drawColor )
2022-10-15 08:51:38 +00:00
} else {
drawColor := color . RGBA { 60 , 60 , 60 , 255 }
DrawPolygon ( screen , o . Shape . ( * resolv . ConvexPolygon ) , drawColor )
2022-10-14 10:02:03 +00:00
}
}
2022-10-15 13:39:22 +00:00
world . Game . DebugDraw ( screen , world . Space )
2022-10-14 10:02:03 +00:00
if world . Game . ShowHelpText {
world . Game . DrawText ( screen , 16 , 16 ,
"~ Collider Display test ~" ,
"F1: Toggle Debug View" ,
"F2: Show / Hide help text" ,
"R: Restart world" ,
fmt . Sprintf ( "%d FPS (frames per second)" , int ( ebiten . CurrentFPS ( ) ) ) ,
fmt . Sprintf ( "%d TPS (ticks per second)" , int ( ebiten . CurrentTPS ( ) ) ) ,
)
}
}