source: trunk/doc/src/examples/rogue.qdoc@ 1168

Last change on this file since 1168 was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

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