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.
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]
Figure D.2: Several rectangle morphs
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
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].
The width of the torpedo is 4 pixels and its height 8 pixels:
Torpedo>>morphExtent ^ `4 @ 8`
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.
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]
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]
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)
../..