Exemple #1
0
    public FP.Vector vecStart; // if rotation is later implemented, can store it in z value

    #endregion Fields

    #region Constructors

    public Move(long timeStartVal, long timeEndVal, FP.Vector vecStartVal, FP.Vector vecEndVal)
    {
        timeStart = timeStartVal;
        timeEnd = timeEndVal;
        vecStart = vecStartVal;
        vecEnd = vecEndVal;
    }
    public FP.Vector pos; // where to move to

    #endregion Fields

    #region Constructors

    public MoveCmdEvt(long timeVal, long timeCmdVal, Dictionary<int, int[]> pathsVal, FP.Vector posVal, Formation formationVal, bool autoTimeTravelVal)
        : base(timeVal, timeCmdVal, pathsVal)
    {
        pos = posVal;
        formation = formationVal;
        autoTimeTravel = autoTimeTravelVal;
    }
 public MakeUnitCmdEvt(long timeVal, long timeCmdVal, Dictionary<int, int[]> pathsVal, int typeVal, FP.Vector posVal, bool autoTimeTravelVal, bool autoRepeatVal = false)
     : base(timeVal, timeCmdVal, pathsVal)
 {
     type = typeVal;
     pos = posVal;
     autoTimeTravel = autoTimeTravelVal;
     autoRepeat = autoRepeatVal;
 }
Exemple #4
0
 /// <summary>
 /// returns where new unit of specified type can move out of the way after specified path makes it
 /// </summary>
 /// <remarks>chooses a random location between makeUnitMinDist and makeUnitMaxDist away from path</remarks>
 private FP.Vector makeUnitMovePos(long time, Path path, UnitType type)
 {
     FP.Vector ret;
     do {
         ret = new FP.Vector((long)((UnityEngine.Random.value - 0.5) * type.makeUnitMaxDist * 2),
             (long)((UnityEngine.Random.value - 0.5) * type.makeUnitMaxDist * 2));
     } while (ret.lengthSq() < type.makeUnitMinDist * type.makeUnitMinDist
         || ret.lengthSq() > type.makeUnitMaxDist * type.makeUnitMaxDist);
     return ret + path.posWhen(time);
 }
