Hal Canary | 8800042 | 2020-01-15 11:51:12 -0500 | [diff] [blame] | 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" |
| 4 | REG_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|"; |
| 19 | const char* input = "uf100+91dr180|f3+2|+89uf60+90r2$f20-90dr60|f1+6|u-90f20$-90f50-90f30d+180f60uf1000"; |
| 20 | |
| 21 | struct Turtle { float x; float y; float h; bool p; } t; |
| 22 | |
| 23 | const 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 | |
| 32 | const 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; |
John Stiles | 488654b | 2021-08-11 11:01:17 -0400 | [diff] [blame] | 44 | Turtle nt = { t.x + sinf(r) * d, t.y - cosf(r) * d, t.h, t.p }; |
Hal Canary | 8800042 | 2020-01-15 11:51:12 -0500 | [diff] [blame] | 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 | |
| 61 | void 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 |