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 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 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 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 LinkedList<Vector> multiIntersect(Ray ray) { var intersections = new LinkedList<Vector>(); var rays = new LinkedList<Ray>(); var arcs = new LinkedList<Arc>(); getEdges(rays, arcs); foreach (var side in rays) { var sideIntersection = ray.intersect(side); if (sideIntersection != null) { intersections.AddLast(sideIntersection ?? new Vector()); } } foreach (var arc in arcs) { var arcIntersections = arc.multiIntersect(ray); if (arcIntersections != null) { foreach (var inters in arcIntersections) { intersections.AddLast(inters); } } } return intersections; }
void getEdges(LinkedList<Ray> rays, LinkedList<Arc> arcs) { foreach (AxisDirection dir in Enum.GetValues(typeof(AxisDirection))) { if (!canGoInDirection(dir)) { var sideCenter = center + new Vector(dir) * (Constants.tileSize * 0.5 - Constants.roadMargin); var sideHalfLength = (Constants.tileSize * 0.5 - Constants.roadMargin * 2); var side = Ray.line( sideCenter + new Vector(dir.turnLeft()) * sideHalfLength, sideCenter + new Vector(dir.turnRight()) * sideHalfLength ); rays.AddLast(side); } var nextDir = dir.turnLeft(); if (!canGoInDirection(dir) && !canGoInDirection(nextDir)) { var arcCenter = center + (new Vector(dir) + new Vector(nextDir)) * (Constants.tileSize * 0.5 - Constants.roadMargin * 2); var arc = new Arc(arcCenter, Constants.roadMargin, nextDir.angle(), dir.angle()); arcs.AddLast(arc); } else if (canGoInDirection(dir) && canGoInDirection(nextDir)) { var arcCenter = center + (new Vector(dir) + new Vector(nextDir)) * (Constants.tileSize * 0.5); var arc = new Arc(arcCenter, Constants.roadMargin, nextDir.back().angle(), dir.back().angle()); arcs.AddLast(arc); } else if (!canGoInDirection(dir) && canGoInDirection(nextDir)) { var lineFrom = center + (new Vector(dir) + new Vector(nextDir)) * (Constants.tileSize * 0.5); lineFrom = lineFrom - (new Vector(dir) * Constants.roadMargin); var side = new Ray(lineFrom, new Vector(nextDir.back()) * Constants.roadMargin * 2); rays.AddLast(side); } else if (canGoInDirection(dir) && !canGoInDirection(nextDir)) { var lineFrom = center + (new Vector(dir) + new Vector(nextDir)) * (Constants.tileSize * 0.5); lineFrom = lineFrom - (new Vector(nextDir) * Constants.roadMargin); var side = new Ray(lineFrom, new Vector(dir.back()) * Constants.roadMargin * 2); rays.AddLast(side); } } }
public Vector? intersect(Ray ray) { var intersections = multiIntersect(ray); if (intersections.Count == 0) return null; Vector? vec = null; var dist = double.MaxValue; foreach (var intersection in intersections) { var curDist = (intersection - ray.position).length; if (curDist < dist) { dist = curDist; vec = intersection; } } return vec; }
public bool isIntersect(Ray ray) { var rays = new LinkedList<Ray>(); var arcs = new LinkedList<Arc>(); getEdges(rays, arcs); foreach (var side in rays) { var sideIntersection = ray.intersect(side); if (sideIntersection != null) { return true; } } foreach (var arc in arcs) { var arcIntersections = arc.multiIntersect(ray); if (arcIntersections != null) { return true; } } return false; }
public AxisDirection? borderAnyIntersectionDirection(Ray ray, AxisDirection? exceptDir = null) { foreach (AxisDirection dir in Enum.GetValues(typeof(AxisDirection))) { if (dir == exceptDir) continue; var side = lineForDirection(dir); if (ray.intersect(side) != null) { //(ray.intersect(side) ?? new Vector(0, 0)).draw(0xFF0000); return dir; } } return null; }
public Vector? intersect(Ray o) { var p = position; var r = direction; var q = o.position; var s = o.direction; if (r.cross (s) == 0) { return null; } else { var t = (q - p).cross(s) / r.cross(s); var u = -(p - q).cross(r) / r.cross(s); if (t >= 0 && t <= 1 && u >= 0 && u <= 1) { return p + t * r; } else { return null; } } }
public bool isIntersect(Ray ray) { foreach (AxisDirection dir in Enum.GetValues(typeof(AxisDirection))) { var edge = edgeInDirection(dir); if (ray.intersect(edge) != null) { return true; } } return false; }
public bool isIntersect(Ray ray) { var e = ray.position; var d = ray.direction; var f = e - position; var a = d * d; var b = 2 * (f * d); var c = (f * f) - radius * radius; var D = b * b - 4 * a * c; if (D < 0) return false; if (D == 0) { // impossible D = 0.00001; } var sD = Math.Sqrt(D); var a2 = a * 2; var t1 = (-b + sD) / a2; var t2 = (-b - sD) / a2; var p1 = ray.position + ray.direction * t1; var p2 = ray.position + ray.direction * t2; var havePoint1 = t1 >= 0 && t1 <= 1; var havePoint2 = t2 >= 0 && t2 <= 1; return havePoint1 || havePoint2; }
public Vector[] multiIntersect(Ray ray) { var e = ray.position; var d = ray.direction; var f = e - position; var a = d * d; var b = 2 * (f * d); var c = (f * f) - radius * radius; var D = b * b - 4 * a * c; if (D < 0) return null; if (D == 0) { // impossible D = 0.00001; } var sD = Math.Sqrt(D); var a2 = a * 2; var t1 = (-b + sD) / a2; var t2 = (-b - sD) / a2; var p1 = ray.position + ray.direction * t1; var p2 = ray.position + ray.direction * t2; var havePoint1 = t1 >= 0 && t1 <= 1 && isPointInArcSector(p1); var havePoint2 = t2 >= 0 && t2 <= 1 && isPointInArcSector(p2); if (havePoint1 && havePoint2) { return new Vector[] { p1, p2 }; } else if (havePoint1) { return new Vector[] { p1 }; } else if (havePoint2) { return new Vector[] { p2 }; } else { return null; } }