package types import ( "sync" "time" pb "gitea.boner.be/bdnugget/goonserver/actions" rl "github.com/gen2brain/raylib-go/raylib" ) type Player struct { sync.RWMutex Model rl.Model Texture rl.Texture2D PosActual rl.Vector3 PosTile Tile TargetPath []Tile Speed float32 ActionQueue []*pb.Action ID int32 QuitDone chan struct{} CurrentTick int64 UserData interface{} FloatingMessage *FloatingMessage IsMoving bool AnimationFrame int32 LastAnimUpdate time.Time LastUpdateTime time.Time InterpolationProgress float32 } func (p *Player) MoveTowards(target Tile, deltaTime float32, mapGrid [][]Tile) { p.Lock() defer p.Unlock() targetPos := rl.Vector3{ X: float32(target.X * TileSize), Y: mapGrid[target.X][target.Y].Height * TileHeight, Z: float32(target.Y * TileSize), } direction := rl.Vector3Subtract(targetPos, p.PosActual) distance := rl.Vector3Length(direction) if distance > 1.0 { wasMoving := p.IsMoving p.IsMoving = true if !wasMoving { p.AnimationFrame = 0 } oldFrame := p.AnimationFrame p.AnimationFrame += int32(deltaTime * 60) rl.TraceLog(rl.LogInfo, "Walk frame update: %d -> %d (delta: %f)", oldFrame, p.AnimationFrame, deltaTime) } else { wasMoving := p.IsMoving p.IsMoving = false if wasMoving { p.AnimationFrame = 0 } oldFrame := p.AnimationFrame p.AnimationFrame += int32(deltaTime * 60) rl.TraceLog(rl.LogInfo, "Idle frame update: %d -> %d (delta: %f)", oldFrame, p.AnimationFrame, deltaTime) } if distance > 0 { direction = rl.Vector3Scale(direction, p.Speed*deltaTime/distance) } if distance > 1.0 { p.PosActual = rl.Vector3Add(p.PosActual, direction) } else { p.PosActual = targetPos p.PosTile = target if len(p.TargetPath) > 1 { p.TargetPath = p.TargetPath[1:] } } } func NewPlayer(state *pb.PlayerState) *Player { return &Player{ PosActual: rl.Vector3{ X: float32(state.X * TileSize), Y: float32(state.Y * TileHeight), Z: float32(state.Y * TileSize), }, PosTile: Tile{X: int(state.X), Y: int(state.Y)}, Speed: 50.0, ID: state.PlayerId, IsMoving: false, AnimationFrame: 0, LastAnimUpdate: time.Now(), LastUpdateTime: time.Now(), InterpolationProgress: 1.0, } } func (p *Player) UpdatePosition(state *pb.PlayerState, tickRate time.Duration) { p.Lock() defer p.Unlock() targetTile := Tile{X: int(state.X), Y: int(state.Y)} if p.PosTile != targetTile { p.PosTile = targetTile p.LastUpdateTime = time.Now() p.InterpolationProgress = 0 p.TargetPath = []Tile{targetTile} } } func (p *Player) ForceResync(state *pb.PlayerState) { p.Lock() defer p.Unlock() p.PosTile = Tile{X: int(state.X), Y: int(state.Y)} p.PosActual = rl.Vector3{ X: float32(state.X * TileSize), Y: float32(state.Y * TileHeight), Z: float32(state.Y * TileSize), } p.TargetPath = nil p.ActionQueue = nil p.InterpolationProgress = 1.0 }