|
P3-SDK 0.9
P3 Software Development Kit
|
As described in the Modes section, the execution of a P3 app is controlled by a group of modes. When modes are created, they're given a priority, and they start running when they're added to the P3's mode queue. Here's an example of creating and starting a mode:
In this example, ShotsMode is a class (definition not shown) that inherits from Multimorphic.NetProcMachine.Machine.Mode. When a mode is created, the main p3 object and an integer representing its priority are passed into the constructor. In this case, a pre-defined constant Priorities.PRIORITY_MECH contains the priority number. Keeping all priorities defined in a central place makes it easier to manage priorities for all modes.
After being added to the mode queue via the p3.AddMode(shotsMode) call, shotsMode is effectively running. Running means that the mode is active and ready to receive events from the P3. Events can be switch events from the actual P3 machine, timer events, or events sent from other modes or GUI scripts. Refer to the Events in Mode Layer and Events in GUI Layer sections for more information on events.
To stop a mode from running, simply remove it from the mode queue as follows:
Note - Common mistakes made with modes include creating them but never starting them and creating them with too low of a priority. Higher priority modes receive events before lower priority modes, and a mode can decide whether or not an event it receives should continue being serviced by lower priority modes.
All P3 apps have an app mode which starts the proceedings (usually by starting the attract mode and a game manager mode) and ends the proceedings (by shutting down the app).
In the interim, the game manager mode will start the primary game mode when appropriate. When the game manager receives an event indicating that the start button has been pressed, it checks the money mode (which is started by the game manager mode when it initializes) to ensure that enough credits are available, then it will start the base game mode (e.g. P3SABaseGameMode).
The base game mode starts the flipper mode and ball launch mode to enable game play. It will also start ball drain mode to catch the end of a ball. The game mode keeps track of the number of balls in play as well as the balls remaining in the game. A separate score mode keeps track of the score.
The framework includes frequently required modes. Some examples of common modes are:
| Mode | Responsibility |
|---|---|
| BaseGameMode | - Derived from BaseAppMode, which instantiates modes used in all apps (e.g. VolumeMode, etc). - The base mode used in all games. - Instantiates modes that make up the entire game (e.g. AttractMode, GameManagerMode, GameAttributeManagerMode, etc) - This is not the base class of all game modes. Base here means Primary, Central or Core mode. |
| AttractMode | - Show ready-for-game state to the user - Attract art, sound, and lightshow - Receive notification of Start button press - Start game mode |
| GameManagerMode | - Starts money mode - Awaits Start button presses - Starts game mode - Awaits game ending |
| GameAttributeManagerMode | - Keeps track of all DataManagerModes, which are modes used to track data (settings, statistics, high scores, etc.) |
| MoneyMode | - Receives events from coin door mechs and attract mode to add/subtract credits - Reports number of credits available |
| BallLauncherMode | - Launches a ball into play |
| BallSaveMode | - Watches for ball drains within a defined timeframe - Prevents registration of a ball drain during saver time - Triggers BallLauncherMode when a ball drains during saver time |
| BallSearchMode | - Watches for absence of switch activity (an indicator of a potential stuck ball situation). - Activates all mechanisms until switch activity is received. |
As a developer, you can extend and customize the provided Modes to best suit the specific behavior for your app. It is inevitable that you will sub-class (i.e., extend) the provided mode classes to leverage the methods and fields they define, and amend or augment functionality as needed. For example, every Mode that you will define could be sub-classed from P3Mode:
However in many cases, it may be better to sub-class one of the P3Mode subclasses that have been provided (GameMode). For example, a common usage is to define your own subclass of GameMode (<AppCode>GameMode) and then subclass this class to be able to reuse helpful methods that you define along the way.
Note - This section describes how to send and receive events in Modes. For sending and receiving events in GUI scripts, please refer to Events in GUI Layer.
Pinball gameplay modes are generally event driven in that gameplay doesn't advance until a specific sequence of events (e.g. switch events or timer events) occurs. Similarly, the modes that make up a pinball application don't advance until they receive events.
The P3 framework supports 4 different types of events in Modes.
Events can be sent from a mode to one or more other modes by posting it as follows. Data can be any type of data. Event handlers need to cast the information back to the desired type.
Events can be sent from a mode to a GUI script by posting it as follows:
Note - To send the same event data to both Mode and GUI, two separate Posts are required, one PostModeEventToModes and one PostModeEventToGUI.
It is possible to emulate a function returning a value using two events. The first event queries for the value. The target Mode receives that event and reacts by sending a response event. The return value is the event argument of the second event. Since the event handlers of Mode-to-Mode events are executed before PostModeToModes() returns, the return value will be available right after the first Post call. The response event handler is only needed for a short time, it can be removed as soon as the response is received.
This is an example using a real event supported by the framework:
This is an example how the framework might have implemented the "Evt_GetTiltWarnings" event:
Event debugging will show which class posts the event and when, and it will show who handles the event. In the case of a switch event or a ModeToMode event, both of which propagate through the priority-based mode queue, the logging information will show all of the modes that handle the event before its propagation is stopped by a mode returning SWITCH_STOP or EVENT_STOP.
More mode information: