mirror of
https://github.com/genxium/DelayNoMore
synced 2024-12-25 11:18:55 +00:00
Preparing for go2cs transpiling.
This commit is contained in:
parent
6b503ec95d
commit
04d8013cbb
@ -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
@ -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
|
||||||
|
@ -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,6 +31,118 @@ type CharacterConfig struct {
|
|||||||
SkillMapper SkillMapperType
|
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{
|
var Characters = map[int]*CharacterConfig{
|
||||||
0: &CharacterConfig{
|
0: &CharacterConfig{
|
||||||
SpeciesId: 0,
|
SpeciesId: 0,
|
||||||
@ -58,41 +170,7 @@ var Characters = map[int]*CharacterConfig{
|
|||||||
WallJumpingInitVelY: int32(float64(7) * WORLD_TO_VIRTUAL_GRID_RATIO),
|
WallJumpingInitVelY: int32(float64(7) * WORLD_TO_VIRTUAL_GRID_RATIO),
|
||||||
WallSlidingVelY: int32(float64(-1) * WORLD_TO_VIRTUAL_GRID_RATIO),
|
WallSlidingVelY: int32(float64(-1) * WORLD_TO_VIRTUAL_GRID_RATIO),
|
||||||
|
|
||||||
SkillMapper: func(patternId int, currPlayerDownsync *PlayerDownsync) int {
|
SkillMapper: defaultSkillMapper,
|
||||||
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
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
1: &CharacterConfig{
|
1: &CharacterConfig{
|
||||||
SpeciesId: 1,
|
SpeciesId: 1,
|
||||||
@ -120,40 +198,7 @@ var Characters = map[int]*CharacterConfig{
|
|||||||
WallJumpingInitVelY: int32(float64(7) * WORLD_TO_VIRTUAL_GRID_RATIO),
|
WallJumpingInitVelY: int32(float64(7) * WORLD_TO_VIRTUAL_GRID_RATIO),
|
||||||
WallSlidingVelY: int32(float64(-1) * WORLD_TO_VIRTUAL_GRID_RATIO),
|
WallSlidingVelY: int32(float64(-1) * WORLD_TO_VIRTUAL_GRID_RATIO),
|
||||||
|
|
||||||
SkillMapper: func(patternId int, currPlayerDownsync *PlayerDownsync) int {
|
SkillMapper: defaultSkillMapper,
|
||||||
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
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
4096: &CharacterConfig{
|
4096: &CharacterConfig{
|
||||||
SpeciesId: 4096,
|
SpeciesId: 4096,
|
||||||
@ -177,45 +222,7 @@ var Characters = map[int]*CharacterConfig{
|
|||||||
DashingEnabled: true,
|
DashingEnabled: true,
|
||||||
OnWallEnabled: false,
|
OnWallEnabled: false,
|
||||||
|
|
||||||
SkillMapper: func(patternId int, currPlayerDownsync *PlayerDownsync) int {
|
SkillMapper: defaultSkillMapper,
|
||||||
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
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -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),
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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.
|
||||||
|
@ -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
|
||||||
|
@ -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.
|
// 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
|
||||||
|
@ -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
|
||||||
|
@ -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.
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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 {
|
||||||
|
Loading…
Reference in New Issue
Block a user