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

@ -461,7 +461,7 @@
"array": [ "array": [
0, 0,
0, 0,
210.43877906529718, 210.4441731196186,
0, 0,
0, 0,
0, 0,

File diff suppressed because one or more lines are too long

View File

@ -655,7 +655,7 @@ func ApplyInputFrameDownsyncDynamicsOnSingleRenderFrame(inputsBuffer *resolv.Rin
jumpedOrNotList[i] = jumpedOrNot jumpedOrNotList[i] = jumpedOrNot
joinIndex := currPlayerDownsync.JoinIndex joinIndex := currPlayerDownsync.JoinIndex
skillId := chConfig.SkillMapper(patternId, currPlayerDownsync) skillId := chConfig.SkillMapper(patternId, currPlayerDownsync, chConfig.SpeciesId)
if skillConfig, existent := skills[skillId]; existent { if skillConfig, existent := skills[skillId]; existent {
thatPlayerInNextFrame.ActiveSkillId = int32(skillId) thatPlayerInNextFrame.ActiveSkillId = int32(skillId)
thatPlayerInNextFrame.ActiveSkillHit = 0 thatPlayerInNextFrame.ActiveSkillHit = 0

View File

@ -1,6 +1,6 @@
package battle package battle
type SkillMapperType func(patternId int, currPlayerDownsync *PlayerDownsync) int type SkillMapperType = func(patternId int, currPlayerDownsync *PlayerDownsync, speciesId int) int
type CharacterConfig struct { type CharacterConfig struct {
SpeciesId int SpeciesId int
@ -31,34 +31,9 @@ type CharacterConfig struct {
SkillMapper SkillMapperType SkillMapper SkillMapperType
} }
var Characters = map[int]*CharacterConfig{ func defaultSkillMapper(patternId int, currPlayerDownsync *PlayerDownsync, speciesId int) int {
0: &CharacterConfig{ switch speciesId {
SpeciesId: 0, case 0:
SpeciesName: "MonkGirl",
InAirIdleFrameIdxTurningPoint: 11,
InAirIdleFrameIdxTurnedCycle: 1,
LayDownFrames: int32(16),
LayDownFramesToRecover: int32(16),
GetUpInvinsibleFrames: int32(10),
GetUpFramesToRecover: int32(27),
Speed: int32(float64(2.1) * WORLD_TO_VIRTUAL_GRID_RATIO),
JumpingInitVelY: int32(float64(8) * WORLD_TO_VIRTUAL_GRID_RATIO),
JumpingFramesToRecover: int32(2),
InertiaFramesToRecover: int32(9),
DashingEnabled: true,
OnWallEnabled: true,
WallJumpingFramesToRecover: int32(8), // 8 would be the minimum for an avg human
WallJumpingInitVelX: int32(float64(2.8) * WORLD_TO_VIRTUAL_GRID_RATIO), // Default is "appeared facing right", but actually holding ctrl against left
WallJumpingInitVelY: int32(float64(7) * WORLD_TO_VIRTUAL_GRID_RATIO),
WallSlidingVelY: int32(float64(-1) * WORLD_TO_VIRTUAL_GRID_RATIO),
SkillMapper: func(patternId int, currPlayerDownsync *PlayerDownsync) int {
if 1 == patternId { if 1 == patternId {
if 0 == currPlayerDownsync.FramesToRecover { if 0 == currPlayerDownsync.FramesToRecover {
if currPlayerDownsync.InAir { if currPlayerDownsync.InAir {
@ -92,35 +67,7 @@ var Characters = map[int]*CharacterConfig{
// By default no skill can be fired // By default no skill can be fired
return NO_SKILL return NO_SKILL
}, case 1:
},
1: &CharacterConfig{
SpeciesId: 1,
SpeciesName: "KnifeGirl",
InAirIdleFrameIdxTurningPoint: 9,
InAirIdleFrameIdxTurnedCycle: 1,
LayDownFrames: int32(16),
LayDownFramesToRecover: int32(16),
GetUpInvinsibleFrames: int32(10),
GetUpFramesToRecover: int32(27),
Speed: int32(float64(2.2) * WORLD_TO_VIRTUAL_GRID_RATIO), // I don't know why "2.2" is so special that it throws a compile error
JumpingInitVelY: int32(float64(7.5) * WORLD_TO_VIRTUAL_GRID_RATIO),
JumpingFramesToRecover: int32(2),
InertiaFramesToRecover: int32(9),
DashingEnabled: true,
OnWallEnabled: true,
WallJumpingFramesToRecover: int32(8), // 8 would be the minimum for an avg human
WallJumpingInitVelX: int32(float64(2.8) * WORLD_TO_VIRTUAL_GRID_RATIO), // Default is "appeared facing right", but actually holding ctrl against left
WallJumpingInitVelY: int32(float64(7) * WORLD_TO_VIRTUAL_GRID_RATIO),
WallSlidingVelY: int32(float64(-1) * WORLD_TO_VIRTUAL_GRID_RATIO),
SkillMapper: func(patternId int, currPlayerDownsync *PlayerDownsync) int {
if 1 == patternId { if 1 == patternId {
if 0 == currPlayerDownsync.FramesToRecover { if 0 == currPlayerDownsync.FramesToRecover {
if currPlayerDownsync.InAir { if currPlayerDownsync.InAir {
@ -153,31 +100,7 @@ var Characters = map[int]*CharacterConfig{
// By default no skill can be fired // By default no skill can be fired
return NO_SKILL return NO_SKILL
}, case 4096:
},
4096: &CharacterConfig{
SpeciesId: 4096,
SpeciesName: "Monk",
InAirIdleFrameIdxTurningPoint: 42,
InAirIdleFrameIdxTurnedCycle: 2,
LayDownFrames: int32(14),
LayDownFramesToRecover: int32(14),
GetUpInvinsibleFrames: int32(8),
GetUpFramesToRecover: int32(30),
Speed: int32(float64(1.8) * WORLD_TO_VIRTUAL_GRID_RATIO),
JumpingInitVelY: int32(float64(7.8) * WORLD_TO_VIRTUAL_GRID_RATIO),
JumpingFramesToRecover: int32(2),
InertiaFramesToRecover: int32(9),
DashingEnabled: true,
OnWallEnabled: false,
SkillMapper: func(patternId int, currPlayerDownsync *PlayerDownsync) int {
if 1 == patternId { if 1 == patternId {
if 0 == currPlayerDownsync.FramesToRecover { if 0 == currPlayerDownsync.FramesToRecover {
if currPlayerDownsync.InAir { if currPlayerDownsync.InAir {
@ -215,7 +138,91 @@ var Characters = map[int]*CharacterConfig{
// By default no skill can be fired // By default no skill can be fired
return NO_SKILL return NO_SKILL
}
return NO_SKILL
}
var Characters = map[int]*CharacterConfig{
0: &CharacterConfig{
SpeciesId: 0,
SpeciesName: "MonkGirl",
InAirIdleFrameIdxTurningPoint: 11,
InAirIdleFrameIdxTurnedCycle: 1,
LayDownFrames: int32(16),
LayDownFramesToRecover: int32(16),
GetUpInvinsibleFrames: int32(10),
GetUpFramesToRecover: int32(27),
Speed: int32(float64(2.1) * WORLD_TO_VIRTUAL_GRID_RATIO),
JumpingInitVelY: int32(float64(8) * WORLD_TO_VIRTUAL_GRID_RATIO),
JumpingFramesToRecover: int32(2),
InertiaFramesToRecover: int32(9),
DashingEnabled: true,
OnWallEnabled: true,
WallJumpingFramesToRecover: int32(8), // 8 would be the minimum for an avg human
WallJumpingInitVelX: int32(float64(2.8) * WORLD_TO_VIRTUAL_GRID_RATIO), // Default is "appeared facing right", but actually holding ctrl against left
WallJumpingInitVelY: int32(float64(7) * WORLD_TO_VIRTUAL_GRID_RATIO),
WallSlidingVelY: int32(float64(-1) * WORLD_TO_VIRTUAL_GRID_RATIO),
SkillMapper: defaultSkillMapper,
}, },
1: &CharacterConfig{
SpeciesId: 1,
SpeciesName: "KnifeGirl",
InAirIdleFrameIdxTurningPoint: 9,
InAirIdleFrameIdxTurnedCycle: 1,
LayDownFrames: int32(16),
LayDownFramesToRecover: int32(16),
GetUpInvinsibleFrames: int32(10),
GetUpFramesToRecover: int32(27),
Speed: int32(float64(2.2) * WORLD_TO_VIRTUAL_GRID_RATIO), // I don't know why "2.2" is so special that it throws a compile error
JumpingInitVelY: int32(float64(7.5) * WORLD_TO_VIRTUAL_GRID_RATIO),
JumpingFramesToRecover: int32(2),
InertiaFramesToRecover: int32(9),
DashingEnabled: true,
OnWallEnabled: true,
WallJumpingFramesToRecover: int32(8), // 8 would be the minimum for an avg human
WallJumpingInitVelX: int32(float64(2.8) * WORLD_TO_VIRTUAL_GRID_RATIO), // Default is "appeared facing right", but actually holding ctrl against left
WallJumpingInitVelY: int32(float64(7) * WORLD_TO_VIRTUAL_GRID_RATIO),
WallSlidingVelY: int32(float64(-1) * WORLD_TO_VIRTUAL_GRID_RATIO),
SkillMapper: defaultSkillMapper,
},
4096: &CharacterConfig{
SpeciesId: 4096,
SpeciesName: "Monk",
InAirIdleFrameIdxTurningPoint: 42,
InAirIdleFrameIdxTurnedCycle: 2,
LayDownFrames: int32(14),
LayDownFramesToRecover: int32(14),
GetUpInvinsibleFrames: int32(8),
GetUpFramesToRecover: int32(30),
Speed: int32(float64(1.8) * WORLD_TO_VIRTUAL_GRID_RATIO),
JumpingInitVelY: int32(float64(7.8) * WORLD_TO_VIRTUAL_GRID_RATIO),
JumpingFramesToRecover: int32(2),
InertiaFramesToRecover: int32(9),
DashingEnabled: true,
OnWallEnabled: false,
SkillMapper: defaultSkillMapper,
}, },
} }
@ -226,7 +233,7 @@ var skills = map[int]*Skill{
RecoveryFramesOnHit: int32(30), RecoveryFramesOnHit: int32(30),
ReleaseTriggerType: int32(1), ReleaseTriggerType: int32(1),
BoundChState: ATK_CHARACTER_STATE_ATK1, BoundChState: ATK_CHARACTER_STATE_ATK1,
Hits: []interface{}{ Hits: []AnyBullet{
&MeleeBullet{ &MeleeBullet{
Bullet: &BulletConfig{ Bullet: &BulletConfig{
StartupFrames: int32(7), StartupFrames: int32(7),
@ -261,7 +268,7 @@ var skills = map[int]*Skill{
RecoveryFramesOnHit: int32(36), RecoveryFramesOnHit: int32(36),
ReleaseTriggerType: int32(1), ReleaseTriggerType: int32(1),
BoundChState: ATK_CHARACTER_STATE_ATK2, BoundChState: ATK_CHARACTER_STATE_ATK2,
Hits: []interface{}{ Hits: []AnyBullet{
&MeleeBullet{ &MeleeBullet{
Bullet: &BulletConfig{ Bullet: &BulletConfig{
StartupFrames: int32(18), StartupFrames: int32(18),
@ -295,7 +302,7 @@ var skills = map[int]*Skill{
RecoveryFramesOnHit: int32(50), RecoveryFramesOnHit: int32(50),
ReleaseTriggerType: int32(1), ReleaseTriggerType: int32(1),
BoundChState: ATK_CHARACTER_STATE_ATK3, BoundChState: ATK_CHARACTER_STATE_ATK3,
Hits: []interface{}{ Hits: []AnyBullet{
&MeleeBullet{ &MeleeBullet{
Bullet: &BulletConfig{ Bullet: &BulletConfig{
StartupFrames: int32(8), StartupFrames: int32(8),
@ -324,7 +331,7 @@ var skills = map[int]*Skill{
RecoveryFramesOnHit: int32(30), RecoveryFramesOnHit: int32(30),
ReleaseTriggerType: int32(1), ReleaseTriggerType: int32(1),
BoundChState: ATK_CHARACTER_STATE_ATK1, BoundChState: ATK_CHARACTER_STATE_ATK1,
Hits: []interface{}{ Hits: []AnyBullet{
&MeleeBullet{ &MeleeBullet{
Bullet: &BulletConfig{ Bullet: &BulletConfig{
StartupFrames: int32(7), StartupFrames: int32(7),
@ -359,7 +366,7 @@ var skills = map[int]*Skill{
RecoveryFramesOnHit: int32(36), RecoveryFramesOnHit: int32(36),
ReleaseTriggerType: int32(1), ReleaseTriggerType: int32(1),
BoundChState: ATK_CHARACTER_STATE_ATK2, BoundChState: ATK_CHARACTER_STATE_ATK2,
Hits: []interface{}{ Hits: []AnyBullet{
&MeleeBullet{ &MeleeBullet{
Bullet: &BulletConfig{ Bullet: &BulletConfig{
StartupFrames: int32(18), StartupFrames: int32(18),
@ -393,7 +400,7 @@ var skills = map[int]*Skill{
RecoveryFramesOnHit: int32(45), RecoveryFramesOnHit: int32(45),
ReleaseTriggerType: int32(1), ReleaseTriggerType: int32(1),
BoundChState: ATK_CHARACTER_STATE_ATK3, BoundChState: ATK_CHARACTER_STATE_ATK3,
Hits: []interface{}{ Hits: []AnyBullet{
&MeleeBullet{ &MeleeBullet{
Bullet: &BulletConfig{ Bullet: &BulletConfig{
StartupFrames: int32(8), StartupFrames: int32(8),
@ -422,7 +429,7 @@ var skills = map[int]*Skill{
RecoveryFramesOnHit: int32(30), RecoveryFramesOnHit: int32(30),
ReleaseTriggerType: int32(1), ReleaseTriggerType: int32(1),
BoundChState: ATK_CHARACTER_STATE_ATK1, BoundChState: ATK_CHARACTER_STATE_ATK1,
Hits: []interface{}{ Hits: []AnyBullet{
&MeleeBullet{ &MeleeBullet{
Bullet: &BulletConfig{ Bullet: &BulletConfig{
StartupFrames: int32(7), StartupFrames: int32(7),
@ -457,7 +464,7 @@ var skills = map[int]*Skill{
RecoveryFramesOnHit: int32(36), RecoveryFramesOnHit: int32(36),
ReleaseTriggerType: int32(1), ReleaseTriggerType: int32(1),
BoundChState: ATK_CHARACTER_STATE_ATK2, BoundChState: ATK_CHARACTER_STATE_ATK2,
Hits: []interface{}{ Hits: []AnyBullet{
&MeleeBullet{ &MeleeBullet{
Bullet: &BulletConfig{ Bullet: &BulletConfig{
StartupFrames: int32(18), StartupFrames: int32(18),
@ -491,7 +498,7 @@ var skills = map[int]*Skill{
RecoveryFramesOnHit: int32(40), RecoveryFramesOnHit: int32(40),
ReleaseTriggerType: int32(1), ReleaseTriggerType: int32(1),
BoundChState: ATK_CHARACTER_STATE_ATK3, BoundChState: ATK_CHARACTER_STATE_ATK3,
Hits: []interface{}{ Hits: []AnyBullet{
&MeleeBullet{ &MeleeBullet{
Bullet: &BulletConfig{ Bullet: &BulletConfig{
StartupFrames: int32(7), StartupFrames: int32(7),
@ -520,7 +527,7 @@ var skills = map[int]*Skill{
RecoveryFramesOnHit: int32(38), RecoveryFramesOnHit: int32(38),
ReleaseTriggerType: int32(1), ReleaseTriggerType: int32(1),
BoundChState: ATK_CHARACTER_STATE_ATK4, BoundChState: ATK_CHARACTER_STATE_ATK4,
Hits: []interface{}{ Hits: []AnyBullet{
&FireballBullet{ &FireballBullet{
Speed: int32(float64(6) * WORLD_TO_VIRTUAL_GRID_RATIO), Speed: int32(float64(6) * WORLD_TO_VIRTUAL_GRID_RATIO),
Bullet: &BulletConfig{ Bullet: &BulletConfig{
@ -550,7 +557,7 @@ var skills = map[int]*Skill{
RecoveryFramesOnHit: int32(60), RecoveryFramesOnHit: int32(60),
ReleaseTriggerType: int32(1), ReleaseTriggerType: int32(1),
BoundChState: ATK_CHARACTER_STATE_ATK5, BoundChState: ATK_CHARACTER_STATE_ATK5,
Hits: []interface{}{ Hits: []AnyBullet{
&MeleeBullet{ &MeleeBullet{
Bullet: &BulletConfig{ Bullet: &BulletConfig{
StartupFrames: int32(3), StartupFrames: int32(3),
@ -579,7 +586,7 @@ var skills = map[int]*Skill{
RecoveryFramesOnHit: int32(10), RecoveryFramesOnHit: int32(10),
ReleaseTriggerType: int32(1), ReleaseTriggerType: int32(1),
BoundChState: ATK_CHARACTER_STATE_DASHING, BoundChState: ATK_CHARACTER_STATE_DASHING,
Hits: []interface{}{ Hits: []AnyBullet{
&MeleeBullet{ &MeleeBullet{
Bullet: &BulletConfig{ Bullet: &BulletConfig{
StartupFrames: int32(3), StartupFrames: int32(3),
@ -606,7 +613,7 @@ var skills = map[int]*Skill{
RecoveryFramesOnHit: int32(12), RecoveryFramesOnHit: int32(12),
ReleaseTriggerType: int32(1), ReleaseTriggerType: int32(1),
BoundChState: ATK_CHARACTER_STATE_DASHING, BoundChState: ATK_CHARACTER_STATE_DASHING,
Hits: []interface{}{ Hits: []AnyBullet{
&MeleeBullet{ &MeleeBullet{
Bullet: &BulletConfig{ Bullet: &BulletConfig{
StartupFrames: int32(3), StartupFrames: int32(3),
@ -633,7 +640,7 @@ var skills = map[int]*Skill{
RecoveryFramesOnHit: int32(8), RecoveryFramesOnHit: int32(8),
ReleaseTriggerType: int32(1), ReleaseTriggerType: int32(1),
BoundChState: ATK_CHARACTER_STATE_DASHING, BoundChState: ATK_CHARACTER_STATE_DASHING,
Hits: []interface{}{ Hits: []AnyBullet{
&MeleeBullet{ &MeleeBullet{
Bullet: &BulletConfig{ Bullet: &BulletConfig{
StartupFrames: int32(4), StartupFrames: int32(4),
@ -660,7 +667,7 @@ var skills = map[int]*Skill{
RecoveryFramesOnHit: int32(48), RecoveryFramesOnHit: int32(48),
ReleaseTriggerType: int32(1), ReleaseTriggerType: int32(1),
BoundChState: ATK_CHARACTER_STATE_ATK4, BoundChState: ATK_CHARACTER_STATE_ATK4,
Hits: []interface{}{ Hits: []AnyBullet{
&FireballBullet{ &FireballBullet{
Speed: int32(float64(4) * WORLD_TO_VIRTUAL_GRID_RATIO), Speed: int32(float64(4) * WORLD_TO_VIRTUAL_GRID_RATIO),
Bullet: &BulletConfig{ Bullet: &BulletConfig{
@ -690,7 +697,7 @@ var skills = map[int]*Skill{
RecoveryFramesOnHit: int32(60), RecoveryFramesOnHit: int32(60),
ReleaseTriggerType: int32(1), ReleaseTriggerType: int32(1),
BoundChState: ATK_CHARACTER_STATE_ATK4, BoundChState: ATK_CHARACTER_STATE_ATK4,
Hits: []interface{}{ Hits: []AnyBullet{
&FireballBullet{ &FireballBullet{
Speed: int32(float64(4) * WORLD_TO_VIRTUAL_GRID_RATIO), Speed: int32(float64(4) * WORLD_TO_VIRTUAL_GRID_RATIO),
Bullet: &BulletConfig{ Bullet: &BulletConfig{
@ -720,7 +727,7 @@ var skills = map[int]*Skill{
RecoveryFramesOnHit: int32(30), RecoveryFramesOnHit: int32(30),
ReleaseTriggerType: int32(1), ReleaseTriggerType: int32(1),
BoundChState: ATK_CHARACTER_STATE_INAIR_ATK1, BoundChState: ATK_CHARACTER_STATE_INAIR_ATK1,
Hits: []interface{}{ Hits: []AnyBullet{
&MeleeBullet{ &MeleeBullet{
Bullet: &BulletConfig{ Bullet: &BulletConfig{
StartupFrames: int32(3), StartupFrames: int32(3),
@ -749,7 +756,7 @@ var skills = map[int]*Skill{
RecoveryFramesOnHit: int32(20), RecoveryFramesOnHit: int32(20),
ReleaseTriggerType: int32(1), ReleaseTriggerType: int32(1),
BoundChState: ATK_CHARACTER_STATE_INAIR_ATK1, BoundChState: ATK_CHARACTER_STATE_INAIR_ATK1,
Hits: []interface{}{ Hits: []AnyBullet{
&MeleeBullet{ &MeleeBullet{
Bullet: &BulletConfig{ Bullet: &BulletConfig{
StartupFrames: int32(3), StartupFrames: int32(3),
@ -778,7 +785,7 @@ var skills = map[int]*Skill{
RecoveryFramesOnHit: int32(30), RecoveryFramesOnHit: int32(30),
ReleaseTriggerType: int32(1), ReleaseTriggerType: int32(1),
BoundChState: ATK_CHARACTER_STATE_INAIR_ATK1, BoundChState: ATK_CHARACTER_STATE_INAIR_ATK1,
Hits: []interface{}{ Hits: []AnyBullet{
&MeleeBullet{ &MeleeBullet{
Bullet: &BulletConfig{ Bullet: &BulletConfig{
StartupFrames: int32(4), StartupFrames: int32(4),

View File

@ -2,6 +2,8 @@ package battle
// TODO: Replace all "int32", "int64", "uint32" and "uint64" with just "int" for better performance in JavaScript! Reference https://github.com/gopherjs/gopherjs#performance-tips // TODO: Replace all "int32", "int64", "uint32" and "uint64" with just "int" for better performance in JavaScript! Reference https://github.com/gopherjs/gopherjs#performance-tips
type AnyBullet interface{}
type Vec2D struct { type Vec2D struct {
X float64 X float64
Y float64 Y float64
@ -132,7 +134,7 @@ type Skill struct {
RecoveryFramesOnHit int32 RecoveryFramesOnHit int32
ReleaseTriggerType int32 // 1: rising-edge, 2: falling-edge ReleaseTriggerType int32 // 1: rising-edge, 2: falling-edge
BoundChState int32 BoundChState int32
Hits []interface{} // Hits within a "Skill" are automatically triggered Hits []AnyBullet // Hits within a "Skill" are automatically triggered
// [WARN] Multihit of a fireball is more difficult to handle than that of melee, because we have to count from the fireball's first hit; the situation becomes even more complicated when a multihit fireball is in a crowd -- remains to be designed // [WARN] Multihit of a fireball is more difficult to handle than that of melee, because we have to count from the fireball's first hit; the situation becomes even more complicated when a multihit fireball is in a crowd -- remains to be designed
} }

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

View File

@ -10,10 +10,10 @@ type Collision struct {
} }
func NewCollision() *Collision { func NewCollision() *Collision {
return &Collision{ c := &Collision{}
Objects: NewRingBuffer(16), // I don't expect it to exceed 10 actually c.Objects = NewRingBuffer(16) // I don't expect it to exceed 10 actually
Cells: NewRingBuffer(16), c.Cells = NewRingBuffer(16)
} return c
} }
func (cc *Collision) Clear() { 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(). // This slice does not contain the Object that called Check().
func (cc *Collision) ObjectsByTags(tags ...string) []*Object { func (cc *Collision) ObjectsByTags(tags ...string) []*Object {
objects := []*Object{} objs := []*Object{}
rb := cc.Objects rb := cc.Objects
for i := rb.StFrameId; i < rb.EdFrameId; i++ { for i := rb.StFrameId; i < rb.EdFrameId; i++ {
@ -61,30 +61,30 @@ func (cc *Collision) ObjectsByTags(tags ...string) []*Object {
continue continue
} }
if o.HasTags(tags...) { 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. // 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} delta := Vector{0, 0}
if cc.dx < 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 { } 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 { 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 { } 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 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. // NewObject returns a new Object of the specified position and size.
func NewObjectSingleTag(x, y, w, h float64, tag string) *Object { func NewObjectSingleTag(x, y, w, h float64, tag string) *Object {
o := &Object{ o := &Object{}
X: x, o.X = x
Y: y, o.Y = y
W: w, o.W = w
H: h, o.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! 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!
tags: []string{tag}, o.tags = []string{tag}
ignoreList: map[*Object]bool{}, o.ignoreList = make(map[*Object]bool)
}
return o return o
} }
func NewObject(x, y, w, h float64, tags ...string) *Object { func NewObject(x, y, w, h float64, tags ...string) *Object {
o := &Object{ o := &Object{}
X: x, o.X = x
Y: y, o.Y = y
W: w, o.W = w
H: h, o.H = h
TouchingCells: NewRingBuffer(512), o.TouchingCells = NewRingBuffer(512)
tags: []string{}, o.tags = []string{}
ignoreList: map[*Object]bool{}, o.ignoreList = make(map[*Object]bool)
}
if len(tags) > 0 { if len(tags) > 0 {
o.AddTags(tags...) o.AddTags(tags...)
@ -67,7 +65,7 @@ func (obj *Object) Clone() *Object {
if obj.Shape != nil { if obj.Shape != nil {
newObj.SetShape(obj.Shape.Clone()) newObj.SetShape(obj.Shape.Clone())
} }
for k := range obj.ignoreList { for k, _ := range obj.ignoreList {
newObj.AddToIgnoreList(k) newObj.AddToIgnoreList(k)
} }
return newObj return newObj

View File

@ -6,6 +6,8 @@ const (
RING_BUFF_FAILED_TO_SET = int32(2) RING_BUFF_FAILED_TO_SET = int32(2)
) )
type AnyObj interface{}
type RingBuffer struct { type RingBuffer struct {
Ed int32 // write index, open index Ed int32 // write index, open index
St int32 // read index, closed index St int32 // read index, closed index
@ -13,19 +15,19 @@ type RingBuffer struct {
StFrameId int32 StFrameId int32
N 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 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 { func NewRingBuffer(n int32) *RingBuffer {
return &RingBuffer{ ret := &RingBuffer{}
Ed: 0, ret.Ed = 0
St: 0, ret.St = 0
EdFrameId: 0, ret.EdFrameId = 0
StFrameId: 0, ret.StFrameId = 0
N: n, ret.N = n
Cnt: 0, ret.Cnt = 0
Eles: make([]interface{}, n), ret.Eles = make([]AnyObj, n)
} return ret
} }
func (rb *RingBuffer) DryPut() { 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 { for 0 < rb.Cnt && rb.Cnt >= rb.N {
// Make room for the new element // Make room for the new element
rb.Pop() 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 { if 0 == rb.Cnt {
return nil return nil
} }
@ -93,7 +95,7 @@ func (rb *RingBuffer) GetArrIdxByOffset(offsetFromSt int32) int32 {
return -1 return -1
} }
func (rb *RingBuffer) GetByOffset(offsetFromSt int32) interface{} { func (rb *RingBuffer) GetByOffset(offsetFromSt int32) AnyObj {
arrIdx := rb.GetArrIdxByOffset(offsetFromSt) arrIdx := rb.GetArrIdxByOffset(offsetFromSt)
if -1 == arrIdx { if -1 == arrIdx {
return nil return nil
@ -101,7 +103,7 @@ func (rb *RingBuffer) GetByOffset(offsetFromSt int32) interface{} {
return rb.Eles[arrIdx] 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 { if frameId >= rb.EdFrameId || frameId < rb.StFrameId {
return nil 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. // [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 oldStFrameId, oldEdFrameId := rb.StFrameId, rb.EdFrameId
if frameId < oldStFrameId { if frameId < oldStFrameId {
return RING_BUFF_FAILED_TO_SET, oldStFrameId, oldEdFrameId 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 { func NewLine(x, y, x2, y2 float64) *Line {
return &Line{ l := &Line{}
Start: Vector{x, y}, l.Start = Vector{x, y}
End: Vector{x2, y2}, l.End = Vector{x2, y2}
} return l
} }
func (line *Line) Normal() Vector { 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}. // polygon square, with the vertices at {0,0}, {10,0}, {10, 10}, and {0, 10}.
func NewConvexPolygon(points ...float64) *ConvexPolygon { func NewConvexPolygon(points ...float64) *ConvexPolygon {
cp := &ConvexPolygon{ cp := &ConvexPolygon{}
Points: NewRingBuffer(6), // I don't expected more points to be coped with in this particular game cp.Points = NewRingBuffer(6) // I don't expected more points to be coped with in this particular game
Closed: true, cp.Closed = true
}
cp.AddPoints(points...) cp.AddPoints(points...)
@ -241,23 +240,6 @@ func (cp *ConvexPolygon) MoveVec(vec Vector) {
cp.Y += vec.Y() 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. // SATAxes returns the axes of the ConvexPolygon for SAT intersection testing.
func (cp *ConvexPolygon) SATAxes() []Vector { func (cp *ConvexPolygon) SATAxes() []Vector {
lines := cp.Lines() lines := cp.Lines()
@ -294,11 +276,11 @@ type ContactSet struct {
} }
func NewContactSet() *ContactSet { func NewContactSet() *ContactSet {
return &ContactSet{ cs := &ContactSet{}
Points: []Vector{}, cs.Points = []Vector{}
MTV: Vector{0, 0}, cs.MTV = Vector{0, 0}
Center: 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. // 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. // speed of one cell size per collision check to avoid missing any possible collisions.
func NewSpace(spaceWidth, spaceHeight, cellWidth, cellHeight int) *Space { func NewSpace(spaceWidth, spaceHeight, cellWidth, cellHeight int) *Space {
sp := &Space{ sp := &Space{}
CellWidth: cellWidth, sp.CellWidth = cellWidth
CellHeight: cellHeight, sp.CellHeight = cellHeight
}
sp.Resize(spaceWidth/cellWidth, spaceHeight/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 return sp
} }
@ -101,10 +97,10 @@ func (sp *Space) Objects() []*Object {
objectsAdded := map[*Object]bool{} objectsAdded := map[*Object]bool{}
objects := []*Object{} objects := []*Object{}
cyUpper := len(sp.Cells)
for cy := range sp.Cells { for cy := 0; cy < cyUpper; cy++ {
cxUpper := len(sp.Cells[cy])
for cx := range sp.Cells[cy] { for cx := 0; cx < cxUpper; cx++ {
rb := sp.Cells[cy][cx].Objects rb := sp.Cells[cy][cx].Objects
for i := rb.StFrameId; i < rb.EdFrameId; i++ { for i := rb.StFrameId; i < rb.EdFrameId; i++ {
o := rb.GetByFrameId(i).(*Object) 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). // 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) { func (sp *Space) WorldToSpace(x, y float64) (int, int) {
fx := int(math.Floor(x / float64(sp.CellWidth))) // [WARNING] DON'T use "int(...)" syntax to convert float to int, it's not supported by go2cs!
fy := int(math.Floor(y / float64(sp.CellHeight))) var fx int = (int)(math.Floor(x / float64(sp.CellWidth)))
var fy int = (int)(math.Floor(y / float64(sp.CellHeight)))
return fx, fy return fx, fy
} }

View File

@ -31,79 +31,6 @@ func (v Vector) Clone() Vector {
return clone 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 // Magnitude of a vector
func Magnitude(v Vector) float64 { func Magnitude(v Vector) float64 {
return v.Magnitude() return v.Magnitude()
@ -137,121 +64,13 @@ func (v Vector) Unit() Vector {
return v return v
} }
for i := range v { for i := 0; i < len(v); i++ {
v[i] = v[i] / l v[i] = v[i] / l
} }
return v 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 // X is corresponding to doing a v[0] lookup, if index 0 does not exist yet, a
// 0 will be returned instead // 0 will be returned instead
func (v Vector) X() float64 { func (v Vector) X() float64 {