doc/src/examples/rogue.qdoc
branchRCL_3
changeset 7 3f74d0d4af4c
equal deleted inserted replaced
6:dee5afe5301f 7:3f74d0d4af4c
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the documentation of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 /*!
       
    43     \example statemachine/rogue
       
    44     \title Rogue Example
       
    45 
       
    46     The Rogue example shows how to use the Qt state machine for event
       
    47     handling.
       
    48 
       
    49     \image rogue-example.png
       
    50 
       
    51     This example implements a simple text based game. Do you see the
       
    52     \c{@} in the screenshot? That's you, the rogue. The \c{#}
       
    53     characters are walls, and the dots represent floor. In a real
       
    54     game, other ASCII characters would represent all kinds of objects
       
    55     and creatures, for instance, ancient dragons (\c{D}s) or food
       
    56     rations (\c{%}s). But let's not get carried away. In this game,
       
    57     the rogue is simply running around in an empty room.
       
    58 
       
    59     The rogue is moved with the keypad (2, 4, 8, 6). That aside, we
       
    60     have implemented a \c quit command that triggers if the player
       
    61     types \c {q}. The player is then asked if he/she really wants to
       
    62     quit.
       
    63 
       
    64     Most games have commands that need more than one key press (we
       
    65     think of consecutive presses, i.e., not of several keys being
       
    66     pressed at the same time). In this game, only the \c quit command
       
    67     falls under this category, but for the sake of argument, let's
       
    68     imagine a fully-fledged game with a rich set of commands. If we
       
    69     were to implement these by catching key events in
       
    70     \l{QWidget::}{keyPressEvent()}, we would have to keep a lot of
       
    71     class member variables to track the sequence of keys already typed
       
    72     (or find some other way of deducing the current state of a
       
    73     command). This can easily lead to spaghetti, which is--as we all
       
    74     well know, I'm sure--unpleasant. With a state machine, on the
       
    75     other hand, separate states can wait for a single key press, and
       
    76     that makes our lives a lot simpler.
       
    77 
       
    78     The example consists of two classes:
       
    79 
       
    80     \list
       
    81         \o \c Window draws the text display of the game and sets
       
    82             up the state machine. The window also has a status bar
       
    83             above the area in which the rouge moves.
       
    84         \o \c MovementTransition is a transition that carries out
       
    85             a single move of the rogue.
       
    86     \endlist
       
    87 
       
    88     Before we embark on a code walkthrough, it is necessary to take a
       
    89     closer look at the design of the machine. Here is a state chart
       
    90     that shows what we want to achieve:
       
    91 
       
    92     \image rogue-statechart.png
       
    93 
       
    94     The input state waits for a key press to start a new command.
       
    95     When receiving a key it recognizes, it transitions to one of the
       
    96     two commands of the game; though, as we will see, movement is
       
    97     handled by the transition itself. The quit state waits for the
       
    98     player to answer yes or no (by typing \c y or \c n) when asked
       
    99     whether he/she really wants to quit the game.
       
   100 
       
   101     The chart demonstrates how we use one state to wait for a single
       
   102     key press. The press received may trigger one of the transitions
       
   103     connected to the state.
       
   104 
       
   105     \section1 Window Class Definition
       
   106 
       
   107     The \c Window class is a widget that draws the text display of the
       
   108     game. It also sets up the state machine, i.e., creates and
       
   109     connects the states in the machine. It is the key events from this
       
   110     widget that are used by the machine.
       
   111 
       
   112     \snippet examples/statemachine/rogue/window.h 0
       
   113 
       
   114     \c Direction specifies the direction in which the rogue is to
       
   115     move. We use this in \c movePlayer(), which moves the rogue and
       
   116     repaints the window. The game has a status line above the area in
       
   117     which the rogue moves. The \c status property contains the text of
       
   118     this line. We use a property because the QState class allows
       
   119     setting any Qt \l{Qt's Property System}{property} when entered.
       
   120     More on this later.
       
   121 
       
   122     \snippet examples/statemachine/rogue/window.h 1
       
   123 
       
   124     The \c map is an array with the characters that are currently
       
   125     displayed. We set up the array in \c setupMap(), and update it
       
   126     when the rogue is moved. \c pX and \c pY is the current position
       
   127     of the rogue. \c WIDTH and \c HEIGHT are macros specifying the
       
   128     dimensions of the map.
       
   129 
       
   130     The \c paintEvent() function is left out of this walkthrough. We
       
   131     also do not discuss other code that does not concern the state
       
   132     machine (the \c setupMap(), \c status(), \c setStatus(), \c
       
   133     movePlayer(), and \c sizeHint() functions). If you wish to take a
       
   134     look at the code, click on the link for the \c window.cpp file at
       
   135     the top of this page.
       
   136 
       
   137     \section1 Window Class Implementation
       
   138 
       
   139     Here is the constructor of \c Window:
       
   140 
       
   141     \snippet examples/statemachine/rogue/window.cpp 0
       
   142     \dots
       
   143     \snippet examples/statemachine/rogue/window.cpp 1
       
   144 
       
   145     The player starts off at position (5, 5). We then set up the map
       
   146     and statemachine. Let's proceed with the \c buildMachine()
       
   147     function:
       
   148 
       
   149     \snippet examples/statemachine/rogue/window.cpp 2
       
   150 
       
   151     We enter \c inputState when the machine is started and from the \c
       
   152     quitState if the user wants to continue playing. We then set the
       
   153     status to a helpful reminder of how to play the game.
       
   154 
       
   155     First, the \c Movement transition is added to the input state.
       
   156     This will enable the rogue to be moved with the keypad.  Notice
       
   157     that we don't set a target state for the movement transition. This
       
   158     will cause the transition to be triggered (and the
       
   159     \l{QAbstractTransition::}{onTransition()} function to be invoked),
       
   160     but the machine will not leave the \c inputState. If we had set \c
       
   161     inputState as the target state, we would first have left and then
       
   162     entered the \c inputState again.
       
   163 
       
   164     \snippet examples/statemachine/rogue/window.cpp 3
       
   165 
       
   166     When we enter \c quitState, we update the status bar of the
       
   167     window.
       
   168     
       
   169     \c QKeyEventTransition is a utility class that removes the hassle
       
   170     of implementing transitions for \l{QKeyEvent}s. We simply need to
       
   171     specify the key on which the transition should trigger and the
       
   172     target state of the transition.
       
   173 
       
   174     \snippet examples/statemachine/rogue/window.cpp 4
       
   175 
       
   176     The transition from \c inputState allows triggering the quit state
       
   177     when the player types \c {q}.
       
   178     
       
   179     \snippet examples/statemachine/rogue/window.cpp 5
       
   180 
       
   181     The machine is set up, so it's time to start it.
       
   182 
       
   183     \section1 The MovementTransition Class
       
   184 
       
   185     \c MovementTransition is triggered when the player request the
       
   186     rogue to be moved (by typing 2, 4, 6, or 8) when the machine is in
       
   187     the \c inputState.
       
   188 
       
   189     \snippet examples/statemachine/rogue/movementtransition.h 0
       
   190 
       
   191     In the constructor, we tell QEventTransition to only send
       
   192     \l{QEvent::}{KeyPress} events to the
       
   193     \l{QAbstractTransition::}{eventTest()} function:
       
   194 
       
   195     \snippet examples/statemachine/rogue/movementtransition.h 1
       
   196 
       
   197     The KeyPress events come wrapped in \l{QStateMachine::WrappedEvent}s. \c event
       
   198     must be confirmed to be a wrapped event because Qt uses other
       
   199     events internally. After that, it is simply a matter of checking
       
   200     which key has been pressed.
       
   201 
       
   202     Let's move on to the \c onTransition() function:
       
   203 
       
   204     \snippet examples/statemachine/rogue/movementtransition.h 2
       
   205 
       
   206     When \c onTransition() is invoked, we know that we have a
       
   207     \l{QEvent::}{KeyPress} event with 2, 4, 6, or 8, i.e., the event
       
   208     is already unwrapped.
       
   209 
       
   210     \section1 The Roguelike Tradition
       
   211 
       
   212     You might have been wondering why the game features a rogue. Well,
       
   213     these kinds of text based dungeon exploration games date back to a
       
   214     game called, yes, "Rogue". Although outflanked by the technology
       
   215     of modern 3D computer games, roguelikes have a solid community of
       
   216     hard-core, devoted followers.
       
   217 
       
   218     Playing these games can be surprisingly addictive (despite the
       
   219     lack of graphics). Angband, the perhaps most well-known rougelike,
       
   220     is found here: \l{http://rephial.org/}.
       
   221 */
       
   222