A rendering engine library for Go supporting both SDL2 and WebAssembly (HTML Canvas) targets.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

122 lines
2.6 KiB

  1. package render
  2. import (
  3. "fmt"
  4. "strconv"
  5. "strings"
  6. )
  7. // Point holds an X,Y coordinate value.
  8. type Point struct {
  9. X int
  10. Y int
  11. }
  12. // Common points.
  13. var (
  14. Origin Point
  15. )
  16. // NewPoint makes a new Point at an X,Y coordinate.
  17. func NewPoint(x, y int) Point {
  18. return Point{
  19. X: x,
  20. Y: y,
  21. }
  22. }
  23. func (p Point) String() string {
  24. return fmt.Sprintf("%d,%d", p.X, p.Y)
  25. }
  26. // ParsePoint to parse a point from its string representation.
  27. func ParsePoint(v string) (Point, error) {
  28. halves := strings.Split(v, ",")
  29. if len(halves) != 2 {
  30. return Point{}, fmt.Errorf("'%s': not a valid coordinate string", v)
  31. }
  32. x, errX := strconv.Atoi(halves[0])
  33. y, errY := strconv.Atoi(halves[1])
  34. if errX != nil || errY != nil {
  35. return Point{}, fmt.Errorf("invalid coordinate string (X: %v; Y: %v)",
  36. errX,
  37. errY,
  38. )
  39. }
  40. return Point{
  41. X: int(x),
  42. Y: int(y),
  43. }, nil
  44. }
  45. // IsZero returns if the point is the zero value.
  46. func (p Point) IsZero() bool {
  47. return p.X == 0 && p.Y == 0
  48. }
  49. // Inside returns whether the Point falls inside the rect.
  50. //
  51. // NOTICE: the W and H are zero-relative, so a 100x100 box at coordinate
  52. // X,Y would still have W,H of 100.
  53. func (p Point) Inside(r Rect) bool {
  54. var (
  55. x1 = r.X
  56. y1 = r.Y
  57. x2 = r.X + r.W
  58. y2 = r.Y + r.H
  59. )
  60. return ((p.X >= x1 && p.X <= x2) &&
  61. (p.Y >= y1 && p.Y <= y2))
  62. }
  63. // Add (or subtract) the other point to your current point.
  64. func (p *Point) Add(other Point) {
  65. p.X += other.X
  66. p.Y += other.Y
  67. }
  68. // Subtract the other point from your current point.
  69. func (p *Point) Subtract(other Point) {
  70. p.X -= other.X
  71. p.Y -= other.Y
  72. }
  73. // Compare the point to another, returning a delta coordinate.
  74. //
  75. // If the two points are equal the result has X=0 Y=0. Otherwise the X and Y
  76. // return values will be positive or negative numbers of how you could modify
  77. // the current Point to be equal to the other.
  78. func (p *Point) Compare(other Point) Point {
  79. return Point{
  80. X: other.X - p.X,
  81. Y: other.Y - p.Y,
  82. }
  83. }
  84. // MarshalText to convert the point into text so that a render.Point may be used
  85. // as a map key and serialized to JSON.
  86. func (p *Point) MarshalText() ([]byte, error) {
  87. return []byte(fmt.Sprintf("%d,%d", p.X, p.Y)), nil
  88. }
  89. // UnmarshalText to restore it from text.
  90. func (p *Point) UnmarshalText(b []byte) error {
  91. halves := strings.Split(strings.Trim(string(b), `"`), ",")
  92. if len(halves) != 2 {
  93. return fmt.Errorf("'%s': not a valid coordinate string", b)
  94. }
  95. x, errX := strconv.Atoi(halves[0])
  96. y, errY := strconv.Atoi(halves[1])
  97. if errX != nil || errY != nil {
  98. return fmt.Errorf("Point.UnmarshalJSON: Atoi errors (X=%s Y=%s)",
  99. errX,
  100. errY,
  101. )
  102. }
  103. p.X = int(x)
  104. p.Y = int(y)
  105. return nil
  106. }