Example #1
0
            /// <summary>
            ///
            /// </summary>
            /// <param name="state"></param>
            /// <returns></returns>
            public object onInside(CarState.Inside state)
            {
                TrainCar head = owner.head;
                RailRoad rr   = RailRoad.get(state.location);

                Direction go     = rr.Guide();  // angle to go
                Location  newLoc = state.location + go;

                newLoc.z += rr.ZDiff(state.direction);

                if (WorldDefinition.World.IsBorderOfWorld(newLoc))
                {
                    // go outside the world
                    return(new CarState.Outside(newLoc, go, OUTSIDE_COUNTER_INITIAL_VALUE));
                }
                else
                {
                    if (isConnected(newLoc, go))
                    {
                        // the rail needs to be connected
                        return(new CarState.Inside(newLoc, go));
                    }
                    else
                    {
                        return(null);
                    }
                }
            }
Example #2
0
 /// <summary>
 /// Plays a sound effect for this train if necessary.
 /// </summary>
 public void playSound(ISoundEffect se)
 {
     CarState.Inside ins = head.State.asInside();
     if (ins != null)
     {
         se.play(ins.location);  // play the sound
     }
 }
Example #3
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="tr"></param>
        /// <param name="callCount"></param>
        /// <returns></returns>
        public override TimeLength getStopTimeSpan(Train tr, int callCount)
        {
            // calculate the position where the train should stop.
            int pos;

            CarState.Inside ins = tr.head.State.asInside();

            if (owner.direction == ins.direction)
            {
                pos = (owner.length + tr.length) / 2 - 1;
            }
            else
            {
                Debug.Assert(owner.direction == ins.direction.opposite);
                pos = (owner.length - tr.length) / 2;
            }

            if (pos < 0 || pos >= owner.length)
            {
                return(TimeLength.ZERO); // longer than the platform
            }
            if (pos != index)
            {
                return(TimeLength.ZERO); // not at the stop position
            }
            // the train is positioned at the right place.
            if (owner.hostStation == null)
            {
                return(TimeLength.ZERO); // platform is not connected. can't make a stop
            }
            // ask the controller to see if it wants to stop.
            TimeLength ts = tr.controller.getStopTimeSpan(tr, owner.hostStation, callCount);

            if (callCount == 0 && ts.isPositive)
            {
                // if the train stops, unload passengers
                owner.hostStation.unloadPassengers(tr);
            }

            if (callCount != 0 && !ts.isPositive)
            {
                // if the train departs, load passengers
                owner.hostStation.loadPassengers(tr);
                // ring the bell, here we go!
                tr.playSound(owner.bellSound.Sound);
            }

            return(ts);
        }
Example #4
0
            /// <summary>
            ///
            /// </summary>
            /// <param name="state"></param>
            /// <returns></returns>
            public object onOutsie(CarState.Outside state)
            {
                CarState.Inside s = calcReturnPoint(state);
                if (s == null)
                {
                    // all the usable RRs are completely removed.
                    // that means this train is fully outside the world.
                    // so it's OK to remain static.
                    return(state);
                }

                return(new CarState.Outside(
                           s.location - s.direction, s.direction.opposite,
                           OUTSIDE_COUNTER_INITIAL_VALUE - state.timeLeft));
            }
        /// <summary>
        ///
        /// </summary>
        /// <param name="view"></param>
        /// <param name="dc"></param>
        public void DrawAfter(QuarterViewDrawer view, DrawContext dc)
        {
            Train tr = this.selectedTrain;

            if (tr == null || !tr.head.State.isInside)
            {
                return;
            }

            // draw an arrow that indicates the direction of the train
            CarState.Inside ci = tr.head.State.asInside();

            Point pt = view.fromXYZToClient(ci.location);

            pt.Y -= 12;

            ci.direction.drawArrow(dc.Surface, pt);
        }
