mirror of
https://github.com/genxium/DelayNoMore
synced 2024-12-25 03:08:57 +00:00
Preparing for go2cs transpiling.
This commit is contained in:
parent
6b503ec95d
commit
04d8013cbb
@ -461,7 +461,7 @@
|
||||
"array": [
|
||||
0,
|
||||
0,
|
||||
210.43877906529718,
|
||||
210.4441731196186,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
|
File diff suppressed because one or more lines are too long
@ -655,7 +655,7 @@ func ApplyInputFrameDownsyncDynamicsOnSingleRenderFrame(inputsBuffer *resolv.Rin
|
||||
|
||||
jumpedOrNotList[i] = jumpedOrNot
|
||||
joinIndex := currPlayerDownsync.JoinIndex
|
||||
skillId := chConfig.SkillMapper(patternId, currPlayerDownsync)
|
||||
skillId := chConfig.SkillMapper(patternId, currPlayerDownsync, chConfig.SpeciesId)
|
||||
if skillConfig, existent := skills[skillId]; existent {
|
||||
thatPlayerInNextFrame.ActiveSkillId = int32(skillId)
|
||||
thatPlayerInNextFrame.ActiveSkillHit = 0
|
||||
|
@ -1,6 +1,6 @@
|
||||
package battle
|
||||
|
||||
type SkillMapperType func(patternId int, currPlayerDownsync *PlayerDownsync) int
|
||||
type SkillMapperType = func(patternId int, currPlayerDownsync *PlayerDownsync, speciesId int) int
|
||||
|
||||
type CharacterConfig struct {
|
||||
SpeciesId int
|
||||
@ -31,6 +31,118 @@ type CharacterConfig struct {
|
||||
SkillMapper SkillMapperType
|
||||
}
|
||||
|
||||
func defaultSkillMapper(patternId int, currPlayerDownsync *PlayerDownsync, speciesId int) int {
|
||||
switch speciesId {
|
||||
case 0:
|
||||
if 1 == patternId {
|
||||
if 0 == currPlayerDownsync.FramesToRecover {
|
||||
if currPlayerDownsync.InAir {
|
||||
return 255
|
||||
} else {
|
||||
return 1
|
||||
}
|
||||
} else {
|
||||
// Now that "0 < FramesToRecover", we're only able to fire any skill if it's a cancellation
|
||||
if skillConfig, existent1 := skills[int(currPlayerDownsync.ActiveSkillId)]; existent1 {
|
||||
switch v := skillConfig.Hits[currPlayerDownsync.ActiveSkillHit].(type) {
|
||||
case *MeleeBullet:
|
||||
if v.Bullet.CancellableStFrame <= currPlayerDownsync.FramesInChState && currPlayerDownsync.FramesInChState < v.Bullet.CancellableEdFrame {
|
||||
if nextSkillId, existent2 := v.Bullet.CancelTransit[patternId]; existent2 {
|
||||
return nextSkillId
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if 3 == patternId {
|
||||
if 0 == currPlayerDownsync.FramesToRecover && !currPlayerDownsync.InAir {
|
||||
return 15
|
||||
}
|
||||
} else if 5 == patternId {
|
||||
// Dashing is already constrained by "FramesToRecover & CapturedByInertia" in "deriveOpPattern"
|
||||
if !currPlayerDownsync.InAir {
|
||||
return 12
|
||||
}
|
||||
}
|
||||
|
||||
// By default no skill can be fired
|
||||
return NO_SKILL
|
||||
case 1:
|
||||
if 1 == patternId {
|
||||
if 0 == currPlayerDownsync.FramesToRecover {
|
||||
if currPlayerDownsync.InAir {
|
||||
return 256
|
||||
} else {
|
||||
return 4
|
||||
}
|
||||
} else {
|
||||
// Now that "0 < FramesToRecover", we're only able to fire any skill if it's a cancellation
|
||||
if skillConfig, existent1 := skills[int(currPlayerDownsync.ActiveSkillId)]; existent1 {
|
||||
switch v := skillConfig.Hits[currPlayerDownsync.ActiveSkillHit].(type) {
|
||||
case *MeleeBullet:
|
||||
if v.Bullet.CancellableStFrame <= currPlayerDownsync.FramesInChState && currPlayerDownsync.FramesInChState < v.Bullet.CancellableEdFrame {
|
||||
if nextSkillId, existent2 := v.Bullet.CancelTransit[patternId]; existent2 {
|
||||
return nextSkillId
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if 3 == patternId {
|
||||
if 0 == currPlayerDownsync.FramesToRecover && !currPlayerDownsync.InAir {
|
||||
return 16
|
||||
}
|
||||
} else if 5 == patternId {
|
||||
// Air dash allowed for this character
|
||||
// Dashing is already constrained by "FramesToRecover & CapturedByInertia" in "deriveOpPattern"
|
||||
return 13
|
||||
}
|
||||
|
||||
// By default no skill can be fired
|
||||
return NO_SKILL
|
||||
case 4096:
|
||||
if 1 == patternId {
|
||||
if 0 == currPlayerDownsync.FramesToRecover {
|
||||
if currPlayerDownsync.InAir {
|
||||
return 257
|
||||
} else {
|
||||
return 7
|
||||
}
|
||||
} else {
|
||||
// Now that "0 < FramesToRecover", we're only able to fire any skill if it's a cancellation
|
||||
if skillConfig, existent1 := skills[int(currPlayerDownsync.ActiveSkillId)]; existent1 {
|
||||
switch v := skillConfig.Hits[currPlayerDownsync.ActiveSkillHit].(type) {
|
||||
case *MeleeBullet:
|
||||
if v.Bullet.CancellableStFrame <= currPlayerDownsync.FramesInChState && currPlayerDownsync.FramesInChState < v.Bullet.CancellableEdFrame {
|
||||
if nextSkillId, existent2 := v.Bullet.CancelTransit[patternId]; existent2 {
|
||||
return nextSkillId
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if 2 == patternId {
|
||||
if 0 == currPlayerDownsync.FramesToRecover && !currPlayerDownsync.InAir {
|
||||
return 11
|
||||
}
|
||||
} else if 3 == patternId {
|
||||
if 0 == currPlayerDownsync.FramesToRecover && !currPlayerDownsync.InAir {
|
||||
return 10
|
||||
}
|
||||
} else if 5 == patternId {
|
||||
// Dashing is already constrained by "FramesToRecover & CapturedByInertia" in "deriveOpPattern"
|
||||
if !currPlayerDownsync.InAir {
|
||||
return 14
|
||||
}
|
||||
}
|
||||
|
||||
// By default no skill can be fired
|
||||
return NO_SKILL
|
||||
}
|
||||
|
||||
return NO_SKILL
|
||||
}
|
||||
|
||||
var Characters = map[int]*CharacterConfig{
|
||||
0: &CharacterConfig{
|
||||
SpeciesId: 0,
|
||||
@ -58,41 +170,7 @@ var Characters = map[int]*CharacterConfig{
|
||||
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 0 == currPlayerDownsync.FramesToRecover {
|
||||
if currPlayerDownsync.InAir {
|
||||
return 255
|
||||
} else {
|
||||
return 1
|
||||
}
|
||||
} else {
|
||||
// Now that "0 < FramesToRecover", we're only able to fire any skill if it's a cancellation
|
||||
if skillConfig, existent1 := skills[int(currPlayerDownsync.ActiveSkillId)]; existent1 {
|
||||
switch v := skillConfig.Hits[currPlayerDownsync.ActiveSkillHit].(type) {
|
||||
case *MeleeBullet:
|
||||
if v.Bullet.CancellableStFrame <= currPlayerDownsync.FramesInChState && currPlayerDownsync.FramesInChState < v.Bullet.CancellableEdFrame {
|
||||
if nextSkillId, existent2 := v.Bullet.CancelTransit[patternId]; existent2 {
|
||||
return nextSkillId
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if 3 == patternId {
|
||||
if 0 == currPlayerDownsync.FramesToRecover && !currPlayerDownsync.InAir {
|
||||
return 15
|
||||
}
|
||||
} else if 5 == patternId {
|
||||
// Dashing is already constrained by "FramesToRecover & CapturedByInertia" in "deriveOpPattern"
|
||||
if !currPlayerDownsync.InAir {
|
||||
return 12
|
||||
}
|
||||
}
|
||||
|
||||
// By default no skill can be fired
|
||||
return NO_SKILL
|
||||
},
|
||||
SkillMapper: defaultSkillMapper,
|
||||
},
|
||||
1: &CharacterConfig{
|
||||
SpeciesId: 1,
|
||||
@ -120,40 +198,7 @@ var Characters = map[int]*CharacterConfig{
|
||||
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 0 == currPlayerDownsync.FramesToRecover {
|
||||
if currPlayerDownsync.InAir {
|
||||
return 256
|
||||
} else {
|
||||
return 4
|
||||
}
|
||||
} else {
|
||||
// Now that "0 < FramesToRecover", we're only able to fire any skill if it's a cancellation
|
||||
if skillConfig, existent1 := skills[int(currPlayerDownsync.ActiveSkillId)]; existent1 {
|
||||
switch v := skillConfig.Hits[currPlayerDownsync.ActiveSkillHit].(type) {
|
||||
case *MeleeBullet:
|
||||
if v.Bullet.CancellableStFrame <= currPlayerDownsync.FramesInChState && currPlayerDownsync.FramesInChState < v.Bullet.CancellableEdFrame {
|
||||
if nextSkillId, existent2 := v.Bullet.CancelTransit[patternId]; existent2 {
|
||||
return nextSkillId
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if 3 == patternId {
|
||||
if 0 == currPlayerDownsync.FramesToRecover && !currPlayerDownsync.InAir {
|
||||
return 16
|
||||
}
|
||||
} else if 5 == patternId {
|
||||
// Air dash allowed for this character
|
||||
// Dashing is already constrained by "FramesToRecover & CapturedByInertia" in "deriveOpPattern"
|
||||
return 13
|
||||
}
|
||||
|
||||
// By default no skill can be fired
|
||||
return NO_SKILL
|
||||
},
|
||||
SkillMapper: defaultSkillMapper,
|
||||
},
|
||||
4096: &CharacterConfig{
|
||||
SpeciesId: 4096,
|
||||
@ -177,45 +222,7 @@ var Characters = map[int]*CharacterConfig{
|
||||
DashingEnabled: true,
|
||||
OnWallEnabled: false,
|
||||
|
||||
SkillMapper: func(patternId int, currPlayerDownsync *PlayerDownsync) int {
|
||||
if 1 == patternId {
|
||||
if 0 == currPlayerDownsync.FramesToRecover {
|
||||
if currPlayerDownsync.InAir {
|
||||
return 257
|
||||
} else {
|
||||
return 7
|
||||
}
|
||||
} else {
|
||||
// Now that "0 < FramesToRecover", we're only able to fire any skill if it's a cancellation
|
||||
if skillConfig, existent1 := skills[int(currPlayerDownsync.ActiveSkillId)]; existent1 {
|
||||
switch v := skillConfig.Hits[currPlayerDownsync.ActiveSkillHit].(type) {
|
||||
case *MeleeBullet:
|
||||
if v.Bullet.CancellableStFrame <= currPlayerDownsync.FramesInChState && currPlayerDownsync.FramesInChState < v.Bullet.CancellableEdFrame {
|
||||
if nextSkillId, existent2 := v.Bullet.CancelTransit[patternId]; existent2 {
|
||||
return nextSkillId
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if 2 == patternId {
|
||||
if 0 == currPlayerDownsync.FramesToRecover && !currPlayerDownsync.InAir {
|
||||
return 11
|
||||
}
|
||||
} else if 3 == patternId {
|
||||
if 0 == currPlayerDownsync.FramesToRecover && !currPlayerDownsync.InAir {
|
||||
return 10
|
||||
}
|
||||
} else if 5 == patternId {
|
||||
// Dashing is already constrained by "FramesToRecover & CapturedByInertia" in "deriveOpPattern"
|
||||
if !currPlayerDownsync.InAir {
|
||||
return 14
|
||||
}
|
||||
}
|
||||
|
||||
// By default no skill can be fired
|
||||
return NO_SKILL
|
||||
},
|
||||
SkillMapper: defaultSkillMapper,
|
||||
},
|
||||
}
|
||||
|
||||
@ -226,7 +233,7 @@ var skills = map[int]*Skill{
|
||||
RecoveryFramesOnHit: int32(30),
|
||||
ReleaseTriggerType: int32(1),
|
||||
BoundChState: ATK_CHARACTER_STATE_ATK1,
|
||||
Hits: []interface{}{
|
||||
Hits: []AnyBullet{
|
||||
&MeleeBullet{
|
||||
Bullet: &BulletConfig{
|
||||
StartupFrames: int32(7),
|
||||
@ -261,7 +268,7 @@ var skills = map[int]*Skill{
|
||||
RecoveryFramesOnHit: int32(36),
|
||||
ReleaseTriggerType: int32(1),
|
||||
BoundChState: ATK_CHARACTER_STATE_ATK2,
|
||||
Hits: []interface{}{
|
||||
Hits: []AnyBullet{
|
||||
&MeleeBullet{
|
||||
Bullet: &BulletConfig{
|
||||
StartupFrames: int32(18),
|
||||
@ -295,7 +302,7 @@ var skills = map[int]*Skill{
|
||||
RecoveryFramesOnHit: int32(50),
|
||||
ReleaseTriggerType: int32(1),
|
||||
BoundChState: ATK_CHARACTER_STATE_ATK3,
|
||||
Hits: []interface{}{
|
||||
Hits: []AnyBullet{
|
||||
&MeleeBullet{
|
||||
Bullet: &BulletConfig{
|
||||
StartupFrames: int32(8),
|
||||
@ -324,7 +331,7 @@ var skills = map[int]*Skill{
|
||||
RecoveryFramesOnHit: int32(30),
|
||||
ReleaseTriggerType: int32(1),
|
||||
BoundChState: ATK_CHARACTER_STATE_ATK1,
|
||||
Hits: []interface{}{
|
||||
Hits: []AnyBullet{
|
||||
&MeleeBullet{
|
||||
Bullet: &BulletConfig{
|
||||
StartupFrames: int32(7),
|
||||
@ -359,7 +366,7 @@ var skills = map[int]*Skill{
|
||||
RecoveryFramesOnHit: int32(36),
|
||||
ReleaseTriggerType: int32(1),
|
||||
BoundChState: ATK_CHARACTER_STATE_ATK2,
|
||||
Hits: []interface{}{
|
||||
Hits: []AnyBullet{
|
||||
&MeleeBullet{
|
||||
Bullet: &BulletConfig{
|
||||
StartupFrames: int32(18),
|
||||
@ -393,7 +400,7 @@ var skills = map[int]*Skill{
|
||||
RecoveryFramesOnHit: int32(45),
|
||||
ReleaseTriggerType: int32(1),
|
||||
BoundChState: ATK_CHARACTER_STATE_ATK3,
|
||||
Hits: []interface{}{
|
||||
Hits: []AnyBullet{
|
||||
&MeleeBullet{
|
||||
Bullet: &BulletConfig{
|
||||
StartupFrames: int32(8),
|
||||
@ -422,7 +429,7 @@ var skills = map[int]*Skill{
|
||||
RecoveryFramesOnHit: int32(30),
|
||||
ReleaseTriggerType: int32(1),
|
||||
BoundChState: ATK_CHARACTER_STATE_ATK1,
|
||||
Hits: []interface{}{
|
||||
Hits: []AnyBullet{
|
||||
&MeleeBullet{
|
||||
Bullet: &BulletConfig{
|
||||
StartupFrames: int32(7),
|
||||
@ -457,7 +464,7 @@ var skills = map[int]*Skill{
|
||||
RecoveryFramesOnHit: int32(36),
|
||||
ReleaseTriggerType: int32(1),
|
||||
BoundChState: ATK_CHARACTER_STATE_ATK2,
|
||||
Hits: []interface{}{
|
||||
Hits: []AnyBullet{
|
||||
&MeleeBullet{
|
||||
Bullet: &BulletConfig{
|
||||
StartupFrames: int32(18),
|
||||
@ -491,7 +498,7 @@ var skills = map[int]*Skill{
|
||||
RecoveryFramesOnHit: int32(40),
|
||||
ReleaseTriggerType: int32(1),
|
||||
BoundChState: ATK_CHARACTER_STATE_ATK3,
|
||||
Hits: []interface{}{
|
||||
Hits: []AnyBullet{
|
||||
&MeleeBullet{
|
||||
Bullet: &BulletConfig{
|
||||
StartupFrames: int32(7),
|
||||
@ -520,7 +527,7 @@ var skills = map[int]*Skill{
|
||||
RecoveryFramesOnHit: int32(38),
|
||||
ReleaseTriggerType: int32(1),
|
||||
BoundChState: ATK_CHARACTER_STATE_ATK4,
|
||||
Hits: []interface{}{
|
||||
Hits: []AnyBullet{
|
||||
&FireballBullet{
|
||||
Speed: int32(float64(6) * WORLD_TO_VIRTUAL_GRID_RATIO),
|
||||
Bullet: &BulletConfig{
|
||||
@ -550,7 +557,7 @@ var skills = map[int]*Skill{
|
||||
RecoveryFramesOnHit: int32(60),
|
||||
ReleaseTriggerType: int32(1),
|
||||
BoundChState: ATK_CHARACTER_STATE_ATK5,
|
||||
Hits: []interface{}{
|
||||
Hits: []AnyBullet{
|
||||
&MeleeBullet{
|
||||
Bullet: &BulletConfig{
|
||||
StartupFrames: int32(3),
|
||||
@ -579,7 +586,7 @@ var skills = map[int]*Skill{
|
||||
RecoveryFramesOnHit: int32(10),
|
||||
ReleaseTriggerType: int32(1),
|
||||
BoundChState: ATK_CHARACTER_STATE_DASHING,
|
||||
Hits: []interface{}{
|
||||
Hits: []AnyBullet{
|
||||
&MeleeBullet{
|
||||
Bullet: &BulletConfig{
|
||||
StartupFrames: int32(3),
|
||||
@ -606,7 +613,7 @@ var skills = map[int]*Skill{
|
||||
RecoveryFramesOnHit: int32(12),
|
||||
ReleaseTriggerType: int32(1),
|
||||
BoundChState: ATK_CHARACTER_STATE_DASHING,
|
||||
Hits: []interface{}{
|
||||
Hits: []AnyBullet{
|
||||
&MeleeBullet{
|
||||
Bullet: &BulletConfig{
|
||||
StartupFrames: int32(3),
|
||||
@ -633,7 +640,7 @@ var skills = map[int]*Skill{
|
||||
RecoveryFramesOnHit: int32(8),
|
||||
ReleaseTriggerType: int32(1),
|
||||
BoundChState: ATK_CHARACTER_STATE_DASHING,
|
||||
Hits: []interface{}{
|
||||
Hits: []AnyBullet{
|
||||
&MeleeBullet{
|
||||
Bullet: &BulletConfig{
|
||||
StartupFrames: int32(4),
|
||||
@ -660,7 +667,7 @@ var skills = map[int]*Skill{
|
||||
RecoveryFramesOnHit: int32(48),
|
||||
ReleaseTriggerType: int32(1),
|
||||
BoundChState: ATK_CHARACTER_STATE_ATK4,
|
||||
Hits: []interface{}{
|
||||
Hits: []AnyBullet{
|
||||
&FireballBullet{
|
||||
Speed: int32(float64(4) * WORLD_TO_VIRTUAL_GRID_RATIO),
|
||||
Bullet: &BulletConfig{
|
||||
@ -690,7 +697,7 @@ var skills = map[int]*Skill{
|
||||
RecoveryFramesOnHit: int32(60),
|
||||
ReleaseTriggerType: int32(1),
|
||||
BoundChState: ATK_CHARACTER_STATE_ATK4,
|
||||
Hits: []interface{}{
|
||||
Hits: []AnyBullet{
|
||||
&FireballBullet{
|
||||
Speed: int32(float64(4) * WORLD_TO_VIRTUAL_GRID_RATIO),
|
||||
Bullet: &BulletConfig{
|
||||
@ -720,7 +727,7 @@ var skills = map[int]*Skill{
|
||||
RecoveryFramesOnHit: int32(30),
|
||||
ReleaseTriggerType: int32(1),
|
||||
BoundChState: ATK_CHARACTER_STATE_INAIR_ATK1,
|
||||
Hits: []interface{}{
|
||||
Hits: []AnyBullet{
|
||||
&MeleeBullet{
|
||||
Bullet: &BulletConfig{
|
||||
StartupFrames: int32(3),
|
||||
@ -749,7 +756,7 @@ var skills = map[int]*Skill{
|
||||
RecoveryFramesOnHit: int32(20),
|
||||
ReleaseTriggerType: int32(1),
|
||||
BoundChState: ATK_CHARACTER_STATE_INAIR_ATK1,
|
||||
Hits: []interface{}{
|
||||
Hits: []AnyBullet{
|
||||
&MeleeBullet{
|
||||
Bullet: &BulletConfig{
|
||||
StartupFrames: int32(3),
|
||||
@ -778,7 +785,7 @@ var skills = map[int]*Skill{
|
||||
RecoveryFramesOnHit: int32(30),
|
||||
ReleaseTriggerType: int32(1),
|
||||
BoundChState: ATK_CHARACTER_STATE_INAIR_ATK1,
|
||||
Hits: []interface{}{
|
||||
Hits: []AnyBullet{
|
||||
&MeleeBullet{
|
||||
Bullet: &BulletConfig{
|
||||
StartupFrames: int32(4),
|
||||
|
@ -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
|
||||
|
||||
type AnyBullet interface{}
|
||||
|
||||
type Vec2D struct {
|
||||
X float64
|
||||
Y float64
|
||||
@ -132,7 +134,7 @@ type Skill struct {
|
||||
RecoveryFramesOnHit int32
|
||||
ReleaseTriggerType int32 // 1: rising-edge, 2: falling-edge
|
||||
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
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
}
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
|
Loading…
Reference in New Issue
Block a user