2022-10-14 10:02:03 +00:00
package main
import (
2022-10-15 08:51:38 +00:00
. "dnmshared"
2022-11-12 03:20:16 +00:00
. "dnmshared/sharedprotos"
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: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-11-09 06:20:26 +00:00
playerPosList := * ( 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-11-12 12:34:38 +00:00
virtualGridToWorldRatio := 0.1
playerDefaultSpeed := 20
minStep := ( int ( float64 ( playerDefaultSpeed ) * virtualGridToWorldRatio ) << 2 )
playerColliderRadius := float64 ( 24 )
2022-11-09 06:20:26 +00:00
playerColliders := make ( [ ] * resolv . Object , len ( playerPosList . Eles ) )
2022-11-12 04:18:00 +00:00
space := resolv . NewSpace ( int ( spaceW ) , int ( spaceH ) , minStep , minStep )
2022-11-09 06:20:26 +00:00
for i , playerPos := range playerPosList . Eles {
playerCollider := GenerateRectCollider ( playerPos . X , playerPos . 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-11-12 12:34:38 +00:00
Logger . Info ( fmt . Sprintf ( "Player Collider#%d: player world pos =(%.2f, %.2f), shape=%v" , i , playerPos . X , playerPos . Y , ConvexPolygonStr ( playerCollider . Shape . ( * resolv . ConvexPolygon ) ) ) )
2022-10-22 05:38:10 +00:00
playerColliders [ i ] = playerCollider
2022-10-15 08:51:38 +00:00
space . Add ( playerCollider )
}
barrierLocalId := 0
2022-11-09 06:20:26 +00:00
for _ , barrierUnaligned := range barrierList . Eles {
2022-10-19 07:10:11 +00:00
barrierCollider := GenerateConvexPolygonCollider ( barrierUnaligned , spaceOffsetX , spaceOffsetY , "Barrier" )
2022-11-12 12:34:38 +00:00
Logger . Info ( fmt . Sprintf ( "Added barrier: shape=%v" , ConvexPolygonStr ( barrierCollider . Shape . ( * resolv . ConvexPolygon ) ) ) )
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-11-12 03:41:18 +00:00
moveToCollide := true
2022-10-22 05:38:10 +00:00
if moveToCollide {
2022-11-12 12:34:38 +00:00
proposedDx , proposedDy := - 50.0 , - 60.0
2022-11-12 03:20:16 +00:00
effPushback := Vec2D { X : float64 ( 0 ) , Y : float64 ( 0 ) }
2022-10-22 05:38:10 +00:00
toTestPlayerCollider := playerColliders [ 0 ]
2022-11-12 12:34:38 +00:00
toTestPlayerCollider . X += proposedDx
toTestPlayerCollider . Y += proposedDy
2022-11-12 03:20:16 +00:00
toTestPlayerCollider . Update ( )
2022-11-12 12:34:38 +00:00
if collision := toTestPlayerCollider . Check ( 0 , 0 ) ; collision != nil {
2022-10-22 05:38:10 +00:00
playerShape := toTestPlayerCollider . Shape . ( * resolv . ConvexPolygon )
2022-11-12 03:20:16 +00:00
for _ , obj := range collision . Objects {
barrierShape := obj . Shape . ( * resolv . ConvexPolygon )
2022-11-12 12:34:38 +00:00
if overlapped , pushbackX , pushbackY , overlapResult := CalcPushbacks ( 0 , 0 , playerShape , barrierShape ) ; overlapped {
Logger . Warn ( fmt . Sprintf ( "Overlapped: a=%v, b=%v, pushbackX=%v, pushbackY=%v" , ConvexPolygonStr ( playerShape ) , ConvexPolygonStr ( barrierShape ) , pushbackX , pushbackY ) )
2022-11-12 03:20:16 +00:00
effPushback . X += pushbackX
effPushback . Y += pushbackY
} else {
2022-11-12 12:34:38 +00:00
Logger . Warn ( fmt . Sprintf ( "Collided BUT not overlapped: a=%v, b=%v, overlapResult=%v" , ConvexPolygonStr ( playerShape ) , ConvexPolygonStr ( barrierShape ) , overlapResult ) )
2022-11-12 03:20:16 +00:00
}
2022-10-22 05:38:10 +00:00
}
2022-11-12 03:20:16 +00:00
toTestPlayerCollider . X -= effPushback . X
toTestPlayerCollider . Y -= effPushback . Y
toTestPlayerCollider . Update ( )
Logger . Info ( fmt . Sprintf ( "effPushback={%v, %v}" , effPushback . X , effPushback . Y ) )
2022-10-22 05:38:10 +00:00
}
}
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 ( ) ) ) ,
)
}
}