> For the complete documentation index, see [llms.txt](https://sungcheol-kim.gitbook.io/fractal-graphics-with-opengl/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://sungcheol-kim.gitbook.io/fractal-graphics-with-opengl/turtle_graphics.md).

# 부록 : 거북이 그래픽스의 이해

## Turtle Graphics?

거북이 그래픽스는 전진과 회전의 두가지 동작으로만 그래픽을 그리는 것으로 그래픽스 프로그래밍의 가장 기초가 된다. 가장 기초가 되지만 재귀 호출과 함께 사용되면 너무나 신비한 그림을 만들어낸다. 아마 그 놀라움에 입을 다물지 못 할 것이다.

이번 장에서는 필자가 파이썬의 터틀그래픽스 라이브러리를 축약하여 BCB 용으로 만든 터틀그래픽스 라이브러리의 설치와 사용법을 알아보고 간단한 거북이 그래픽스를 해볼 것이다. 거북이 그래픽스를 활용하는 것은 프랙탈을 배울 때까지 우선 미루어 놓자.

## BCB 거북이 그래픽 라이브러리 설치

필자가 만든 [거북이 그래픽스 라이브러리](https://github.com/skyfe79/FractalTutorial/tree/master/turtle-graphics/turtle_lib)를 받으면 위의 3가지 파일이 압축되어 있다. 압축을 푼 후 거북이 그래픽스를 할 프로젝트 디렉토리에 복사하길 바란다.

![](/files/-M3x20etNvR3_NVcTECk)

그런 후 아래처럼 프로젝트 메니져에 Turtle.lib 파일을 추가한다.

![](/files/-M3x20evk1C6SS1_mjwv)

그런 다음 메인 폼의 유닛 파일에 다음과 같이 코드를 입력한다. 여기서 말하는 프로젝트는 그래픽스 템플릿 으로부터 파생된 프로젝트를 말한다.

```cpp
// header file
#include "Turtle.h"

class TMainForm : public TForm
{
    ...
    Graphics::TBitmap* OffScreen;
    INT16 VideoModeX, VideoModeY;
    /**/Turtle turtle; 
    ... 
};
```

```cpp
source file
void __fastcall TMainForm::FormCreate(TObject *Sender)
{
    ...

    OffScreen = new Graphics::TBitmap();
    OffScreen->Width = VideoModeX;
    OffScreen->Height = VideoModeY;

    /**/turtle.AttachCanvas(OffScreen->Canvas);
    /**/turtle.SetStartPoint(OffScreen->Width/2-15, OffScreen->Height/2-40);


    ... 
}
```

이 것으로 거북이 그래픽스를 할 모든 준비가 끝났다. 위에서 turtle 은 거북이 그래픽스 라이브러리의 인스턴스로 우리와 즐겁게 놀 거북이이다 ;) turtle.AttachCanvas() 메서드는 거북이가 돌아다닐 모래사장을 정하는 것과 같다. 우리는 오프스크린 비트맵에 그릴 것이므로 그것의 캔바스를 거북이에게 설정했다. turtle.SetStartPoint() 메서드는 거북이가 출발할 위치를 설정한다. 폼의 중간에서 약간 좌상단 쯤 되는 위치다.

## Turtle 클래스 메서드 소개

* Turtle(void)
  * 거북이를 생성한다.
* Turtle(TCanvas\* Canvas)
  * 거북이를 생성하지만 생성시 거북이가 돌아다닐 캔바스를 설정할 수 있다.
* void AttachCanvas(TCanvas\* Canvas)
  * 거북이가 돌아다닐 캔바스를 설정한다.
* TCanvas\* GetCanvas(void)
  * 현재 거북이가 돌아다니고 있는 캔바스를 얻어 온다
* void SetStartPoint(int x, int y)
  * 거북이가 출발할 시작 위치를 설정한다.
* void Forward(double length)
  * length 만큼 앞으로 전진한다.
* void Backward(double length)&#x20;
  * length 만큼 뒤로 후진한다.
* void Left(double angle)
  * angle 만큼 왼쪽(반시계방향)으로 회전한다.
* void Right(double angle)
  * angle 만큼 오른쪽(시계방향)으로 회전한다.
* void Up(void)
  * 거북이를 들어 올린다;) 즉 이 함수를 실행하면 Forward() 및 Backward() 를 해도 거북이가 지나간 흔적이 그려지지 않는다.
* void Down(void)
  * 거북이를 내려 놓는다;) 즉 이 함수를 실행하면 Forward() 및 Backward() 를 하면 거북이가 지나간 흔적이 그려진다.&#x20;

    거북이가 생성될 때 기본 모드는 Down() 으로 되어 있다.

## 즐거운 Turtle 그래픽스의 세계로 ;)

