예제 #1
0
        /// <summary>
        /// Executes a single AGI interpreter tick, or cycle. This method is invoked 60 times a
        /// second, but the rate at which the logics are run and the animation updated is determined
        /// by the animation interval variable.
        /// </summary>
        public void Tick()
        {
            // Regardless of whether we're already in a Tick, we keep counting the number of Ticks.
            state.TotalTicks++;

            // Tick is called 60 times a second, so every 60th call, the second clock ticks. We
            // deliberately do this outside of the main Tick block because some scripts wait for
            // the clock to reach a certain clock value, which will never happen if the block isn't
            // updated outside of the Tick block.
            if ((state.TotalTicks % 60) == 0)
            {
                UpdateGameClock();
            }

            // Only one thread can be running the core interpreter cycle at a time.
            if (!inTick)
            {
                inTick = true;

                // Proceed only if the animation tick count has reached the set animation interval x 3.
                if (++state.AnimationTicks < (state.Vars[Defines.ANIMATION_INT] * 3))
                {
                    inTick = false;
                    return;
                }

                // Reset animation tick count.
                state.AnimationTicks = 0;

                // Clear controllers and get user input.
                ProcessUserInput();

                // Update input line text on every cycle.
                textGraphics.UpdateInputLine(false);

                // If ego is under program control, override user input as to his direction.
                if (!state.UserControl)
                {
                    state.Vars[Defines.EGODIR] = ego.Direction;
                }
                else
                {
                    ego.Direction = state.Vars[Defines.EGODIR];
                }

                // Calculate the direction in which objects will move, based on their MotionType. We do
                // this here, i.e. call UpdateObjectDirections() before starting the logic scan, to
                // allow ego's direction to be known to the logics even when ego is on a move.obj().
                UpdateObjectDirections();

                // Continue scanning LOGIC 0 while the return value is above 0, indicating a room change.
                while (NewRoom(commands.ExecuteLogic(0)))
                {
                    ;
                }

                // Set ego's direction from the variable.
                ego.Direction = state.Vars[Defines.EGODIR];

                // Update the status line, in case the score or sound status have changed.
                textGraphics.UpdateStatusLine();

                state.Vars[Defines.OBJHIT]  = 0;
                state.Vars[Defines.OBJEDGE] = 0;

                // Clear the restart, restore, & init logics flags.
                state.Flags[Defines.INITLOGS] = false;
                state.Flags[Defines.RESTART]  = false;
                state.Flags[Defines.RESTORE]  = false;

                // If in graphics mode, animate the AnimatedObjects.
                if (state.GraphicsMode)
                {
                    AnimateObjects();
                }

                // If there is an open text window, we render it now.
                if (textGraphics.IsWindowOpen())
                {
                    textGraphics.DrawWindow();
                }

                // Store what the key states were in this cycle before leaving.
                for (int i = 0; i < 256; i++)
                {
                    userInput.OldKeys[i] = userInput.Keys[i];
                }

                inTick = false;
            }
        }