public void Update(double updateFactor) { if (speed.SumComponentSqrs() > 0.0D) position += speed * updateFactor; if (game.CarMovementAirFrictionFactor > 0) { double lastMovementTransferFactor = Math.Pow(1.0D - game.CarMovementAirFrictionFactor, updateFactor); speed *= lastMovementTransferFactor; } if (game.CarLengthwiseMovementFrictionFactor > 0.0D) { double velocityLength = speed.Magnitude; if (velocityLength > 0.0D) { double velocityChange = game.CarLengthwiseMovementFrictionFactor * updateFactor; if (velocityChange >= velocityLength) { speed = new Vector(0.0D, 0.0D); } else if (velocityChange > 0.0D) { speed *= (1.0D - velocityChange / velocityLength); } } } }
public override bool tryDrive(Vehicle vehicle, List<Tile> tilePath, Move move) { if (tilePath.Count < 4) return false; var current = MyStrategy.map.tileAt(vehicle.position); var currentToFirst = current.directionForTile(tilePath[0]).Value; var firstToSecond = tilePath[0].directionForTile(tilePath[1]).Value; var secondToThird = tilePath[1].directionForTile(tilePath[2]).Value; var thirdToFour = tilePath[2].directionForTile(tilePath[3]).Value; if (!currentToFirst.isSameAxis(firstToSecond)) return false; if (firstToSecond.isSameAxis(secondToThird)) return false; if (firstToSecond.back() != thirdToFour) return false; var turningFrom = new Vector(currentToFirst); var turningTo = new Vector(firstToSecond); move.EnginePower = 1; move.WheelTurn = vehicle.steeringAngleForDirection(vehicle.stabilizationDir(turningFrom, current.center, turningTo, -0.25 * Constants.tileSize)); if (vehicle.speed.length > 15) { move.IsBrake = true; } else { move.IsBrake = false; } return true; }
public DynamicState( Vector position, Vector velocity, Vector force, double angle, double angularVelocity, double torque) { this.velocity = velocity; this.force = force; this.angularVelocity = angularVelocity; this.torque = torque; }
public SimulatedPosition(Car self, Game game) { this.game = game; position = new Vector(self.X,self.Y); speed = new Vector(self.SpeedX,self.SpeedY); enginePower = self.EnginePower; }
public DynamicState(DynamicState state) { this.position = state.position; this.angle = state.angle; this.velocity = state.velocity; this.force = state.force; this.angularVelocity = state.angularVelocity; this.torque = state.torque; }
public Arc(Vector position, double _raduis, double fromAngle, double toAngle) : this() { while (fromAngle > Math.PI) fromAngle -= Math.PI * 2; while (fromAngle < -Math.PI) fromAngle += Math.PI * 2; while (toAngle > Math.PI) toAngle -= Math.PI * 2; while (toAngle < -Math.PI) toAngle += Math.PI * 2; this.position = position; this.radius = _raduis; this.fromAngle = fromAngle; this.toAngle = toAngle; }
public void setMedianVelocity(Vector medianVelocity) { currentState.medianVelocity = medianVelocity; }
public void setForce(Vector force) { currentState.force = force; }
public DynamicState() { this.velocity = new Vector(0.0D, 0.0D); this.medianVelocity = new Vector(0.0D, 0.0D); this.force = new Vector(0.0D, 0.0D); }
public static LinkedList<TilePathNode> findPathFromWaypoints(int[][] waypoints, RoadMap roadMap, Vector startPosition, Vector startForward, int skipWaypoints = 1) { var path = new LinkedList<TilePathNode>(); var lastTile = roadMap.tileAt(startPosition); for (int i = skipWaypoints, iend = waypoints.Length * 2 + 1; i < iend; ++i) { var currentTile = roadMap.tileAt(waypoints[i % waypoints.Length][0], waypoints[i % waypoints.Length][1]); Vector startDir; if (i == skipWaypoints) { //initial startDir = startForward; } else { startDir = new Vector(0, 0); } var mpath = findPathBetween(lastTile, currentTile, startDir); foreach (TilePathNode node in mpath) { path.AddLast(node); } if (path.Last != null) { var lastNode = path.Last.Value; lastNode.waypointIndex = i % waypoints.Length; path.Last.Value = lastNode; } lastTile = currentTile; } return path; }
public Ray(Vector position, Vector direction) : this() { this.position = position; this.direction = direction; }
public Rect(Vector a, Vector b) { min = new Vector(Math.Min(a.x, b.x), Math.Min(a.y, b.y)); max = new Vector(Math.Max(a.x, b.x), Math.Max(a.y, b.y)); }
public void setVelocity(Vector velocity) { currentState.velocity = velocity; }
public override bool tryDrive(Vehicle vehicle, List<Tile> tilePath, Move move) { if (tilePath.Count < 3) return false; var currentTile = MyStrategy.map.tileAt(vehicle.position); Vector turningTo; Vector turningFrom; { var firstToSecond = tilePath[0].directionForTile(tilePath[1]).Value; turningTo = new Vector(firstToSecond); if (firstToSecond != tilePath[1].directionForTile(tilePath[2])) { return false; } var currentToFirst = currentTile.directionForTile(tilePath[0]).Value; if (currentToFirst.isSameAxis(firstToSecond)) { return false; } turningFrom = new Vector(currentToFirst); } if (vehicle.speed.length > 10) { var innerSide1 = Ray.line( currentTile.center + turningTo * (Constants.tileSize * 0.5 - Constants.roadMargin) - turningFrom * Constants.tileSize * 0.5, currentTile.center + turningTo * (Constants.tileSize * 0.5 - Constants.roadMargin) + turningFrom * Constants.tileSize * 0.5 ); //innerSide1.draw(0x00FF00); var innerCircle = new Circle(currentTile.center + (turningTo + turningFrom) * Constants.tileSize * 0.5, Constants.roadMargin); //innerCircle.draw(0x00FF00); var innerCircleExtended = new Circle(innerCircle.position, innerCircle.radius + 10); var backWall = new Ray(tilePath[0].center + turningFrom * (Constants.tileSize * 0.5 - Constants.roadMargin) - turningTo * Constants.tileSize * 0.5, turningTo * Constants.tileSize * 2); //backWall.draw(0x00FF00); if (vehicle.forward * turningFrom > 0.45) { var vv = new VirtualVehicle(vehicle); var steering = Math.Sign(turningFrom.angleTo(turningTo)); for (int i = 0; i < 100; ++i) { vv.simulateTick(1.0, steering); if (vv.rect.isIntersect(innerSide1) || vv.rect.isIntersect(innerCircle)) { move.EnginePower = 1; move.WheelTurn = vehicle.steeringAngleForDirection(vehicle.stabilizationDir(turningFrom, currentTile.center, turningTo, -0.15 * Constants.tileSize)); move.IsBrake = false; return true; } if (vv.rect.isIntersect(backWall)) { move.IsBrake = true; move.EnginePower = 1; move.WheelTurn = steering; return true; } if (tilePath[1].rect.contains(vv.position)) { // защита от слишком быстрого захода в поворот и ударения в заднюю стенку for (int j = 0; j < 50; ++j) { vv.simulateTick(1, steering); if (vv.rect.isIntersect(backWall)) { move.EnginePower = 1; move.WheelTurn = steering; move.IsBrake = true; return true; } //vv.position.draw(0x00FF00); //vv.rect.draw(0x0000FF); } move.EnginePower = 1; move.WheelTurn = steering; move.IsBrake = false; return true; } //vv.position.draw(0xFF0000); //vv.rect.draw(0x0000FF); } } else if (vehicle.forward * turningTo > 0.5) { var vv = new VirtualVehicle(vehicle); var steering = Math.Sign(turningFrom.angleTo(turningTo)); for (int i = 0; i < 100; ++i) { vv.simulateTick(1.0, 0); if (vv.rect.isIntersect(innerSide1) || vv.rect.isIntersect(innerCircleExtended)) { move.EnginePower = 1; move.WheelTurn = -steering; move.IsBrake = false; return true; } if (tilePath[1].rect.contains(vv.position)) { move.EnginePower = 1; move.WheelTurn = 0; move.IsBrake = false; return true; } //vv.position.draw(0xFF0000); //vv.rect.draw(0x0000FF); } } else { move.IsBrake = true; move.WheelTurn = 0; move.EnginePower = 1; return true; } } move.IsBrake = false; move.EnginePower = 1; var turn = turningTo + turningFrom; move.WheelTurn = vehicle.steeringAngleForDirection(turn); return true; }
public Vector stabilizationDir(Vector baseDir, Vector sideCenter, Vector sideDir, double sidePosition) { var dist = (position - sideCenter) * sideDir + sidePosition; return baseDir - sideDir * dist / Constants.tileSize; }
public double cross(Vector o) { return x * o.y - y * o.x; }
public double angleTo(Vector o) { double relAngle = o.angle - angle; while (relAngle > Math.PI) relAngle -= 2 * Math.PI; while (relAngle < -Math.PI) relAngle += 2 * Math.PI; return relAngle; }
public static bool Equals(Vector a, Vector b) { const double E = 0.0001; return Math.Abs(a.x - b.x) < E && Math.Abs(a.y - b.y) < E; }
public bool contains(Vector point) { return point.x <= max.x && point.x >= min.x && point.y <= max.y && point.y >= min.y; }
public void setPosition(Vector position) { currentState.position = new Vector(position); }
public static Ray line(Vector p1, Vector p2) { return new Ray(p1, p2 - p1); }
public override bool tryDrive(Vehicle vehicle, List<Tile> tilePath, Move move) { if (tilePath.Count < 2) return false; var current = MyStrategy.map.tileAt(vehicle.position); var currentToFirst = current.directionForTile(tilePath[0]).Value; var firstToSecond = tilePath[0].directionForTile(tilePath[1]).Value; var secondToThird = tilePath[1].directionForTile(tilePath[2]).Value; if (currentToFirst.isSameAxis(firstToSecond)) return false; if (currentToFirst.back() != secondToThird) return false; var turningFrom = new Vector(currentToFirst); var turningTo = new Vector(firstToSecond); if (vehicle.speed.length > 10) { var steering = Math.Sign(turningFrom.angleTo(turningTo)); var backWall = new Ray( tilePath[0].center + turningFrom * (Constants.tileSize * 0.5 - Constants.roadMargin) - turningTo * Constants.tileSize * 0.5, turningTo * Constants.tileSize * 2 ); var backSideWall = new Ray( backWall.p2 - turningTo * Constants.roadMargin, -turningFrom * (Constants.tileSize - Constants.roadMargin) ); var innerWall = new Ray(current.center + turningTo * (Constants.tileSize * 0.5 - Constants.roadMargin) - turningFrom * Constants.tileSize * 0.5, turningFrom * Constants.tileSize); var innerCircle = new Circle(current.center + (new Vector(currentToFirst) + new Vector(firstToSecond)) * Constants.tileSize * 0.5, Constants.roadMargin); backWall.draw(0x00FF00); backSideWall.draw(0x00FF00); innerWall.draw(0x00FF00); innerCircle.draw(0x00FF00); var vv = new VirtualVehicle(vehicle); for (int i = 0; i < 100; ++i) { vv.simulateTick(0.5, steering); var rect = vv.rect; if (rect.isIntersect(innerWall) || rect.isIntersect(innerCircle)) { move.EnginePower = 1; move.WheelTurn = -steering; move.IsBrake = false; return true; } if (rect.isIntersect(backWall) || rect.isIntersect(backSideWall)) { move.IsBrake = false; move.EnginePower = -1; //move.WheelTurn = vehicle.steeringAngleForDirection(vehicle.stabilizationDir(turningFrom, current.center, turningTo, -0.25 * Constants.tileSize)); move.WheelTurn = steering; return true; } vv.position.draw(0xFF0000); vv.rect.draw(0x0000FF); } } move.EnginePower = 0.5; move.WheelTurn = vehicle.steeringAngleForDirection(vehicle.stabilizationDir(turningFrom, current.center, turningTo, -0.25 * Constants.tileSize)); move.IsBrake = false; return true; }
public double steeringAngleForDirection(Vector direction) { return forward.angleTo(direction) * 4 * Math.Sign(speed * forward); }
public double lineDistance(Vector p) { var p1 = this.p1; var p2 = this.p2; return Math.Abs((p2.y - p1.y) * p.x - (p2.x - p1.x) * p.y + p2.x * p1.y - p2.y * p1.x) / (p1 - p2).length; }
public override bool tryDrive(Vehicle vehicle, List<Tile> tilePath, Move move) { var current = MyStrategy.map.tileAt(vehicle.position); AxisDirection dir; { dir = current.directionForTile(tilePath[0]) ?? AxisDirection.up; for (int i = 1; i < 3 && i < tilePath.Count; ++i) { if (tilePath[i - 1].directionForTile(tilePath[i]) != dir) return false; } } var dirVec = new Vector(dir); var last = current; int lineTilesCtr = 0; foreach (var tile in tilePath) { if (dir.turnLeft() == last.directionForTile(tile)) { var turnVector = new Vector(dir.turnLeft()); var dist = (vehicle.position - current.center) * turnVector + 0.15 * Constants.tileSize; dirVec -= turnVector * dist / Constants.tileSize; break; } else if (dir.turnRight() == last.directionForTile(tile)) { var turnVector = new Vector(dir.turnRight()); var dist = (vehicle.position - current.center) * turnVector + 0.15 * Constants.tileSize; dirVec -= turnVector * dist / Constants.tileSize; break; } else if (dir != last.directionForTile(tile)) break; lineTilesCtr += 1; last = tile; } if (lineTilesCtr >= 8) { move.IsUseNitro = true; } if (vehicle.forward * dirVec > 0.3) { move.EnginePower = 1; move.WheelTurn = vehicle.steeringAngleForDirection(dirVec); } else { move.EnginePower = 0.2; move.WheelTurn = vehicle.steeringAngleForDirection(dirVec); } move.IsBrake = false; return true; }
public PathNode(Vector pos) { position = pos; importance = 0; }
public override bool tryDrive(Vehicle vehicle, List<Tile> tilePath, Move move) { if (tilePath.Count < 3) return false; var currentTile = MyStrategy.map.tileAt(vehicle.position); Vector target; Vector turningFrom; Vector turningTo; { var currentToFirst = currentTile.directionForTile(tilePath[0]).Value; var firstToSecond = tilePath[0].directionForTile(tilePath[1]).Value; var secondToThird = tilePath[1].directionForTile(tilePath[2]).Value; if (currentToFirst != secondToThird) { return false; } if (firstToSecond.isSameAxis(currentToFirst)) { return false; } turningFrom = new Vector(currentToFirst); turningTo = new Vector(firstToSecond); target = tilePath[2].center - turningFrom * 0.5 * Constants.tileSize; } var vehicleToTarget = target - vehicle.position; if (vehicle.speed.length > 10 && vehicle.forward * (turningFrom + turningTo) > 0) { var steering = Math.Sign(turningFrom.angleTo(turningTo)); Ray side = new Ray( tilePath[0].center - turningTo * (Constants.tileSize * 0.5 - Constants.roadMargin) - turningFrom * Constants.tileSize * 0.5, turningFrom * (Constants.tileSize - Constants.roadMargin) ); Ray back = new Ray(side.p2, turningTo * (Constants.tileSize - Constants.roadMargin)); Circle backCircle = new Circle(back.p2 + turningFrom * Constants.roadMargin, Constants.roadMargin); Ray innerSide = new Ray( currentTile.center + turningTo * (Constants.tileSize * 0.5 - Constants.roadMargin) - turningFrom * Constants.tileSize * 0.5, turningFrom * Constants.tileSize ); Circle innerCircle = new Circle(innerSide.p2 + turningTo * Constants.roadMargin, Constants.roadMargin); side.draw(0x00FF00); back.draw(0x00FF00); backCircle.draw(0x00FF00); innerSide.draw(0x00FF00); innerCircle.draw(0x00FF00); var vv = new VirtualVehicle(vehicle); for (int i = 0; i < 100; ++i) { vv.simulateTick(1.0, 0.0); var rect = vv.rect; if (rect.isIntersect(side) || rect.isIntersect(back) || rect.isIntersect(backCircle)) { vv = new VirtualVehicle(vehicle); for (int j = 0; j < 100; ++j) { vv.simulateTick(1, steering); if (rect.isIntersect(innerSide) || rect.isIntersect(innerCircle)) { move.EnginePower = 1; move.IsBrake = true; move.WheelTurn = steering; return true; } } move.EnginePower = 1; move.IsBrake = false; move.WheelTurn = steering; return true; } else if (rect.isIntersect(innerSide) || rect.isIntersect(innerCircle)) { vv = new VirtualVehicle(vehicle); for (int j = 0; j < 100; ++j) { vv.simulateTick(1, -steering); if (rect.isIntersect(innerSide) || rect.isIntersect(innerCircle)) { move.EnginePower = 1; move.IsBrake = true; move.WheelTurn = -steering; return true; } } move.EnginePower = 1; move.IsBrake = false; move.WheelTurn = -steering; return true; } if (tilePath[2].rect.contains(vv.position)) { move.EnginePower = 1; move.IsBrake = false; move.WheelTurn = vehicle.steeringAngleForDirection(vehicleToTarget); return true; } rect.draw(0x0000FF); vv.position.draw(0xFF0000); } move.EnginePower = 1; move.IsBrake = false; move.WheelTurn = vehicle.steeringAngleForDirection(vehicleToTarget); //new Ray(vehicle.position, vehicleToTarget).draw(0x00FFFF); return true; } if (vehicle.forward * vehicleToTarget < 0.5) { if (vehicle.speed.length > 10) { move.IsBrake = true; } move.EnginePower = 0.3; } else { move.EnginePower = 1; } move.WheelTurn = vehicle.steeringAngleForDirection(vehicleToTarget); move.IsBrake = false; return true; }
public PathNode(Vector pos, double importance) { position = pos; this.importance = importance; }
public override bool tryDrive(Vehicle vehicle, List<Tile> tilePath, Move move) { if (tilePath.Count < 3) return false; var currentTile = MyStrategy.map.tileAt(vehicle.position); Vector turningTo; Vector turningFrom; { var currentToFirst = currentTile.directionForTile(tilePath[0]).Value; var firstToSecond = tilePath[0].directionForTile(tilePath[1]).Value; var secondToThird = tilePath[1].directionForTile(tilePath[2]).Value; if (currentToFirst != firstToSecond) return false; if (firstToSecond.isSameAxis(secondToThird)) return false; if (tilePath.Count >= 4) { if (tilePath[2].directionForTile(tilePath[3]).Value.back() == currentToFirst) return false; } turningFrom = new Vector(currentToFirst); turningTo = new Vector(secondToThird); } if (vehicle.speed.length > 10 && vehicle.forward * turningFrom > 0.45) { var vv = new VirtualVehicle(vehicle); var steering = Math.Sign(turningFrom.angleTo(turningTo)); var innerSide1 = Ray.line( currentTile.center + turningTo * (Constants.tileSize * 0.5 - Constants.roadMargin) - turningFrom * Constants.tileSize * 0.5, currentTile.center + turningTo * (Constants.tileSize * 0.5 - Constants.roadMargin) + turningFrom * Constants.tileSize * 0.5 ); //innerSide1.draw(0x00FF00); var innerSide2 = new Ray(innerSide1.position + turningFrom * Constants.tileSize, innerSide1.direction); //innerSide2.draw(0x00FF00); var innerCircle = new Circle(currentTile.center + (turningTo + turningFrom) * Constants.tileSize * 0.5 + turningFrom * Constants.tileSize, Constants.roadMargin); //innerCircle.draw(0x00FF00); var backWall = new Ray(tilePath[1].center + turningFrom * (Constants.tileSize * 0.5 - Constants.roadMargin) - turningTo * (Constants.tileSize * 0.5), turningTo * 2 * Constants.tileSize); //backWall.draw(0x00FF00); var outerSide = new Ray(currentTile.center - turningTo * (Constants.halfTileSize - Constants.roadMargin) - turningFrom * Constants.halfTileSize, turningFrom * Constants.tileSize * 3); //outerSide.draw(0x00FF00); for (int i = 0; i < 100; ++i) { vv.simulateTick(1.0, steering); if (vv.rect.isIntersect(innerSide1) || vv.rect.isIntersect(innerSide2)) break; if (vv.rect.isIntersect(innerCircle)) break; if (vv.rect.isIntersect(outerSide)) { var target = currentTile.center + turningFrom * Constants.tileSize * 1.5; move.WheelTurn = steering; move.EnginePower = 1; move.IsBrake = true; return true; } if (vv.rect.isIntersect(backWall)) { move.EnginePower = 1; move.WheelTurn = steering; move.IsBrake = true; return true; } if (tilePath[2].rect.contains(vv.position)) { // защита от слишком быстрого захода в поворот и ударения в заднюю стенку for (int j = 0; j < 50; ++j) { vv.simulateTick(1, steering); if (vv.rect.isIntersect(backWall)) { move.EnginePower = 1; move.WheelTurn = steering; move.IsBrake = true; return true; } //vv.position.draw(0x00FF00); //vv.rect.draw(0x0000FF); } move.EnginePower = 1; move.WheelTurn = steering; move.IsBrake = false; return true; } //vv.position.draw(0xFF0000); //vv.rect.draw(0x0000FF); } } move.WheelTurn = vehicle.steeringAngleForDirection((currentTile.center + turningFrom * Constants.tileSize * 1.5) - vehicle.position); move.EnginePower = 1; move.IsBrake = false; return true; }
public static LinkedList<TilePathNode> findPathBetween(Tile from, Tile to, Vector startDirection) { var roadMap = from.roadMap; var cost = new double[roadMap.width, roadMap.height]; for (int x = 0; x < roadMap.width; ++x) { for (int y = 0; y < roadMap.height; ++y) { cost[x, y] = double.MaxValue; } } var backDir = new AxisDirection[roadMap.width, roadMap.height]; var speedDir = new Vector[roadMap.width, roadMap.height]; var queue = new Queue<Tile>(); queue.Enqueue(from); cost[from.posX, from.posY] = 0; speedDir[from.posX, from.posY] = startDirection; while (queue.Count > 0) { var current = queue.Dequeue(); foreach (AxisDirection dir in Enum.GetValues(typeof(AxisDirection))) { if (current.canGoInDirection(dir)) { var next = current.nextTileInDirection(dir); if (next != null) { double nextCost = cost[current.posX, current.posY] + 1; if (speedDir[current.posX, current.posY] * new Vector(dir) < 0.01) nextCost += 1; if (cost[next.posX, next.posY] > nextCost) { cost[next.posX, next.posY] = nextCost; backDir[next.posX, next.posY] = dir.back(); speedDir[next.posX, next.posY] = new Vector(dir); if (!queue.Contains(next)) queue.Enqueue(next); } } } } } var list = new LinkedList<TilePathNode>(); { var current = to; if (cost[to.posX, to.posY] == -1) return list; // SHEEIT, UNKNOWN TILES while (current != from) { list.AddFirst(new TilePathNode(current)); current = current.nextTileInDirection(backDir[current.posX, current.posY]); if (current == null) return list; } } return list; }