Fixed character offset in OfflineMap2.

This commit is contained in:
genxium 2022-12-25 14:18:48 +08:00
parent 72782735d3
commit 013c1ea312
15 changed files with 514 additions and 212930 deletions

File diff suppressed because one or more lines are too long

View File

@ -1,6 +1,6 @@
{
"ver": "1.0.5",
"uuid": "c402c9d1-1d32-4dbb-993a-6bfa0099fa2b",
"uuid": "d41313ca-b2c3-4436-a05f-7e0eb290b1e6",
"isPlugin": true,
"loadPluginInWeb": true,
"loadPluginInNative": true,

View File

@ -1,5 +1,5 @@
syntax = "proto3";
option go_package = "jsexport/protos"; // here "./" 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 protos;
import "geometry.proto"; // The import path here is only w.r.t. the proto file, not the Go package.

View File

@ -97,7 +97,7 @@
"__id__": 1
},
"_children": [],
"_active": false,
"_active": true,
"_components": [
{
"__id__": 3
@ -129,7 +129,7 @@
"ctor": "Float64Array",
"array": [
0,
0,
45,
0,
0,
0,

View File

@ -440,7 +440,7 @@
"array": [
0,
0,
209.73151519075364,
217.37237634989413,
0,
0,
0,

View File

@ -461,7 +461,7 @@
"array": [
0,
0,
216.05530045313827,
217.37237634989413,
0,
0,
0,

View File

@ -461,7 +461,7 @@
"array": [
0,
0,
216.50635094610968,
217.37237634989413,
0,
0,
0,

View File

@ -13,7 +13,7 @@ cc.Class({
onLoad() {
const self = this;
window.mapIns = self;
self.showCriticalCoordinateLabels = true;
self.showCriticalCoordinateLabels = false;
const mapNode = self.node;
const canvasNode = mapNode.parent;
@ -375,7 +375,18 @@ cc.Class({
halfColliderHeight = playerDownsyncInfo.ColliderRadius + playerDownsyncInfo.ColliderRadius; // avoid multiplying
const colliderWidth = halfColliderWidth + halfColliderWidth,
colliderHeight = halfColliderHeight + halfColliderHeight; // avoid multiplying
const newPlayerCollider = gopkgs.GenerateRectColliderJs(wx, wy, colliderWidth, colliderHeight, self.snapIntoPlatformOverlap, self.snapIntoPlatformOverlap, self.snapIntoPlatformOverlap, self.snapIntoPlatformOverlap, self.spaceOffsetX, self.spaceOffsetY, playerDownsyncInfo, "Player");
const [cx, cy] = gopkgs.WorldToPolygonColliderBLPos(wx, wy, halfColliderWidth, halfColliderHeight, self.snapIntoPlatformOverlap, self.snapIntoPlatformOverlap, self.snapIntoPlatformOverlap, self.snapIntoPlatformOverlap, self.spaceOffsetX, self.spaceOffsetY);
const gopkgsBoundaryAnchor = gopkgs.NewVec2DJs(cx, cy);
const gopkgsBoundaryPts = [
gopkgs.NewVec2DJs(0, 0),
gopkgs.NewVec2DJs(self.snapIntoPlatformOverlap + colliderWidth + self.snapIntoPlatformOverlap, 0),
gopkgs.NewVec2DJs(self.snapIntoPlatformOverlap + colliderWidth + self.snapIntoPlatformOverlap, self.snapIntoPlatformOverlap + colliderHeight + self.snapIntoPlatformOverlap),
gopkgs.NewVec2DJs(0, self.snapIntoPlatformOverlap + colliderHeight + self.snapIntoPlatformOverlap)
];
const gopkgsBoundary = gopkgs.NewPolygon2DJs(gopkgsBoundaryAnchor, gopkgsBoundaryPts);
const newPlayerCollider = gopkgs.GenerateConvexPolygonColliderJs(gopkgsBoundary, self.spaceOffsetX, self.spaceOffsetY, playerDownsyncInfo, "Player");
//const newPlayerCollider = gopkgs.GenerateRectColliderJs(wx, wy, colliderWidth, colliderHeight, self.snapIntoPlatformOverlap, self.snapIntoPlatformOverlap, self.snapIntoPlatformOverlap, self.snapIntoPlatformOverlap, self.spaceOffsetX, self.spaceOffsetY, playerDownsyncInfo, "Player");
self.gopkgsCollisionSys.Add(newPlayerCollider);
const collisionPlayerIndex = self.collisionPlayerIndexPrefix + joinIndex;
self.gopkgsCollisionSysMap[collisionPlayerIndex] = newPlayerCollider;
@ -394,4 +405,45 @@ cc.Class({
return [newPlayerNode, playerScriptIns];
},
showDebugBoundaries(rdf) {
const self = this;
const leftPadding = self.snapIntoPlatformOverlap,
rightPadding = self.snapIntoPlatformOverlap,
topPadding = self.snapIntoPlatformOverlap,
bottomPadding = self.snapIntoPlatformOverlap;
if (self.showCriticalCoordinateLabels) {
let g = self.g;
g.clear();
const collisionSpaceObjs = gopkgs.GetCollisionSpaceObjsJs(self.gopkgsCollisionSys);
for (let k in collisionSpaceObjs) {
const body = collisionSpaceObjs[k];
let padding = 0;
if (null != body.Data && null != body.Data.JoinIndex) {
// character
if (1 == body.Data.JoinIndex) {
g.strokeColor = cc.Color.BLUE;
} else {
g.strokeColor = cc.Color.RED;
}
padding = self.snapIntoPlatformOverlap;
} else {
// barrier
g.strokeColor = cc.Color.WHITE;
}
const points = body.Shape.Points;
const wpos = [body.X-self.spaceOffsetX, body.Y-self.spaceOffsetY];
g.moveTo(wpos[0], wpos[1]);
const cnt = points.length;
for (let j = 0; j < cnt; j += 1) {
const x = wpos[0]+points[j][0],
y = wpos[1]+points[j][1];
g.lineTo(x, y);
}
g.lineTo(wpos[0], wpos[1]);
g.stroke();
}
}
},
});

View File

@ -1,13 +1,13 @@
package models
package battle
import (
. "dnmshared"
. "dnmshared/sharedprotos"
"github.com/kvartborg/vector"
"github.com/solarlune/resolv"
. "jsexport/protos"
"math"
)
const (
MAX_FLOAT64 = 1.7e+308
COLLISION_PLAYER_INDEX_PREFIX = (1 << 17)
COLLISION_BARRIER_INDEX_PREFIX = (1 << 16)
COLLISION_BULLET_INDEX_PREFIX = (1 << 15)
@ -55,6 +55,206 @@ func DecodeInput(encodedInput uint64) *InputFrameDecoded {
}
}
type SatResult struct {
Overlap float64
OverlapX float64
OverlapY float64
AContainedInB bool
BContainedInA bool
Axis vector.Vector
}
func CalcPushbacks(oldDx, oldDy float64, playerShape, barrierShape *resolv.ConvexPolygon) (bool, float64, float64, *SatResult) {
origX, origY := playerShape.Position()
defer func() {
playerShape.SetPosition(origX, origY)
}()
playerShape.SetPosition(origX+oldDx, origY+oldDy)
overlapResult := &SatResult{
Overlap: 0,
OverlapX: 0,
OverlapY: 0,
AContainedInB: true,
BContainedInA: true,
Axis: vector.Vector{0, 0},
}
if overlapped := isPolygonPairOverlapped(playerShape, barrierShape, overlapResult); overlapped {
pushbackX, pushbackY := overlapResult.Overlap*overlapResult.OverlapX, overlapResult.Overlap*overlapResult.OverlapY
return true, pushbackX, pushbackY, overlapResult
} else {
return false, 0, 0, overlapResult
}
}
func isPolygonPairOverlapped(a, b *resolv.ConvexPolygon, result *SatResult) bool {
aCnt, bCnt := len(a.Points), len(b.Points)
// Single point case
if 1 == aCnt && 1 == bCnt {
if nil != result {
result.Overlap = 0
}
return a.Points[0][0] == b.Points[0][0] && a.Points[0][1] == b.Points[0][1]
}
if 1 < aCnt {
for _, axis := range a.SATAxes() {
if isPolygonPairSeparatedByDir(a, b, axis.Unit(), result) {
return false
}
}
}
if 1 < bCnt {
for _, axis := range b.SATAxes() {
if isPolygonPairSeparatedByDir(a, b, axis.Unit(), result) {
return false
}
}
}
return true
}
func isPolygonPairSeparatedByDir(a, b *resolv.ConvexPolygon, e vector.Vector, result *SatResult) bool {
/*
[WARNING] This function is deliberately made private, it shouldn't be used alone (i.e. not along the norms of a polygon), otherwise the pushbacks calculated would be meaningless.
Consider the following example
a: {
anchor: [1337.19 1696.74]
points: [[0 0] [24 0] [24 24] [0 24]]
},
b: {
anchor: [1277.72 1570.56]
points: [[642.57 319.16] [0 319.16] [5.73 0] [643.75 0.90]]
}
e = (-2.98, 1.49).Unit()
*/
var aStart, aEnd, bStart, bEnd float64 = MAX_FLOAT64, -MAX_FLOAT64, MAX_FLOAT64, -MAX_FLOAT64
for _, p := range a.Points {
dot := (p[0]+a.X)*e[0] + (p[1]+a.Y)*e[1]
if aStart > dot {
aStart = dot
}
if aEnd < dot {
aEnd = dot
}
}
for _, p := range b.Points {
dot := (p[0]+b.X)*e[0] + (p[1]+b.Y)*e[1]
if bStart > dot {
bStart = dot
}
if bEnd < dot {
bEnd = dot
}
}
if aStart > bEnd || aEnd < bStart {
// Separated by unit vector "e"
return true
}
if nil != result {
overlap := float64(0)
if aStart < bStart {
result.AContainedInB = false
if aEnd < bEnd {
overlap = aEnd - bStart
result.BContainedInA = false
} else {
option1 := aEnd - bStart
option2 := bEnd - aStart
if option1 < option2 {
overlap = option1
} else {
overlap = -option2
}
}
} else {
result.BContainedInA = false
if aEnd > bEnd {
overlap = aStart - bEnd
result.AContainedInB = false
} else {
option1 := aEnd - bStart
option2 := bEnd - aStart
if option1 < option2 {
overlap = option1
} else {
overlap = -option2
}
}
}
currentOverlap := result.Overlap
absoluteOverlap := overlap
if overlap < 0 {
absoluteOverlap = -overlap
}
if (0 == result.Axis[0] && 0 == result.Axis[1]) || currentOverlap > absoluteOverlap {
var sign float64 = 1
if overlap < 0 {
sign = -1
}
result.Overlap = absoluteOverlap
result.OverlapX = e[0] * sign
result.OverlapY = e[1] * sign
}
result.Axis = e
}
// the specified unit vector "e" doesn't separate "a" and "b", overlap result is generated
return false
}
func WorldToVirtualGridPos(wx, wy, worldToVirtualGridRatio float64) (int32, int32) {
// [WARNING] Introduces loss of precision!
// 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(math.Round(wx * worldToVirtualGridRatio))
var virtualGridY int32 = int32(math.Round(wy * worldToVirtualGridRatio))
return virtualGridX, virtualGridY
}
func VirtualGridToWorldPos(vx, vy int32, virtualGridToWorldRatio float64) (float64, float64) {
// No loss of precision
var wx float64 = float64(vx) * virtualGridToWorldRatio
var wy float64 = float64(vy) * virtualGridToWorldRatio
return wx, wy
}
func WorldToPolygonColliderBLPos(wx, wy, halfBoundingW, halfBoundingH, topPadding, bottomPadding, leftPadding, rightPadding, collisionSpaceOffsetX, collisionSpaceOffsetY float64) (float64, float64) {
return wx - halfBoundingW - leftPadding + collisionSpaceOffsetX, wy - halfBoundingH - bottomPadding + collisionSpaceOffsetY
}
func PolygonColliderBLToWorldPos(cx, cy, halfBoundingW, halfBoundingH, topPadding, bottomPadding, leftPadding, rightPadding, collisionSpaceOffsetX, collisionSpaceOffsetY float64) (float64, float64) {
return cx + halfBoundingW + leftPadding - collisionSpaceOffsetX, cy + halfBoundingH + bottomPadding - collisionSpaceOffsetY
}
func PolygonColliderBLToVirtualGridPos(cx, cy, halfBoundingW, halfBoundingH, topPadding, bottomPadding, leftPadding, rightPadding, collisionSpaceOffsetX, collisionSpaceOffsetY float64, worldToVirtualGridRatio float64) (int32, int32) {
wx, wy := PolygonColliderBLToWorldPos(cx, cy, halfBoundingW, halfBoundingH, topPadding, bottomPadding, leftPadding, rightPadding, collisionSpaceOffsetX, collisionSpaceOffsetY)
return WorldToVirtualGridPos(wx, wy, worldToVirtualGridRatio)
}
func VirtualGridToPolygonColliderBLPos(vx, vy int32, halfBoundingW, halfBoundingH, topPadding, bottomPadding, leftPadding, rightPadding, collisionSpaceOffsetX, collisionSpaceOffsetY float64, virtualGridToWorldRatio float64) (float64, float64) {
wx, wy := VirtualGridToWorldPos(vx, vy, virtualGridToWorldRatio)
return WorldToPolygonColliderBLPos(wx, wy, halfBoundingW, halfBoundingH, topPadding, bottomPadding, leftPadding, rightPadding, collisionSpaceOffsetX, collisionSpaceOffsetY)
}
func CalcHardPushbacksNorms(playerCollider *resolv.Object, playerShape *resolv.ConvexPolygon, snapIntoPlatformOverlap float64, pEffPushback *Vec2D) []Vec2D {
ret := make([]Vec2D, 0, 10) // no one would simultaneously have more than 5 hardPushbacks
collision := playerCollider.Check(0, 0)
@ -82,7 +282,6 @@ func CalcHardPushbacksNorms(playerCollider *resolv.Object, playerShape *resolv.C
}
func ApplyInputFrameDownsyncDynamicsOnSingleRenderFrame(delayedInputFrame, delayedInputFrameForPrevRenderFrame *InputFrameDownsync, currRenderFrame *RoomDownsyncFrame, collisionSys *resolv.Space, collisionSysMap map[int32]*resolv.Object, gravityX, gravityY, jumpingInitVelY, inputDelayFrames, inputScaleFrames int32, collisionSpaceOffsetX, collisionSpaceOffsetY, snapIntoPlatformOverlap, snapIntoPlatformThreshold, worldToVirtualGridRatio, virtualGridToWorldRatio float64) *RoomDownsyncFrame {
topPadding, bottomPadding, leftPadding, rightPadding := snapIntoPlatformOverlap, snapIntoPlatformOverlap, snapIntoPlatformOverlap, snapIntoPlatformOverlap
// [WARNING] This function MUST BE called while "InputsBufferLock" is locked!
roomCapacity := len(currRenderFrame.PlayersArr)
nextRenderFramePlayers := make([]*PlayerDownsync, roomCapacity)
@ -171,8 +370,7 @@ func ApplyInputFrameDownsyncDynamicsOnSingleRenderFrame(delayedInputFrame, delay
newVy += thatPlayerInNextFrame.VelY
}
halfColliderWidth, halfColliderHeight := currPlayerDownsync.ColliderRadius, currPlayerDownsync.ColliderRadius+currPlayerDownsync.ColliderRadius // avoid multiplying
playerCollider.X, playerCollider.Y = VirtualGridToPolygonColliderBLPos(newVx, newVy, halfColliderWidth, halfColliderHeight, topPadding, bottomPadding, leftPadding, rightPadding, collisionSpaceOffsetX, collisionSpaceOffsetY, virtualGridToWorldRatio)
playerCollider.X, playerCollider.Y = VirtualGridToPolygonColliderBLPos(newVx, newVy, playerCollider.W*0.5, playerCollider.H*0.5, 0, 0, 0, 0, collisionSpaceOffsetX, collisionSpaceOffsetY, virtualGridToWorldRatio)
// Update in the collision system
playerCollider.Update()
@ -263,8 +461,7 @@ func ApplyInputFrameDownsyncDynamicsOnSingleRenderFrame(delayedInputFrame, delay
playerCollider := collisionSysMap[collisionPlayerIndex]
// Update "virtual grid position"
thatPlayerInNextFrame := nextRenderFramePlayers[i]
halfColliderWidth, halfColliderHeight := currPlayerDownsync.ColliderRadius, currPlayerDownsync.ColliderRadius+currPlayerDownsync.ColliderRadius // avoid multiplying
thatPlayerInNextFrame.VirtualGridX, thatPlayerInNextFrame.VirtualGridY = PolygonColliderBLToVirtualGridPos(playerCollider.X-effPushbacks[joinIndex-1].X, playerCollider.Y-effPushbacks[joinIndex-1].Y, halfColliderWidth, halfColliderHeight, topPadding, bottomPadding, leftPadding, rightPadding, collisionSpaceOffsetX, collisionSpaceOffsetY, worldToVirtualGridRatio)
thatPlayerInNextFrame.VirtualGridX, thatPlayerInNextFrame.VirtualGridY = PolygonColliderBLToVirtualGridPos(playerCollider.X-effPushbacks[joinIndex-1].X, playerCollider.Y-effPushbacks[joinIndex-1].Y, playerCollider.W*0.5, playerCollider.H*0.5, 0, 0, 0, 0, collisionSpaceOffsetX, collisionSpaceOffsetY, worldToVirtualGridRatio)
}
return &RoomDownsyncFrame{
@ -272,3 +469,81 @@ func ApplyInputFrameDownsyncDynamicsOnSingleRenderFrame(delayedInputFrame, delay
PlayersArr: nextRenderFramePlayers,
}
}
func GenerateRectCollider(wx, wy, w, h, topPadding, bottomPadding, leftPadding, rightPadding, spaceOffsetX, spaceOffsetY float64, data interface{}, tag string) *resolv.Object {
blX, blY := WorldToPolygonColliderBLPos(wx, wy, w*0.5, h*0.5, topPadding, bottomPadding, leftPadding, rightPadding, spaceOffsetX, spaceOffsetY)
return generateRectColliderInCollisionSpace(blX, blY, leftPadding+w+rightPadding, bottomPadding+h+topPadding, data, tag)
}
func generateRectColliderInCollisionSpace(blX, blY, w, h float64, data interface{}, tag string) *resolv.Object {
collider := resolv.NewObject(blX, blY, w, h, tag) // Unlike its frontend counter part, the position of a "resolv.Object" must be specified by "bottom-left point" because "w" and "h" must be positive, see "resolv.Object.BoundsToSpace" for details
shape := resolv.NewRectangle(0, 0, w, h)
collider.SetShape(shape)
collider.Data = data
return collider
}
func GenerateConvexPolygonCollider(unalignedSrc *Polygon2D, spaceOffsetX, spaceOffsetY float64, data interface{}, tag string) *resolv.Object {
aligned := AlignPolygon2DToBoundingBox(unalignedSrc)
var w, h float64 = 0, 0
shape := resolv.NewConvexPolygon()
for i, pi := range aligned.Points {
for j, pj := range aligned.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)
}
}
}
for i := 0; i < len(aligned.Points); i++ {
p := aligned.Points[i]
shape.AddPoints(p.X, p.Y)
}
collider := resolv.NewObject(aligned.Anchor.X+spaceOffsetX, aligned.Anchor.Y+spaceOffsetY, w, h, tag)
collider.SetShape(shape)
collider.Data = data
return collider
}
func AlignPolygon2DToBoundingBox(input *Polygon2D) *Polygon2D {
// Transform again to put "anchor" at the "bottom-left point (w.r.t. world space)" of the bounding box for "resolv"
boundingBoxBL := &Vec2D{
X: MAX_FLOAT64,
Y: MAX_FLOAT64,
}
for _, p := range input.Points {
if p.X < boundingBoxBL.X {
boundingBoxBL.X = p.X
}
if p.Y < boundingBoxBL.Y {
boundingBoxBL.Y = p.Y
}
}
// Now "input.Anchor" should move to "input.Anchor+boundingBoxBL", thus "boundingBoxBL" is also the value of the negative diff for all "input.Points"
output := &Polygon2D{
Anchor: &Vec2D{
X: input.Anchor.X + boundingBoxBL.X,
Y: input.Anchor.Y + boundingBoxBL.Y,
},
Points: make([]*Vec2D, len(input.Points)),
}
for i, p := range input.Points {
output.Points[i] = &Vec2D{
X: p.X - boundingBoxBL.X,
Y: p.Y - boundingBoxBL.Y,
}
}
return output
}

View File

@ -0,0 +1,90 @@
package battle
type Vec2D struct {
X float64
Y float64
}
type Polygon2D struct {
Anchor *Vec2D
Points []*Vec2D
}
type PlayerDownsync struct {
Id int32
VirtualGridX int32
VirtualGridY int32
DirX int32
DirY int32
VelX int32
VelY int32
Speed int32
BattleState int32
JoinIndex int32
ColliderRadius float64
Removed bool
Score int32
LastMoveGmtMillis int32
FramesToRecover int32
Hp int32
MaxHp int32
CharacterState int32
InAir bool
Name string
DisplayName string
Avatar string
}
type InputFrameDecoded struct {
Dx int32
Dy int32
BtnALevel int32
BtnBLevel int32
}
type InputFrameUpsync struct {
InputFrameId int32
Encoded uint64
}
type InputFrameDownsync struct {
InputFrameId int32
InputList []uint64
ConfirmedList uint64
}
type Barrier struct {
Boundary *Polygon2D
}
type MeleeBullet struct {
// for offender
BattleLocalId int32
StartupFrames int32
ActiveFrames int32
RecoveryFrames int32
RecoveryFramesOnBlock int32
RecoveryFramesOnHit int32
Moveforward *Vec2D
HitboxOffset float64
HitboxSize *Vec2D
OriginatedRenderFrameId int32
// for defender
HitStunFrames int32
BlockStunFrames int32
Pushback float64
ReleaseTriggerType int32
Damage int32
OffenderJoinIndex int32
OffenderPlayerId int32
}
type RoomDownsyncFrame struct {
Id int32
PlayersArr []*PlayerDownsync
CountdownNanos int64
MeleeBullets []*MeleeBullet
BackendUnconfirmedMask uint64
ShouldForceResync bool
Players map[int32]*PlayerDownsync
}

View File

@ -3,17 +3,11 @@ module jsexport
go 1.18
require (
dnmshared v0.0.0
github.com/gopherjs/gopherjs v1.18.0-beta1
github.com/solarlune/resolv v0.5.1
)
require (
github.com/kvartborg/vector v0.0.0-20200419093813-2cba0cabb4f0 // indirect
github.com/solarlune/resolv v0.5.1 // indirect
go.uber.org/atomic v1.3.2 // indirect
go.uber.org/multierr v1.1.0 // indirect
go.uber.org/zap v1.9.1 // indirect
google.golang.org/protobuf v1.28.1 // indirect
)
replace dnmshared => ../dnmshared

View File

@ -1,19 +1,22 @@
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
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/gopherjs/gopherjs v1.17.2 h1:fQnZVsXk8uxXIStYb0N4bGk7jeyTalG/wsZjQ25dO0g=
github.com/gopherjs/gopherjs v1.17.2/go.mod h1:pRRIvn/QzFLrKfvEz3qUuEhtE/zLCWfreZ6J5gM2i+k=
github.com/gopherjs/gopherjs v1.18.0-beta1 h1:IbykhVEq4SAjwyBRuNHl0aOO6w6IqgL3RUdMhoBo4mY=
github.com/gopherjs/gopherjs v1.18.0-beta1/go.mod h1:6UY8PXRnu51MqjYCCY4toG0S5GeH5uVJ3qDxIsa+kqo=
github.com/kvartborg/vector v0.0.0-20200419093813-2cba0cabb4f0 h1:v8lWpj5957KtDMKu+xQtlu6G3ZoZR6Tn9bsfZCRG5Xw=
github.com/kvartborg/vector v0.0.0-20200419093813-2cba0cabb4f0/go.mod h1:GAX7tMJqXx9fB1BrsTWPOXy6IBRX+J461BffVPAdpwo=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/solarlune/resolv v0.5.1 h1:Ul6PAs/zaxiMUOEYz1Z6VeUj5k3CDcWMvSh+kivybDY=
github.com/solarlune/resolv v0.5.1/go.mod h1:HjM2f/0NoVjVdZsi26GtugX5aFbA62COEFEXkOhveRw=
go.uber.org/atomic v1.3.2 h1:2Oa65PReHzfn29GpvgsYwloV9AVFHPDk8tYxt2c2tr4=
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/multierr v1.1.0 h1:HoEmRHQPVSqub6w2z2d2EOVs2fjyFRGyofhKuyDq0QI=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
go.uber.org/zap v1.9.1 h1:XCJQEf3W6eZaVwhRBof6ImoYGJSITeKWsyeh3HFu/5o=
go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4=
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60=
go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/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=

View File

@ -1,12 +1,9 @@
package main
import (
. "dnmshared"
. "dnmshared/sharedprotos"
"github.com/gopherjs/gopherjs/js"
"github.com/solarlune/resolv"
"jsexport/models"
. "jsexport/protos"
. "jsexport/battle"
)
func NewCollisionSpaceJs(spaceW, spaceH, minStepW, minStepH int) *js.Object {
@ -69,6 +66,15 @@ func NewInputFrameDownsyncJs(inputFrameId int32, inputList []uint64, confirmedLi
})
}
func GetCollisionSpaceObjsJs(space *resolv.Space) []*js.Object {
objs := space.Objects()
ret := make([]*js.Object, 0, len(objs))
for _, obj := range objs {
ret = append(ret, js.MakeFullWrapper(obj))
}
return ret
}
func GetPlayersArrJs(rdf *RoomDownsyncFrame) []*js.Object {
// We couldn't just use the existing getters or field names to access non-primitive fields in Js
ret := make([]*js.Object, 0, len(rdf.PlayersArr))
@ -80,15 +86,15 @@ func GetPlayersArrJs(rdf *RoomDownsyncFrame) []*js.Object {
func GenerateRectColliderJs(wx, wy, w, h, topPadding, bottomPadding, leftPadding, rightPadding, spaceOffsetX, spaceOffsetY float64, data interface{}, tag string) *js.Object {
/*
[WARNING] It's important to note that we don't need "js.MakeFullWrapper" for a call sequence as follows.
```
var space = gopkgs.NewCollisionSpaceJs(2048, 2048, 8, 8);
var a = gopkgs.GenerateRectColliderJs(189, 497, 48, 48, snapIntoPlatformOverlap, snapIntoPlatformOverlap, snapIntoPlatformOverlap, snapIntoPlatformOverlap, spaceOffsetX, spaceOffsetY, "Player");
space.Add(a);
```
The "space" variable doesn't need access to the field of "a" in JavaScript level to run "space.Add(...)" method, which is good.
[WARNING] It's important to note that we don't need "js.MakeFullWrapper" for a call sequence as follows.
```
var space = gopkgs.NewCollisionSpaceJs(2048, 2048, 8, 8);
var a = gopkgs.GenerateRectColliderJs(189, 497, 48, 48, snapIntoPlatformOverlap, snapIntoPlatformOverlap, snapIntoPlatformOverlap, snapIntoPlatformOverlap, spaceOffsetX, spaceOffsetY, "Player");
space.Add(a);
```
The "space" variable doesn't need access to the field of "a" in JavaScript level to run "space.Add(...)" method, which is good.
However, the full wrapper access here is used for updating "collider.X/collider.Y" at JavaScript runtime.
However, the full wrapper access here is used for updating "collider.X/collider.Y" at JavaScript runtime.
*/
return js.MakeFullWrapper(GenerateRectCollider(wx, wy, w, h, topPadding, bottomPadding, leftPadding, rightPadding, spaceOffsetX, spaceOffsetY, data, tag))
@ -106,7 +112,7 @@ func CheckCollisionJs(obj *resolv.Object, dx, dy float64) *js.Object {
func ApplyInputFrameDownsyncDynamicsOnSingleRenderFrameJs(delayedInputFrame, delayedInputFrameForPrevRenderFrame *InputFrameDownsync, currRenderFrame *RoomDownsyncFrame, collisionSys *resolv.Space, collisionSysMap map[int32]*resolv.Object, gravityX, gravityY, jumpingInitVelY, inputDelayFrames, inputScaleFrames int32, collisionSpaceOffsetX, collisionSpaceOffsetY, snapIntoPlatformOverlap, snapIntoPlatformThreshold, worldToVirtualGridRatio, virtualGridToWorldRatio float64) *js.Object {
// We need access to all fields of RoomDownsyncFrame for displaying in frontend
return js.MakeFullWrapper(models.ApplyInputFrameDownsyncDynamicsOnSingleRenderFrame(delayedInputFrame, delayedInputFrameForPrevRenderFrame, currRenderFrame, collisionSys, collisionSysMap, gravityX, gravityY, jumpingInitVelY, inputDelayFrames, inputScaleFrames, collisionSpaceOffsetX, collisionSpaceOffsetY, snapIntoPlatformOverlap, snapIntoPlatformThreshold, worldToVirtualGridRatio, virtualGridToWorldRatio))
return js.MakeFullWrapper(ApplyInputFrameDownsyncDynamicsOnSingleRenderFrame(delayedInputFrame, delayedInputFrameForPrevRenderFrame, currRenderFrame, collisionSys, collisionSysMap, gravityX, gravityY, jumpingInitVelY, inputDelayFrames, inputScaleFrames, collisionSpaceOffsetX, collisionSpaceOffsetY, snapIntoPlatformOverlap, snapIntoPlatformThreshold, worldToVirtualGridRatio, virtualGridToWorldRatio))
}
func main() {
@ -121,7 +127,10 @@ func main() {
"GenerateRectColliderJs": GenerateRectColliderJs,
"GenerateConvexPolygonColliderJs": GenerateConvexPolygonColliderJs,
"GetPlayersArrJs": GetPlayersArrJs,
"GetCollisionSpaceObjsJs": GetCollisionSpaceObjsJs,
"ApplyInputFrameDownsyncDynamicsOnSingleRenderFrameJs": ApplyInputFrameDownsyncDynamicsOnSingleRenderFrameJs,
"CheckCollisionJs": CheckCollisionJs,
"WorldToPolygonColliderBLPos": WorldToPolygonColliderBLPos, // No need to wrap primitive return types
"PolygonColliderBLToWorldPos": PolygonColliderBLToWorldPos,
"CheckCollisionJs": CheckCollisionJs,
})
}

File diff suppressed because it is too large Load Diff

View File

@ -9,7 +9,7 @@ protoc -I=$golang_basedir_1/../frontend/assets/resources/pbfiles/ --go_out=. geo
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 )/jsexport
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"