如何在屏幕坐标上使用trig来计算点之间的角度

时间:2015-11-22 15:22:17

标签: math go trigonometry

我正在开发一款游戏。这个游戏是自上而下的,实时的,并且必须以路径为特色。我的游戏必须计算玩家当前位置与他们点击步行之间的角度 问题是,我正在使用屏幕坐标,因为在" x增加到右边,y增加到底部"

我在这里使用了一些代码

package main

import (
  "fmt"
  "math"
)

func main() {
  position1 := &Position{550, 200}
  position2 := &Position{700, 500}
  vector1 := CreatePathVector(position1, position2, 50)

  fmt.Printf("position1: %v\nposition2: %v\n", position1, position2)

  position := position1
  for i := 0; i < 5; i++ {
    position = position.Add(vector1)
    fmt.Printf("next position: %v\n", position)
  }

  position3 := &Position{400, 500}
  position4 := &Position{700, 400}
  vector2 := CreatePathVector(position3, position4, 50)

  fmt.Printf("position3: %v\nposition4: %v\n", position3, position4)

  position = position3
  for i := 0; i < 5; i++ {
    position = position.Add(vector2)
    fmt.Printf("next position: %v\n", position)
  }
}

type Position struct {
  X float64
  Y float64
}

type Vector struct {
  Radians  float64
  Distance float64
}

func CreatePathVector(pos1 *Position, pos2 *Position, speed int) *Vector {
  ydiff := pos2.Y - pos1.Y
  xdiff := pos2.X - pos1.X
  radians := math.Atan2(ydiff, xdiff)

  return &Vector{
    Radians:  radians,
    Distance: float64(speed),
  }
}

func (p *Position) Add(v *Vector) *Position {
  return &Position{
    X: p.X + math.Sin(v.Radians)*v.Distance,
    Y: p.Y + math.Cos(v.Radians)*v.Distance,
  }
}

这是输出

position1: &{550 200}
position2: &{700 500}
next position: &{594.7213595499958 222.3606797749979}
next position: &{639.4427190999916 244.72135954999578}
next position: &{684.1640786499873 267.0820393249937}
next position: &{728.8854381999831 289.44271909999156}
next position: &{773.6067977499789 311.80339887498945}
position3: &{400 500}
position4: &{700 400}
next position: &{384.1886116991581 547.4341649025257}
next position: &{368.37722339831623 594.8683298050514}
next position: &{352.56583509747435 642.3024947075771}
next position: &{336.75444679663246 689.7366596101028}
next position: &{320.9430584957906 737.1708245126285}

正如您所看到的,在两个示例中,重复添加矢量的步骤并未转向目的地

1 个答案:

答案 0 :(得分:3)

如果您选择使用我在评论中建议的笛卡尔坐标,那么这就是您的代码的样子:

package main

import (
  "fmt"
  "math"
)

func main() {
  position1 := &Position{550, 200}
  position2 := &Position{700, 500}
  vector1 := CreatePathVector(position1, position2, 70)

  fmt.Printf("position1: %v\nposition2: %v\n", position1, position2)

  position := position1
  for i := 0; i < 5; i++ {
    position = position.Add(vector1)
    fmt.Printf("next position: %v\n", position)
  }

  position3 := &Position{400, 500}
  position4 := &Position{700, 400}
  vector2 := CreatePathVector(position3, position4, 50)

  fmt.Printf("position3: %v\nposition4: %v\n", position3, position4)

  position = position3
  for i := 0; i < 5; i++ {
    position = position.Add(vector2)
    fmt.Printf("next position: %v\n", position)
  }
}

type Position struct {
  X float64
  Y float64
}

type Vector struct {
  dX  float64
  dY float64
}

func CreatePathVector(pos1 *Position, pos2 *Position, speed int) *Vector {
  ydiff := pos2.Y - pos1.Y
  xdiff := pos2.X - pos1.X
  mag := math.Sqrt(xdiff*xdiff+ydiff*ydiff)


  return &Vector{
    dX:  xdiff/mag*float64(speed),
    dY:  ydiff/mag*float64(speed),
  }
}

func (p *Position) Add(v *Vector) *Position {
  return &Position{
    X: p.X + v.dX,
    Y: p.Y + v.dY,
  }
}

如果您想坚持角度,只需切换Cos中的SinAdd即可。这是因为屏幕的方向无关紧要:如果您从t = arctan(y/x)开始y,则会从sin(t)返回x而从cos(t)返回x,无论是什么yfunc (p *Position) Add(v *Vector) *Position { return &Position{ X: p.X + math.Cos(v.Radians)*v.Distance, Y: p.Y + math.Sin(v.Radians)*v.Distance, } } 代表。所以添加应该是这样的:

match

我之前做过小游戏,我也试过用角度来移动。我的建议是不要尝试。如果你想为你的游戏添加更逼真的物理,矢量和线性代数将是你最好的朋友。在我看来,角度和三角形太乱了。