/// <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; } }