자\~ 이제 거북이 그래픽스의 세계로 떠날 모든 준비가 끝난 것 같다. 그럼 즐겁게 거북이를 움직여 볼까? ;) 참고로, 여기에 나오는 코드는 모두 DrawGraphics() 의 메서드안에서 수행되는 것이다.

우선 다음 코드를 입력해보자.

```cpp
turtle.Forward(100);
turtle.Right(360/3); 
Sleep(50);
Flip();
```

![결과](/files/-M3x20exGlWo55I0E7Xa)

위처럼 정 삼각형이 그려졌는가? 이 번에는 사각형을 그려보자.

```cpp
turtle.Forward(100);
turtle.Right(360/4);
Sleep(50);
Flip();
```

![결과](/files/-M3x20ezddHSFL_cyIqj)

거북이 그래픽스가 더욱더 재미 있다. 삼각형은 각이 3개인 도형이다. 따라서 360/3 을 하면 삼각형을 그리기 위해 필요한 회전각을 구할 수 있다. 사각형은 각이 4개인 도형이다. 역시 360/4 를 하면 사각형을 그리기 위한 회전각을 구할 수 있다. 그렇다면 원은 어떻게 그릴까? 예전에 그리스의 수학자 아르키메데스는 원의 넓이를 구하기 위해서 넓이를 구하고자 하는 원에 내접하는 사각형에서 하나하나 각을 늘려나가면서 이 각의 수를 무한대로 생각하여 원의 넓이를 구했다. 그렇다 원은 각이 무한개로 있는 도형으로 생각할 수 있다. 하지만 여기서는 360 개의 각이 있는 원을 그려보겠다. 360/360 = 1 로 회전각은 1이다.

```cpp
turtle.Forward(1);
turtle.Right1(1);
Sleep(50);
Flip();
```

![결과](/files/-M3x20f0wNsbJLovOciT)

회전각이 작을 수록 더 이쁜 원이 그려질 것이다. 밤하늘에 무엇이 뜨는가? 별이 뜬다. 자 그럼 별을 그려볼까?

```cpp
turtle.Forward(50);
turtle.Right(144);
Sleep(50);
Flip();
```

![결과](/files/-M3x20f2QwzByqs90EH2)

이제부터 단순한 반복이 낳는 아름다움을 살펴볼 것이다. 루프의 수와 회전각의 관계를 관심 있게 봐주길 바란다.

```cpp
for(int t=0; t<6; t++) //DrawGraphics 에서 그린다면 이 루프는 생략가능하다. 
{ 
    for(int i=0; i<6; i++)
    {
        turtle.Forward(40);
        turtle.Right(60);
        Sleep(50);
        Flip();
    }
    turtle.Right(60); 
}
```

![결과](/files/-M3x20f404SRAw-lh9O2)

60 \* 6 = 360 임을 안다면 루프카운터와 회전각의 관계를 알 것이다. 각이 더 많고 회전각이 작은 도형들을 그려보자.

```cpp
for(int i=0; i<12; i++)
{
    turtle.Forward(25);
    turtle.Right(30);
    Sleep(50);
    Flip();
}
turtle.Right(360/12);
```

![결과](/files/-M3x20f6SsRyQ78HAamx)

참 신기하지 않은가? 그럼 이번에는 가장 밖에 있는 turtle.Right() 메서드에 임의의 값을 주어보자.

```cpp
for(int i=0; i<12; i++)
{
    turtle.Forward(25);
    turtle.Right(30);
    Sleep(50);
    Flip();
}
turtle.Right(360/24);
```

![결과](/files/-M3x20f87of-OsJdJYin)

turtle.Up() 과 turtle.Down() 메서드로 점선 도형 그리기

```cpp
for(int i=0; i<5; i++)
{
    turtle.Forward(5);
    turtle.Up();
    turtle.Forward(5);
    turtle.Down();
    Sleep(50);
    Flip();
}
turtle.Right(360/4);
```

![결과](/files/-M3x20fAaJkoDbpM3NN_)

## 끝맺음

거북이 그래픽스를 이용해 간단한 도형그리기를 해 보았다. 느낌이 어떤까? 각의 수와 회전각등을 조절해서 여러 도형을 그려보길 바란다. 거북이 그래픽스는 여기서 끝나는 것이 아니다. 재귀호출을 만나면 거의 환상적인 모습으로 변신한다. 프랙탈은 후에 다루기로 하자! 필자가 아직 공부를 못 했다 ;) 그리고 위의 코드는 모두 다 DrawGraphics 메서드 안에서 수행됨을 말하며 루프문의 수행시간이 길어 진다면 루프의 안에 Application->ProcessMessages(); 를 넣어주자. 그래야 루프 수행 중에도 예제 어플리케이션을 제어할 수 있다.
