Preparing for go2cs transpiling.

This commit is contained in:
genxium
2023-03-01 18:20:54 +08:00
parent 6b503ec95d
commit 04d8013cbb
13 changed files with 217 additions and 434 deletions

View File

@@ -8,11 +8,11 @@ type Cell struct {
// newCell creates a new cell at the specified X and Y position. Should not be used directly.
func newCell(x, y int) *Cell {
return &Cell{
X: x,
Y: y,
Objects: NewRingBuffer(16), // A single cell is so small thus wouldn't have many touching objects simultaneously
}
c := &Cell{}
c.X = x
c.Y = y
c.Objects = NewRingBuffer(16) // A single cell is so small thus wouldn't have many touching objects simultaneously
return c
}
// register registers an object with a Cell. Should not be used directly.

View File

@@ -10,10 +10,10 @@ type Collision struct {
}
func NewCollision() *Collision {
return &Collision{
Objects: NewRingBuffer(16), // I don't expect it to exceed 10 actually
Cells: NewRingBuffer(16),
}
c := &Collision{}
c.Objects = NewRingBuffer(16) // I don't expect it to exceed 10 actually
c.Cells = NewRingBuffer(16)
return c
}
func (cc *Collision) Clear() {
@@ -52,7 +52,7 @@ func (cc *Collision) HasTags(tags ...string) bool {
// This slice does not contain the Object that called Check().
func (cc *Collision) ObjectsByTags(tags ...string) []*Object {
objects := []*Object{}
objs := []*Object{}
rb := cc.Objects
for i := rb.StFrameId; i < rb.EdFrameId; i++ {
@@ -61,30 +61,30 @@ func (cc *Collision) ObjectsByTags(tags ...string) []*Object {
continue
}
if o.HasTags(tags...) {
objects = append(objects, o)
objs = append(objs, o)
}
}
return objects
return objs
}
// ContactWithObject returns the delta to move to come into contact with the specified Object.
func (cc *Collision) ContactWithObject(object *Object) Vector {
func (cc *Collision) ContactWithObject(obj *Object) Vector {
delta := Vector{0, 0}
if cc.dx < 0 {
delta[0] = object.X + object.W - cc.checkingObject.X
delta[0] = obj.X + obj.W - cc.checkingObject.X
} else if cc.dx > 0 {
delta[0] = object.X - cc.checkingObject.W - cc.checkingObject.X
delta[0] = obj.X - cc.checkingObject.W - cc.checkingObject.X
}
if cc.dy < 0 {
delta[1] = object.Y + object.H - cc.checkingObject.Y
delta[1] = obj.Y + obj.H - cc.checkingObject.Y
} else if cc.dy > 0 {
delta[1] = object.Y - cc.checkingObject.H - cc.checkingObject.Y
delta[1] = obj.Y - cc.checkingObject.H - cc.checkingObject.Y
}
return delta

View File

@@ -1,24 +0,0 @@
//go:build !amd64 || noasm
// +build !amd64 noasm
package resolv
// This function is from the gonum repository:
// https://github.com/gonum/gonum/blob/c3867503e73e5c3fee7ab93e3c2c562eb2be8178/internal/asm/f64/axpy.go#L23
func axpyUnitaryTo(dst []float64, alpha float64, x, y []float64) {
dim := len(y)
for i, v := range x {
if i == dim {
return
}
dst[i] = alpha*v + y[i]
}
}
// This function is from the gonum repository:
// https://github.com/gonum/gonum/blob/c3867503e73e5c3fee7ab93e3c2c562eb2be8178/internal/asm/f64/scal.go#L23
func scalUnitaryTo(dst []float64, alpha float64, x []float64) {
for i := range x {
dst[i] *= alpha
}
}

View File

@@ -17,29 +17,27 @@ type Object struct {
// NewObject returns a new Object of the specified position and size.
func NewObjectSingleTag(x, y, w, h float64, tag string) *Object {
o := &Object{
X: x,
Y: y,
W: w,
H: h,
TouchingCells: NewRingBuffer(512), // [WARNING] Should make N large enough to cover all "TouchingCells", otherwise some cells would fail to unregister an object, resulting in memory corruption and incorrect detection result!
tags: []string{tag},
ignoreList: map[*Object]bool{},
}
o := &Object{}
o.X = x
o.Y = y
o.W = w
o.H = h
o.TouchingCells = NewRingBuffer(512) // [WARNING] Should make N large enough to cover all "TouchingCells", otherwise some cells would fail to unregister an object, resulting in memory corruption and incorrect detection result!
o.tags = []string{tag}
o.ignoreList = make(map[*Object]bool)
return o
}
func NewObject(x, y, w, h float64, tags ...string) *Object {
o := &Object{
X: x,
Y: y,
W: w,
H: h,
TouchingCells: NewRingBuffer(512),
tags: []string{},
ignoreList: map[*Object]bool{},
}
o := &Object{}
o.X = x
o.Y = y
o.W = w
o.H = h
o.TouchingCells = NewRingBuffer(512)
o.tags = []string{}
o.ignoreList = make(map[*Object]bool)
if len(tags) > 0 {
o.AddTags(tags...)
@@ -67,7 +65,7 @@ func (obj *Object) Clone() *Object {
if obj.Shape != nil {
newObj.SetShape(obj.Shape.Clone())
}
for k := range obj.ignoreList {
for k, _ := range obj.ignoreList {
newObj.AddToIgnoreList(k)
}
return newObj

View File

@@ -6,6 +6,8 @@ const (
RING_BUFF_FAILED_TO_SET = int32(2)
)
type AnyObj interface{}
type RingBuffer struct {
Ed int32 // write index, open index
St int32 // read index, closed index
@@ -13,19 +15,19 @@ type RingBuffer struct {
StFrameId int32
N int32
Cnt int32 // the count of valid elements in the buffer, used mainly to distinguish what "st == ed" means for "Pop" and "Get" methods
Eles []interface{}
Eles []AnyObj
}
func NewRingBuffer(n int32) *RingBuffer {
return &RingBuffer{
Ed: 0,
St: 0,
EdFrameId: 0,
StFrameId: 0,
N: n,
Cnt: 0,
Eles: make([]interface{}, n),
}
ret := &RingBuffer{}
ret.Ed = 0
ret.St = 0
ret.EdFrameId = 0
ret.StFrameId = 0
ret.N = n
ret.Cnt = 0
ret.Eles = make([]AnyObj, n)
return ret
}
func (rb *RingBuffer) DryPut() {
@@ -41,7 +43,7 @@ func (rb *RingBuffer) DryPut() {
}
}
func (rb *RingBuffer) Put(pItem interface{}) {
func (rb *RingBuffer) Put(pItem AnyObj) {
for 0 < rb.Cnt && rb.Cnt >= rb.N {
// Make room for the new element
rb.Pop()
@@ -55,7 +57,7 @@ func (rb *RingBuffer) Put(pItem interface{}) {
}
}
func (rb *RingBuffer) Pop() interface{} {
func (rb *RingBuffer) Pop() AnyObj {
if 0 == rb.Cnt {
return nil
}
@@ -93,7 +95,7 @@ func (rb *RingBuffer) GetArrIdxByOffset(offsetFromSt int32) int32 {
return -1
}
func (rb *RingBuffer) GetByOffset(offsetFromSt int32) interface{} {
func (rb *RingBuffer) GetByOffset(offsetFromSt int32) AnyObj {
arrIdx := rb.GetArrIdxByOffset(offsetFromSt)
if -1 == arrIdx {
return nil
@@ -101,7 +103,7 @@ func (rb *RingBuffer) GetByOffset(offsetFromSt int32) interface{} {
return rb.Eles[arrIdx]
}
func (rb *RingBuffer) GetByFrameId(frameId int32) interface{} {
func (rb *RingBuffer) GetByFrameId(frameId int32) AnyObj {
if frameId >= rb.EdFrameId || frameId < rb.StFrameId {
return nil
}
@@ -109,7 +111,7 @@ func (rb *RingBuffer) GetByFrameId(frameId int32) interface{} {
}
// [WARNING] During a battle, frontend could receive non-consecutive frames (either renderFrame or inputFrame) due to resync, the buffer should handle these frames properly.
func (rb *RingBuffer) SetByFrameId(pItem interface{}, frameId int32) (int32, int32, int32) {
func (rb *RingBuffer) SetByFrameId(pItem AnyObj, frameId int32) (int32, int32, int32) {
oldStFrameId, oldEdFrameId := rb.StFrameId, rb.EdFrameId
if frameId < oldStFrameId {
return RING_BUFF_FAILED_TO_SET, oldStFrameId, oldEdFrameId

View File

@@ -27,10 +27,10 @@ type Line struct {
}
func NewLine(x, y, x2, y2 float64) *Line {
return &Line{
Start: Vector{x, y},
End: Vector{x2, y2},
}
l := &Line{}
l.Start = Vector{x, y}
l.End = Vector{x2, y2}
return l
}
func (line *Line) Normal() Vector {
@@ -82,10 +82,9 @@ type ConvexPolygon struct {
// polygon square, with the vertices at {0,0}, {10,0}, {10, 10}, and {0, 10}.
func NewConvexPolygon(points ...float64) *ConvexPolygon {
cp := &ConvexPolygon{
Points: NewRingBuffer(6), // I don't expected more points to be coped with in this particular game
Closed: true,
}
cp := &ConvexPolygon{}
cp.Points = NewRingBuffer(6) // I don't expected more points to be coped with in this particular game
cp.Closed = true
cp.AddPoints(points...)
@@ -241,23 +240,6 @@ func (cp *ConvexPolygon) MoveVec(vec Vector) {
cp.Y += vec.Y()
}
// Project projects (i.e. flattens) the ConvexPolygon onto the provided axis.
func (cp *ConvexPolygon) Project(axis Vector) Projection {
axis = axis.Unit()
vertices := cp.Transformed()
min := axis.Dot(Vector{vertices[0][0], vertices[0][1]})
max := min
for i := 1; i < len(vertices); i++ {
p := axis.Dot(Vector{vertices[i][0], vertices[i][1]})
if p < min {
min = p
} else if p > max {
max = p
}
}
return Projection{min, max}
}
// SATAxes returns the axes of the ConvexPolygon for SAT intersection testing.
func (cp *ConvexPolygon) SATAxes() []Vector {
lines := cp.Lines()
@@ -294,11 +276,11 @@ type ContactSet struct {
}
func NewContactSet() *ContactSet {
return &ContactSet{
Points: []Vector{},
MTV: Vector{0, 0},
Center: Vector{0, 0},
}
cs := &ContactSet{}
cs.Points = []Vector{}
cs.MTV = Vector{0, 0}
cs.Center = Vector{}
return cs
}
// LeftmostPoint returns the left-most point out of the ContactSet's Points slice. If the Points slice is empty somehow, this returns nil.

View File

@@ -16,16 +16,12 @@ type Space struct {
// speed of one cell size per collision check to avoid missing any possible collisions.
func NewSpace(spaceWidth, spaceHeight, cellWidth, cellHeight int) *Space {
sp := &Space{
CellWidth: cellWidth,
CellHeight: cellHeight,
}
sp := &Space{}
sp.CellWidth = cellWidth
sp.CellHeight = cellHeight
sp.Resize(spaceWidth/cellWidth, spaceHeight/cellHeight)
// sp.Resize(int(math.Ceil(float64(spaceWidth)/float64(cellWidth))),
// int(math.Ceil(float64(spaceHeight)/float64(cellHeight))))
return sp
}
@@ -101,10 +97,10 @@ func (sp *Space) Objects() []*Object {
objectsAdded := map[*Object]bool{}
objects := []*Object{}
for cy := range sp.Cells {
for cx := range sp.Cells[cy] {
cyUpper := len(sp.Cells)
for cy := 0; cy < cyUpper; cy++ {
cxUpper := len(sp.Cells[cy])
for cx := 0; cx < cxUpper; cx++ {
rb := sp.Cells[cy][cx].Objects
for i := rb.StFrameId; i < rb.EdFrameId; i++ {
o := rb.GetByFrameId(i).(*Object)
@@ -208,8 +204,9 @@ func (sp *Space) UnregisterAllObjects() {
// WorldToSpace converts from a world position (x, y) to a position in the Space (a grid-based position).
func (sp *Space) WorldToSpace(x, y float64) (int, int) {
fx := int(math.Floor(x / float64(sp.CellWidth)))
fy := int(math.Floor(y / float64(sp.CellHeight)))
// [WARNING] DON'T use "int(...)" syntax to convert float to int, it's not supported by go2cs!
var fx int = (int)(math.Floor(x / float64(sp.CellWidth)))
var fy int = (int)(math.Floor(y / float64(sp.CellHeight)))
return fx, fy
}

View File

@@ -31,79 +31,6 @@ func (v Vector) Clone() Vector {
return clone
}
/*
// Add a vector with a vector or a set of vectors
func Add(v1 Vector, vs ...Vector) Vector {
return v1.Clone().Add(vs...)
}
// Add a vector with a vector or a set of vectors
func (v Vector) Add(vs ...Vector) Vector {
dim := len(v)
for i := range vs {
if len(vs[i]) > dim {
axpyUnitaryTo(v, 1, v, vs[i][:dim])
} else {
axpyUnitaryTo(v, 1, v, vs[i])
}
}
return v
}
// Sub subtracts a vector with another vector or a set of vectors
func Sub(v1 Vector, vs ...Vector) Vector {
return v1.Clone().Sub(vs...)
}
// Sub subtracts a vector with another vector or a set of vectors
func (v Vector) Sub(vs ...Vector) Vector {
dim := len(v)
for i := range vs {
if len(vs[i]) > dim {
axpyUnitaryTo(v, -1, vs[i][:dim], v)
} else {
axpyUnitaryTo(v, -1, vs[i], v)
}
}
return v
}
// Scale vector with a given size
func Scale(v Vector, size float64) Vector {
return v.Clone().Scale(size)
}
// Scale vector with a given size
func (v Vector) Scale(size float64) Vector {
scalUnitaryTo(v, size, v)
return v
}
*/
// Equal compares that two vectors are equal to each other
func Equal(v1, v2 Vector) bool {
return v1.Equal(v2)
}
// Equal compares that two vectors are equal to each other
func (v Vector) Equal(v2 Vector) bool {
if len(v) != len(v2) {
return false
}
for i := range v {
if math.Abs(v[i]-v2[i]) > 1e-8 {
return false
}
}
return true
}
// Magnitude of a vector
func Magnitude(v Vector) float64 {
return v.Magnitude()
@@ -137,121 +64,13 @@ func (v Vector) Unit() Vector {
return v
}
for i := range v {
for i := 0; i < len(v); i++ {
v[i] = v[i] / l
}
return v
}
// Dot product of two vectors
func Dot(v1, v2 Vector) float64 {
result, dim1, dim2 := 0., len(v1), len(v2)
if dim1 > dim2 {
v2 = append(v2, make(Vector, dim1-dim2)...)
}
if dim1 < dim2 {
v1 = append(v1, make(Vector, dim2-dim1)...)
}
for i := range v1 {
result += v1[i] * v2[i]
}
return result
}
// Dot product of two vectors
func (v Vector) Dot(v2 Vector) float64 {
return Dot(v, v2)
}
// Cross product of two vectors
func Cross(v1, v2 Vector) Vector {
return v1.Cross(v2)
}
// Cross product of two vectors
func (v Vector) Cross(v2 Vector) Vector {
if len(v) != 3 || len(v2) != 3 {
return nil
}
return Vector{
v[Y]*v2[Z] - v[Z]*v2[Y],
v[Z]*v2[X] - v[X]*v2[Z],
v[X]*v2[Z] - v[Z]*v2[X],
}
}
// Rotate is rotating a vector around a specified axis.
// If no axis are specified, it will default to the Z axis.
//
// If a vector with more than 3-dimensions is rotated, it will cut the extra
// dimensions and return a 3-dimensional vector.
//
// NOTE: the ...Axis is just syntactic sugar that allows the axis to not be
// specified and default to Z, if multiple axis is passed the first will be
// set as the rotation axis
func Rotate(v Vector, angle float64, as ...Axis) Vector {
return v.Clone().Rotate(angle, as...)
}
// Rotate is rotating a vector around a specified axis.
// If no axis are specified, it will default to the Z axis.
//
// If a vector with more than 3-dimensions is rotated, it will cut the extra
// dimensions and return a 3-dimensional vector.
//
// NOTE: the ...Axis is just syntactic sugar that allows the axis to not be
// specified and default to Z, if multiple axis is passed the first will be
// set as the rotation axis
func (v Vector) Rotate(angle float64, as ...Axis) Vector {
axis, dim := Z, len(v)
if dim == 0 {
return v
}
if len(as) > 0 {
axis = as[0]
}
if dim == 1 && axis != Z {
v = append(v, 0, 0)
}
if (dim < 2 && axis == Z) || (dim == 2 && axis != Z) {
v = append(v, 0)
}
x, y := v[X], v[Y]
cos, sin := math.Cos(angle), math.Sin(angle)
switch axis {
case X:
z := v[Z]
v[Y] = y*cos - z*sin
v[Z] = y*sin + z*cos
case Y:
z := v[Z]
v[X] = x*cos + z*sin
v[Z] = -x*sin + z*cos
case Z:
v[X] = x*cos - y*sin
v[Y] = x*sin + y*cos
}
if dim > 3 {
return v[:3]
}
return v
}
// X is corresponding to doing a v[0] lookup, if index 0 does not exist yet, a
// 0 will be returned instead
func (v Vector) X() float64 {