1// Copyright 2020 Google LLC. 2// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. 3#include "tools/fiddle/examples.h" 4REG_FIDDLE_ANIMATED(Turtle, 256, 256, false, 0, 2) { 5// Simple turtle based graphics. The turtle starts out at 128, 128, looking North, pen down. 6// The input string is read left to right (but see 'r' below). Commands are a single character, 7// sometimes followed by additional arguments: 8// 9// u : Raises the pen 10// d : Lowers the pen 11// + : Reads integer N, rotates turtle N degrees clockwise 12// - : Reads integer N, rotates turtle N degrees counterclockwise 13// f : Reads integer N, moves turtle forwards N units 14// r : Reads integer N, then separator character C. C should be some non-digit, non-command 15// character. Repeats all commands after C until the next instance of C, N times. Can be 16// nested. 17//const char* input = "r2[r3(f50+90f50+90f50+90f50(+45uf50d["; 18//const char* input = "r360|f1+1|"; 19const char* input = "uf100+91dr180|f3+2|+89uf60+90r2$f20-90dr60|f1+6|u-90f20$-90f50-90f30d+180f60uf1000"; 20 21struct Turtle { float x; float y; float h; bool p; } t; 22 23const SkPaint& p() { 24 static SkPaint paint; 25 paint.setColor(SK_ColorBLACK); 26 paint.setAntiAlias(true); 27 paint.setStyle(SkPaint::kStroke_Style); 28 paint.setStrokeWidth(0); 29 return paint; 30} 31 32const char* eval(SkCanvas* canvas, const char* s, char e, float& dist, float& l, bool pt) { 33 while (*s != e) { 34 switch(*s++) { 35 case 'u': t.p = false; break; 36 case 'd': t.p = true; break; 37 case '+': t.h += atoi(s); break; 38 case '-': t.h -= atoi(s); break; 39 case 'f': { 40 float d = atoi(s); 41 d = std::min(d, l); 42 dist += d; l -= d; 43 float r = t.h * 0.01745329f; 44 Turtle nt = { t.x + sinf(r) * d, t.y - cosf(r) * d, t.h, t.p }; 45 if (pt && t.p) canvas->drawLine(t.x, t.y, nt.x, nt.y, p()); 46 t = nt; 47 break; 48 } 49 case 'r': { 50 int c = atoi(s); 51 while (*s >= '0' && *s <= '9') { ++s; } 52 auto n = s+1; 53 for (int i = 0; i < c; ++i) { n = eval(canvas, s+1, *s, dist, l, pt); } 54 s = n; 55 } 56 } 57 } 58 return s+1; 59} 60 61void draw(SkCanvas* canvas) { 62 canvas->clear(SK_ColorWHITE); 63 64 t = { 128, 128, 0, true }; 65 float totalDist = 0; 66 float l = 1E9f; 67 eval(canvas, input, 0, totalDist, l, false); 68 69 l = frame * totalDist; 70 t = { 128, 128, 0, true }; 71 eval(canvas, input, 0, totalDist, l, true); 72} 73} // END FIDDLE 74