Exemple #5
0
 /// <summary>
 /// returns where new path with specified units can move out of the way after specified path makes it
 /// </summary>
 /// <remarks>chooses a random location between makePathMinDist() and makePathMaxDist() away from path</remarks>
 private FP.Vector makePathMovePos(long time, Path path, List<Unit> units)
 {
     long makePathMinDist = path.makePathMinDist (time, units);
     long makePathMaxDist = path.makePathMaxDist (time, units);
     FP.Vector ret;
     do {
         ret = new FP.Vector((long)((UnityEngine.Random.value - 0.5) * makePathMaxDist * 2),
             (long)((UnityEngine.Random.value - 0.5) * makePathMaxDist * 2));
     } while (ret.lengthSq() < makePathMinDist * makePathMinDist
         || ret.lengthSq() > makePathMaxDist * makePathMaxDist);
     return ret + path.posWhen(time);
 }
 public override void apply(Sim g)
 {
     Dictionary<Path, List<Unit>> exPaths = existingPaths (g);
     List<List<Path>> formationOrder = new List<List<Path>>();
     List<int> nSeeUnits = new List<int>();
     FP.Vector goal, rows = new FP.Vector(), offset = new FP.Vector();
     long spacing = 0;
     // order paths in formation
     foreach (KeyValuePair<Path, List<Unit>> path in exPaths) {
         if (path.Key.canMove(timeCmd, path.Value)) {
             int i;
             for (i = 0; i < formationOrder.Count; i++) {
                 if (path.Key.moves.Last ().vecEnd.x == formationOrder[i][0].moves.Last ().vecEnd.x
                     && path.Key.moves.Last ().vecEnd.y == formationOrder[i][0].moves.Last ().vecEnd.y) {
                     SimEvt evt = g.events.FindLast (e => e is StackEvt && (e as StackEvt).paths.Contains (path.Key)
                         && formationOrder[i].Find (p => (e as StackEvt).paths.Contains (p)) != null);
                     if (evt != null) {
                         // path is trying to stack onto another commanded path
                         formationOrder[i].Add (path.Key);
                         nSeeUnits[i] = (evt as StackEvt).nSeeUnits;
                         break;
                     }
                 }
             }
             if (i == formationOrder.Count) {
                 // path isn't trying to stack onto another commanded path
                 formationOrder.Add (new List<Path> { path.Key });
                 nSeeUnits.Add (int.MaxValue);
             }
             if (formation == Formation.Tight) {
                 // calculate spacing for tight formation
                 foreach (Unit unit in path.Value) {
                     if (unit.type.tightFormationSpacing > spacing) spacing = unit.type.tightFormationSpacing;
                 }
             }
         }
     }
     if (formationOrder.Count == 0) return;
     // calculate spacing
     // (if tight formation, then spacing was already calculated above)
     // ISSUE #28: loose formation should be triangular
     if (formation == Formation.Loose) {
         spacing = FP.mul(g.visRadius, FP.sqrt2) >> FP.precision << FP.precision;
     } else if (formation == Formation.Ring) {
         spacing = (g.visRadius * 2 >> FP.precision) - 1 << FP.precision;
     }
     if (formation == Formation.Tight || formation == Formation.Loose) {
         rows.x = FP.sqrt(formationOrder.Count);
         rows.y = (formationOrder.Count - 1) / rows.x + 1;
         offset = (rows - new FP.Vector(1, 1)) * spacing / 2;
     } else if (formation == Formation.Ring) {
         offset.x = (formationOrder.Count == 1) ? 0 : FP.div(spacing / 2, FP.sin(FP.pi / formationOrder.Count));
         offset.y = offset.x;
     } else {
         throw new NotImplementedException("requested formation is not implemented");
     }
     if (pos.x < Math.Min(offset.x, g.mapSize / 2)) pos.x = Math.Min(offset.x, g.mapSize / 2);
     if (pos.x > g.mapSize - Math.Min(offset.x, g.mapSize / 2)) pos.x = g.mapSize - Math.Min(offset.x, g.mapSize / 2);
     if (pos.y < Math.Min(offset.y, g.mapSize / 2)) pos.y = Math.Min(offset.y, g.mapSize / 2);
     if (pos.y > g.mapSize - Math.Min(offset.y, g.mapSize / 2)) pos.y = g.mapSize - Math.Min(offset.y, g.mapSize / 2);
     // move units
     for (int i = 0; i < formationOrder.Count; i++) {
         List<Path> movedPaths = new List<Path>();
         foreach (Path path in formationOrder[i]) {
             if (formation == Formation.Tight || formation == Formation.Loose) {
                 goal = pos + new FP.Vector((i % rows.x) * spacing - offset.x, i / rows.x * spacing - offset.y);
             } else if (formation == Formation.Ring) {
                 goal = pos + offset.x * new FP.Vector(FP.cos(2 * FP.pi * i / formationOrder.Count), FP.sin(2 * FP.pi * i / formationOrder.Count));
             } else {
                 throw new NotImplementedException("requested formation is not implemented");
             }
             movedPaths.Add (path.moveTo(timeCmd, new List<Unit>(exPaths[path]), goal, autoTimeTravel));
         }
         g.addStackEvts (movedPaths, nSeeUnits[i]);
     }
 }
Exemple #7
0
 public void exclusiveAdd(Player player, long time)
 {
     if (exclusiveLatest (player)) throw new InvalidOperationException("tile is already exclusive");
     exclusive[player.id].Add (time);
     // add waypoints to let units that can move to adjacent tile (using automatic time travel) move to this tile
     for (int tX = Math.Max (0, x - 1); tX <= Math.Min (g.tileLen () - 1, x + 1); tX++) {
         for (int tY = Math.Max (0, y - 1); tY <= Math.Min (g.tileLen () - 1, y + 1); tY++) {
             if (tX != x || tY != y) {
                 foreach (var waypoint in g.tiles[tX, tY].waypoints) {
                     long halfMoveInterval = new FP.Vector(tX - x << FP.precision, tY - y << FP.precision).length() / g.units[waypoint.Key].type.speed / 2;
                     if (player == g.units[waypoint.Key].player && Waypoint.active (waypoint.Value.Last ())
                         && time >= waypoint.Value.Last ().time + halfMoveInterval) {
                         g.events.addEvt (new WaypointAddEvt(time + halfMoveInterval, g.units[waypoint.Key], this, waypoint.Value.Last (), null));
                     }
                 }
             }
         }
     }
 }
Exemple #8
0
 /// <summary>
 /// returns minimum absolute position where clicking would select the path
 /// </summary>
 public FP.Vector selMinPos(long time)
 {
     FP.Vector ret = new FP.Vector(int.MaxValue, int.MaxValue);
     foreach (Unit unit in segmentWhen(time).units) {
         ret.x = Math.Min (ret.x, unit.type.selMinPos.x);
         ret.y = Math.Min (ret.y, unit.type.selMinPos.y);
     }
     return ret + posWhen(time);
 }