package main
// 二维矢量模拟玩家移动
import (
"fmt"
"math"
)
// 位置坐标结构体
type Vec2 struct {
X, Y float32
}
// 加
func (v Vec2) Add(other Vec2) Vec2 {
return Vec2{
v.X + other.X,
v.Y + other.Y,
}
}
// 减
func (v Vec2) Sub(other Vec2) Vec2 {
return Vec2{
v.X - other.X,
v.Y - other.Y,
}
}
// 乘
func (v Vec2) Scale(s float32) Vec2 {
return Vec2{v.X * s, v.Y * s}
}
// 距离计算
func (v Vec2) DistanceTo(other Vec2) float32 {
dx := v.X - other.X
dy := v.Y - other.Y
return float32(math.Sqrt(float64(dx*dx + dy*dy)))
}
// 插值操作(
func (v Vec2) Normalize() Vec2 {
mag := v.X*v.X + v.Y*v.Y
if mag > 0 {
oneOverMag := 1 / float32(math.Sqrt(float64(mag)))
return Vec2{v.X * oneOverMag, v.Y * oneOverMag}
}
return Vec2{0, 0}
}
// 玩家
type Player struct {
currPos Vec2
targetPos Vec2
speed float32
}
// 玩家移动
func (p *Player) MoveTo(v Vec2) {
p.targetPos = v
}
// 玩家当前位置
func (p *Player) Pos() Vec2 {
return p.currPos
}
// 是否到达目的地
func (p *Player) IsArrived() bool {
return p.currPos.DistanceTo(p.targetPos) < p.speed
}
// 逻辑更新
func (p *Player) Update() {
if !p.IsArrived() {
// 计算当前位置指向目标的朝向
dir := p.targetPos.Sub(p.currPos).Normalize()
// 添加速度矢量生成新的位置
newPos := p.currPos.Add(dir.Scale((p.speed)))
// 移动完成后,更新当前位置
p.currPos = newPos
}
}
// 创建新玩家
func NewPlayer(speed float32) *Player {
return &Player{
speed: speed,
}
}
func main() {
p := NewPlayer(0.5)
p.MoveTo(Vec2{3, 1})
for !p.IsArrived() {
p.Update()
fmt.Println(p.Pos())
}
}
{0.47434163 0.15811388}
{0.94868326 0.31622776}
{1.4230249 0.47434163}
{1.8973665 0.6324555}
{2.3717082 0.7905694}
{2.8460498 0.94868326}