Obviously our Spacewar! game handles events. Firstly we want to control the ships with the keyboard. Secondly, we want the game to pause when the mouse cursor moves out of the game play, and resume when it enters again.
In our design, a unique morph, SpaceWar
instance, models the
game play. Therefore we want this instance to handle the events
described above.
We want to catch events when the mouse cursor moves over our
SpaceWar
morph.
Which method should return true to let the game play be notified with a dedicated messages that the mouse cursor enters or leaves? In which class should we implement this method?
Once we make explicit we want the game play to receive mouse move-over events, we need to set the behavior accordingly with dedicated methods.
Each time the mouse cursor enters the game play, we want to:
HandMorph
instance, an
event object (see event classes hierarchy at the beginning of this
chapter). An event object is interrogated about its hand with the
#hand
message. All in all, we want the keyboard focus to be
targeted toward our game play when the mouse enters:
event hand newKeyboardFocus: self
self startStepping
Which message is sent to the game play to be notified the mouse cursor enters the game play area? How should the matching method be written?
We also want to be informed when the mouse cursor leaves our
SpaceWar
morph. Thanks to the work done in
Exercise 8.1, we already informed Cuis-Smalltalk we want to be
notified of mouse movement over the game play. However we need to code
the behavior when the mouse cursor leaves the game play:
event hand releaseKeyboardFocus: self
self stopStepping
Which message is sent to the game play to be notified the mouse cursor leaves the game play area? How should we write the overridden method?
In graphic user interface, a visual effect is often used to inform the user the keyboard focus changed. In Spacewar! we change the game play background depending on the state of the keyboard focus.
In Figure 8.1, at the left keyboard focus is on the game; at the right keyboard focus is not on the game, it is paused and we can see underneath.
In the Morph framework, the #keyboardFocusChange:
message is sent
to the morph losing or gaining the keyboard focus, its parameter is a
Boolean. Therefore we implement the Figure 8.1 behavior in the
matching SpaceWar
’s method keyboardFocusChange:
SpaceWar>>keyboardFocusChange: gotFocus gotFocus ifTrue: [color := self defaultColor] ifFalse: [color := self defaultColor alpha: 0.5]. self redrawNeeded
To control the space ships, we use the keyboard. Therefore we want the game play to be notified of keyboard events.
Find out which method should return true to let the game be notified of keyboard event.
We can decide to be notified of the key down or key up event and also
key down then up event (key stroke). As long as our
SpaceWar
morph responds true to the #handlesKeyboard
message, it receives the messages #keyUp:
, #keyDown:
and
#keyStroke:
. By default, the matching methods in the
Morph
class do nothing.
The argument of these messages is a KeyboardEvent
object to
which, among other things, you can ask the #keyCharacter
of the
pressed key or test about some special keys as the keyboard
arrows. The first player ship – the green one – is controlled with
the keyboard arrows when there are stroked:
SpaceWar>>keyStroke: event event isArrowUp ifTrue: [^ ships first push]. event isArrowRight ifTrue: [^ ships first right]. event isArrowLeft ifTrue: [^ ships first left]. event isArrowDown ifTrue: [^ ships first fireTorpedo]. ...
To control the second player ship, we use another classic arrangement in QWERTY keyboard controlled game: WASD27.
Append the additional code to Example 8.2 to control the second player ship with the keys WASD. As a reminder, in Smalltalk the character code for q can be written as
$q
.