SqueakByExample:11.8

From 흡혈양파의 번역工房
Jump to navigation Jump to search
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.

완전한 예제

주사위(die)[1]를 굴리기 위한 morph 를 만들어보겠습니다 morph 를 클릭하면, 빠른 반복을 통해 모든면이 변경되어 표시되며, 다시 클릭을 하면 애니메이션을 멈추는 동작이 되도록 할것입니다.


그림 11.8: Morphic 에서의 주사위


Squeak comment.pngMorph 대신에 BorderedMorph의 서브클래스로 die 를 정의하도록 하겠습니다.. 왜나하면 여기서 테두리를 활용할 것이기 때문입니다.


클래스 11.27: 주사위 morph 정의하기

BorderedMorph subclass: #DieMorph
  instanceVariableNames: 'faces dieValue isStopped'
  classVariableNames: ''
  poolDictionaries: ''
  category: 'SBE-Morphic'


인스턴스 변수 faces 는 주사위에 대한 면의 개수를 기록하며, 여기서는 주사위의 면들을 9 개까지 지정하도록 하겠습니다.

dieValue는 현재 표시되고있는 면의 값을 나타내며, isStopped 는 주사위의 애니메이션이 정지된경우 true 가 됩니다. 주사위의 인스턴스를 만들기 위해, DieMorph 의 class side 에 faces: n 메서드를 정의해서, n 개의 면을 가지는 새로운 주사위를 만들어 보겠습니다.


메서드 11.28: 선호하는 면의 개수를 가지는 새로운 주사위를 만들기

DieMorph class>>faces: aNumber
   self new faces: aNumber


initialize 메서드는 이전과 같은 방식으로 instance side 에서 정의합니다. 덧붙이자면 New 는 새롭게 만들어진 인스턴스에 initialize를 전송한다는 것을 기억해 주십시오.


메서드 11.29: DieMorph의 인스턴스 초기화 하기

DieMorph>>initialize
  super initialize.
  self extent: 50 @ 50.
  self useGradientFill; borderWidth: 2; useRoundedCorners.
  self setBorderStyle: #complexRaised.
  self fillStyle direction: self extent.
  self color: Color green.
  dieValue := 1.
  faces := 6.
  isStopped := false


주사위(die)의 모양새를 보다 좋게 하게 위해서, BorderedMorph 의 메서드를 몇가지 사용하겠습니다: 입체적인 효과를 얻기 위해서 테두리선을 굵게하거나, 모서리를 다듬거나, 보이는면에 그라디언트를 적용한다던가 등의 작업을 합니다. instance side 의 faces: 메서드는, 올바른 인자가 주어지고 있는지를 점검하기 위한 내용을 정의합니다.

메서드 11.30: 주사위 면의 개수를 설정하기

DieMorph>>faces: aNumber
  "Set the number of faces"
  (aNumber isInteger
      and: [aNumber > 0]
      and: [aNumber <= 9])
    ifTrue: [faces := aNumber]


주사위를 만들었을 때, 메시지가 전송되는 순서를 리뷰하는 것이 좋습니다. 예를 들어, DieMorph face:9 을 평가한다고 가정해 보겠습니다:

  1. 클래스 메서드 DieMorph class>>faces: 는 DieMorph 클래스에 new 메시지를 발송합니다.
  2. new 메서드(Behavior 클래스로부터 상속된 DieMorph 클래스)를 이용해서, 새로운 인스턴스가 생성되고 initialize 를 생성된 인스턴스에 발송합니다.
  3. DieMorph 에서의 initialize 메서드는 faces 를 초기 값 6 으로 설정합니다.
  4. DieMorph class>>new 메서드를 실행하면 새로운 인스턴스를 만든후, 새로 만들어진 인스턴스에 클래스 메서드인 DieMorph class>>faces: 에 faces: 9메시지를 발송합니다.
  5. 인스턴스 메서드인 DieMorph>>faces: 가 실행되며 인스턴스 변수인 faces 를 9 로 설정합니다.


drawOn: 메서드를 정의하기 전에, 표시되는 면에 그리는 눈의 위치를 요구하는 메서드를 몇개 만들어보겠습니다.


메서드 11.31: die 의 faces 에 점 그림을 배치하기 위한 9 개의 메서드

DieMorph>>face1
  {0.5@0.5}
DieMorph>>face2
  {0.25@0.25 . 0.75@0.75}
DieMorph>>face3
  {0.25@0.25 . 0.75@0.75 . 0.5@0.5}
DieMorph>>face4
  {0.25@0.25 . 0.75@0.25 . 0.75@0.75 . 0.25@0.75}
