go-susapp/movementprocessor.go
2021-12-16 20:57:35 +00:00

88 lines
3.4 KiB
Go

package main
import (
"tea.melonie54.xyz/sean/go-susapp/src/collision"
"tea.melonie54.xyz/sean/go-susapp/src/enum"
"tea.melonie54.xyz/sean/go-susapp/src/gamedata"
"tea.melonie54.xyz/sean/go-susapp/src/innernetobjects"
"tea.melonie54.xyz/sean/go-susapp/src/packets"
"tea.melonie54.xyz/sean/go-susapp/src/protocol"
"tea.melonie54.xyz/sean/go-susapp/src/util"
)
type MovementProcessor struct {
sus *SusApp
}
func (proc *MovementProcessor) Tick(delta int64) {
if proc.sus.state.CurrentGame != nil && proc.sus.state.CurrentGame.NetObjects != nil && proc.sus.networkHandler != nil {
p := protocol.NewEmptyPacket()
cp, ok := proc.sus.state.CurrentGame.PlayerNetObjects.ByPlayerNetID[proc.sus.state.CurrentGame.ClientPlayerNetID]
if ok {
netId := cp.PlayerNetworkTransform
var c0 innernetobjects.InnerNetObject = *proc.sus.state.CurrentGame.NetObjects[netId]
a, ok := c0.(*innernetobjects.PlayerNetworkTransform)
if ok {
a.LastSequenceID++
prevVelocityZero := a.TargetVelocity.X == 0 && a.TargetVelocity.Y == 0
a.TargetVelocity.X = enum.PLAYER_SPEED * proc.sus.state.CurrentGame.GameOptions.PlayerSpeedModifier * proc.sus.state.MovementX / 2
a.TargetVelocity.Y = enum.PLAYER_SPEED * proc.sus.state.CurrentGame.GameOptions.PlayerSpeedModifier * proc.sus.state.MovementY / 2
nextVelocityZero := a.TargetVelocity.X == 0 && a.TargetVelocity.Y == 0
if !nextVelocityZero || prevVelocityZero != nextVelocityZero {
a.TargetPosition.X += a.TargetVelocity.X * (float32(delta) / 1000)
a.TargetPosition.Y -= a.TargetVelocity.Y * (float32(delta) / 1000)
proc.sus.state.PosX = a.TargetPosition.X
proc.sus.state.PosY = a.TargetPosition.Y
if !proc.sus.state.Settings.Debug.DisableCollision {
proc.ProcessCollision(&a.TargetPosition)
}
c0.Write(p, false)
var c1 protocol.UpdateComponent = protocol.UpdateComponent{NetID: netId, RawData: p}
var c2 packets.GameDataSubpacket = &gamedata.DataH2G{Component: &c1}
var c3 protocol.HazelPayload = packets.NewGameDataSingleSubpacket(proc.sus.state.CurrentGame.GameID, &c2)
proc.sus.networkHandler.SendNormalPacket([]*protocol.Hazel{protocol.NewHazelFromPayload(&c3)})
}
}
}
}
}
func (proc *MovementProcessor) ProcessCollision(p *util.Vec2) {
a := util.NewVec2(p.X, p.Y+enum.PLAYER_COLLISION_OFFSET_Y)
if proc.sus.state.Collision != nil {
for _, item := range *proc.sus.state.Collision {
_, a = proc.ProcessPolygonCollision(a, item)
}
}
(*p) = util.NewVec2(a.X, a.Y-enum.PLAYER_COLLISION_OFFSET_Y)
}
func (proc *MovementProcessor) ProcessPolygonCollision(p util.Vec2, item []util.Vec2) (bool, util.Vec2) {
lastPoint := util.Vec2{}
y := false
for i, point := range item {
if i != 0 {
yes, closest := collision.CollisionLineCircle(lastPoint, point, p, enum.PLAYER_COLLISION_RADIUS)
if yes {
p = proc.CalculatePlayerRejectPosition(closest, p, enum.PLAYER_COLLISION_RADIUS)
y = true
}
}
lastPoint = point
}
for _, point := range item {
yes := collision.CollisionPointCircle(point, p, enum.PLAYER_COLLISION_RADIUS)
if yes {
p = proc.CalculatePlayerRejectPosition(point, p, enum.PLAYER_COLLISION_RADIUS)
}
}
return y, p
}
func (proc *MovementProcessor) CalculatePlayerRejectPosition(a util.Vec2, b util.Vec2, dt float32) util.Vec2 {
c := util.NewVec2(b.X-a.X, b.Y-a.Y)
d := util.Sqrt32((c.X * c.X) + (c.Y * c.Y))
t := dt / d
return util.NewVec2(((1-t)*a.X + t*b.X), ((1-t)*a.Y + t*b.Y))
}