Example #6
0
            /// <summary>
            ///
            /// </summary>
            /// <param name="dc"></param>
            /// <param name="pt"></param>
            public override void Draw(DrawContext dc, Point pt)
            {
                Surface display = dc.Surface;

                pt.Y -= 9;      // offset

                CarState.Inside s = State.asInside();
                Debug.Assert(s != null);

                RailRoad rr = s.voxel.railRoad;

                if (rr is SlopeRailRoad)
                { // slope rail
                    SlopeRailRoad srr = (SlopeRailRoad)rr;

                    switch (srr.level)
                    {// apply slope height
                    case 0: break;

                    case 1: pt.Y -= 4; break;

                    case 2: pt.Y += 8; break;

                    case 3: pt.Y += 4; break;
                    }

                    if (!parent.isReversed)
                    {
                        type.DrawSlope(display, pt, s.direction, s.direction == srr.climbDir);
                    }
                    else
                    {
                        type.DrawSlope(display, pt, s.direction.opposite, s.direction != srr.climbDir);
                    }
                }
                else
                { // level rail road
                    int d1 = s.direction.index;
                    int d2 = s.voxel.railRoad.Guide().index;

                    int angle;
                    if (d1 == d2)
                    {
                        angle = d1 * 2;
                    }
                    else
                    {
                        int diff = (d2 - d1) & 7;
                        if (diff == 7)
                        {
                            diff = -1;
                        }

                        int dd = (d2 * 2 + diff * 3) & 15;      // operation is on modulo 16.

                        if (2 < dd && dd < 10)
                        {
                            pt.X += 3;
                        }
                        else
                        {
                            pt.X -= 3;
                        }

                        if (6 < dd && dd <= 14)
                        {
                            pt.Y += 2;
                        }
                        else
                        {
                            pt.Y -= 2;
                        }

                        angle = (d1 * 2 + diff) & 15;
                    }

                    if (parent.isReversed)
                    {
                        angle ^= 8;
                    }

                    type.Draw(display, pt, angle);
                }
            }
Example #7
0
 public object onInside(CarState.Inside state)
 {
     return(state.voxel.isOccupied);
 }
Example #8
0
            /// <summary>
            ///
            /// </summary>
            /// <param name="state"></param>
            /// <returns></returns>
            public object onInside(CarState.Inside state)
            {
                Direction d = state.voxel.railRoad.Guide().opposite;

                return(new CarState.Inside(state.location, d));
            }
Example #9
0
        /// <summary>
        /// Clock event handler.
        /// </summary>
        public void clockHandler()
        {
            Debug.Assert(isPlaced);     // we should have unregistered the handler when the train was removed.

            CarState.Inside ins = head.State.asInside();
            if (ins != null)
            { // this car might need to stop
                TimeLength time = ins.voxel.railRoad.getStopTimeSpan(this, stopCallCount);
                if (time.totalMinutes > 0)
                {
                    stopCallCount++;
                    // a car needs to stop here
                    registerTimer(time);        // resume after the specified time

                    // TODO: see where this train is being stopped. do something if necessary
                    State = TrainStates.StoppingAtStation;
                    return;
                }


                if (time.totalMinutes < 0)
                {
                    reverse();  // turn around
                }
            }

            // this car can now move
            stopCallCount = 0;
            TrainStates s = TrainStates.Moving;

            // determine the next head car state
            CarState next = calcNextTrainCarState[head.State];

            if (next != null)
            {   // if it can move forward
                if (!isBlocked[next])
                {
                    move(next);
                }
                else
                {
                    // otherwise we can't move. emergency stop.
                    s = TrainStates.EmergencyStopping;
                }
            }
            else
            {
                // we can't go forward. turn around
                reverse();
                next = calcNextTrainCarState[head.State];

                if (next != null && !isBlocked[next])
                {
                    move(next);
                }
                else
                {
                    s = TrainStates.EmergencyStopping;
                }
            }
            State = s;  // update the state
            registerTimer();
        }