Better docs, remove WIP Taruga interpreter code
[taruga.git] / include / taruga.hpp
blob09b63bfd4bcb0bd9e9e1a5e964cffe6b8a346e0e
1 /*
2 * taruga
3 * https://github.com/vrmiguel/taruga
5 * Copyright (c) 2020 Vinícius R. Miguel
6 * <vinicius.miguel at unifesp.br>
8 * Permission is hereby granted, free of charge, to any person obtaining a copy
9 * of this software and associated documentation files (the "Software"), to deal
10 * in the Software without restriction, including without limitation the rights
11 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 * copies of the Software, and to permit persons to whom the Software is
13 * furnished to do so, subject to the following conditions:
15 * The above copyright notice and this permission notice shall be included in all
16 * copies or substantial portions of the Software.
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 * SOFTWARE.
27 #ifndef __TARUGA_MAIN_HPP
28 #define __TARUGA_MAIN_HPP
30 #include <SFML/Graphics/RenderWindow.hpp>
31 #include <SFML/Graphics/Sprite.hpp>
32 #include <SFML/Graphics/Texture.hpp>
33 #include <SFML/Window/Event.hpp>
35 #include <cmath>
36 #include <stack>
37 #include <queue>
39 //! TODO:
40 //! Decide whether or not to include a second built-in icon
42 //! Holds a 32x32 PNG cute turtle icon
43 static const uint8_t __turtle_png[1479] = {
44 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d,
45 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x20,
46 0x08, 0x03, 0x00, 0x00, 0x00, 0x44, 0xa4, 0x8a, 0xc6, 0x00, 0x00, 0x00,
47 0x03, 0x73, 0x42, 0x49, 0x54, 0x08, 0x08, 0x08, 0xdb, 0xe1, 0x4f, 0xe0,
48 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x00, 0xdd,
49 0x00, 0x00, 0x00, 0xdd, 0x01, 0x70, 0x53, 0xa2, 0x07, 0x00, 0x00, 0x00,
50 0x19, 0x74, 0x45, 0x58, 0x74, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72,
51 0x65, 0x00, 0x77, 0x77, 0x77, 0x2e, 0x69, 0x6e, 0x6b, 0x73, 0x63, 0x61,
52 0x70, 0x65, 0x2e, 0x6f, 0x72, 0x67, 0x9b, 0xee, 0x3c, 0x1a, 0x00, 0x00,
53 0x02, 0x8b, 0x50, 0x4c, 0x54, 0x45, 0xff, 0xff, 0xff, 0x00, 0x80, 0x80,
54 0x00, 0x80, 0x80, 0x40, 0xff, 0x80, 0x4d, 0xe6, 0x66, 0xb3, 0xe6, 0x33,
55 0x5d, 0xe8, 0x5d, 0xb9, 0xe8, 0x2e, 0x4e, 0xeb, 0x62, 0xb1, 0xd8, 0x3b,
56 0x5b, 0xdb, 0x5b, 0xb6, 0xdb, 0x37, 0xbb, 0xdd, 0x33, 0xb8, 0xe3, 0x39,
57 0x00, 0xaa, 0x61, 0x55, 0xe7, 0x61, 0x55, 0xdf, 0x60, 0x00, 0xad, 0x5b,
58 0x84, 0xe5, 0x46, 0xbc, 0xda, 0x3c, 0x55, 0xe5, 0x62, 0xb7, 0xde, 0x3b,
59 0x00, 0x9f, 0x59, 0xb9, 0xdf, 0x39, 0xb6, 0xdb, 0x37, 0x51, 0xe2, 0x63,
60 0x53, 0xe3, 0x5e, 0xb7, 0xde, 0x37, 0x00, 0xa4, 0x57, 0xb7, 0xdd, 0x3a,
61 0x55, 0xe3, 0x5e, 0x55, 0xe3, 0x61, 0xba, 0xdf, 0x39, 0x52, 0xe4, 0x5e,
62 0x55, 0xe4, 0x61, 0xb9, 0xdc, 0x3a, 0xb8, 0xdd, 0x38, 0xba, 0xde, 0x3a,
63 0x53, 0xe2, 0x61, 0xbb, 0xdf, 0x39, 0x55, 0xe3, 0x60, 0x83, 0xe0, 0x4f,
64 0x00, 0xab, 0x5e, 0x81, 0xde, 0x4c, 0xb9, 0xde, 0x38, 0x0a, 0xae, 0x5a,
65 0x53, 0xe4, 0x5f, 0xba, 0xde, 0x3a, 0x00, 0xaa, 0x5d, 0x54, 0xe4, 0x5f,
66 0x55, 0xe2, 0x60, 0xba, 0xdc, 0x38, 0xb8, 0xde, 0x3a, 0xb9, 0xdd, 0x3a,
67 0xb8, 0xdd, 0x39, 0x00, 0xa0, 0x59, 0x7d, 0xe0, 0x50, 0x02, 0xa2, 0x59,
68 0x53, 0xe3, 0x60, 0xb8, 0xdd, 0x39, 0x54, 0xe3, 0x60, 0xb9, 0xde, 0x3a,
69 0x15, 0x9a, 0x4a, 0x00, 0x9f, 0x57, 0x53, 0xe3, 0x61, 0xb9, 0xde, 0x39,
70 0x00, 0xab, 0x5e, 0x54, 0xe2, 0x60, 0x79, 0xe1, 0x52, 0x54, 0xe3, 0x60,
71 0xb9, 0xdd, 0x3a, 0x00, 0xab, 0x5f, 0xb9, 0xdd, 0x39, 0x55, 0xe3, 0x60,
72 0x54, 0xe3, 0x60, 0xba, 0xdd, 0x39, 0x77, 0xe0, 0x52, 0xb9, 0xdd, 0x39,
73 0xb9, 0xde, 0x39, 0x54, 0xe3, 0x5f, 0x00, 0xab, 0x5f, 0xba, 0xde, 0x39,
74 0xb9, 0xdd, 0x39, 0x55, 0xe3, 0x60, 0x54, 0xe3, 0x60, 0xba, 0xdd, 0x39,
75 0x04, 0x8a, 0x46, 0x31, 0xc8, 0x5e, 0x8e, 0xd1, 0x43, 0x55, 0xe3, 0x60,
76 0xb9, 0xdd, 0x38, 0x55, 0xe3, 0x5f, 0xb9, 0xdd, 0x39, 0xb9, 0xdc, 0x39,
77 0x54, 0xe3, 0x60, 0x00, 0x9e, 0x57, 0x54, 0xe3, 0x60, 0xb9, 0xdd, 0x39,
78 0x54, 0xe3, 0x5f, 0xb9, 0xdd, 0x39, 0x53, 0xe3, 0x60, 0xb9, 0xdd, 0x39,
79 0x00, 0xab, 0x5e, 0x00, 0x9d, 0x56, 0x00, 0xa2, 0x57, 0x54, 0xe3, 0x60,
80 0x00, 0x96, 0x50, 0x3c, 0xbb, 0x52, 0xb9, 0xdd, 0x39, 0x00, 0x9d, 0x56,
81 0x2c, 0xb7, 0x55, 0x54, 0xe3, 0x60, 0x69, 0xe2, 0x59, 0x54, 0xe3, 0x60,
82 0x54, 0xe3, 0x60, 0xb9, 0xdd, 0x39, 0xb9, 0xdd, 0x39, 0x0a, 0xa6, 0x58,
83 0x54, 0xe3, 0x60, 0xb9, 0xdd, 0x39, 0x00, 0x9b, 0x55, 0x54, 0xe3, 0x5f,
84 0xb9, 0xdd, 0x39, 0xb9, 0xdd, 0x39, 0x00, 0x83, 0x44, 0x00, 0x8e, 0x4c,
85 0x0f, 0xa5, 0x55, 0x54, 0xe3, 0x60, 0xb9, 0xdd, 0x39, 0x00, 0x82, 0x41,
86 0x03, 0x98, 0x50, 0x08, 0xa3, 0x56, 0x0d, 0x98, 0x4b, 0x4a, 0xb2, 0x46,
87 0x54, 0xe3, 0x60, 0xb9, 0xdd, 0x39, 0x00, 0x75, 0x39, 0x00, 0x76, 0x39,
88 0x00, 0x76, 0x3a, 0x00, 0x77, 0x3a, 0x00, 0x78, 0x3b, 0x00, 0x79, 0x3c,
89 0x00, 0x7b, 0x3e, 0x00, 0x7c, 0x3e, 0x00, 0x7d, 0x3f, 0x00, 0x7e, 0x3f,
90 0x00, 0x7f, 0x40, 0x00, 0x80, 0x41, 0x00, 0x81, 0x41, 0x00, 0x81, 0x42,
91 0x00, 0x82, 0x42, 0x00, 0x82, 0x43, 0x00, 0x83, 0x43, 0x00, 0x85, 0x44,
92 0x00, 0x85, 0x45, 0x00, 0x87, 0x45, 0x00, 0x87, 0x46, 0x00, 0x88, 0x46,
93 0x00, 0x88, 0x47, 0x00, 0x89, 0x47, 0x00, 0x8d, 0x4b, 0x00, 0x8e, 0x4a,
94 0x00, 0x8e, 0x4b, 0x00, 0x8f, 0x4b, 0x00, 0x90, 0x4b, 0x00, 0x90, 0x4c,
95 0x00, 0x91, 0x4c, 0x00, 0x94, 0x4e, 0x00, 0x95, 0x4f, 0x00, 0x96, 0x50,
96 0x00, 0x96, 0x52, 0x00, 0x97, 0x52, 0x00, 0x99, 0x52, 0x00, 0x99, 0x54,
97 0x00, 0x9a, 0x53, 0x00, 0x9a, 0x54, 0x00, 0x9c, 0x54, 0x00, 0x9d, 0x55,
98 0x00, 0xa2, 0x58, 0x00, 0xa9, 0x5d, 0x00, 0xaa, 0x5d, 0x00, 0xaa, 0x5e,
99 0x00, 0xab, 0x5e, 0x01, 0x8f, 0x4c, 0x01, 0x9b, 0x55, 0x01, 0xab, 0x5e,
100 0x02, 0x9d, 0x56, 0x03, 0x85, 0x43, 0x06, 0xac, 0x5d, 0x07, 0xa3, 0x57,
101 0x09, 0xa5, 0x58, 0x0c, 0xa8, 0x58, 0x12, 0xb0, 0x5a, 0x14, 0xaf, 0x59,
102 0x1e, 0xb3, 0x58, 0x2b, 0xb8, 0x54, 0x2d, 0xc4, 0x5c, 0x37, 0xba, 0x53,
103 0x3c, 0xbb, 0x52, 0x3f, 0xcc, 0x5b, 0x3f, 0xd3, 0x5e, 0x40, 0xd3, 0x5e,
104 0x42, 0xbd, 0x51, 0x4b, 0xdc, 0x5f, 0x50, 0xe0, 0x60, 0x54, 0xe3, 0x60,
105 0x56, 0xe3, 0x5f, 0x57, 0xe3, 0x5f, 0x5a, 0xc3, 0x4c, 0x85, 0xc8, 0x3f,
106 0x88, 0xd0, 0x43, 0x9c, 0xd2, 0x3c, 0xa0, 0xd6, 0x3e, 0xa1, 0xd7, 0x3e,
107 0xaf, 0xda, 0x3b, 0xb5, 0xdc, 0x3a, 0xb9, 0xdd, 0x39, 0x36, 0xf4, 0x4c,
108 0x4d, 0x00, 0x00, 0x00, 0x88, 0x74, 0x52, 0x4e, 0x53, 0x00, 0x02, 0x04,
109 0x04, 0x0a, 0x0a, 0x0b, 0x0b, 0x0d, 0x0d, 0x0e, 0x0e, 0x0f, 0x12, 0x15,
110 0x15, 0x18, 0x1c, 0x1d, 0x22, 0x27, 0x27, 0x28, 0x28, 0x2a, 0x2c, 0x2e,
111 0x2e, 0x35, 0x35, 0x36, 0x3f, 0x3f, 0x41, 0x42, 0x42, 0x44, 0x46, 0x47,
112 0x47, 0x48, 0x4a, 0x4c, 0x4d, 0x4d, 0x4f, 0x56, 0x5c, 0x5d, 0x5e, 0x60,
113 0x60, 0x65, 0x6a, 0x70, 0x81, 0x83, 0x84, 0x90, 0x90, 0x92, 0x92, 0x95,
114 0x98, 0x99, 0x99, 0x9e, 0xa0, 0xa2, 0xa4, 0xa4, 0xaa, 0xaa, 0xac, 0xad,
115 0xad, 0xaf, 0xaf, 0xb0, 0xb3, 0xba, 0xbf, 0xc1, 0xc7, 0xc9, 0xca, 0xcc,
116 0xcf, 0xcf, 0xd0, 0xd0, 0xd3, 0xd3, 0xd6, 0xd8, 0xda, 0xda, 0xda, 0xdb,
117 0xdb, 0xdc, 0xdc, 0xe0, 0xe3, 0xe4, 0xe9, 0xea, 0xea, 0xea, 0xec, 0xed,
118 0xef, 0xef, 0xf0, 0xf1, 0xf6, 0xf7, 0xf8, 0xf9, 0xf9, 0xfb, 0xfb, 0xfb,
119 0xfc, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
120 0xfe, 0xa7, 0x5c, 0x18, 0x53, 0x00, 0x00, 0x02, 0x1a, 0x49, 0x44, 0x41,
121 0x54, 0x38, 0x4f, 0x75, 0xd2, 0xf9, 0x5b, 0x4c, 0x51, 0x18, 0x07, 0xf0,
122 0x83, 0x92, 0x7d, 0x27, 0x4a, 0x52, 0x76, 0x22, 0x6b, 0xb6, 0x42, 0x28,
123 0xfb, 0xbe, 0x65, 0x5f, 0xb2, 0xef, 0x2d, 0x84, 0xca, 0x56, 0x38, 0xd3,
124 0x36, 0x39, 0x97, 0x21, 0xc2, 0xd4, 0x84, 0x19, 0x1c, 0x14, 0x4d, 0x0a,
125 0x65, 0xdf, 0x8f, 0x25, 0xe1, 0xfc, 0x39, 0xce, 0x7b, 0xce, 0xdc, 0x99,
126 0x3b, 0xcf, 0xd3, 0xfd, 0xfe, 0x30, 0xcf, 0x7d, 0xe6, 0xfb, 0x99, 0x3b,
127 0xe7, 0x7d, 0xef, 0x45, 0xc8, 0x98, 0x18, 0xce, 0x19, 0x5b, 0x88, 0x4c,
128 0xd3, 0x3b, 0x1d, 0xc0, 0x8f, 0x11, 0xa6, 0x60, 0x19, 0x07, 0xc0, 0x0e,
129 0x9b, 0xf5, 0xc1, 0x5c, 0x01, 0x36, 0xcc, 0x04, 0xc4, 0xe8, 0xc0, 0xec,
130 0x14, 0xe3, 0x75, 0x30, 0xdb, 0x04, 0x44, 0xe9, 0x60, 0x92, 0x09, 0xe8,
131 0x70, 0x82, 0xff, 0xfb, 0xf3, 0xf9, 0x1b, 0xfb, 0xde, 0xad, 0xf9, 0xbe,
132 0xc5, 0xf0, 0x83, 0xaf, 0x6a, 0xdd, 0x94, 0x3e, 0xcb, 0x99, 0xd8, 0xb2,
133 0x99, 0x3a, 0x70, 0xda, 0x6e, 0x37, 0x84, 0x42, 0xb2, 0x57, 0x07, 0xf8,
134 0xb7, 0xfd, 0x17, 0x6c, 0x3d, 0x47, 0x6c, 0x55, 0x3a, 0x28, 0xcf, 0xc3,
135 0xb9, 0x5b, 0xe6, 0x87, 0x7b, 0xeb, 0xa0, 0xb8, 0x0b, 0xbc, 0xe9, 0x85,
136 0x43, 0x09, 0xd5, 0x5b, 0x1f, 0x7d, 0x62, 0xe7, 0x63, 0x5b, 0xab, 0x3e,
137 0x74, 0x87, 0x38, 0xfc, 0x7b, 0x77, 0xb5, 0x12, 0xaa, 0xa7, 0xf4, 0xa5,
138 0x98, 0x66, 0x7b, 0x08, 0xf4, 0x6d, 0x93, 0x45, 0xdf, 0x28, 0x7e, 0x0b,
139 0xc2, 0xe1, 0xb0, 0x5a, 0x65, 0x4f, 0xe9, 0x3b, 0x21, 0xb6, 0xb5, 0x11,
140 0x20, 0x11, 0xa6, 0xff, 0x09, 0x7f, 0x5f, 0x7d, 0x9d, 0x10, 0x82, 0x31,
141 0x2e, 0x90, 0x07, 0x7d, 0x0d, 0x1b, 0x49, 0x40, 0x68, 0x08, 0xf4, 0xfc,
142 0x03, 0x80, 0x2a, 0xa2, 0x3d, 0x78, 0x78, 0xad, 0x04, 0xe3, 0x72, 0x00,
143 0xf5, 0x00, 0xd8, 0x60, 0x34, 0x55, 0x82, 0x37, 0x00, 0x6e, 0x91, 0xbb,
144 0x70, 0x06, 0x0d, 0x17, 0x02, 0xa8, 0x93, 0x60, 0x0a, 0x5a, 0x27, 0xc1,
145 0x59, 0x97, 0xcb, 0x75, 0x87, 0x5c, 0x7d, 0x02, 0xe0, 0x5e, 0x1e, 0xbe,
146 0x78, 0x45, 0x44, 0x82, 0xb5, 0x28, 0xf3, 0xf4, 0x86, 0xf8, 0x71, 0x3d,
147 0xcf, 0x10, 0x88, 0x53, 0x8d, 0x79, 0x19, 0x43, 0x2c, 0x3d, 0xc6, 0xce,
148 0x58, 0x7f, 0xea, 0x38, 0x1a, 0xd0, 0x1e, 0x46, 0xd9, 0xeb, 0x74, 0x3a,
149 0x6f, 0x93, 0x92, 0xa7, 0x00, 0xee, 0xe7, 0xe3, 0x62, 0x4d, 0xd3, 0xb2,
150 0xe0, 0xfb, 0x76, 0x91, 0x9e, 0x5d, 0xcd, 0x84, 0x33, 0xdc, 0x80, 0x5b,
151 0x50, 0x6a, 0x53, 0x63, 0x6c, 0x46, 0xc6, 0x8c, 0x56, 0x53, 0x5c, 0x7a,
152 0x5c, 0x79, 0xb3, 0xd4, 0x82, 0xed, 0x00, 0xa6, 0xfb, 0x81, 0xae, 0xf2,
153 0x41, 0x95, 0x1a, 0xf7, 0xd0, 0xd7, 0x0f, 0xa0, 0xa5, 0xa2, 0xaf, 0x20,
154 0xb6, 0xb2, 0xb2, 0xa2, 0x22, 0x0b, 0x2e, 0x16, 0xfd, 0x01, 0xff, 0x3e,
155 0x2c, 0xa9, 0x16, 0x7a, 0xf9, 0x2c, 0xec, 0x52, 0xac, 0xe9, 0x63, 0xec,
156 0xa3, 0xd2, 0xf8, 0x97, 0x0a, 0xef, 0xd3, 0x04, 0xd1, 0xc0, 0x52, 0x23,
157 0x7c, 0x7d, 0xf7, 0x34, 0xce, 0x7f, 0x3f, 0xf7, 0xbd, 0x0f, 0x76, 0x4b,
158 0xfe, 0x47, 0xc6, 0x0e, 0x75, 0xf1, 0x82, 0xc5, 0xb0, 0xcc, 0x5f, 0x27,
159 0x7d, 0x6f, 0x54, 0xcd, 0x5b, 0xd8, 0xe2, 0x2c, 0xbd, 0x0f, 0xca, 0x90,
160 0xeb, 0xfe, 0xbb, 0x4f, 0x07, 0x47, 0xbe, 0xca, 0x35, 0xa7, 0xb4, 0xf2,
161 0x80, 0x41, 0x5c, 0x65, 0xf9, 0xc8, 0x39, 0x3b, 0xdd, 0xf4, 0xd8, 0xae,
162 0xc9, 0x2b, 0x98, 0x4a, 0x3f, 0x0f, 0x98, 0xa0, 0xfa, 0x45, 0x1d, 0xc5,
163 0x75, 0xa7, 0x5e, 0xe2, 0xa3, 0xf3, 0x12, 0x05, 0xc6, 0x78, 0x40, 0xf4,
164 0xaa, 0xfd, 0x19, 0x1b, 0xe7, 0x0e, 0x44, 0x86, 0x0c, 0x9d, 0xb7, 0xe9,
165 0xe8, 0x9e, 0x95, 0xa3, 0xc4, 0xd5, 0x7f, 0xbc, 0x59, 0x87, 0x09, 0x1b,
166 0x60, 0xeb, 0xd2, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae,
167 0x42, 0x60, 0x82
170 namespace taruga
173 //! \brief The Icon enum lets the user decide between the built-in icons, Turtle and (TODO) Arrow
175 enum class Icon : bool {
176 Turtle,
177 Arrow,
180 typedef uint8_t u8;
184 //! \brief The Verbosity enum defines the different options for console output verbosity
186 enum class Verbosity : uint8_t {
187 Quiet = 1,
188 Verbose = 2,
189 VeryVerbose = 3,
193 //! \brief The Instruction enum
195 enum class Instruction : uint8_t {
196 Rotate, //! Rotates the turtle by a given amount of degrees
197 Walk, //! Walks forwards (or backwards) by the given amount of units.
198 PenMovement, //! Puts the pen up or down.
199 LineChangeColor, //! Change the line color to something else
200 PopState, //! Returns the turtle state to that of the top of the state stack
201 PushState, //! Saves the current turtle state to the state stack
202 Screenshot, //! Screenshot of the current
203 NewWalkingSpeed, //! Sets a new walking speed
204 NewRotationSpeed, //! Sets a new rotation speed
205 //SpriteChangeColor, //! Change the icon color to something else
206 // Stamp, //! Permanently stamp the sprite at the current position and rotation
210 //! \brief The State struct is used when saving (or loading) the turtle state to (or from) the state stack
212 struct State {
213 float x, y;
214 float angle;
215 bool pen_state; //! True if the pen is down, false if the pen is up
216 sf::Color line_color;
217 State(float _x, float _y, float _angle, bool _pen_state, sf::Color _color) : x(_x), y(_y), angle(_angle), pen_state(_pen_state), line_color(_color) {}
221 //! \brief The Action struct represents a Taruga action, e.g. walking forward, turning right, etc.
223 struct Action {
224 union Data {
225 float new_rotation_speed; //! Used when setting a new rotation speed
226 float new_walking_speed; //! Used when setting a new walking speed
227 float walking_distance; //! Used when setting walking forward or backwards
228 float rotation_angle; //! Used when rotating
229 //sf::Vector2u next_pos; //! Used for teleports (sets the turtle directly in next_pos)
230 uint8_t next_color[3]; //! Used when changing icon color. Using an array here because sf::Color has non-trivial default constructor.
231 bool pen_down; //! Used when setting the pen up or down.
232 const char * filename;
235 Instruction instr;
236 Data data;
237 Action(Instruction m_instr, const Data& m_data) : instr(m_instr), data(m_data) {};
241 //! brief The Line struct holds the starting and ending point of a line.
243 struct Line
245 //! (xi, yi) is the initial point
246 //! (xf, yf) is the destination point
247 float xi, yi, xf, yf;
248 sf::Color color;
249 Line(float _xi, float _yi) : xi(_xi), yi(_yi) {};
250 Line(float _xi, float _yi, float _xf, float _yf, sf::Color c) : xi(_xi), yi(_yi), xf(_xf), yf(_yf), color(c) {};
251 Line(float _xi, float _yi, sf::Color c) : xi(_xi), yi(_yi), color(c) {};
254 class Turtle{
255 private:
256 static constexpr double deg_to_rad = 3.14159265358979323846/180.0;
257 void init(); //! Initializes the variables with their default values
258 std::vector<Line> lines; //! All lines to be drawn.
259 sf::RenderWindow window; //! Window where the scene will be rendered
260 std::string title; //! The window's title
261 std::queue<Action> actions; //! The queue of actions that the turtle is going to do.
262 std::stack<State> states; //! The stack of turtle states. Used with pop_state() and push_state().
263 sf::Texture texture; //! The image to be used on the sprite. Kept in VRAM.
264 sf::Sprite sprite; //! The turtle's sprite.
265 sf::Color line_color; //! The current color of the line the turtle draws
266 sf::Event event; //! Checks for window events
267 bool _pen_down; //! If the pen is up, the turtle will not draw while walking around
268 float walk_spd; //! Turtle's current velocity
269 float angle; //! Turtle's current heading angle in [0, 360)
270 float rot_vel; //! Turtle's rotational velocity
271 uint16_t width; //! Rendering window width
272 uint16_t height; //! Rendering window height
273 float x, y; //! Current positions
275 void _pop_state(); //! Internal logic to pop the state stack and return to a previous state
276 void _push_state(); //! Internal logic to push the state stack in order to save the current state
277 void _save_to_image(const char *); //! Save a screenshot
278 void _move_pen(bool); //! Sets the pen up or down
279 void _draw_line(Line); //! Draws the given line
280 void _draw_sprite(); //! Draws the sprite into the window
281 void _idle(); //! Keeps rendering a static scene. Runs when there are no more actions to do.
282 void _walk(float); //! Internal logic for walking forward in the current heading angle
283 void _rotate(float); //! Internal logic for rotating by a given amount of degrees
284 void _draw_all_lines(bool clear_screen = true); //! Draws all saved lines
285 public:
287 Verbosity verbosity; //! Toggles the verbosity level (Quiet, Verbose or VeryVerbose).
288 void set_window_title(const char* new_title);
289 Turtle() : width(800), height(600) { init(); }
290 Turtle(uint16_t _wth, uint16_t _hgt) : width(_wth), height(_hgt) { init(); }
291 explicit Turtle(const sf::Vector2f& p) : width(p.x), height(p.y) { init(); }
292 void save_to_image(const char *); //! Saves the current window view to an image with the given filename
293 void set_line_color(sf::Color); //! Sets the new color of the line the turtle will draw.
294 void set_line_color(u8, u8, u8); //! Sets the new color of the line the turtle will draw.
295 void set_line_color(u8[3]); //! Sets the new color of the line the turtle will draw.
296 void pen_up(); //! Sets the pen up so lines don't get drawn
297 void pen_down(); //! Sets the pen down so that the turtle draws a line wherever it walks
298 void set_icon(Icon); //! Allows to switch around between the two built-in icons: turtle or straight arrow.
299 void set_icon(sf::Texture); //! Allows for any image to be used as an icon. Do notice that Taruga won't scale the texture. If needed, use the Turtle::scale method.
300 void go_to(float x, float y); //! Transports the turtle to a new point (line not drawn)
301 void go_to(const sf::Vector2f); //! Transports the turtle to a new point (line not drawn)
302 void scale(float, float); //! Scales the turtle sprite
303 void forward(float units); //! Walk forward the given amount of units.
304 void backwards(float units); //! Walk backwards the given amount of units. The same as using forward() with a negative parameter.
305 void turn_right(float ang); //! Turns right by the specified amount of degrees.
306 void set_walking_speed(float); //! Sets a new walking speed
307 void set_rotation_speed(float); //! Sets a new rotation speed
308 void push_state(); //! Saves the current state in a stack
309 void pop_state(); //! Returns the Turtle's state to the top of the state stack
310 void turn_left(float ang); //! Turns left by the specified amount of degrees.
311 void act(); //! Start moving the turtle. Will deplete the actions queue.
312 std::queue<Action> get_queue(); //! Returns a copy of the action queue. Used by the interpreter
315 std::queue<Action> Turtle::get_queue()
317 return actions;
320 void Turtle::set_walking_speed(float new_speed)
322 Action::Data data; data.new_walking_speed = new_speed;
323 actions.push(Action(Instruction::NewWalkingSpeed, data));
326 void Turtle::set_rotation_speed(float new_speed)
328 Action::Data data; data.new_rotation_speed = new_speed;
329 actions.push(Action(Instruction::NewRotationSpeed, data));
332 void Turtle::_pop_state()
334 if(states.empty())
336 if(verbosity >= Verbosity::Verbose)
338 fprintf(stderr, "pop_state() called with an empty state stack.\n");
341 const State backup_state = states.top();
342 this->x = backup_state.x;
343 this->y = backup_state.y;
344 this->angle = backup_state.angle;
345 this->_pen_down = backup_state.pen_state;
346 this->line_color = backup_state.line_color;
347 sprite.setRotation(backup_state.angle);
348 sprite.setPosition(x, y);
349 _draw_sprite();
350 states.pop();
353 void Turtle::_push_state()
355 State backup_state(x, y, angle, _pen_down, line_color);
356 states.push(backup_state);
359 void Turtle::pop_state()
361 Action::Data data; //! We don't really have any data to use here
362 actions.push(Action(Instruction::PopState, data));
365 void Turtle::push_state()
367 Action::Data data;
368 actions.push(Action(Instruction::PushState, data));
371 void Turtle::save_to_image(const char * _filename)
373 Action::Data data; data.filename = _filename;
374 actions.push(Action(Instruction::Screenshot, data));
377 void Turtle::_save_to_image(const char * filename)
379 _draw_all_lines();
380 _draw_sprite();
381 sf::Vector2u window_size = window.getSize();
382 sf::Texture window_texture;
383 window_texture.create(window_size.x, window_size.y);
384 window_texture.update(window);
385 sf::Image screenshot = window_texture.copyToImage();
386 screenshot.saveToFile(filename);
390 void Turtle::_move_pen(bool m_pen_down)
392 Action::Data data; data.pen_down = m_pen_down;
393 actions.push(Action(Instruction::PenMovement, data));
396 void Turtle::pen_up()
398 this->_move_pen(false);
401 void Turtle::pen_down()
403 this->_move_pen(true);
406 void Turtle::set_line_color(sf::Color color)
408 this->set_line_color(color.r, color.g, color.b);
411 void Turtle::set_line_color(u8 r, u8 g, u8 b)
413 Action::Data data;
414 data.next_color[0] = r; data.next_color[1] = g; data.next_color[2] = b;
415 actions.push(Action(Instruction::LineChangeColor, data));
418 void Turtle::set_line_color(u8 color[3])
420 this->set_line_color(color[0], color[1], color[2]);
423 void Turtle::turn_left(float deg)
425 this->turn_right(-deg);
428 void Turtle::turn_right(float deg)
430 deg -= deg >= 360.0 ? 360. : 0.; //! Likewise, we must decrease the angle if it's too big
431 Action::Data data; data.rotation_angle = deg;
432 actions.push(Action(Instruction::Rotate, data));
435 void Turtle::forward(float units)
437 Action::Data data; data.walking_distance = units;
438 actions.push(Action(Instruction::Walk, data));
441 void Turtle::backwards(float units)
443 this->forward(-units);
446 void Turtle::_draw_all_lines(bool clear_screen)
448 if (clear_screen)
450 window.clear(sf::Color::White);
452 for (auto line : lines)
454 sf::Vertex line_vertices[2] = {
455 sf::Vertex(sf::Vector2f(line.xi, line.yi)),
456 sf::Vertex(sf::Vector2f(line.xf, line.yf))
458 line_vertices[0].color = line.color;
459 line_vertices[1].color = line.color;
460 window.draw(line_vertices, 2, sf::Lines);
464 void Turtle::_draw_line(Line new_line)
466 _draw_all_lines();
468 if (_pen_down)
470 sf::Vertex line_vertices[2] = {
471 sf::Vertex(sf::Vector2f(new_line.xi, new_line.yi)),
472 sf::Vertex(sf::Vector2f(new_line.xf, new_line.yf))
475 line_vertices[0].color = new_line.color;
476 line_vertices[1].color = new_line.color;
478 window.draw(line_vertices, 2, sf::Lines);
482 void Turtle::_draw_sprite()
484 _draw_all_lines();
485 window.draw(sprite);
486 window.display();
490 //! \brief Turtle::_rotate is the internal function that rotates the sprite.
492 void Turtle::_rotate(float deg)
494 if(verbosity >= Verbosity::Verbose)
496 fprintf(stderr, "Turtle::_rotate(%.2f) started. Current angle: %.2f.\n", deg, this->angle);
499 sprite.setOrigin(16, 16);
500 //! At the end of the procedure, the final angle must be equal to `obj`.
501 const float obj = this->angle + deg;
502 if (deg > 0)
504 for (; this->angle < obj; this->angle+=this->rot_vel)
506 sprite.setRotation(this->angle);
507 this->_draw_sprite();
509 } else {
510 for (; this->angle > obj; this->angle-=this->rot_vel)
512 sprite.setRotation(this->angle);
513 this->_draw_sprite();
517 //! The angles need to be in the [0, 360) range
518 //! If the angle is negative, we make it positive again
519 this->angle += this->angle < 0 ? 360. : 0.;
520 //! Likewise, we must decrease the angle if it's too big
521 this->angle -= this->angle >= 360.0 ? 360. : 0.;
523 if(verbosity == Verbosity::VeryVerbose)
525 fprintf(stderr, "Turtle::_rotate(%.2f) finished. Current angle: %.2f. Current pos.: (%0.2f, %0.2f)\n", deg, this->angle, this->x, this->y);
531 //! \brief Turtle::_walk is the internal function that animates the walking of the turtle.
532 //! Note: This function does not draw a straight line during its mid-steps (but arrives where it needs to arrive in the end) and that is an intentional choice.
533 //! If you'd like to make your turtle move straight in the direction it needs to go, update the midsteps with the same calculation used on `ep`.
535 void Turtle::_walk(float distance)
537 if (verbosity >= Verbosity::Verbose)
539 fprintf(stderr, "Turtle::_walk(%.2f) started. Current pos: (%0.2f, %0.2f). Current angle: %f\n", distance, this->x, this->y, angle);
542 //! Converts the current angle to radians
543 const float ang_rad = angle*deg_to_rad;
545 //! ep := the final point
546 const sf::Vector2f ep (x + sin(ang_rad) * distance, y - cos(ang_rad) * distance);
548 float x_spd = 0., y_spd = 0.f; //! The speed in which the turtle will walk in the x and y direction
549 int x_iters = 0, y_iters = 0; //! How many times we'll update each coordinate
551 if (x > ep.x)
553 x_spd = -walk_spd; //! Our end-point has a smaller x-coord, so we have to decrease it.
554 } else if (x < ep.x) {
555 x_spd = walk_spd; //! Our end-point has a greater x-coord, so we have to decrease it.
556 } //! if x == ep.x, the default of 0.0f will keep them equal
558 x_iters = std::abs((x - ep.x)/walk_spd); //! Approximately how many times we'll have to update the x-coord.
560 //! The same logic applies to the y-coordinate
561 if (y > ep.y)
563 y_spd = -walk_spd;
564 } else if (y < ep.y)
566 y_spd = walk_spd;
569 y_iters = std::abs((y - ep.y)/walk_spd); //! Approximately how many times we'll have to update the y-coord.
571 Line line(x, y, this->line_color);
573 //! As cited before, this will make the turtle walked in a "crooked" way, but at the end, his position and the line drawn will be correct.
574 //! I prefer this as, in most cases, the movement done by the turtle looks similar to that of the threading of a needle, which I think is aesthetically pleasing.
575 while((x_iters >= 0) || (y_iters >= 0))
577 if (x_iters-- >= 0) { x += x_spd; }
578 if (y_iters-- >= 0) { y += y_spd; }
579 line.xf = x; line.yf = y;
580 sprite.setPosition(x, y);
581 _draw_line(line);
582 window.draw(sprite);
583 window.display();
586 //! The loop above may only get us close to the correct end-point, so we'll guarantee that we're getting there correctly now.
587 sprite.setPosition(ep);
588 line.xf = x = ep.x;
589 line.yf = y = ep.y;
590 _draw_sprite();
592 if (_pen_down)
594 //! We only need to save this line if the pen was down
595 lines.push_back(line);
598 if(verbosity == Verbosity::VeryVerbose){
599 fprintf(stderr, "Turtle::_walk(%.2f) finished. Current pos: (%.2f, %.2f).\n", distance, this->x, this->y);
604 //! \brief Turtle::init initializes Turtle variables
606 void Turtle::init()
608 this->verbosity = Verbosity::Quiet;
609 this->x = width/2;
610 this->y = height/2;
611 this->rot_vel = 0.5;
612 this->_pen_down = true;
613 this->walk_spd = 0.25;
614 this->angle = 0;
615 this->line_color = sf::Color::Black;
619 //! \brief Turtle::_idle keeps rendering a static scene
621 void Turtle::_idle()
623 //! TODO: check for window events here
624 for (;;) { _draw_all_lines(); window.draw(sprite); window.display(); }
627 void Turtle::set_window_title(const char * new_title)
629 this->window.setTitle(new_title);
632 void Turtle::set_icon(sf::Texture t)
634 //! TODO: check lifetime
635 texture = t;
636 sprite.setTexture(t);
639 void Turtle::set_icon(Icon icon)
641 if (icon == Icon::Arrow)
643 //! TODO
644 } else {
645 texture.loadFromMemory(__turtle_png, 1479);
648 sprite.setTexture(texture);
653 //! \brief Turtle::act runs through the action queue and animates the turtle
655 void Turtle::act()
657 window.setFramerateLimit(60);
658 if (title.empty())
660 title = "Ruga Window";
662 if (sprite.getTexture() == nullptr)
664 //! Icon not set, default to turtle.
665 set_icon(Icon::Turtle);
668 if(verbosity >= Verbosity::Verbose)
670 fprintf(stderr, "\nStarting act() with actions.size() = %lu\n", (unsigned long) actions.size());
673 sprite.setPosition(x, y);
675 window.create(sf::VideoMode(width, height), title);
677 while (window.isOpen())
679 while (window.pollEvent(event))
681 if (event.type == sf::Event::Closed) { window.close(); }
684 //! If there are no more actions to do, idle until user closes the window
685 if(actions.empty()) { _idle(); } //! TODO: check events within _idle
687 Action &current = actions.front();
689 switch (current.instr)
691 case Instruction::Rotate:
692 _rotate(current.data.rotation_angle);
693 break;
694 case Instruction::Walk:
695 _walk(current.data.walking_distance);
696 break;
697 case Instruction::PenMovement:
698 _pen_down = current.data.pen_down;
699 break;
700 case Instruction::Screenshot:
701 _save_to_image(current.data.filename);
702 break;
703 case Instruction::PopState:
704 this->_pop_state();
705 break;
706 case Instruction::PushState:
707 this->_push_state();
708 break;
709 case Instruction::NewWalkingSpeed:
710 this->walk_spd = current.data.new_walking_speed;
711 break;
712 case Instruction::NewRotationSpeed:
713 this->rot_vel = current.data.new_rotation_speed;
714 break;
715 case Instruction::LineChangeColor:
716 const auto newc = current.data.next_color;
717 this->line_color = sf::Color(newc[0], newc[1], newc[2]);
718 break;
720 actions.pop();
724 } //! <- This brace closes the namespace
726 #endif