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"
"github.com/solarlune/resolv"
2022-10-15 08:51:38 +00:00
"go.uber.org/zap"
"image/color"
2022-10-14 10:47:09 +00:00
2022-10-15 08:51:38 +00:00
"math"
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-15 08:51:38 +00:00
// TODO: Move collider y-axis transformation to a "dnmshared"
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 {
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"
2022-10-15 08:51:38 +00:00
playerCollider . SetShape ( playerColliderShape )
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 {
barrier := AlignPolygon2DToBoundingBox ( barrierUnaligned )
2022-10-15 08:51:38 +00:00
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 )
2022-10-19 00:32:20 +00:00
Logger . Info ( fmt . Sprintf ( "Added barrier: shape=%v" , barrierCollider . Shape ) )
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
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 ) )
}
toTestPlayerCollider . Update ( )
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 ( ) ) ) ,
)
}
}