goonscape/types/player.go
2025-02-14 13:35:09 +01:00

129 lines
3.0 KiB
Go

package types
import (
"sync"
"time"
pb "gitea.boner.be/bdnugget/goonserver/actions"
rl "github.com/gen2brain/raylib-go/raylib"
)
type Player struct {
sync.RWMutex
PosActual rl.Vector3
PosTile Tile
TargetPath []Tile
ActionQueue []*pb.Action
Speed float32
ID int32
IsMoving bool
AnimationFrame int32
LastAnimUpdate time.Time
LastUpdateTime time.Time
InterpolationProgress float32
FloatingMessage *FloatingMessage
QuitDone chan struct{}
UserData interface{}
Model rl.Model
Texture rl.Texture2D
Username string
}
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(),
}
}
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
}