2d移动功能优化,新增相关事件
This commit is contained in:
parent
5bc2edf166
commit
e4df8d2693
|
@ -7,58 +7,135 @@ import (
|
|||
"time"
|
||||
)
|
||||
|
||||
func NewMoving2D() *Moving2D {
|
||||
func NewMoving2D(options ...Moving2DOption) *Moving2D {
|
||||
moving2D := &Moving2D{
|
||||
entities: map[int64]*moving2DTarget{},
|
||||
timeUnit: float64(time.Millisecond),
|
||||
idle: time.Millisecond * 100,
|
||||
event: make(chan func(), 1000),
|
||||
}
|
||||
for _, option := range options {
|
||||
option(moving2D)
|
||||
}
|
||||
go moving2D.handle()
|
||||
go func() {
|
||||
for event := range moving2D.event {
|
||||
event()
|
||||
}
|
||||
}()
|
||||
return moving2D
|
||||
}
|
||||
|
||||
type Moving2D struct {
|
||||
rw sync.RWMutex
|
||||
entities map[int64]*moving2DTarget
|
||||
timeUnit float64
|
||||
idle time.Duration
|
||||
event chan func()
|
||||
close bool
|
||||
|
||||
position2DChangeEventHandles []game.Position2DChangeEventHandle
|
||||
position2DDestinationEventHandles []game.Position2DDestinationEventHandle
|
||||
}
|
||||
|
||||
func (slf *Moving2D) MoveTo(entity game.Moving2DEntity, x float64, y float64) {
|
||||
guid := entity.GetGuid()
|
||||
current := time.Now().UnixMilli()
|
||||
slf.rw.Lock()
|
||||
defer slf.rw.Unlock()
|
||||
if slf.close {
|
||||
return
|
||||
}
|
||||
entityTarget, exist := slf.entities[guid]
|
||||
if !exist {
|
||||
entityTarget = &moving2DTarget{
|
||||
Moving2DEntity: entity,
|
||||
x: x,
|
||||
y: y,
|
||||
lastMoveTime: current,
|
||||
}
|
||||
slf.entities[guid] = entityTarget
|
||||
return
|
||||
}
|
||||
entityTarget.x = x
|
||||
entityTarget.y = y
|
||||
entityTarget.lastMoveTime = current
|
||||
}
|
||||
|
||||
func (slf *Moving2D) StopMove(guid int64) {
|
||||
slf.rw.Lock()
|
||||
delete(slf.entities, guid)
|
||||
slf.rw.Unlock()
|
||||
}
|
||||
|
||||
func (slf *Moving2D) RegPosition2DChangeEvent(handle game.Position2DChangeEventHandle) {
|
||||
slf.position2DChangeEventHandles = append(slf.position2DChangeEventHandles, handle)
|
||||
}
|
||||
|
||||
func (slf *Moving2D) OnPosition2DChangeEvent(entity game.Moving2DEntity, oldX, oldY float64) {
|
||||
for _, handle := range slf.position2DChangeEventHandles {
|
||||
handle(slf, entity, oldX, oldY)
|
||||
}
|
||||
}
|
||||
|
||||
func (slf *Moving2D) RegPosition2DDestinationEvent(handle game.Position2DDestinationEventHandle) {
|
||||
slf.position2DDestinationEventHandles = append(slf.position2DDestinationEventHandles, handle)
|
||||
}
|
||||
|
||||
func (slf *Moving2D) OnPosition2DDestinationEvent(entity game.Moving2DEntity) {
|
||||
for _, handle := range slf.position2DDestinationEventHandles {
|
||||
handle(slf, entity)
|
||||
}
|
||||
}
|
||||
|
||||
type moving2DTarget struct {
|
||||
game.Moving2DEntity
|
||||
x, y float64
|
||||
lastMoveTime int64
|
||||
}
|
||||
|
||||
func (slf *Moving2D) MoveTo(entity game.Moving2DEntity, x float64, y float64) {
|
||||
func (slf *Moving2D) Release() {
|
||||
slf.rw.Lock()
|
||||
slf.entities[entity.GetGuid()] = &moving2DTarget{
|
||||
Moving2DEntity: entity,
|
||||
x: x,
|
||||
y: y,
|
||||
lastMoveTime: time.Now().UnixMilli(),
|
||||
}
|
||||
slf.rw.Unlock()
|
||||
}
|
||||
|
||||
type Moving2D struct {
|
||||
rw sync.RWMutex
|
||||
entities map[int64]*moving2DTarget
|
||||
defer slf.rw.Unlock()
|
||||
slf.close = true
|
||||
close(slf.event)
|
||||
}
|
||||
|
||||
func (slf *Moving2D) handle() {
|
||||
for {
|
||||
slf.rw.Lock()
|
||||
if slf.close {
|
||||
slf.rw.Unlock()
|
||||
return
|
||||
}
|
||||
for guid, entity := range slf.entities {
|
||||
entity := entity
|
||||
x, y := entity.GetPosition()
|
||||
angle := g2d.CalcAngle(x, y, entity.x, entity.y)
|
||||
moveTime := time.Now().UnixMilli()
|
||||
interval := float64(moveTime - entity.lastMoveTime)
|
||||
distance := interval * entity.GetSpeed()
|
||||
nx, ny := g2d.CalculateNewCoordinate(x, y, angle, distance)
|
||||
if g2d.CalcDistance(nx, ny, entity.x, entity.y) <= distance {
|
||||
distance := g2d.CalcDistance(x, y, entity.x, entity.y)
|
||||
moveDistance := interval * entity.GetSpeed() / slf.timeUnit
|
||||
if moveDistance > distance || (x == entity.x && y == entity.y) {
|
||||
entity.SetPosition(entity.x, entity.y)
|
||||
delete(slf.entities, guid)
|
||||
return
|
||||
slf.event <- func() {
|
||||
slf.OnPosition2DDestinationEvent(entity)
|
||||
}
|
||||
return
|
||||
} else {
|
||||
nx, ny := g2d.CalculateNewCoordinate(x, y, angle, distance)
|
||||
entity.SetPosition(nx, ny)
|
||||
entity.lastMoveTime = moveTime
|
||||
slf.event <- func() {
|
||||
slf.OnPosition2DChangeEvent(entity, x, y)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(slf.entities) == 0 {
|
||||
slf.rw.Unlock()
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
time.Sleep(slf.idle)
|
||||
} else {
|
||||
slf.rw.Unlock()
|
||||
}
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
package builtin
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Moving2DOption func(moving *Moving2D)
|
||||
|
||||
// WithMoving2DTimeUnit 通过特定时间单位创建
|
||||
// - 默认单位为1毫秒,最小单位也为1毫秒
|
||||
func WithMoving2DTimeUnit(duration time.Duration) Moving2DOption {
|
||||
return func(moving *Moving2D) {
|
||||
if duration < time.Millisecond {
|
||||
panic(errors.New("time unit milliseconds minimum"))
|
||||
}
|
||||
moving.timeUnit = float64(duration)
|
||||
}
|
||||
}
|
||||
|
||||
// WithMoving2DIdleWaitTime 通过特定的空闲等待时间创建
|
||||
// - 默认情况下在没有新的移动计划时将限制 100 毫秒
|
||||
func WithMoving2DIdleWaitTime(duration time.Duration) Moving2DOption {
|
||||
return func(moving *Moving2D) {
|
||||
moving.idle = duration
|
||||
}
|
||||
}
|
|
@ -2,5 +2,21 @@ package game
|
|||
|
||||
// Moving2D 2D移动功能接口定义
|
||||
type Moving2D interface {
|
||||
// MoveTo 设置对象移动至特定位置
|
||||
MoveTo(entity Moving2DEntity, x float64, y float64)
|
||||
// StopMove 终止特定对象的移动
|
||||
StopMove(guid int64)
|
||||
|
||||
// RegPosition2DChangeEvent 对象位置改变时将立即执行被注册的事件处理函数
|
||||
RegPosition2DChangeEvent(handle Position2DChangeEventHandle)
|
||||
OnPosition2DChangeEvent(entity Moving2DEntity, oldX, oldY float64)
|
||||
|
||||
// RegPosition2DDestinationEvent 对象抵达终点时将立即执行被注册的事件处理函数
|
||||
RegPosition2DDestinationEvent(handle Position2DDestinationEventHandle)
|
||||
OnPosition2DDestinationEvent(entity Moving2DEntity)
|
||||
}
|
||||
|
||||
type (
|
||||
Position2DChangeEventHandle func(moving Moving2D, entity Moving2DEntity, oldX, oldY float64)
|
||||
Position2DDestinationEventHandle func(moving Moving2D, entity Moving2DEntity)
|
||||
)
|
||||
|
|
Loading…
Reference in New Issue