private void avoidSideCrash(Move moveResult, Vector needDirAngle = null) { HashSet <IPhysicEvent> events = calculateAvoidMapCrashEvents(moveResult); IPhysicEvent passageLine = events.ComeContaints(PhysicEventType.PassageLine) ? events.GetEvent(PhysicEventType.PassageLine) : null; IPhysicEvent mapCrash = events.ComeContaints(PhysicEventType.MapCrash) ? events.GetEvent(PhysicEventType.MapCrash) : null; IPhysicEvent objectsCrash = events.ComeContaints(PhysicEventType.ObjectsCrash) ? events.GetEvent(PhysicEventType.ObjectsCrash) : null; IPhysicEvent crash = (null != objectsCrash && objectsCrash.TickCome > 1) ? objectsCrash : mapCrash; if (null != crash) { int tickToPassageLine = (null != passageLine) ? passageLine.TickCome : maxIterationCount; if (crash.TickCome < tickToPassageLine) { Vector dir = new Vector(dirMove.X, dirMove.Y); PCar physicCar = crash.CarCome; Tuple <Vector, Vector> crashInfo = crash.infoCome as Tuple <Vector, Vector>; Logger.instance.Assert(null != crashInfo, "Can't get crash info"); Vector sideNormal = crashInfo.Item2; double angle = dir.Angle.AngleDeviation(sideNormal.Angle); if (Vector.sincos(car.Angle).Dot(dir) > 0 || 0 == angle) { angle = car.Angle.AngleDeviation(sideNormal.Angle); } bool notCurrentTurnSide = null != needDirAngle && sideNormal.Dot(needDirAngle) > 0; if (!checkStrongParallel(crash) || notCurrentTurnSide) { moveResult.WheelTurn = car.WheelTurn - speedSign * Math.Sign(angle) * game.CarWheelTurnChangePerTick; } bool isParallel = Vector.sincos(car.Angle).Dot(sideNormal).LessDotWithAngle(Math.PI / 9); //20 degrees isParallel |= physicCar.Dir.Dot(sideNormal).LessDotWithAngle(Math.PI / 9); //20 degrees int ticksToZeroEnginePower = (int)(Math.Abs(car.EnginePower) / game.CarEnginePowerChangePerTick); if (!isParallel && speedSign > 0 && crash.TickCome < ticksToZeroEnginePower) { if (moveResult.EnginePower > 0.5) { moveResult.EnginePower -= game.CarEnginePowerChangePerTick; } } if (!isParallel) { moveResult.IsBrake = moveResult.IsBrake || car.Speed() > Constant.MinBrakeSpeed; } } } }
private void turn(Move moveResult, Vector needDirAngle) { PCar iterCar = new PCar(car, game); iterCar.setEnginePower(enginePowerSign); Vector endPoint = endTile.ToVector(1 - dirMove.X, 1 - dirMove.Y); endPoint = endPoint + new Vector(dirMove.X, dirMove.Y) * game.TrackTileMargin; double speedSign = Math.Sign(Vector.sincos(car.Angle).Dot(new Vector(car.SpeedX, car.SpeedY))); HashSet <IPhysicEvent> events = calculateTurnEvents(iterCar, needDirAngle); IPhysicEvent passageLine = events.ComeContaints(PhysicEventType.PassageLine) ? events.GetEvent(PhysicEventType.PassageLine) : null; IPhysicEvent outLine = events.ComeContaints(PhysicEventType.OutLine) ? events.GetEvent(PhysicEventType.OutLine) : null; IPhysicEvent speedReach = events.ComeContaints(PhysicEventType.SpeedReach) ? events.GetEvent(PhysicEventType.SpeedReach) : null; if (null != passageLine && null != outLine) { int speedReachTick = null != speedReach ? speedReach.TickCome : maxIterationCount; if (speedReachTick * iterCar.CalculateBrakeFactor() > outLine.TickCome) { moveResult.IsBrake = car.Speed() > Constant.MinBrakeSpeed; } } if (!hasReserveTicks(iterCar, needDirAngle)) { HashSet <IPhysicEvent> crashEvents = calculateTurnMapCrashEvents(iterCar, needDirAngle, moveResult.IsBrake); IPhysicEvent mapBrakeCrash = crashEvents.ComeContaints(PhysicEventType.ObjectsCrash) ? crashEvents.GetEvent(PhysicEventType.ObjectsCrash) : null; IPhysicEvent passageLineBrake = crashEvents.ComeContaints(PhysicEventType.PassageLine) ? crashEvents.GetEvent(PhysicEventType.PassageLine) : null; //bool endMove = checkStrongParallel(mapBrakeCrash); int tickToZeroWheelTurn = (int)Math.Round(Math.Abs(iterCar.WheelTurn / game.CarWheelTurnChangePerTick)); bool nearEndAndCrash = (null != mapBrakeCrash && null != passageLine && mapBrakeCrash.TickCome <= tickToZeroWheelTurn && passageLine.TickCome < tickToZeroWheelTurn); if ((null == mapBrakeCrash && null != passageLineBrake) || nearEndAndCrash) { moveResult.WheelTurn = new PCar(car, game).WheelTurnForEndZeroWheelTurn(needDirAngle.Angle, speedSign); } } if (isMovedOutFromLine(iterCar, needDirAngle)) { moveResult.WheelTurn = new PCar(car, game).WheelTurnForEndZeroWheelTurn(needDirAngle.Angle, speedSign); } }
private bool checkStrongParallel(IPhysicEvent mapCrash) { if (null == mapCrash) { return(false); } Tuple <Vector, Vector> crashInfo = mapCrash.infoCome as Tuple <Vector, Vector>; if (null == crashInfo) { return(false); } Vector sideNormal = crashInfo.Item2; bool isStrongParallel = Vector.sincos(car.Angle).Dot(sideNormal).LessDotWithAngle(Math.PI / 18); //10 degrees isStrongParallel &= mapCrash.CarCome.Dir.Dot(sideNormal).LessDotWithAngle(Math.PI / 18); //10 degrees return(isStrongParallel); }