DieMorph>>face5
  {0.25@0.25 . 0.75@0.25 . 0.75@0.75 . 0.25@0.75 . 0.5@0.5}
DieMorph>>face6
  {0.25@0.25 . 0.75@0.25 . 0.75@0.75 . 0.25@0.75 . 0.25@0.5 . 0.75@0.5}
DieMorph>>face7
  {0.25@0.25 . 0.75@0.25 . 0.75@0.75 . 0.25@0.75 . 0.25@0.5 . 0.75@0.5 . 0.5@0.5}
DieMorph>>face8
  {0.25@0.25 . 0.75@0.25 . 0.75@0.75 . 0.25@0.75 . 0.25@0.5 . 0.75@0.5 . 0.5@0.5 . 0.5@0.25}
DieMorph>>face9
  {0.25@0.25 . 0.75@0.25 . 0.75@0.75 . 0.25@0.75 . 0.25@0.5 . 0.75@0.5 . 0.5@0.5 . 0.5@0.25 . 0.5@0.75}


각 좌표는 1 x 1 크기의 사각형 범위안에 있습니다; 보여지는 면에 표시될 점의 현재 값은 그대로 사용하기에는 너무 작기때문에, 실제 표시작업에 사용하기 위해서는 값을 조절해야 합니다.


drawOn: 메서드는 두 가지 작업을 수행합니다: 주사위의 배경을 그리기 위해서 super 클래스로 메시지를 전송하며, 주사위에 들어갈 점을 그립니다.


메서드 11.32: 주사위 morph 그리기

DieMorph>>drawOn: aCanvas
  super drawOn: aCanvas.
  (self perform: ('face' , dieValue asString) asSymbol)
    do: [:aPoint | self drawDotOn: aCanvas at: aPoint]


위 메서드의 뒷부분은 스몰토크의 replection 기능을 사용합니다. 주사위의 면에 점을 그리는 작업은, faceX 메서드로부터 얻은 좌표의 콜렉션에 대해서, 순서대로 각 좌표에 대한 drawDotOn:at: 메시지를 보내서 진행합니다. 알맞은 faceX 메서드를 호출하기 위해, perform: 메서드를 사용해서, ('face', dieValueasString) asSymbol 에 의해 만들어진 string 을 메시지로 전송합니다. 이런식의 perform: 메서드에 대한 사용법은 몇번 더 보게 될겁니다.


메서드 11.33: 면에 한개의 점 그리기

DieMorph>>drawDotOn: aCanvas at: aPoint
  aCanvas
    fillOval: (Rectangle
      center: self position + (self extent * aPoint)
      extent: self extent / 6)
    color: Color black


좌표의 숫자범위는 현재 [0:1] 사이에 있기때문에, 주사위의 크기에 맞게 점의 좌표를 계산하기 위해서 self extent * aPoint 를 사용해서 좌표값을 변경하도록 하겠습니다.


Squeak comment.png워크스페이스를 통해서 주사위 인스턴스를 만들 수 있습니다.:

(DieMorph faces: 6) openInWorld.


주사위의 보여지는 면을 바꾸기 위해서, myDie dieValue: 4 와 같은 동작이 가능한 접근자accessor 를 만들어보겠습니다.

메서드 11.34: 주사위(die)의 현재 값을 설정하기

DieMorph>>dieValue: aNumber
  (aNumber isInteger
      and: [aNumber > 0]
      and: [aNumber <= faces])
    ifTrue:
      [dieValue := aNumber.
      self changed]


이제 주사위의 모든 면을 빠르게 보여주기 위한 애니메이션 시스템을 사용할 것입니다:


메서드 11.35: 주사위에 애니메이션 효과 주기

DieMorph>>stepTime
   100

DieMorph>>step
  isStopped ifFalse: [self dieValue: (1 to: faces) atRandom]


이제 주사위가 작동합니다!

클릭으로 애니메이션을 시작하거나 멈추기 위해, 이전에 마우스 이벤트에 관해 배운 내용을 적용해 보겠습니다. 먼저, 마우스 이벤트의 수신을 활성화합니다:


메서드 11.36: 애니메이션을 시작하고 멈추기 위해 마우스 클릭 처리하기

DieMorph>>handlesMouseDown: anEvent
   true

DieMorph>>mouseDown: anEvent
  anEvent redButtonPressed
    ifTrue: [isStopped := isStopped not]


이제 주사위를 클릭하면, 주사위가 돌아갑니다.


Notes

  1. NB: One die, two dice