The Fundamentals of Morph

Exercise 7.1

The drawOn: method is modified to draw two distinct, unconnected lines:

LineExampleMorph>>drawOn: aCanvas
   aCanvas strokeWidth: 20 color: Color green do: [
      aCanvas
         moveTo: 0 @ 0;
         lineTo: 200 @ 200;
         moveTo: 200 @ 0;
         lineTo: 0 @ 200 ]

Learn how the #moveTo: message moves the pencil to a given position with the pen up, then the #lineTo: asks the pencil to draw from that previous position to this new position.

Exercise 7.2

We create a RectangleExampleMorph, subclass of PlacedMorph:

PlacedMorph subclass: #RectangleExampleMorph
   instanceVariableNames: 'fillColor'
   classVariableNames: ''
   poolDictionaries: ''
   category: 'Morphic-Learning'

Then its necessary methods to initialize and to draw the morph:

initialize
   super initialize .
   fillColor := Color random alpha: 0.5

drawOn: aCanvas
   aCanvas
      strokeWidth: 1
      color: Color blue
      fillColor: fillColor
      do: [
         aCanvas moveTo: 0 @ 0;
            lineTo: 200 @ 0;
            lineTo: 200 @ 100;
            lineTo: 0 @ 100;
            lineTo: 0 @ 0]
E-exeRectMorph

Figure D.2: Several rectangle morphs

Exercise 7.3

Among the clock parts (submorphs) we only need to modify the drawing of the ClockSecondHandMorph class. The disc is surrounded with a thin red line and filled in yellow.

ClockSecondHandMorph>>drawOn: aCanvas
   aCanvas strokeWidth: 1.5 color: Color red do: [
      aCanvas
         moveTo: 0 @ 0;
         lineTo: 85 @ 0 ].
   aCanvas ellipseCenter: 0 @ -70 radius: 3 @ 3 
      borderWidth: 1 
      borderColor: Color red fillColor: Color yellow

Exercise 7.4

On top of the drawOn: method, we also want the acceleration variable to take a range of values between 0 and 50.

SpaceShip>>push
"Init an accelaration boost"
   fuel isZero ifTrue: [^ self].
   fuel := fuel - 1.
   acceleration := (acceleration + 10) min: 50
SpaceShip>>unpush
"Stop the accelaration boost"
   acceleration := acceleration - 5 max: 0
drawOn: canvas
../..
"Draw gas exhaust"
   acceleration ifNotZero: [
      canvas
         line: c
         to: 0 acceleration
         width: 1 + acceleration / 8
         color: Color orange].

Exercise 7.5

The width of the torpedo is 4 pixels and its height 8 pixels:

Torpedo>>morphExtent
   ^ `4 @ 8`

Exercise 7.6

The Torpedo’s drawOn: method is very similar to the one in SpaceShip class:

Torpedo>>drawOn: canvas
   | a b c |
   a := 0 @ -4.
   b := -2 @ 4.
   c := 2 @ 4.
   canvas line: a to: b width: 2 color: color.
   canvas line: c to: b width: 2 color: color.
   canvas line: a to: c width: 2 color: color.

Exercise 7.7

We use a local variable because we use two times the vertices, one to draw the ship and a second time to draw the gas exhaust.

SpaceShip>>drawOn: canvas
   | vertices  |
   vertices := self class vertices.
   canvas line: vertices first to: vertices second width: 2 color: color.
   canvas line: vertices second to: vertices third width: 2 color: color.
   canvas line: vertices third to: vertices fourth width: 2 color: color.
   canvas line: vertices fourth to: vertices first width: 2 color: color.
   "Draw gas exhaust"
   acceleration ifNotZero: [
      canvas line: vertices third to: 0@35 width: 1 color: Color gray]

Exercise 7.8

You need both to iterate each vertex of the vertices array and access the subsequent vertex by index. The arithmetic reminder operation #\\ is needed to keep the index in the boundary of the collection.

When size is 4 (Space ship diagram), the argument (i \\ size + 1) takes alternatively the following values:

Mobile>>drawOn: canvas polygon: vertices
   | size |
   size := vertices size.
   vertices withIndexDo: [: aPoint :i |
      canvas
         line: aPoint
         to: ( vertices at: (i  \\ size + 1) )
         width: 2
         color: color]

Exercise 7.9

Just replace each morph position distance approach with the intersection detection between the morphs’ display bounds:

SpaceWar>>collisionsShips
   (ships first collides: ships second)
   ../..

SpaceWar>>collisionsShipsTorpedoes
   ships do: [:aShip | 
      torpedoes do: [:aTorpedo |
         (aShip collides: aTorpedo)
   ../..

SpaceWar>>collisionsTorpedoesStar
   torpedoes do: [:each | 
      (each collides: centralStar)
   ../..