public Vehicle(int id, int offSetX, int offSetY, int velocity, int height, int width, EdgeRoad currentEdge)
        {
            CurrentEdge = currentEdge;
            ID          = id;

            Position = new Point2D(currentEdge.From);

            Position.X += offSetX;
            Position.Y += offSetY;

            NewPositionY = Position.Y;
            NewPositionX = Position.X;

            Velocity    = velocity;
            OldVelocity = Velocity;
            Height      = height;
            Width       = width;
            State       = VehicleState.Move;

            MovementVetorX = 0;
            MovementVetorY = 0;

            image = new Image();

            Turn = currentEdge.Direction;
        }
        public void AddPipe(EdgeRoad pipe, IntersectionPipeType type)
        {
            intersectionPipes.Add(new IntersectionPipe(pipe, type));

            if (type == IntersectionPipeType.In)
            {
                Connectors.Add(new Point2D(pipe.To.X, pipe.To.Y));
            }
            else if (type == IntersectionPipeType.Out)
            {
                Connectors.Add(new Point2D(pipe.From.X, pipe.From.Y));
            }
        }
        private void setNewPositionForOutrun(ref EdgeRoad closestEdge)
        {
            switch (CurrentEdge.Direction)
            {
            case CardinalDirection.East:
            case CardinalDirection.West:
                NewPositionY = closestEdge.From.Y;
                break;

            case CardinalDirection.North:
            case CardinalDirection.South:
                NewPositionX = closestEdge.From.X;
                break;
            }
        }
        private bool isNextLaneFreeForOutrun(EdgeRoad closestEdge, List <Vehicle> vehicles)
        {
            if (closestEdge == null)
            {
                return(false);
            }

            foreach (var vehicle in vehicles)
            {
                if (vehicle.ID == ID)
                {
                    continue;
                }

                if (vehicle.CurrentEdge.ID != closestEdge.ID)
                {
                    continue;
                }

                switch (CurrentEdge.Direction)
                {
                case CardinalDirection.North:
                case CardinalDirection.South:
                    if (doesVectorIntrudeOnVectorY(Position.Y, Position.Y + Width, vehicle.Position.Y, vehicle.Position.Y + vehicle.Width))
                    {
                        return(false);
                    }
                    break;

                case CardinalDirection.West:
                case CardinalDirection.East:
                    if (doesVectorIntrudeOnVectorX(Position.X, Position.X + Width, vehicle.Position.X, vehicle.Position.X + vehicle.Width))
                    {
                        return(false);
                    }
                    break;
                }
            }

            return(true);
        }
        private void setClosestEdgeRoad(ref EdgeRoad edgeRoadToSet, IEnumerable <EdgeRoad> restEdges)
        {
            int closestEdgeDistance = 0;

            foreach (var edge in restEdges)
            {
                switch (CurrentEdge.Direction)
                {
                case CardinalDirection.South:
                case CardinalDirection.North:
                    if (closestEdgeDistance == 0)
                    {
                        closestEdgeDistance = Math.Abs(edge.From.X - CurrentEdge.From.X);
                        edgeRoadToSet       = edge;
                    }
                    else if (closestEdgeDistance != 0 && Math.Abs(edge.From.X - CurrentEdge.From.X) < closestEdgeDistance)
                    {
                        closestEdgeDistance = Math.Abs(edge.From.X - CurrentEdge.From.X);
                        edgeRoadToSet       = edge;
                    }
                    break;

                case CardinalDirection.West:
                case CardinalDirection.East:
                    if (closestEdgeDistance == 0)
                    {
                        closestEdgeDistance = Math.Abs(edge.From.Y - CurrentEdge.From.Y);
                        edgeRoadToSet       = edge;
                    }
                    else if (closestEdgeDistance != 0 && Math.Abs(edge.From.Y - CurrentEdge.From.Y) < closestEdgeDistance)
                    {
                        closestEdgeDistance = Math.Abs(edge.From.Y - CurrentEdge.From.Y);
                        edgeRoadToSet       = edge;
                    }
                    break;
                }
            }
        }
        public override void act(SimulationState state)
        {
            MovementVetorX = 0;
            MovementVetorY = 0;

            if (State == VehicleState.NoIntersection)
            {
                spawnFromEdgeWithNoIntersectionToNewEdge(state.intersections.SelectMany(ip => ip.intersectionPipes).ToList(), state.edgePipes);
                rotateTexture();
            }
            else if (NextEdge != null && State == VehicleState.OnIntersection)
            {
                moveToNewConnectors();
                rotateTexture();
                return;
            }

            var restEdges = state.edgePipes
                            .Where(e => e.ID == CurrentEdge.PipeID)
                            .FirstOrDefault().Edges
                            .Where(e => e.ID != CurrentEdge.ID);

            foreach (var vehicle in state.vehicles)
            {
                if (State == VehicleState.InIntersectionQueue || State == VehicleState.NoIntersection || !restEdges.Where(re => re.PipeID == vehicle.CurrentEdge.PipeID).Any())
                {
                    continue;
                }

                setCloserPositionToOutrunNewPosition();

                bool isOnIntersection = isVehicleOnIntersection();

                CurrentConnectorY = CurrentEdge.To.Y;
                CurrentConnectorX = CurrentEdge.To.X;

                if (isOnIntersection)
                {
                    OldVelocity = Velocity;
                    Velocity    = 0;

                    bool noIntersection = !state.intersections
                                          .Any(ip => ip.intersectionPipes
                                               .Any(p => p.EdgeRoad.ID == CurrentEdge.ID && p.IntersectionType == IntersectionPipeType.In));

                    if (noIntersection)
                    {
                        State = VehicleState.NoIntersection;
                    }
                    else
                    {
                        CurrentIntersectionID = state.intersections.SingleOrDefault(ip => ip.intersectionPipes.Any(p => p.EdgeRoad.ID == CurrentEdge.ID && p.IntersectionType == IntersectionPipeType.In)).ID;
                        State = VehicleState.InIntersectionQueue;
                    }

                    continue;
                }

                if (vehicle.ID == ID)
                {
                    continue;
                }

                if (vehicle.CurrentEdge.ID == CurrentEdge.ID && isVehicleInFront(vehicle) && isVehicleNCarWidthInFrontAtLeast(2, vehicle))
                {
                    Velocity = vehicle.Velocity;

                    if (restEdges.Count() == 0)
                    {
                        continue;
                    }

                    EdgeRoad closestEdge = null;
                    setClosestEdgeRoad(ref closestEdge, restEdges);

                    if (isNextLaneFreeForOutrun(closestEdge, state.vehicles))
                    {
                        setNewPositionForOutrun(ref closestEdge);
                        CurrentEdge = closestEdge;
                        Velocity   += 1;
                    }
                }
            }

            prepareMovementVector();

            Position.X += MovementVetorX;
            Position.Y += MovementVetorY;
        }
 public IntersectionPipe(EdgeRoad edgeRoad, IntersectionPipeType intersectionType)
 {
     EdgeRoad         = edgeRoad;
     IntersectionType = intersectionType;
 }