A broken commit.

This commit is contained in:
yflu 2022-11-09 12:19:29 +08:00
parent f37f4337de
commit d3d3629618
19 changed files with 3660 additions and 3867 deletions

View File

@ -1,4 +1,4 @@
module server module battle_srv
go 1.19 go 1.19

View File

@ -7,13 +7,13 @@ import (
"os" "os"
"os/signal" "os/signal"
"path/filepath" "path/filepath"
"server/api" "battle_srv/api"
"server/api/v1" "battle_srv/api/v1"
. "server/common" . "battle_srv/common"
"server/env_tools" "battle_srv/env_tools"
"server/models" "battle_srv/models"
"server/storage" "battle_srv/storage"
"server/ws" "battle_srv/ws"
"syscall" "syscall"
"time" "time"

View File

@ -68,9 +68,9 @@ func toPbPlayers(modelInstances map[int32]*Player) map[int32]*pb.Player {
for k, last := range modelInstances { for k, last := range modelInstances {
toRet[k] = &pb.Player{ toRet[k] = &pb.Player{
Id: last.Id, Id: last.Id,
X: last.X, VirtualGridX: last.VirtualGridX,
Y: last.Y, VirtualGridY: last.VirtualGridY,
Dir: &pb.Direction{ Dir: &pb.Direction{
Dx: last.Dir.Dx, Dx: last.Dir.Dx,
Dy: last.Dir.Dy, Dy: last.Dir.Dy,

View File

@ -33,30 +33,31 @@ func InitPlayerBattleStateIns() {
} }
type Player struct { type Player struct {
Id int32 `json:"id,omitempty" db:"id"` // Meta info fields
X float64 `json:"x,omitempty"` Id int32 `json:"id,omitempty" db:"id"`
Y float64 `json:"y,omitempty"`
Dir *Direction `json:"dir,omitempty"`
Speed float64 `json:"speed,omitempty"`
BattleState int32 `json:"battleState,omitempty"`
LastMoveGmtMillis int32 `json:"lastMoveGmtMillis,omitempty"`
Score int32 `json:"score,omitempty"`
Removed bool `json:"removed,omitempty"`
JoinIndex int32
Name string `json:"name,omitempty" db:"name"` Name string `json:"name,omitempty" db:"name"`
DisplayName string `json:"displayName,omitempty" db:"display_name"` DisplayName string `json:"displayName,omitempty" db:"display_name"`
Avatar string `json:"avatar,omitempty"` Avatar string `json:"avatar,omitempty"`
FrozenAtGmtMillis int64 `json:"-" db:"-"` // DB only fields
AddSpeedAtGmtMillis int64 `json:"-" db:"-"` CreatedAt int64 `db:"created_at"`
CreatedAt int64 `json:"-" db:"created_at"` UpdatedAt int64 `db:"updated_at"`
UpdatedAt int64 `json:"-" db:"updated_at"` DeletedAt NullInt64 `db:"deleted_at"`
DeletedAt NullInt64 `json:"-" db:"deleted_at"` TutorialStage int `db:"tutorial_stage"`
TutorialStage int `json:"-" db:"tutorial_stage"`
AckingFrameId int32 `json:"ackingFrameId"` // in-battle info fields
AckingInputFrameId int32 `json:"-"` VirtualGridX int32
LastSentInputFrameId int32 `json:"-"` VirtualGridY int32
Dir *Direction
Speed int32
BattleState int32
LastMoveGmtMillis int32
Score int32
Removed bool
JoinIndex int32
AckingFrameId int32
AckingInputFrameId int32
LastSentInputFrameId int32
} }
func ExistPlayerByName(name string) (bool, error) { func ExistPlayerByName(name string) (bool, error) {

View File

@ -13,9 +13,9 @@ import (
"math/rand" "math/rand"
"os" "os"
"path/filepath" "path/filepath"
. "server/common" . "battle_srv/common"
"server/common/utils" "battle_srv/common/utils"
pb "server/pb_output" pb "battle_srv/protos"
"strings" "strings"
"sync" "sync"
"sync/atomic" "sync/atomic"
@ -82,10 +82,10 @@ var DIRECTION_DECODER_INVERSE_LENGTH = []float64{
1.0, 1.0,
0.5, 0.5,
0.5, 0.5,
0.4472, 0.44, // Actually it should be "0.4472", but truncated for better precision sync as well as a reduction of speed in diagonal direction
0.4472, 0.44,
0.4472, 0.44,
0.4472, 0.44,
0.5, 0.5,
0.5, 0.5,
1.0, 1.0,
@ -128,12 +128,14 @@ func calRoomScore(inRoomPlayerCount int32, roomPlayerCnt int, currentRoomBattleS
} }
type Room struct { type Room struct {
Id int32 Id int32
Capacity int Capacity int
playerColliderRadius float64 playerColliderRadius float64
Players map[int32]*Player collisionSpaceOffsetX float64
PlayersArr []*Player // ordered by joinIndex collisionSpaceOffsetY float64
CollisionSysMap map[int32]*resolv.Object Players map[int32]*Player
PlayersArr []*Player // ordered by joinIndex
CollisionSysMap map[int32]*resolv.Object
/** /**
* The following `PlayerDownsyncSessionDict` is NOT individually put * The following `PlayerDownsyncSessionDict` is NOT individually put
* under `type Player struct` for a reason. * under `type Player struct` for a reason.
@ -177,11 +179,15 @@ type Room struct {
NstDelayFrames int32 // network-single-trip delay in the count of render frames, proposed to be (InputDelayFrames >> 1) because we expect a round-trip delay to be exactly "InputDelayFrames" NstDelayFrames int32 // network-single-trip delay in the count of render frames, proposed to be (InputDelayFrames >> 1) because we expect a round-trip delay to be exactly "InputDelayFrames"
InputScaleFrames uint32 // inputDelayedAndScaledFrameId = ((originalFrameId - InputDelayFrames) >> InputScaleFrames) InputScaleFrames uint32 // inputDelayedAndScaledFrameId = ((originalFrameId - InputDelayFrames) >> InputScaleFrames)
JoinIndexBooleanArr []bool JoinIndexBooleanArr []bool
RollbackEstimatedDt float64
RollbackEstimatedDtMillis float64 RollbackEstimatedDtMillis float64
RollbackEstimatedDtNanos int64 RollbackEstimatedDtNanos int64
LastRenderFrameIdTriggeredAt int64 LastRenderFrameIdTriggeredAt int64
WorldToVirtualGridRatio float64
VirtualGridToWorldRatio float64
PlayerDefaultSpeed int32
StageName string StageName string
StageDiscreteW int32 StageDiscreteW int32
StageDiscreteH int32 StageDiscreteH int32
@ -192,11 +198,6 @@ type Room struct {
BackendDynamicsEnabled bool BackendDynamicsEnabled bool
} }
const (
PLAYER_DEFAULT_SPEED = float64(200) // Hardcoded
ADD_SPEED = float64(100) // Hardcoded
)
func (pR *Room) updateScore() { func (pR *Room) updateScore() {
pR.Score = calRoomScore(pR.EffectivePlayerCount, pR.Capacity, pR.State) pR.Score = calRoomScore(pR.EffectivePlayerCount, pR.Capacity, pR.State)
} }
@ -218,9 +219,7 @@ func (pR *Room) AddPlayerIfPossible(pPlayerFromDbInit *Player, session *websocke
pPlayerFromDbInit.AckingInputFrameId = -1 pPlayerFromDbInit.AckingInputFrameId = -1
pPlayerFromDbInit.LastSentInputFrameId = MAGIC_LAST_SENT_INPUT_FRAME_ID_NORMAL_ADDED pPlayerFromDbInit.LastSentInputFrameId = MAGIC_LAST_SENT_INPUT_FRAME_ID_NORMAL_ADDED
pPlayerFromDbInit.BattleState = PlayerBattleStateIns.ADDED_PENDING_BATTLE_COLLIDER_ACK pPlayerFromDbInit.BattleState = PlayerBattleStateIns.ADDED_PENDING_BATTLE_COLLIDER_ACK
pPlayerFromDbInit.FrozenAtGmtMillis = -1 // Hardcoded temporarily. pPlayerFromDbInit.Speed = pR.PlayerDefaultSpeed
pPlayerFromDbInit.Speed = PLAYER_DEFAULT_SPEED // Hardcoded temporarily.
pPlayerFromDbInit.AddSpeedAtGmtMillis = -1 // Hardcoded temporarily.
pR.Players[playerId] = pPlayerFromDbInit pR.Players[playerId] = pPlayerFromDbInit
pR.PlayerDownsyncSessionDict[playerId] = session pR.PlayerDownsyncSessionDict[playerId] = session
@ -421,7 +420,7 @@ func (pR *Room) StartBattle() {
spaceOffsetX := float64(spaceW) * 0.5 spaceOffsetX := float64(spaceW) * 0.5
spaceOffsetY := float64(spaceH) * 0.5 spaceOffsetY := float64(spaceH) * 0.5
pR.refreshColliders(spaceW, spaceH, spaceOffsetX, spaceOffsetY) pR.refreshColliders(spaceW, spaceH)
/** /**
* Will be triggered from a goroutine which executes the critical `Room.AddPlayerIfPossible`, thus the `battleMainLoop` should be detached. * Will be triggered from a goroutine which executes the critical `Room.AddPlayerIfPossible`, thus the `battleMainLoop` should be detached.
@ -799,6 +798,9 @@ func (pR *Room) OnDismissed() {
// Always instantiates new HeapRAM blocks and let the old blocks die out due to not being retained by any root reference. // Always instantiates new HeapRAM blocks and let the old blocks die out due to not being retained by any root reference.
pR.playerColliderRadius = float64(12) // hardcoded pR.playerColliderRadius = float64(12) // hardcoded
pR.WorldToVirtualGridRatio = float64(10)
pR.VirtualGridToWorldRatio = float64(1.0) / pR.WorldToVirtualGridRatio // this is a one-off computation, should avoid division in iterations
pR.PlayerDefaultSpeed = int32(3 * pR.WorldToVirtualGridRatio) // Hardcoded in virtual grids per frame
pR.Players = make(map[int32]*Player) pR.Players = make(map[int32]*Player)
pR.PlayersArr = make([]*Player, pR.Capacity) pR.PlayersArr = make([]*Player, pR.Capacity)
pR.CollisionSysMap = make(map[int32]*resolv.Object) pR.CollisionSysMap = make(map[int32]*resolv.Object)
@ -820,7 +822,6 @@ func (pR *Room) OnDismissed() {
pR.NstDelayFrames = 8 pR.NstDelayFrames = 8
pR.InputScaleFrames = uint32(2) pR.InputScaleFrames = uint32(2)
pR.ServerFps = 60 pR.ServerFps = 60
pR.RollbackEstimatedDt = 0.016667 // Use fixed-and-low-precision to mitigate the inconsistent floating-point-number issue between Golang and JavaScript
pR.RollbackEstimatedDtMillis = 16.667 // Use fixed-and-low-precision to mitigate the inconsistent floating-point-number issue between Golang and JavaScript pR.RollbackEstimatedDtMillis = 16.667 // Use fixed-and-low-precision to mitigate the inconsistent floating-point-number issue between Golang and JavaScript
pR.RollbackEstimatedDtNanos = 16666666 // A little smaller than the actual per frame time, just for preventing FAST FRAME pR.RollbackEstimatedDtNanos = 16666666 // A little smaller than the actual per frame time, just for preventing FAST FRAME
pR.BattleDurationFrames = 30 * pR.ServerFps pR.BattleDurationFrames = 30 * pR.ServerFps
@ -947,8 +948,7 @@ func (pR *Room) onPlayerAdded(playerId int32) {
if nil == playerPos { if nil == playerPos {
panic(fmt.Sprintf("onPlayerAdded error, nil == playerPos, roomId=%v, playerId=%v, roomState=%v, roomEffectivePlayerCount=%v", pR.Id, playerId, pR.State, pR.EffectivePlayerCount)) panic(fmt.Sprintf("onPlayerAdded error, nil == playerPos, roomId=%v, playerId=%v, roomState=%v, roomEffectivePlayerCount=%v", pR.Id, playerId, pR.State, pR.EffectivePlayerCount))
} }
pR.Players[playerId].X = playerPos.X pR.Players[playerId].VirtualGridX, pR.Players[playerId].VirtualGridY = pR.worldToVirtualGridPos(playerPos.X, playerPos.Y)
pR.Players[playerId].Y = playerPos.Y
break break
} }
@ -1215,12 +1215,15 @@ func (pR *Room) applyInputFrameDownsyncDynamics(fromRenderFrameId int32, toRende
if 0.0 == decodedInputSpeedFactor { if 0.0 == decodedInputSpeedFactor {
continue continue
} }
baseChange := player.Speed * pR.RollbackEstimatedDt * decodedInputSpeedFactor baseChange := float64(player.Speed) * pR.VirtualGridToWorldRatio * decodedInputSpeedFactor
oldDx, oldDy := baseChange*float64(decodedInput[0]), baseChange*float64(decodedInput[1]) oldDx, oldDy := baseChange*float64(decodedInput[0]), baseChange*float64(decodedInput[1])
dx, dy := oldDx, oldDy dx, dy := oldDx, oldDy
collisionPlayerIndex := COLLISION_PLAYER_INDEX_PREFIX + joinIndex collisionPlayerIndex := COLLISION_PLAYER_INDEX_PREFIX + joinIndex
playerCollider := pR.CollisionSysMap[collisionPlayerIndex] playerCollider := pR.CollisionSysMap[collisionPlayerIndex]
// Reset playerCollider position from the "virtual grid position"
playerCollider.X, playerCollider.Y = pR.virtualGridToPlayerColliderPos(player.VirtualGridX, player.VirtualGridY)
if collision := playerCollider.Check(oldDx, oldDy, "Barrier"); collision != nil { if collision := playerCollider.Check(oldDx, oldDy, "Barrier"); collision != nil {
playerShape := playerCollider.Shape.(*resolv.ConvexPolygon) playerShape := playerCollider.Shape.(*resolv.ConvexPolygon)
for _, obj := range collision.Objects { for _, obj := range collision.Objects {
@ -1242,8 +1245,7 @@ func (pR *Room) applyInputFrameDownsyncDynamics(fromRenderFrameId int32, toRende
player.Dir.Dx = decodedInput[0] player.Dir.Dx = decodedInput[0]
player.Dir.Dy = decodedInput[1] player.Dir.Dy = decodedInput[1]
player.X = playerCollider.X + pR.playerColliderRadius - spaceOffsetX player.VirtualGridX, player.VirtualGridY = pR.playerColliderAnchorToVirtualGridPos(playerCollider.X, playerCollider.Y)
player.Y = playerCollider.Y + pR.playerColliderRadius - spaceOffsetY
} }
} }
@ -1261,13 +1263,14 @@ func (pR *Room) inputFrameIdDebuggable(inputFrameId int32) bool {
return 0 == (inputFrameId % 10) return 0 == (inputFrameId % 10)
} }
func (pR *Room) refreshColliders(spaceW, spaceH int32, spaceOffsetX, spaceOffsetY float64) { func (pR *Room) refreshColliders(spaceW, spaceH int32) {
// Kindly note that by now, we've already got all the shapes in the tmx file into "pR.(Players | Barriers)" from "ParseTmxLayersAndGroups" // Kindly note that by now, we've already got all the shapes in the tmx file into "pR.(Players | Barriers)" from "ParseTmxLayersAndGroups"
minStep := int(3) // the approx minimum distance a player can move per frame minStep := int(3) // the approx minimum distance a player can move per frame in world coordinate
space := resolv.NewSpace(int(spaceW), int(spaceH), minStep, minStep) // allocate a new collision space everytime after a battle is settled space := resolv.NewSpace(int(spaceW), int(spaceH), minStep, minStep) // allocate a new collision space everytime after a battle is settled
for _, player := range pR.Players { for _, player := range pR.Players {
playerCollider := GenerateRectCollider(player.X, player.Y, pR.playerColliderRadius*2, pR.playerColliderRadius*2, spaceOffsetX, spaceOffsetY, "Player") wx, wy := pR.virtualGridToWorldPos(player.VirtualGridX, player.VirtualGridY)
playerCollider := GenerateRectCollider(wx, wy, pR.playerColliderRadius*2, pR.playerColliderRadius*2, pR.collisionSpaceOffsetX, pR.collisionSpaceOffsetY, "Player")
space.Add(playerCollider) space.Add(playerCollider)
// Keep track of the collider in "pR.CollisionSysMap" // Keep track of the collider in "pR.CollisionSysMap"
joinIndex := player.JoinIndex joinIndex := player.JoinIndex
@ -1278,7 +1281,7 @@ func (pR *Room) refreshColliders(spaceW, spaceH int32, spaceOffsetX, spaceOffset
for _, barrier := range pR.Barriers { for _, barrier := range pR.Barriers {
boundaryUnaligned := barrier.Boundary boundaryUnaligned := barrier.Boundary
barrierCollider := GenerateConvexPolygonCollider(boundaryUnaligned, spaceOffsetX, spaceOffsetY, "Barrier") barrierCollider := GenerateConvexPolygonCollider(boundaryUnaligned, pR.collisionSpaceOffsetX, pR.collisionSpaceOffsetY, "Barrier")
space.Add(barrierCollider) space.Add(barrierCollider)
} }
} }
@ -1286,3 +1289,35 @@ func (pR *Room) refreshColliders(spaceW, spaceH int32, spaceOffsetX, spaceOffset
func (pR *Room) printBarrier(barrierCollider *resolv.Object) { func (pR *Room) printBarrier(barrierCollider *resolv.Object) {
Logger.Info(fmt.Sprintf("Barrier in roomId=%v: w=%v, h=%v, shape=%v", pR.Id, barrierCollider.W, barrierCollider.H, barrierCollider.Shape)) Logger.Info(fmt.Sprintf("Barrier in roomId=%v: w=%v, h=%v, shape=%v", pR.Id, barrierCollider.W, barrierCollider.H, barrierCollider.Shape))
} }
func (pR *Room) worldToVirtualGridPos(x, y float64) (int32, int32) {
// In JavaScript floating numbers suffer from seemingly non-deterministic arithmetics, and even if certain libs solved this issue by approaches such as fixed-point-number, they might not be used in other libs -- e.g. the "collision libs" we're interested in -- thus couldn't kill all pains.
var virtualGridX int32 = int32(x * pR.WorldToVirtualGridRatio)
var virtualGridY int32 = int32(y * pR.WorldToVirtualGridRatio)
return virtualGridX, virtualGridY
}
func (pR *Room) virtualGridToWorldPos(vx, vy int32) (float64, float64) {
var x float64 = float64(vx) * pR.VirtualGridToWorldRatio
var y float64 = float64(vy) * pR.VirtualGridToWorldRatio
return x, y
}
func (pR *Room) playerWorldToCollisionPos(wx, wy float64) (float64, float64) {
// TODO: remove this duplicate code w.r.t. "dnmshared/resolv_helper.go"
return wx - pR.playerColliderRadius + pR.collisionSpaceOffsetX, wy - pR.playerColliderRadius + pR.collisionSpaceOffsetY
}
func (pR *Room) playerColliderAnchorToWorldPos(cx, cy float64) (float64, float64) {
return cx + pR.playerColliderRadius - pR.collisionSpaceOffsetX, cy + pR.playerColliderRadius - pR.collisionSpaceOffsetY
}
func (pR *Room) playerColliderAnchorToVirtualGridPos(cx, cy float64) (int32, int32) {
wx, wy := pR.playerColliderAnchorToWorldPos(cx, cy)
return pR.worldToVirtualGridPos(wx, wy)
}
func (pR *Room) virtualGridToPlayerColliderPos(vx, vy int32) (float64, float64) {
wx, wy := pR.virtualGridToWorldPos(vx, vy)
return pR.playerWorldToCollisionPos(wx, wy)
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -8,9 +8,9 @@ import (
"github.com/gorilla/websocket" "github.com/gorilla/websocket"
"go.uber.org/zap" "go.uber.org/zap"
"net/http" "net/http"
. "server/common" . "battle_srv/common"
"server/models" "battle_srv/models"
pb "server/pb_output" pb "battle_srv/protos"
"strconv" "strconv"
"sync/atomic" "sync/atomic"
"time" "time"
@ -263,9 +263,11 @@ func Serve(c *gin.Context) {
InputFrameUpsyncDelayTolerance: pRoom.InputFrameUpsyncDelayTolerance, InputFrameUpsyncDelayTolerance: pRoom.InputFrameUpsyncDelayTolerance,
MaxChasingRenderFramesPerUpdate: pRoom.MaxChasingRenderFramesPerUpdate, MaxChasingRenderFramesPerUpdate: pRoom.MaxChasingRenderFramesPerUpdate,
PlayerBattleState: pThePlayer.BattleState, // For frontend to know whether it's rejoining PlayerBattleState: pThePlayer.BattleState, // For frontend to know whether it's rejoining
RollbackEstimatedDt: pRoom.RollbackEstimatedDt,
RollbackEstimatedDtMillis: pRoom.RollbackEstimatedDtMillis, RollbackEstimatedDtMillis: pRoom.RollbackEstimatedDtMillis,
RollbackEstimatedDtNanos: pRoom.RollbackEstimatedDtNanos, RollbackEstimatedDtNanos: pRoom.RollbackEstimatedDtNanos,
WorldToVirtualGridRatio: pRoom.WorldToVirtualGridRatio,
VirtualGridToWorldRatio: pRoom.VirtualGridToWorldRatio,
} }
resp := &pb.WsResp{ resp := &pb.WsResp{

View File

@ -3,11 +3,11 @@ module viscol
go 1.19 go 1.19
require ( require (
dnmshared 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 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
dnmshared v0.0.0
) )
require ( require (
@ -22,6 +22,7 @@ require (
golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56 // indirect golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56 // indirect
golang.org/x/mobile v0.0.0-20220722155234-aaac322e2105 // indirect golang.org/x/mobile v0.0.0-20220722155234-aaac322e2105 // indirect
golang.org/x/sys v0.0.0-20220818161305-2296e01440c6 // indirect golang.org/x/sys v0.0.0-20220818161305-2296e01440c6 // indirect
google.golang.org/protobuf v1.28.1 // indirect
) )
replace dnmshared => ../dnmshared replace dnmshared => ../dnmshared

View File

@ -7,6 +7,8 @@ github.com/go-gl/glfw/v3.3/glfw v0.0.0-20220806181222-55e207c401ad h1:kX51IjbsJP
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20220806181222-55e207c401ad/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20220806181222-55e207c401ad/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g= github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g=
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/hajimehoshi/bitmapfont/v2 v2.2.1 h1:y7zcy02/UgO24IL3COqYtrRZzhRucNBtmCo/SNU648k= github.com/hajimehoshi/bitmapfont/v2 v2.2.1 h1:y7zcy02/UgO24IL3COqYtrRZzhRucNBtmCo/SNU648k=
github.com/hajimehoshi/bitmapfont/v2 v2.2.1/go.mod h1:wjrYAy8vKgj9JsFgnYAOK346/uvE22TlmqouzdnYIs0= github.com/hajimehoshi/bitmapfont/v2 v2.2.1/go.mod h1:wjrYAy8vKgj9JsFgnYAOK346/uvE22TlmqouzdnYIs0=
github.com/hajimehoshi/ebiten/v2 v2.4.7 h1:XuvB7R0Rbw/O7g6vNU8gqr5b9e7MNhhAONMSsyreLDI= github.com/hajimehoshi/ebiten/v2 v2.4.7 h1:XuvB7R0Rbw/O7g6vNU8gqr5b9e7MNhhAONMSsyreLDI=
@ -93,4 +95,8 @@ golang.org/x/tools v0.1.8-0.20211022200916-316ba0b74098/go.mod h1:LGqMHiF4EqQNHR
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=

View File

@ -2,46 +2,45 @@ package dnmshared
import ( import (
"math" "math"
. "dnmshared/protos"
) )
// Use type `float64` for json unmarshalling of numbers.
type Direction struct {
Dx int32 `json:"dx,omitempty"`
Dy int32 `json:"dy,omitempty"`
}
type Vec2D struct {
X float64 `json:"x,omitempty"`
Y float64 `json:"y,omitempty"`
}
func NormVec2D(dx, dy float64) Vec2D { func NormVec2D(dx, dy float64) Vec2D {
return Vec2D{dy, -dx} return Vec2D{X: dy, Y:-dx}
} }
type Polygon2D struct { func AlignPolygon2DToBoundingBox(input *Polygon2D) *Polygon2D {
Anchor *Vec2D `json:"-"` // This "Polygon2D.Anchor" is used to be assigned to "B2BodyDef.Position", which in turn is used as the position of the FIRST POINT of the polygon. // Transform again to put "anchor" at the top-left point of the bounding box for "resolv"
Points []*Vec2D `json:"-"` boundingBoxTL := &Vec2D{
X: math.MaxFloat64,
Y: math.MaxFloat64,
}
for _, p := range input.Points {
if p.X < boundingBoxTL.X {
boundingBoxTL.X = p.X
}
if p.Y < boundingBoxTL.Y {
boundingBoxTL.Y = p.Y
}
}
/* // Now "input.Anchor" should move to "input.Anchor+boundingBoxTL", thus "boundingBoxTL" is also the value of the negative diff for all "input.Points"
When used to represent a "polyline directly drawn in a `Tmx file`", we can initialize both "Anchor" and "Points" simultaneously. output := &Polygon2D{
Anchor: &Vec2D{
X: input.Anchor.X + boundingBoxTL.X,
Y: input.Anchor.Y + boundingBoxTL.Y,
},
Points: make([]*Vec2D, len(input.Points)),
}
Yet when used to represent a "polyline drawn in a `Tsx file`", we have to first initialize "Points w.r.t. center of the tile-rectangle", and then "Anchor(initially nil) of the tile positioned in the `Tmx file`". for i, p := range input.Points {
output.Points[i] = &Vec2D{
X: p.X - boundingBoxTL.X,
Y: p.Y - boundingBoxTL.Y,
}
}
Refer to https://shimo.im/docs/SmLJJhXm2C8XMzZT for more information. return output
*/
/*
[WARNING] Used to cache "`TileWidth & TileHeight` of a Tsx file" only.
*/
TileWidth int
TileHeight int
/*
[WARNING] Used to cache "`Width & TileHeight` of an object in Tmx file" only.
*/
TmxObjectWidth float64
TmxObjectHeight float64
} }
func Distance(pt1 *Vec2D, pt2 *Vec2D) float64 { func Distance(pt1 *Vec2D, pt2 *Vec2D) float64 {

View File

@ -1,3 +1,3 @@
module tiled module dnmshared
go 1.19 go 1.19

View File

@ -0,0 +1,425 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.28.1
// protoc v3.7.1
// source: geometry.proto
package protos
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
type Direction struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Dx int32 `protobuf:"varint,1,opt,name=dx,proto3" json:"dx,omitempty"`
Dy int32 `protobuf:"varint,2,opt,name=dy,proto3" json:"dy,omitempty"`
}
func (x *Direction) Reset() {
*x = Direction{}
if protoimpl.UnsafeEnabled {
mi := &file_geometry_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *Direction) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*Direction) ProtoMessage() {}
func (x *Direction) ProtoReflect() protoreflect.Message {
mi := &file_geometry_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use Direction.ProtoReflect.Descriptor instead.
func (*Direction) Descriptor() ([]byte, []int) {
return file_geometry_proto_rawDescGZIP(), []int{0}
}
func (x *Direction) GetDx() int32 {
if x != nil {
return x.Dx
}
return 0
}
func (x *Direction) GetDy() int32 {
if x != nil {
return x.Dy
}
return 0
}
type Vec2D struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
X float64 `protobuf:"fixed64,1,opt,name=x,proto3" json:"x,omitempty"`
Y float64 `protobuf:"fixed64,2,opt,name=y,proto3" json:"y,omitempty"`
}
func (x *Vec2D) Reset() {
*x = Vec2D{}
if protoimpl.UnsafeEnabled {
mi := &file_geometry_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *Vec2D) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*Vec2D) ProtoMessage() {}
func (x *Vec2D) ProtoReflect() protoreflect.Message {
mi := &file_geometry_proto_msgTypes[1]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use Vec2D.ProtoReflect.Descriptor instead.
func (*Vec2D) Descriptor() ([]byte, []int) {
return file_geometry_proto_rawDescGZIP(), []int{1}
}
func (x *Vec2D) GetX() float64 {
if x != nil {
return x.X
}
return 0
}
func (x *Vec2D) GetY() float64 {
if x != nil {
return x.Y
}
return 0
}
type Polygon2D struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Anchor *Vec2D `protobuf:"bytes,1,opt,name=anchor,proto3" json:"anchor,omitempty"`
Points []*Vec2D `protobuf:"bytes,2,rep,name=points,proto3" json:"points,omitempty"`
}
func (x *Polygon2D) Reset() {
*x = Polygon2D{}
if protoimpl.UnsafeEnabled {
mi := &file_geometry_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *Polygon2D) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*Polygon2D) ProtoMessage() {}
func (x *Polygon2D) ProtoReflect() protoreflect.Message {
mi := &file_geometry_proto_msgTypes[2]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use Polygon2D.ProtoReflect.Descriptor instead.
func (*Polygon2D) Descriptor() ([]byte, []int) {
return file_geometry_proto_rawDescGZIP(), []int{2}
}
func (x *Polygon2D) GetAnchor() *Vec2D {
if x != nil {
return x.Anchor
}
return nil
}
func (x *Polygon2D) GetPoints() []*Vec2D {
if x != nil {
return x.Points
}
return nil
}
type Vec2DList struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Eles []*Vec2D `protobuf:"bytes,1,rep,name=eles,proto3" json:"eles,omitempty"`
}
func (x *Vec2DList) Reset() {
*x = Vec2DList{}
if protoimpl.UnsafeEnabled {
mi := &file_geometry_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *Vec2DList) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*Vec2DList) ProtoMessage() {}
func (x *Vec2DList) ProtoReflect() protoreflect.Message {
mi := &file_geometry_proto_msgTypes[3]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use Vec2DList.ProtoReflect.Descriptor instead.
func (*Vec2DList) Descriptor() ([]byte, []int) {
return file_geometry_proto_rawDescGZIP(), []int{3}
}
func (x *Vec2DList) GetEles() []*Vec2D {
if x != nil {
return x.Eles
}
return nil
}
type Polygon2DList struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Eles []*Polygon2D `protobuf:"bytes,1,rep,name=eles,proto3" json:"eles,omitempty"`
}
func (x *Polygon2DList) Reset() {
*x = Polygon2DList{}
if protoimpl.UnsafeEnabled {
mi := &file_geometry_proto_msgTypes[4]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *Polygon2DList) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*Polygon2DList) ProtoMessage() {}
func (x *Polygon2DList) ProtoReflect() protoreflect.Message {
mi := &file_geometry_proto_msgTypes[4]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use Polygon2DList.ProtoReflect.Descriptor instead.
func (*Polygon2DList) Descriptor() ([]byte, []int) {
return file_geometry_proto_rawDescGZIP(), []int{4}
}
func (x *Polygon2DList) GetEles() []*Polygon2D {
if x != nil {
return x.Eles
}
return nil
}
var File_geometry_proto protoreflect.FileDescriptor
var file_geometry_proto_rawDesc = []byte{
0x0a, 0x0e, 0x67, 0x65, 0x6f, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x12, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x22, 0x2b, 0x0a, 0x09, 0x44, 0x69, 0x72, 0x65,
0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x0e, 0x0a, 0x02, 0x64, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28,
0x05, 0x52, 0x02, 0x64, 0x78, 0x12, 0x0e, 0x0a, 0x02, 0x64, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28,
0x05, 0x52, 0x02, 0x64, 0x79, 0x22, 0x23, 0x0a, 0x05, 0x56, 0x65, 0x63, 0x32, 0x44, 0x12, 0x0c,
0x0a, 0x01, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x01, 0x52, 0x01, 0x78, 0x12, 0x0c, 0x0a, 0x01,
0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x01, 0x52, 0x01, 0x79, 0x22, 0x59, 0x0a, 0x09, 0x50, 0x6f,
0x6c, 0x79, 0x67, 0x6f, 0x6e, 0x32, 0x44, 0x12, 0x25, 0x0a, 0x06, 0x61, 0x6e, 0x63, 0x68, 0x6f,
0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
0x2e, 0x56, 0x65, 0x63, 0x32, 0x44, 0x52, 0x06, 0x61, 0x6e, 0x63, 0x68, 0x6f, 0x72, 0x12, 0x25,
0x0a, 0x06, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0d,
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x56, 0x65, 0x63, 0x32, 0x44, 0x52, 0x06, 0x70,
0x6f, 0x69, 0x6e, 0x74, 0x73, 0x22, 0x2e, 0x0a, 0x09, 0x56, 0x65, 0x63, 0x32, 0x44, 0x4c, 0x69,
0x73, 0x74, 0x12, 0x21, 0x0a, 0x04, 0x65, 0x6c, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b,
0x32, 0x0d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x56, 0x65, 0x63, 0x32, 0x44, 0x52,
0x04, 0x65, 0x6c, 0x65, 0x73, 0x22, 0x36, 0x0a, 0x0d, 0x50, 0x6f, 0x6c, 0x79, 0x67, 0x6f, 0x6e,
0x32, 0x44, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x25, 0x0a, 0x04, 0x65, 0x6c, 0x65, 0x73, 0x18, 0x01,
0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x50, 0x6f,
0x6c, 0x79, 0x67, 0x6f, 0x6e, 0x32, 0x44, 0x52, 0x04, 0x65, 0x6c, 0x65, 0x73, 0x42, 0x12, 0x5a,
0x10, 0x64, 0x6e, 0x6d, 0x73, 0x68, 0x61, 0x72, 0x65, 0x64, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
file_geometry_proto_rawDescOnce sync.Once
file_geometry_proto_rawDescData = file_geometry_proto_rawDesc
)
func file_geometry_proto_rawDescGZIP() []byte {
file_geometry_proto_rawDescOnce.Do(func() {
file_geometry_proto_rawDescData = protoimpl.X.CompressGZIP(file_geometry_proto_rawDescData)
})
return file_geometry_proto_rawDescData
}
var file_geometry_proto_msgTypes = make([]protoimpl.MessageInfo, 5)
var file_geometry_proto_goTypes = []interface{}{
(*Direction)(nil), // 0: protos.Direction
(*Vec2D)(nil), // 1: protos.Vec2D
(*Polygon2D)(nil), // 2: protos.Polygon2D
(*Vec2DList)(nil), // 3: protos.Vec2DList
(*Polygon2DList)(nil), // 4: protos.Polygon2DList
}
var file_geometry_proto_depIdxs = []int32{
1, // 0: protos.Polygon2D.anchor:type_name -> protos.Vec2D
1, // 1: protos.Polygon2D.points:type_name -> protos.Vec2D
1, // 2: protos.Vec2DList.eles:type_name -> protos.Vec2D
2, // 3: protos.Polygon2DList.eles:type_name -> protos.Polygon2D
4, // [4:4] is the sub-list for method output_type
4, // [4:4] is the sub-list for method input_type
4, // [4:4] is the sub-list for extension type_name
4, // [4:4] is the sub-list for extension extendee
0, // [0:4] is the sub-list for field type_name
}
func init() { file_geometry_proto_init() }
func file_geometry_proto_init() {
if File_geometry_proto != nil {
return
}
if !protoimpl.UnsafeEnabled {
file_geometry_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Direction); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_geometry_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Vec2D); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_geometry_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Polygon2D); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_geometry_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Vec2DList); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_geometry_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Polygon2DList); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_geometry_proto_rawDesc,
NumEnums: 0,
NumMessages: 5,
NumExtensions: 0,
NumServices: 0,
},
GoTypes: file_geometry_proto_goTypes,
DependencyIndexes: file_geometry_proto_depIdxs,
MessageInfos: file_geometry_proto_msgTypes,
}.Build()
File_geometry_proto = out.File
file_geometry_proto_rawDesc = nil
file_geometry_proto_goTypes = nil
file_geometry_proto_depIdxs = nil
}

View File

@ -6,6 +6,7 @@ import (
"github.com/solarlune/resolv" "github.com/solarlune/resolv"
"math" "math"
"strings" "strings"
. "dnmshared/protos"
) )
func ConvexPolygonStr(body *resolv.ConvexPolygon) string { func ConvexPolygonStr(body *resolv.ConvexPolygon) string {

View File

@ -11,6 +11,7 @@ import (
"math" "math"
"strconv" "strconv"
"strings" "strings"
. "dnmshared/protos"
) )
const ( const (
@ -173,8 +174,6 @@ func (l *TmxLayer) decodeBase64() ([]uint32, error) {
return gids, nil return gids, nil
} }
type Vec2DList []*Vec2D
type Polygon2DList []*Polygon2D
type StrToVec2DListMap map[string]*Vec2DList type StrToVec2DListMap map[string]*Vec2DList
type StrToPolygon2DListMap map[string]*Polygon2DList type StrToPolygon2DListMap map[string]*Polygon2DList
@ -235,8 +234,6 @@ func tsxPolylineToOffsetsWrtTileCenter(pTmxMapIns *TmxMap, singleObjInTsxFile *T
thePolygon2DFromPolyline := &Polygon2D{ thePolygon2DFromPolyline := &Polygon2D{
Anchor: nil, Anchor: nil,
Points: make([]*Vec2D, pointsCount), Points: make([]*Vec2D, pointsCount),
TileWidth: pTsxIns.TileWidth,
TileHeight: pTsxIns.TileHeight,
} }
/* /*
@ -327,7 +324,7 @@ func DeserializeTsxToColliderDict(pTmxMapIns *TmxMap, byteArrOfTsxFile []byte, f
if _, ok := theStrToPolygon2DListMap[key]; ok { if _, ok := theStrToPolygon2DListMap[key]; ok {
pThePolygon2DList = theStrToPolygon2DListMap[key] pThePolygon2DList = theStrToPolygon2DListMap[key]
} else { } else {
thePolygon2DList := make(Polygon2DList, 0) thePolygon2DListEles := make([]*Polygon2D, 0)
theStrToPolygon2DListMap[key] = &thePolygon2DList theStrToPolygon2DListMap[key] = &thePolygon2DList
pThePolygon2DList = theStrToPolygon2DListMap[key] pThePolygon2DList = theStrToPolygon2DListMap[key]
} }
@ -442,40 +439,3 @@ func (pTmxMapIns *TmxMap) continuousObjLayerOffsetToContinuousMapNodePos(continu
return toRet return toRet
} }
func AlignPolygon2DToBoundingBox(input *Polygon2D) *Polygon2D {
// Transform again to put "anchor" at the top-left point of the bounding box for "resolv"
float64Max := float64(99999999999999.9)
boundingBoxTL := &Vec2D{
X: float64Max,
Y: float64Max,
}
for _, p := range input.Points {
if p.X < boundingBoxTL.X {
boundingBoxTL.X = p.X
}
if p.Y < boundingBoxTL.Y {
boundingBoxTL.Y = p.Y
}
}
// Now "input.Anchor" should move to "input.Anchor+boundingBoxTL", thus "boundingBoxTL" is also the value of the negative diff for all "input.Points"
output := &Polygon2D{
Anchor: &Vec2D{
X: input.Anchor.X + boundingBoxTL.X,
Y: input.Anchor.Y + boundingBoxTL.Y,
},
Points: make([]*Vec2D, len(input.Points)),
TileWidth: input.TileWidth,
TileHeight: input.TileHeight,
}
for i, p := range input.Points {
output.Points[i] = &Vec2D{
X: p.X - boundingBoxTL.X,
Y: p.Y - boundingBoxTL.Y,
}
}
return output
}

View File

@ -0,0 +1,27 @@
syntax = "proto3";
option go_package = "dnmshared/protos"; // here "./" corresponds to the "--go_out" value in "protoc" command
package protos;
message Direction {
int32 dx = 1;
int32 dy = 2;
}
message Vec2D {
double x = 1;
double y = 2;
}
message Polygon2D {
Vec2D anchor = 1;
repeated Vec2D points = 2;
}
message Vec2DList {
repeated Vec2D eles = 1;
}
message Polygon2DList {
repeated Polygon2D eles = 1;
}

View File

@ -1,30 +1,8 @@
syntax = "proto3"; syntax = "proto3";
option go_package = "."; // "./" corresponds to the "--go_out" value in "protoc" command option go_package = "battle_srv/protos"; // here "./" corresponds to the "--go_out" value in "protoc" command
package treasurehunterx; package protos;
import "geometry.proto"; // The import path here is only w.r.t. the proto file, not the Go package.
message Direction {
int32 dx = 1;
int32 dy = 2;
}
message Vec2D {
double x = 1;
double y = 2;
}
message Polygon2D {
Vec2D Anchor = 1;
repeated Vec2D Points = 2;
}
message Vec2DList {
repeated Vec2D vec2DList = 1;
}
message Polygon2DList {
repeated Polygon2D polygon2DList = 1;
}
message BattleColliderInfo { message BattleColliderInfo {
string stageName = 1; string stageName = 1;
@ -46,17 +24,19 @@ message BattleColliderInfo {
int32 inputFrameUpsyncDelayTolerance = 16; int32 inputFrameUpsyncDelayTolerance = 16;
int32 maxChasingRenderFramesPerUpdate = 17; int32 maxChasingRenderFramesPerUpdate = 17;
int32 playerBattleState = 18; int32 playerBattleState = 18;
double rollbackEstimatedDt = 19; double rollbackEstimatedDtMillis = 19;
double rollbackEstimatedDtMillis = 20; int64 rollbackEstimatedDtNanos = 20;
int64 rollbackEstimatedDtNanos = 21;
double worldToVirtualGridRatio = 21;
double virtualGridToWorldRatio = 22;
} }
message Player { message Player {
int32 id = 1; int32 id = 1;
double x = 2; int32 virtualGridX = 2;
double y = 3; int32 virtualGridY = 3;
Direction dir = 4; Direction dir = 4;
double speed = 5; int32 speed = 5; // in terms of virtual grid units
int32 battleState = 6; int32 battleState = 6;
int32 lastMoveGmtMillis = 7; int32 lastMoveGmtMillis = 7;
int32 score = 10; int32 score = 10;

View File

@ -2,11 +2,16 @@
# GOLANG part # GOLANG part
# You have to download the OS binary "protoc" from `https://developers.google.com/protocol-buffers/docs/downloads` and set it to $PATH appropriately. # You have to download the OS binary "protoc" from `https://developers.google.com/protocol-buffers/docs/downloads` and set it to $PATH appropriately.
# You have to install `proto-gen-go` by `go get -u github.com/golang/protobuf/protoc-gen-go` as instructed in https://developers.google.com/protocol-buffers/docs/gotutorial too. # You have to install `proto-gen-go` by `go install google.golang.org/protobuf/cmd/protoc-gen-go@latest` as instructed in https://developers.google.com/protocol-buffers/docs/gotutorial#compiling-your-protocol-buffers too.
golang_basedir=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )/battle_srv golang_basedir_1=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )/dnmshared
mkdir -p $golang_basedir/pb_output protoc -I=$golang_basedir_1/../frontend/assets/resources/pbfiles/ --go_out=. geometry.proto
protoc -I=$golang_basedir/../frontend/assets/resources/pbfiles/ --go_out=$golang_basedir/pb_output room_downsync_frame.proto echo "GOLANG part 1 done"
# [WARNING] The following "room_downsync_frame.proto" is generated in another Go package than "geometry.proto", but the generated Go codes are also required to work with imports correctly!
golang_basedir_2=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )/battle_srv
protoc -I=$golang_basedir_2/../frontend/assets/resources/pbfiles/ --go_out=. room_downsync_frame.proto
echo "GOLANG part 2 done"
# JS part # JS part
js_basedir=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )/frontend js_basedir=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )/frontend
@ -19,4 +24,4 @@ js_outdir=$js_basedir/assets/scripts/modules
# The specific filename is respected by "frontend/build-templates/wechatgame/game.js". # The specific filename is respected by "frontend/build-templates/wechatgame/game.js".
pbjs -t static-module -w commonjs --keep-case --force-message -o $js_outdir/room_downsync_frame_proto_bundle.forcemsg.js $js_basedir/assets/resources/pbfiles/room_downsync_frame.proto pbjs -t static-module -w commonjs --keep-case --force-message -o $js_outdir/room_downsync_frame_proto_bundle.forcemsg.js $js_basedir/assets/resources/pbfiles/room_downsync_frame.proto
sed -i 's#require("protobufjs/minimal")#require("./protobuf-with-floating-num-decoding-endianess-toggle")#g' $js_outdir/room_downsync_frame_proto_bundle.forcemsg.js echo "JavaScript part done"