summaryrefslogtreecommitdiffstats
path: root/examples/scxml/pinball/doc/src/pinball.qdoc
diff options
context:
space:
mode:
Diffstat (limited to 'examples/scxml/pinball/doc/src/pinball.qdoc')
-rw-r--r--examples/scxml/pinball/doc/src/pinball.qdoc478
1 files changed, 0 insertions, 478 deletions
diff --git a/examples/scxml/pinball/doc/src/pinball.qdoc b/examples/scxml/pinball/doc/src/pinball.qdoc
deleted file mode 100644
index aa12e42..0000000
--- a/examples/scxml/pinball/doc/src/pinball.qdoc
+++ /dev/null
@@ -1,478 +0,0 @@
-// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
-
-/*!
- \example pinball
- \title Qt SCXML Pinball Example
- \ingroup examples-qtscxml
- \brief Encapsulates the internal logic of an application in an SCXML file.
-
- \e {Pinball} demonstrates a clear separation between the user interface,
- which may be easily replaced, and the internal logic encapsulated in an
- SCXML file, which could also be used with another user interface.
-
- \include examples-run.qdocinc
-
- \section1 Pinball Features
-
- \image pinball.png Screenshot of the Pinball example
-
- The Pinball example mimics a pinball game. The targets on the pinball table
- are substituted by GUI controls, mainly by push buttons. Display elements,
- including current score, highscore, and targets' lights, are substituted by
- labels. Usually, the state of the targets' lights changes very often during
- a game: the lights get turned on or off permanently or they blink at varying
- speed indicating a game (or a certain target) entered a temporary state. The
- state of each target light is presented as an enabled or a disabled label.
- There is no real ball, but clicking a target's button represents hitting a
- real pinball target with a ball.
-
- Our pinball contains the following features:
- \list
- \li Initially and when the game ends, the pinball table
- enters \c offState. In that state, all lights on the table
- blink slowly (at intervals of 1 second).
- \li After clicking the \uicontrol START button, the pinball table
- enters \c onState. All lights are turned off and the
- pinball table is ready to be played.
- \li When the table is in \c onState and the players
- click the \uicontrol {BALL OUT} button, the game ends
- and enters \c offState. If the players' score is
- higher than the current highscore, the highscore is updated.
- \li The goal is to collect the \uicontrol JACKPOT. In order to do that,
- the players must hit all five \uicontrol CRAZY letters twice.
- They have unlimited time for hitting them for the first time.
- However, after they have collected all the letters for the first time,
- they enter the \c hurryState and must collect
- them again within 5 seconds. If the time has passed and
- the letters were not collected again, the players must
- start collecting the letters from scratch.
- \li Scores:
- \list
- \li 1.000 per letter hit when not in \c hurryState.
- \li 10.000 per letter hit when in \c hurryState.
- \li 100.000 bonus for all 5 letters when not in \c hurryState.
- \li 1.000.000 bonus for all 5 letters when in \c hurryState
- (\uicontrol JACKPOT).
- \endlist
- \li When not in \c hurryState, the letters already hit should blink
- at intermediate speed (500ms). Letters not hit yet should stay off.
- \li When in \c hurryState, the letters already hit should
- stay on. Letters not hit yet should blink fast (200ms).
- In addition, the \uicontrol HURRY light should blink at the same speed.
- \li When the jackpot gets collected, the \uicontrol JACKPOT light should
- stay on.
- \endlist
-
- \section1 SCXML Part: Internal Logic Description
-
- The \e pinball.scxml file describes the internal logic implemented for the
- pinball game. In this example, we have chosen the ECMAScript data model:
-
- \quotefromfile pinball/pinball.scxml
- \skipto scxml
- \printuntil ecmascript
-
- The ECMAScript data model enables declaring variables with initial values
- that can be modified later. We declare the \c "highscore" and \c "score"
- variables with the initial values of 0:
-
- \printuntil </datamodel>
-
- We define a root parallel state \c "global", with two child states,
- \c guiControl and \c internalState, which are also parallel. Because the top
- \c global state is parallel, all of its direct children are active when it
- is active. In this example, the role of \c global is to collect the child
- states and make them both active at a time.
-
- \image pinball-statechart-global.png
-
- \section2 Maintaining Light State
-
- The \c guiControl element is responsible for maintaining the current
- state of each light control that is visible on the pinball table.
- Each light has a corresponding state.
-
- \image pinball-statechart-guicontrol.png
-
- For example, the light of the letter
- \uicontrol C corresponds to the \c cLight state. Each light state has two
- child states indicating whether the light is on or off:
-
- \printuntil target="cLightOn"
- \printuntil /^\ {12}<\//
-
- As mentioned before, the \c guiControl state is always active, and since
- it is of parallel type, all its direct children are always active too.
- Therefore, the \c cLight state is always active. However,
- only one of its children, \c cLightOn or \c cLightOff, is active at a time.
- The same applies to the other children of the \c guiControl state.
- In addition, we define transitions between on and off substates. For example,
- whenever the active state is \c cLightOn and a \c turnOffC event is received,
- we change the active substate of \c cLight to \c cLightOff.
- Whenever the active state is \c cLightOff and we receive a \c turnOnC event,
- we change the active substate of \c cLight to \c cLightOn.
-
- In our application, we use instances of QLabel class in C++
- to represent real lights on the table. When the light transitions
- into the \e on or \e off state, we enable or disable the particular label
- accordingly. The connection between the state machine and the GUI
- part of the application will be shown in the \l {cpp}{C++ code} later on. For now,
- it is enough to realize that changes to active states inside
- the state machine will serve as the external interface of the state machine
- that the other parts of the application (such as the GUI part) can listen to.
-
- All of the mentioned events that switch the state of a light
- will be generated by this state machine inside the \c internalState
- in reaction to running timers or external triggers.
-
- \section2 Maintaining Game State
-
- The \c internalState state consists of two main parts: \c logicalState and \c workflow.
-
- \image pinball-statechart-internalstate.png
-
- The \c logicalState state holds the definitions for the modes that the game is able
- to go into and for the logical states of collected targets. The \c workflow state
- implements a generator for light blinking and calculates most of the new states
- the machine should go into depending on incoming events and on currently active states.
- As mentioned already, \c internalState is always active, and since
- it is of a parallel type, \c logicalState and \c workflow are always active too.
-
- \section2 Maintaining Logical State of Buttons
-
- The \c logicalState state consist of two parts: \c letterState and \c modeState.
-
- \image pinball-statechart-logicalstate.png
-
- As previously mentioned, \c logicalState is always active, and since
- it is of parallel type, the \c letterState and \c modeState children are always
- active too. Now let us look at the first part, the \c letterState, which contains
- one parallel \c lettersState:
-
- \quotefromfile pinball/pinball.scxml
- \skipto letterState
- \printuntil lettersState
- \printuntil letter.R
- \dots 28
- \skipto /^\ {24}<\//
- \printuntil letter.A
- \dots 28
- \skipto /^\ {24}<\//
- \printuntil letter.Z
- \dots 28
- \skipto /^\ {24}<\//
- \printuntil letter.Y
- \dots 28
- \skipto /^\ {24}<\//
- \printuntil /^\ {16}<\//
-
- The \c lettersState state maintains the logical state of the buttons pretending to
- be targets that were clicked by the players. The letter state for the letter
- \uicontrol C holds whether the target for the letter \uicontrol C was hit,
- while the light state for the letter \uicontrol C holds whether the light
- for the target for the letter \uicontrol C should be currently on or off.
- In a real pinball game, these states are usually orthogonal,
- which means that if you have not hit a target yet, the target is blinking,
- indicating that it is currently worth hitting. This blinking
- means that the light state switches between on and off at short intervals,
- while the target state is continuously off, because it has not been hit yet.
- The author of a pinball table can decide that
- after a target is hit (that is, after the target state switches to on)
- the target's light is continuously turned off or on or the intervals between
- lights blinking become shorter or longer.
-
- As mentioned before, \c letterState is always active, which means
- that its only child \c lettersState should always be active too. However,
- there is one exception: for a short while the \c lettersState may
- end up being \e {not active}. This happens when the transition for
- \c lettersState is being performed. This transition is triggered when
- the \c resetLetters event occurs, and it instructs the state machine
- to exit \c lettersState and all its descendant states and reenter
- \c lettersState and set up all its descendant states with their initial states.
- In short, the \c resetLetters event resets the \c lettersState and all its
- descendant states to the default configuration.
-
- The \c lettersState contains five direct substates that
- correspond to five different letters. The content for other letters' states
- than C is not shown here, but it is analogous to the content for C's state.
-
- The \c {letter.C} state contains two substates reflecting its off and on states:
- \c cLetterOff and \c cLetterOn. The \c {letter.C} state inside its parallel
- parent \c lettersState is always active (under the condition that
- \c lettersState is active, as described before). However,
- only one of its child states is active at a time: \c cLetterOff or \c cLetterOn.
- The initial substate of the \c {letter.C} state is \c cLetterOff meaning
- that whenever the \c {letter.C} state is being activated (which happens
- initially and after the \c resetLetters event) its active
- substate will be set to \c cLetterOff.
-
- The \c cLetterOff state defines a transition, which will be triggered by
- the \c {cLetterTriggered} event. This transition activates \c cLetterOn,
- the other child of \c {letter.C}, only when the machine is in \c onState
- (that is, when the pinball game is running).
- The \c {cLetterTriggered} event is expected to be an event posted into the state machine
- from outside of the state machine. This event should be generated when
- the ball hits the letter \uicontrol C target. In our example we mimic
- it by the clicking the letter \uicontrol C button.
-
- The \c cLetterOn state is defined as a final state, which means that
- whenever this state is activated the \c {done.state.letter.C} event
- will be automatically posted by the state machine. This event will be used
- later for updating the current score.
-
- Moreover, when all \c lettersState children reach their final state,
- the state machine will automatically post the \c {done.state.lettersState} event.
- This event will be used later, too, for updating the current score
- and for turning on or off the hurry state.
-
- \section2 Maintaining Game Modes
-
- The \c modeState state consists of two substates, \c offState and \c onState.
-
- \image pinball-statechart-modestate.png
-
- The \c offState state describes what should happen before the pinball game
- is started and when it is over,
- while \c onState represents the logic appropriate for the active game.
-
- \quotefromfile pinball/pinball.scxml
- \skipto offState
- \printuntil /^\ {20}<\//
-
- When the pinball application starts or a game ends, the machine goes into
- \c offState. Entering that state invokes some actions, which are
- enclosed inside an \c <onentry> element. First, we update the \c highScore
- variable in case the current \c highScore value is less than current \c score value.
- This is being checked inside the \c "cond" attribute of the \c <if> element
- (note that we need to escape the "<" character with "&lt;").
- Even in the \c off state, we want to show the last reached score,
- so we do not clear it here; we will do that when we enter the \c on state.
- Next, we raise two events: \c resetLetters to logically reset
- all letters that might have been hit during the last game and \c update
- to immediately activate the blinking and updating of all lights.
- When the machine is in \c offState, it is ready to transition into the
- \c onState if only the \c startTriggered event occurs, which is described
- by the <transition> element. This event is expected to be generated externally
- after clicking the \uicontrol START button on the pinball table.
-
- \skipto onState
- \printuntil /^\ {20}<\//
-
- \section2 Game On
-
- When the state machine enters \c onState, it first clears the current score
- variable. The \c onState state is of the parallel type and has two direct child states:
- \c hurryState and \c jackpotState. They are active as long as
- their parent, \c onState, is active. Both \c hurryState and \c jackpotState
- contain two substates that reflect their off and on states.
- Only one substate of \c hurryState and one substate of \c jackpotState
- can be active at a time. Initially, the off substates are active.
-
- \image pinball-statechart-onstate.png
-
- Whenever we enter \c hurryStateOff or \c hurryStateOn, we generate the same
- two events we generate when entering the \c onState state: \c resetLetters and
- \c update. In addition, when we enter the \c hurryStateOn state, we send a delayed
- event, \c goToHurryOff, with a delay of five seconds, marked with \c hurryId.
- This means that after five seconds we just
- switch the state back to \c hurryStateOff without granting the bonus points.
- In this way, we implement the five-second hurry feature of the pinball table.
- We also define transitions from \c hurryStateOff to \c hurryStateOn when the
- \c goToHurryOn event occurs and from \c hurryStateOn to \c hurryStateOff
- when the \c goToHurryOff event occurs. When we exit the \c hurryStateOn
- state, we cancel the possibly pending delayed event that was marked with
- \c hurryId. This is important in case the five seconds have not elapsed yet,
- but players have collected all the five letters in the hurry state. We then
- collect the jackpot and want the pending timer to finish.
-
- The substates of \c jackpotState generate the request to update the state
- of lights. The \c jackpotStateOff state defines the transition to \c jackpotStateOn
- when the \c goForJackpot event occurs. The opposite transition is not
- needed, because when the jackpot gets collected, the corresponding light
- remains lit until the end of game. When a new game starts, the \c jackpotState
- is entered again which causes its initial active substate to be
- \c jackpotStateOff.
-
- In addition, the \c onState state defines one transition in reaction to the
- \c ballOutTriggered event which instructs the machine to go into the \c offState.
- The \c ballOutTriggered event is expected to be an event posted into the state machine
- from outside of the state machine. This event should be generated when
- the ball gets out of playing area of the table. In our example we mimic
- it by the clicking \uicontrol {BALL OUT} button. Posting the event from outside of state
- machine will be shown in the \l{cpp}{C++ code} later on.
-
- \section2 Generating Blinking Lights
-
- The \c workflow state is responsible for generating the blinking lights. The
- generator is defined in its \c lightImpulseGenerator substate. In addition,
- it is responsible for reacting to events that have been posted so far from
- the other parts of the state machine.
-
- \quotefromfile pinball/pinball.scxml
- \skipto workflow
- \printuntil done.state.letter.*
- \dots 20
- \skipto /^\ {16}<\//
- \printuntil done.state.lettersState
- \dots 20
- \skipto /^\ {16}<\//
- \printuntil updateLights
- \dots 20
- \skipto /^\ {16}<\//
- \printuntil updateLightsAccordingToLettersState
- \dots 20
- \skipto /^\ {16}<\//
- \printuntil turnOnLights
- \dots 20
- \skipto /^\ {16}<\//
- \printuntil turnOffLights
- \dots 20
- \skipto /^\ {16}<\//
- \printuntil /^\ {12}<\//
-
- The \c lightImpulseGenerator contains two child states:
- \c lightImpulseOn and \c lightImpulseOff, with only one active at a time.
-
- \image pinball-statechart-workflow.png
-
- Whenever the delayed \c lightImpulse event is being delivered, it immediately
- causes the transition from \c lightImpluseOn into \c lightImpulseOff or vice versa,
- depending on the state the machine was in. In effect, the \c lightImpulseGenerator
- toggles between its on and off state. These transitions are defined inside
- \c lightImpulseGenerator, so it means that during this toggling the machine
- also exits \c lightImpulseGenerator and reenters it immediately afterwards.
- Entering \c lightImpulseGenerator causes the generation of the \c update event.
- The \c update event triggers a targetless transition and posts two other
- events: \c scheduleNewImpulse and \c updateLights. The first one,
- \c scheduleNewImpulse, returns back to the \c lightImpulseGenerator, which
- posts a delayed \c lightImpulse event. After the delay,
- the \c lightImpulse event gets delivered back to \c lightImpulseGenerator,
- which causes it to toggle its substate again. In this way, the machine
- enters into a cycle. The current delay of the \c lightImpulse
- event depends on the state in which the machine was in the time of posting
- the delayed event. If a \c scheduleNewImpulse event occurs on demand, before
- the next delayed \c lightImpulse event gets delivered, we cancel any
- possible pending events.
-
- \quotefromfile pinball/pinball.scxml
- \skipto workflow
- \skipto done.state.letter.*
- \printuntil /^\ {16}<\//
- \printuntil /^\ {16}<\//
-
- Whenever we receive the event the name of which matches the
- \c {done.state.letter.*}, we update the current score.
- When the machine enters the final substate of the \c {letter.C},
- it emits the \c {done.state.letter.C} event. The same happens for
- all other letters we have previously defined. We capture the events for all
- letters, that is why we have used an asterisk
- after a dot in the event name.
- The transition above is targetless, since we just
- listen for matching events and update the internal data accordingly
- without changing any active state. The new score is being
- increased by 1.000 or 10.000 points, depending on whether we currently are
- in \c hurryStateOff or \c hurryStateOn.
- After the score is updated, we generate the \c updateLights event
- in order to immediately update the letters' lights accordingly.
- We do not generate the \c update event here, since we do not want to toggle
- the light impulse now, but just update the lights according to
- the current impulse state.
-
- We also intercept the \c {done.state.lettersState} event,
- which is being generated when all the letters have been hit.
- Depending on which state we are currently in, we grant the players either
- a small bonus of 100.000 or a big one of 1.000.000 (jackpot).
- In addition, we toggle the \c hurryState substate by
- sending the \c goToHurryOn or \c goToHurryOff event.
- When all letters have been collected while in \c hurryStateOn,
- we also raise the \c goForJackpot event which instructs
- the machine to activate the \c jackpotStateOn.
-
- \skipto updateLights
- \printuntil /^\ {16}<\//
- \printuntil updateLightsAccordingToLettersState
- \printuntil /^\ {16}<\//
- \printuntil turnOnLights
- \printuntil /^\ {16}<\//
- \printuntil turnOffLights
- \printuntil /^\ {16}<\//
-
- When we receive the \c updateLights event, we first want to send a
- \c updateScore event outside of the state machine. We pass
- the current values of the \c highScore and \c score variables to the event.
- This event is received by the C++ part.
-
- Next, depending on whether we are in \c jackpotStateOn or \c jackpotStateOff,
- we send the \c turnOnJackpot or the \c turnOffJackpot event,
- which instructs the \c guiControl state to transition to
- \c jackpotLightOn or \c jackpotLightOff, respectively.
-
- When the machine is in \e idle state, (that is, in the off state)
- or when the game is on, but no interaction occurs,
- the \c updateLights event is delivered periodically
- during the game, each time with the \c lightImpulseOn or
- \c lightImpulseOff state toggled. Depending on the
- current state of the light impulse and on the active state (\c offState,
- \c hurryStateOff or \c hurryStateOn), we turn on or off all the lights
- according to the description of the pinball table.
-
- \section1 GUI Part: User Interface Description
-
- The GUI part of the application consists of a \e mainwindow.ui
- file which describes the static user interface of the game.
-
- \target cpp
- \section1 C++ Part: Glue GUI with SCXML
-
- The C++ part of the application consists of a
- \c MainWindow class which glues the GUI part with the SCXML part.
- The class is declared in \e mainwindow.h.
-
- \quotefromfile pinball/mainwindow.h
- \skipto MainWindow
- \printuntil };
-
- The \c MainWindow class holds the pointer to the
- \c {QScxmlStateMachine *m_machine} which is the state machine
- class automatically generated by Qt out of SCMXL file
- and the pointer to the \c {Ui::MainWindow *m_ui} which
- describes the GUI part. It also declares two helper methods.
-
- \quotefromfile pinball/mainwindow.cpp
- \skipto #include
- \printuntil /\}$/
-
- The constructor of the \c MainWindow class
- instantiates the GUI part of the application
- and stores the pointer to the passed \c QScxmlStateMachine.
- It also initializes the GUI part and glues the
- GUI part to the state machine by connecting
- their communication interfaces together.
-
- The \c initAndConnect() method connects
- the state with the corresponding GUI widget by
- binding its activity with the enabling of the widget,
- so that whenever the state is active, its corresponding
- widget is enabled and whenever the state is inactive,
- the widget is disabled. We do that for all lights, targets,
- and description labels.
-
- We also intercept the \c updateScore event sent by the state machine,
- in order to update the score displays with the values
- passed with the event.
-
- The info about hitting any GUI target needs to be passed
- to the state machine and we do that by connecting
- all target buttons' \c clicked signals to the lambda expressions
- which submit the corresponding event into the state machine.
-
- \quotefromfile pinball/main.cpp
- \skipto #include
- \printuntil /\}$/
-
- In the \c main() function in the \e main.cpp file, we instantiate the
- \c app application object, \c Pinball state machine,
- and \c MainWindow GUI class. We initialize and start the state machine,
- show the main window, and execute the application.
-*/