삽질하는플머

책장 넘기는 효과 구현하기 - 3.

여가생활/산수공부

1편 - http://oranke.tistory.com/119

2편 - http://oranke.tistory.com/120


어디 제약될 필요 없는 블로그질이라고 해도... 시작한 일은 끝을 봐야 하는 법인데 너무 오래 끌었다. 

지난번 글 이후 초딩이던 큰아들놈은 중학생이 되었고, 신생아였던 둘째가 초딩이 되었으니 세월이 많이 흐르기는 했다. 

블로그 검색로그에 간간히 남아있는 "책장 넘기기 효과"를 보며 어떤 형태로건 마무리를 지어야지 라고 생각하였다. 

(사실... 하드 정리하다가 짱박혀있던 소스를 발견한 이유가 크지만...)


기억을 되살리기 위해 이전 강좌에서 언급했던 몇가지 변수를 되짚어보자. 


  • MvTL - 상단 모서리 이동점
  • MvBL - 하단 모서리 이동점
  • 접힘점1 - 책장이 접힌 위쪽 좌표
  • 접힘점2 - 책장이 접힌 아래쪽 좌표


MvTL값을 임의 위치에 놓고 다른 점들을 비례식으로 계산할 때, MvTL 위치를 적절히 제한해주어야 한다는 것이 지난 글의 마지막이었다. 

그렇다면 어떤 녀석을 구속조건으로 삼으면 좋을까. 


페이지가 이동할 때 접힘점 1과 2, 그리고 이동점간의 관계를 가만히 생각해보자. 


접힘점1을 적당한 위치에 고정하고 이동점 MvTL을 이리저리 움직여보면, 접힘점 2는 책장의 수직부분과 하단부분 내에서 위치하게 된다. 책장이 찢어지지 않는 이상 이 범위를 벗어나지 않게 되므로 0~1 사이의 비율값으로 나타낼 수 있다. 상단, 하단, 수직부분의 비율값을 각각 조절비율 rT, rB, rM 이라고 부르자. 


기준점 MvTL이 주어질 때의 조절비율을 계산하고, 얻어진 비율값을 0~1 사이로 제한한 뒤 다시 기준점을 계산하면, 책장의 모양이 유지되는 적절한 위치값들을 얻을 수 있다. 조금 복잡하게 들릴지 몰라도 어차피 계산은 컴퓨터가 하는 것이니 일단 시켜보자. 


비율변화를 적절히 제한하고 또 구현을 편하게 하기 위해 스크롤바 컨트롤을 사용했다. 

폼 위에 ScrollT, ScrollM, ScrollB 세 개의 TScrollBar를 올리고 Min값은 0, Max값은 10000으로 설정한다. 








마우스가 눌린 Y좌표에 따라 페이지 윗부분을 움직일지, 아니면 아래부분을 움직일지 여부를 결정하기 위해 적절한 타입을 정의하자. 


type

  TRateCalcType = (rctTop, rctBottom);


var
  RateCalcType: TRateCalcType;




이 값은 폼의 MouseDown 이벤트에서 할당한다. 


procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton;

  Shift: TShiftState; X, Y: Integer);

begin

  // 화면의 세로 기준으로 절반을 넘어가면 하단을 기준으로 계산.

  if Y > (ClientHeight / 2) then

    RateCalcType := rctBottom

  else

    RateCalcType := rctTop;

......





비율계산타입 RateCalcType과 페이지의 폭, 너비, 그리고 MvTL값을 기준으로 지난번의 비례식을 사용해 rT, rM, rB를 계산해보자. 


CalcPagePosRate





이렇게 계산된 비율값으로부터 다시 상, 하단 이동점들과 접힘점들을 계산하는 함수는 다음과 같다. 

CalcPageInfo





폼의 마우스 이동에서 계산한 비율을 스크롤바에 던지고, OnChange 이벤트에서 화면을 적절히 구성한 결과물은 다음과 같다. 






소스와 실행파일은 여기에. 터보델파이로 빌드되었다. 


BookTest.7z



앞의 코드에서 언급된 TVector2f 및 벡터연산 함수는 여기 포함된 소스를 참고하자. 

위의 설명이 조금 이상하더라도 마우스와 스크롤바를 이리저리 옮겨보면 글쓴놈의 의도가 금방 이해 될 것이다. 




함께 포함된 BookTest2.exe 는 MvTL 위치선정함수(CalcMoveBasePos)의 테스트코드를 풀고 적절한 댐퍼를 추가한 것이다. 

왠지 그럴듯해 보이지 않는가??? 




-----

마우스 위치에 따라 "division by zero" 예외가 발생합니다. 
이전에 다운받았던 분들은 Unit1.pas 의 말미에 initialization 섹션을 추가하고 다음 코드를 넣어주세요. 

......

initialization
  Set8087CW($133F);

end.