5.6 Spacewar!’s methods

You are already acquainted to the writing of simple methods for the Spacewar! game. We will write some more and learn how to categorize them.

5.6.1 Initializing the game play

We want to add the initialize method to our SpaceWar class. Of course we need to use the System Browser: ...World menu → Open...Browser...

As a reminder, proceed as follows (if necessary observe Figure 2.1):

  1. In the Class Category pane at the far left, scroll down to the Spacewar! category, then select it.
  2. In the Class pane, select the class SpaceWar.
  3. Below, click the instance button to expose the instance side methods of the SpaceWar class. It is the default behavior of the browser anyway, so you can skip this step as long as you have not clicked on the class button.
  4. In the Method Category pane, select the category -- all --. A method source code template shows up in the pane below:
    messageSelectorAndArgumentNames
      "comment stating purpose of message"
      | temporary variable names |
      statements
    

    The template comes in four lines: the method name, a comment, local variable declaration and statements. You can select all and delete it or edit each line of the template as needed.

    In our case, we select it all and replace it with the SpaceWar>>initialize source code:

    SpaceWar>>initialize
      "We want to capture keyboard and mouse events, 
      start the game loop(step) and initialize the actors."
      super initialize.
      color := self defaultColor.
      self setProperty: #'handlesKeyboard' toValue: true.
      self setProperty: #'handlesMouseOver:' toValue: true.
      self startSteppingStepTime: self stepTime.
      self initializeActors
    

    Example 5.7: Initialize SpaceWar

  5. Once edited, save-it with Ctrl-s or ...right click → Accept (s)...

The newly created method shows up in the Method pane. You can get it categorized automatically too: with the mouse, go over the Method Category pane ...right click → categorize all uncategorized (c)..

 CuisLogo In the SpaceWar class, add the teleport: method as defined in Example 5.3 then categorize it in the events method category.

Exercise 5.3: Categorize a method

5.6.2 Space ship controls

In a previous chapter, you wrote as an exercise simple implementation of the control ship methods. The definitive control methods of the SpaceShip class are rewritten as:

SpaceShip>>push
  "Init an acceleration boost"
  fuel isZero ifTrue: [^ self].
  fuel := fuel - 1.
  acceleration := 50

SpaceShip>>unpush
  "Stop the acceleration boost"
  acceleration := 0

SpaceShip>>right
  "Rotate the ship to its right"
  self heading: self heading + 0.1
  
SpaceShip>>left
  "Rotate the ship to its left"
  self heading: self heading - 0.1

Example 5.8: Ship controls

Observe the right and left methods, they are mostly identical to the ones asked in Exercise 3.12. We don’t modify directly the heading attribute, we use the methods heading: and heading to read and write this information.

 CuisLogo Categorize the control methods in a newly created method category named control.

Exercise 5.4: Categorize control methods

Control will not be complete without the method to fire a torpedo. It is more complex to correctly initialize a torpedo. This is because a space ship is typically in motion, and in addition its heading and velocity are changing frequently. Therefore the torpedo must be set up according to the current space ship position, heading, and velocity before being fired.

SpaceShip>>fireTorpedo
  "Fire a torpedo in the direction of
  the ship heading with its velocity"
  | torpedo | 
  torpedoes isZero ifTrue: [ ^ self].
  torpedoes := torpedoes - 1.
  torpedo := Torpedo new.
  torpedo 
    position: position + self nose;
    heading: self heading;
    velocity: velocity;
    color: self color muchLighter.
  owner addTorpedo: torpedo

Example 5.9: Firing a torpedo from a space ship in motion

ch05-SpacewarGamePlay

Figure 5.1: Spacewar! torpedoes around

5.6.3 Collisions

In a previous chapter we gave a small taste of the collision detection code between the space ships and the central star. It relies on iterator, block of code and control flow.

However we have other scenarios as ship-ship, torpedo-Sun and torpedo-ship collisions.

 CuisLogo How will you write the method to detect the collision between the two ships and take action accordingly? (Adapt from Example 4.23).

Exercise 5.5: Ships collision

The detection between the two ships and the possible numerous torpedoes required two enumerators with nested blocks of code:

SpaceWar>>collisionsShipsTorpedoes
ships do: [:aShip | 
  torpedoes do: [:aTorpedo |
    (aShip morphPosition dist: aTorpedo morphPosition) < 15 ifTrue: [
      aShip flashWith: Color red.
      aTorpedo flashWith: Color orange.
      self destroyTorpedo: aTorpedo.
      self teleport: aShip]
  ]
]

Example 5.10: Collision between the ships and the torpedoes

The last torpedo-Sun scenario collision is left as an exercise for you.

 CuisLogo Write the method to detect the collisions between the torpedoes and the central star and take action accordingly. (Adapt from Example 4.23 and Example 5.10.)

Exercise 5.6: Collision between the torpedoes and the Sun