util.dart 4.61 KB
Newer Older
1 2 3 4
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

5
part of flutter_sprites;
6

7 8 9 10 11

math.Random _random = new math.Random();

// Random methods

12
/// Returns a random [double] in the range of 0.0 to 1.0.
13 14 15 16
double randomDouble() {
  return _random.nextDouble();
}

17
/// Returns a random [double] in the range of -1.0 to 1.0.
18 19 20 21
double randomSignedDouble() {
  return _random.nextDouble() * 2.0 - 1.0;
}

22
/// Returns a random [int] from 0 to max - 1.
23 24 25 26
int randomInt(int max) {
  return _random.nextInt(max);
}

27
/// Returns either [true] or [false] in a most random fashion.
Viktor Lidholt's avatar
Viktor Lidholt committed
28 29 30 31
bool randomBool() {
  return _random.nextDouble() < 0.5;
}

32 33
// atan2

34
class _Atan2Constants {
35

36
  _Atan2Constants() {
37 38
    for (int i = 0; i <= size; i++) {
      double f = i.toDouble() / size.toDouble();
39 40 41 42 43 44 45 46
      ppy[i] = math.atan(f) * stretch / math.PI;
      ppx[i] = stretch * 0.5 - ppy[i];
      pny[i] = -ppy[i];
      pnx[i] = ppy[i] - stretch * 0.5;
      npy[i] = stretch - ppy[i];
      npx[i] = ppy[i] + stretch * 0.5;
      nny[i] = ppy[i] - stretch;
      nnx[i] = -stretch * 0.5 - ppy[i];
47 48 49
    }
  }

50 51
  static const int size = 1024;
  static const double stretch = math.PI;
52

53 54 55 56 57 58 59 60 61 62 63 64
  static const int ezis = -size;

  final Float64List ppy = new Float64List(size + 1);
  final Float64List ppx = new Float64List(size + 1);
  final Float64List pny = new Float64List(size + 1);
  final Float64List pnx = new Float64List(size + 1);
  final Float64List npy = new Float64List(size + 1);
  final Float64List npx = new Float64List(size + 1);
  final Float64List nny = new Float64List(size + 1);
  final Float64List nnx = new Float64List(size + 1);
}

65 66
/// Provides convenience methods for calculations often carried out in graphics.
/// Some of the methods are returning approximations.
67 68 69
class GameMath {
  static final _Atan2Constants _atan2 = new _Atan2Constants();

70 71
  /// Returns the angle of two vector components. The result is less acurate
  /// than the standard atan2 function in the math package.
72
  static double atan2(double y, double x) {
73 74 75
    if (x >= 0) {
      if (y >= 0) {
        if (x >= y)
76
          return _atan2.ppy[(_Atan2Constants.size * y / x + 0.5).toInt()];
77
        else
78
          return _atan2.ppx[(_Atan2Constants.size * x / y + 0.5).toInt()];
79 80
      } else {
        if (x >= -y)
81
          return _atan2.pny[(_Atan2Constants.ezis * y / x + 0.5).toInt()];
82
        else
83
          return _atan2.pnx[(_Atan2Constants.ezis * x / y + 0.5).toInt()];
84 85 86 87
      }
    } else {
      if (y >= 0) {
        if (-x >= y)
88
          return _atan2.npy[(_Atan2Constants.ezis * y / x + 0.5).toInt()];
89
        else
90
          return _atan2.npx[(_Atan2Constants.ezis * x / y + 0.5).toInt()];
91 92
      } else {
        if (x <= y)
93
          return _atan2.nny[(_Atan2Constants.size * y / x + 0.5).toInt()];
94
        else
95
          return _atan2.nnx[(_Atan2Constants.size * x / y + 0.5).toInt()];
96 97 98
      }
    }
  }
99

100 101 102
  /// Approximates the distance between two points. The returned value can be
  /// up to 6% wrong in the worst case.
  static double distanceBetweenPoints(Point a, Point b) {
103 104 105 106 107 108 109 110 111 112 113 114
    double dx = a.x - b.x;
    double dy = a.y - b.y;
    if (dx < 0.0) dx = -dx;
    if (dy < 0.0) dy = -dy;
    if (dx > dy) {
      return dx + dy/2.0;
    }
    else {
      return dy + dx/2.0;
    }
  }

115 116
  /// Interpolates a [double] between [a] and [b] according to the
  /// [filterFactor], which should be in the range of 0.0 to 1.0.
117 118 119
  static double filter (double a, double b, double filterFactor) {
      return (a * (1-filterFactor)) + b * filterFactor;
  }
120

121 122
  /// Interpolates a [Point] between [a] and [b] according to the
  /// [filterFactor], which should be in the range of 0.0 to 1.0.
123 124 125
  static Point filterPoint(Point a, Point b, double filterFactor) {
    return new Point(filter(a.x, b.x, filterFactor), filter(a.y, b.y, filterFactor));
  }
126

127 128 129
  /// Returns the intersection between two line segmentss defined by p0, p1 and
  /// q0, q1. If the lines are not intersecting null is returned.
  static Point lineIntersection(Point p0, Point p1, Point q0, Point q1) {
130 131
    double epsilon = 1e-10;

132 133 134
    Vector2 r = new Vector2(p1.x - p0.x, p1.y - p0.y);
    Vector2 s = new Vector2(q1.x - q0.x, q1.y - q0.y);
    Vector2 qp = new Vector2(q0.x - p0.x, q0.y - p0.y);
135 136 137 138 139 140 141 142 143 144 145 146

    double rxs = cross2(r, s);

    if (rxs.abs() < epsilon) {
      // The lines are linear or collinear
      return null;
    }

    double t = cross2(qp, s) / rxs;
    double u = cross2(qp, r) / rxs;

    if ((0.0 <= t && t <= 1.0) && (0.0 <= u && u <= 1.0)) {
147
      return new Point(p0.x + t * r.x, p0.y + t * r.y);
148 149 150 151 152
    }

    // No intersection between the lines
    return null;
  }
153
}