example을 직접 만들어서 구동해본다!
1. Basic Drawing
우선 BasicDrawing을 만들어서 사각형을 그려보았다.
bool content(tvg::Canvas* canvas, uint32_t w, uint32_t h)override
{
auto shape = tvg::Shape::gen();
shape->appendRect(100,100,100,100);
shape->fill(0,255,255);
canvas->add(shape);
return true;
}
2. Basic Animation
그리고 애니메이션을 과제로 제출해보고 싶어서 애니메이션을 만드는 코드를 짰다.
여기서 삽질을 좀 했는데 다른 CustomTransform의 코드를 보고 사각형을 생성하고 x위치에 1.0f씩 더하는 코드를 짰다. 빌드하고 실행했는데 잔상이 남아있었다. 알고보니 main 함수에서 tvgexam::main을 실행할 때 4번째 인자인 clearBuffer에 true를 전달해줘야 이전에 그려진 그림이 사라졌다.
struct UserExample : tvgexam::Example
{
float y=100.0f;
bool content(tvg::Canvas* canvas, uint32_t w, uint32_t h)override
{
return update(canvas,0);
}
bool update(tvg::Canvas* canvas, uint32_t elapsed) override
{
if (!tvgexam::verify(canvas->remove())) return false;
auto progress = tvgexam::progress(elapsed, 5.0f, true);
float x = 100.0f + progress * 500.0f;
// 사각형 생성
auto shape = tvg::Shape::gen();
shape->appendRect(x, y, 100, 100);
shape->fill(0, 255, 255);
canvas->add(shape);
return true;
}
};
결과물
3. Scramble Text
이제 드디어 scramble text를 구현해볼 차례이다.
text는 랜덤 문자열에서 ThorVG Scramble Text를 점점 맞춰가는 방식으로 구현하려고 한다.
단계를 구상하는 부분은 직접 했지만 c++ 코드를 작성하는 부분에 있어서는 claude의 도움을 많이 받았다.(사실은 과제를 하는 시간이 늦은 시간이라 구현을 맡겼다.)
단계는
- 표시하고자 하는 텍스트와 랜덤 문자열을 준비한다.
- 원본 문자열에서 먼저 표시할 부분의 index 배열을 랜덤으로 섞어 order에 저장한다.
- 0.1초 단위로 최대 애니메이션을 수행한다.
- 미리 만들어둔 order index를 이용해 랜덤 문자열에서 original text로 점점 변환해간다.
struct UserExample : tvgexam::Example
{
const char* originalText = "ThorVG Scramble Text";
const char* randomText = "!<>-_\\/[]{}=+*^?#________";
vector<int> order;
string scrambled;
uint32_t lastStep = UINT32_MAX;
void mix()
{
order.resize(strlen(originalText));
iota(order.begin(), order.end(), 0);
static mt19937 rng{random_device{}()};
shuffle(order.begin(), order.end(), rng);
}
bool content(tvg::Canvas* canvas, uint32_t w, uint32_t h) override
{
if(!tvgexam::verify(tvg::Text::load(EXAMPLE_DIR"/font/PublicSans-Regular.ttf"))) return false;
mix();
return true;
}
bool update(tvg::Canvas* canvas, uint32_t elapsed) override
{
if (!tvgexam::verify(canvas->remove())) return false;
//0.1초 단위로만 문자열 재생성
auto step = elapsed / 100;
if (step != lastStep) {
lastStep = step;
auto len = strlen(originalText);
auto fixed = min<size_t>(size_t(elapsed) * len / 2600, len);
static mt19937 rng{random_device{}()};
uniform_int_distribution<size_t> dist(0, strlen(randomText) - 1);
scrambled.clear();
for (size_t i = 0; i < len; ++i) {
auto end = order.begin() + fixed;
if (find(order.begin(), end, int(i)) != end) {
scrambled += originalText[i];
} else {
scrambled += randomText[dist(rng)];
}
}
}
auto displayText = tvg::Text::gen();
displayText->font("PublicSans-Regular");
displayText->text(scrambled.c_str());
displayText->size(48);
displayText->fill(255, 255, 255);
displayText->translate(100, 100);
canvas->add(displayText);
return true;
}
};
댓글
Discussion 원문