greg.cpp
· 8.1 KiB · C++
Исходник
Playground
#include <M5Unified.h>
#include <M5GFX.h>
template<uint32_t size>
struct stack {
int data[size] = {};
uint32_t top = 0;
inline void push(int symbol) {
if(!full()) {
data[top++] = symbol;
}
}
inline int pop() {
if(!empty()) {
return data[--top];
}
return 0;
}
inline int peek() {
if(!empty()) {
return data[top - 1];
}
return 0;
}
inline bool empty() {
return top == 0;
}
inline bool full() {
return top >= size;
}
inline void clear() {
top = 0;
}
void print() {
for(uint32_t cursor = 0; cursor < top; cursor++) {
Serial.printf("%d ", data[cursor]);
}
Serial.println();
}
};
template<uint32_t stack_size, uint32_t program_size>
struct generator {
stack<stack_size> stack;
char program[program_size] = {};
uint32_t length = program_size;
generator() {
randomize();
}
generator(const char* program) {
uint32_t cursor = 0;
while(program[cursor] != '\0' && cursor < program_size - 1) {
this->program[cursor] = program[cursor];
cursor++;
}
length = cursor;
this->program[length + 1] = '\0';
}
char random_command() {
const char commands[] = "0123456789abcdefxywhtrsopzq_=+*&|^~<>-/%";
return commands[random(0, sizeof(commands) - 1)];
}
void randomize() {
length = random(2, program_size-1);
for(uint32_t cursor = 0; cursor < length; cursor++) {
program[cursor] = random_command();
}
program[length] = '\0';
}
int run(uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint32_t t, int previous, uint16_t tx, uint16_t ty) {
for(uint32_t cursor = 0; cursor < length; cursor++) {
char instruction = program[cursor];
if(instruction >= '0' && instruction <= '9') {
stack.push(instruction - '0');
} else if(instruction >= 'a' && instruction <= 'f') {
stack.push((instruction - 'a') + 10);
} else {
switch(instruction) {
case 'x': stack.push(x); break;
case 'y': stack.push(y); break;
case 'w': stack.push(w); break;
case 'h': stack.push(h); break;
case 't': stack.push(t); break;
case 'r': stack.push(random()); break;
case 's': stack.push(sin(stack.pop()) * INT_MAX); break;
case 'o': stack.push(cos(stack.pop()) * INT_MAX); break;
case 'p': stack.push(previous); break;
case 'z': stack.push(tx); break;
case 'q': stack.push(ty); break;
case '_': stack.push(abs(stack.pop())); break;
case '=': stack.push(stack.pop() == stack.pop()); break;
case '+': stack.push(stack.pop() + stack.pop()); break;
case '*': stack.push(stack.pop() * stack.pop()); break;
case '&': stack.push(stack.pop() & stack.pop()); break;
case '|': stack.push(stack.pop() | stack.pop()); break;
case '^': stack.push(stack.pop() ^ stack.pop()); break;
case '~': stack.push(~stack.pop()); break;
case '<': {
int first = stack.pop();
int second = stack.pop();
stack.push(second < first);
break;
}
case '>': {
int first = stack.pop();
int second = stack.pop();
stack.push(second < first);
break;
}
case '-': {
int first = stack.pop();
int second = stack.pop();
if(first == 0) {
first = -1;
}
if(second == 0) {
second = -1;
}
stack.push(second - first);
break;
}
case '/': {
int first = stack.pop();
int second = stack.pop();
stack.push(second / first);
break;
}
case '%': {
int first = stack.pop();
int second = stack.pop();
stack.push(second % first);
break;
}
default: break;
}
}
}
return stack.pop();
}
void print(uint32_t size) {
M5.Display.pushState();
M5.Display.writeFillRect(0, M5.Display.height() - (size * 8), M5.Display.width(), M5.Display.height(), TFT_BLACK);
M5.Display.setCursor(0, M5.Display.height() - (size * 8) + 4);
M5.Display.setTextSize(3);
M5.Display.setTextWrap(true);
M5.Display.setTextColor(TFT_DARKGREY, TFT_BLACK);
for(uint32_t instruction = 0; instruction < length; instruction++) {
M5.Display.print(program[instruction]);
}
M5.Display.popState();
}
};
uint32_t width = 0;
uint32_t height = 0;
uint32_t size = 10;
uint32_t tile_size = 1;
uint32_t t = 0;
uint32_t cooldown = 0;
uint8_t wait = 25;
int8_t offset = 1;
generator<256, 53*3> pixel("xy+xy-&9f+%9>8-");
inline bool shaken(float ax, float ay, float az) {
return (abs(ax) >= 1.75) || (abs(ay) >= 1.5) || (abs(az) >= 1.75);
}
void intro() {
M5.Display.setTextSize(4);
M5.Display.drawCenterString("For Greg", M5.Display.width() / 2, (M5.Display.height() / 2) - 16);
M5.Display.drawCenterString("From Nouveau", M5.Display.width() / 2, (M5.Display.height() / 2) + 16);
M5.Display.setTextColor(random(0, UINT16_MAX), random(0, UINT16_MAX));
delay(5000);
M5.Display.clear();
M5.Display.setTextSize(size);
int previous = pixel.run(0, 0, width, height, 0, 0, 0, 0);
for(uint32_t x = 0; x < width; x++) {
for(uint32_t y = 0; y < height; y++) {
const int value = pixel.run(x, y, width, height, t, previous, 0, 0);
const int character = (abs(value % 17)) + 127;
M5.Display.drawChar(character, x * tile_size, y * tile_size);
previous = value;
delay(1);
}
}
delay(1000);
M5.Display.setTextSize(4);
M5.Display.setTextColor(TFT_CYAN, TFT_DARKCYAN);
M5.Display.drawCenterString(" ", M5.Display.width() / 2, (M5.Display.height() / 2) - 48);
M5.Display.drawCenterString(" ALL THESE WORLDS ", M5.Display.width() / 2, (M5.Display.height() / 2) - 16);
M5.Display.drawCenterString(" ARE YOURS ", M5.Display.width() / 2, (M5.Display.height() / 2) + 16);
M5.Display.drawCenterString(" ", M5.Display.width() / 2, (M5.Display.height() / 2) + 48);
delay(5000);
pixel.randomize();
M5.Display.fillRect(0, 0, M5.Display.width(), M5.Display.height(), TFT_BLACK);
delay(1000);
}
void setup(void) {
Serial.begin(9600);
M5.begin();
M5.Display.setRotation(1);
M5.Display.setFont(&fonts::Font8x8C64);
M5.Display.waitDisplay();
size = 2;
tile_size = size * 8;
width = M5.Display.width() / tile_size;
height = (M5.Display.height() / tile_size) - 1;
intro();
size = 10;
tile_size = size * 8;
width = M5.Display.width() / tile_size;
height = (M5.Display.height() / tile_size) - 1;
M5.Display.setTextSize(size);
M5.Display.setTextColor(random(), random());
pixel.print(size);
}
void loop(void) {
lgfx::touch_point_t point = {};
float ax = 0, ay = 0, az = 0;
bool touch = false;
M5.Imu.update();
M5.Imu.getAccel(&ax, &ay, &az);
if(M5.Display.getTouchRaw(&point, 1)) {
M5.Display.convertRawXY(&point, 1);
touch = true;
}
M5.Display.startWrite();
int previous = pixel.run(0, 0, width, height, 0, 0, 0, 0);
bool alive = false;
for(uint32_t x = 0; x < width; x++) {
for(uint32_t y = 0; y < height; y++) {
const int value = pixel.run(x, y, width, height, t, previous, map(point.x, 0, M5.Display.width(), 0, width), map(point.y, 0, M5.Display.height(), 0, height));
const int character = (abs(value % 17)) + 127;
M5.Display.drawChar(character, x * tile_size, y * tile_size);
if(((abs(previous % 17)) + 127) != character) {
alive = true;
}
previous = value;
}
}
M5.Display.endWrite();
t += offset;
if(wait > 0) {
wait--;
}
if(cooldown > 0) {
cooldown--;
}
if(touch) {
cooldown = 100;
}
if(!alive) {
wait = 0;
}
if((shaken(ax, ay, az) && !touch) || (wait == 0 && (!alive || cooldown == 0))) {
pixel.randomize();
if(alive) {
M5.Display.setTextColor(random(), random());
}
wait = 50;
pixel.print(size);
t = 0;
}
if(t >= 1000000) {
offset = -1;
} else if(t == 0) {
offset = 1;
}
}
| 1 | #include <M5Unified.h> |
| 2 | #include <M5GFX.h> |
| 3 | |
| 4 | template<uint32_t size> |
| 5 | struct stack { |
| 6 | int data[size] = {}; |
| 7 | uint32_t top = 0; |
| 8 | inline void push(int symbol) { |
| 9 | if(!full()) { |
| 10 | data[top++] = symbol; |
| 11 | } |
| 12 | } |
| 13 | inline int pop() { |
| 14 | if(!empty()) { |
| 15 | return data[--top]; |
| 16 | } |
| 17 | return 0; |
| 18 | } |
| 19 | inline int peek() { |
| 20 | if(!empty()) { |
| 21 | return data[top - 1]; |
| 22 | } |
| 23 | return 0; |
| 24 | } |
| 25 | inline bool empty() { |
| 26 | return top == 0; |
| 27 | } |
| 28 | inline bool full() { |
| 29 | return top >= size; |
| 30 | } |
| 31 | inline void clear() { |
| 32 | top = 0; |
| 33 | } |
| 34 | void print() { |
| 35 | for(uint32_t cursor = 0; cursor < top; cursor++) { |
| 36 | Serial.printf("%d ", data[cursor]); |
| 37 | } |
| 38 | Serial.println(); |
| 39 | } |
| 40 | }; |
| 41 | |
| 42 | template<uint32_t stack_size, uint32_t program_size> |
| 43 | struct generator { |
| 44 | stack<stack_size> stack; |
| 45 | char program[program_size] = {}; |
| 46 | uint32_t length = program_size; |
| 47 | generator() { |
| 48 | randomize(); |
| 49 | } |
| 50 | generator(const char* program) { |
| 51 | uint32_t cursor = 0; |
| 52 | while(program[cursor] != '\0' && cursor < program_size - 1) { |
| 53 | this->program[cursor] = program[cursor]; |
| 54 | cursor++; |
| 55 | } |
| 56 | length = cursor; |
| 57 | this->program[length + 1] = '\0'; |
| 58 | } |
| 59 | char random_command() { |
| 60 | const char commands[] = "0123456789abcdefxywhtrsopzq_=+*&|^~<>-/%"; |
| 61 | return commands[random(0, sizeof(commands) - 1)]; |
| 62 | } |
| 63 | void randomize() { |
| 64 | length = random(2, program_size-1); |
| 65 | for(uint32_t cursor = 0; cursor < length; cursor++) { |
| 66 | program[cursor] = random_command(); |
| 67 | } |
| 68 | program[length] = '\0'; |
| 69 | } |
| 70 | int run(uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint32_t t, int previous, uint16_t tx, uint16_t ty) { |
| 71 | for(uint32_t cursor = 0; cursor < length; cursor++) { |
| 72 | char instruction = program[cursor]; |
| 73 | if(instruction >= '0' && instruction <= '9') { |
| 74 | stack.push(instruction - '0'); |
| 75 | } else if(instruction >= 'a' && instruction <= 'f') { |
| 76 | stack.push((instruction - 'a') + 10); |
| 77 | } else { |
| 78 | switch(instruction) { |
| 79 | case 'x': stack.push(x); break; |
| 80 | case 'y': stack.push(y); break; |
| 81 | case 'w': stack.push(w); break; |
| 82 | case 'h': stack.push(h); break; |
| 83 | case 't': stack.push(t); break; |
| 84 | case 'r': stack.push(random()); break; |
| 85 | case 's': stack.push(sin(stack.pop()) * INT_MAX); break; |
| 86 | case 'o': stack.push(cos(stack.pop()) * INT_MAX); break; |
| 87 | case 'p': stack.push(previous); break; |
| 88 | case 'z': stack.push(tx); break; |
| 89 | case 'q': stack.push(ty); break; |
| 90 | case '_': stack.push(abs(stack.pop())); break; |
| 91 | case '=': stack.push(stack.pop() == stack.pop()); break; |
| 92 | case '+': stack.push(stack.pop() + stack.pop()); break; |
| 93 | case '*': stack.push(stack.pop() * stack.pop()); break; |
| 94 | case '&': stack.push(stack.pop() & stack.pop()); break; |
| 95 | case '|': stack.push(stack.pop() | stack.pop()); break; |
| 96 | case '^': stack.push(stack.pop() ^ stack.pop()); break; |
| 97 | case '~': stack.push(~stack.pop()); break; |
| 98 | case '<': { |
| 99 | int first = stack.pop(); |
| 100 | int second = stack.pop(); |
| 101 | stack.push(second < first); |
| 102 | break; |
| 103 | } |
| 104 | case '>': { |
| 105 | int first = stack.pop(); |
| 106 | int second = stack.pop(); |
| 107 | stack.push(second < first); |
| 108 | break; |
| 109 | } |
| 110 | case '-': { |
| 111 | int first = stack.pop(); |
| 112 | int second = stack.pop(); |
| 113 | if(first == 0) { |
| 114 | first = -1; |
| 115 | } |
| 116 | if(second == 0) { |
| 117 | second = -1; |
| 118 | } |
| 119 | stack.push(second - first); |
| 120 | break; |
| 121 | } |
| 122 | case '/': { |
| 123 | int first = stack.pop(); |
| 124 | int second = stack.pop(); |
| 125 | stack.push(second / first); |
| 126 | break; |
| 127 | } |
| 128 | case '%': { |
| 129 | int first = stack.pop(); |
| 130 | int second = stack.pop(); |
| 131 | stack.push(second % first); |
| 132 | break; |
| 133 | } |
| 134 | default: break; |
| 135 | } |
| 136 | } |
| 137 | } |
| 138 | return stack.pop(); |
| 139 | } |
| 140 | void print(uint32_t size) { |
| 141 | M5.Display.pushState(); |
| 142 | M5.Display.writeFillRect(0, M5.Display.height() - (size * 8), M5.Display.width(), M5.Display.height(), TFT_BLACK); |
| 143 | M5.Display.setCursor(0, M5.Display.height() - (size * 8) + 4); |
| 144 | M5.Display.setTextSize(3); |
| 145 | M5.Display.setTextWrap(true); |
| 146 | M5.Display.setTextColor(TFT_DARKGREY, TFT_BLACK); |
| 147 | for(uint32_t instruction = 0; instruction < length; instruction++) { |
| 148 | M5.Display.print(program[instruction]); |
| 149 | } |
| 150 | M5.Display.popState(); |
| 151 | } |
| 152 | }; |
| 153 | |
| 154 | uint32_t width = 0; |
| 155 | uint32_t height = 0; |
| 156 | uint32_t size = 10; |
| 157 | uint32_t tile_size = 1; |
| 158 | uint32_t t = 0; |
| 159 | uint32_t cooldown = 0; |
| 160 | uint8_t wait = 25; |
| 161 | int8_t offset = 1; |
| 162 | generator<256, 53*3> pixel("xy+xy-&9f+%9>8-"); |
| 163 | |
| 164 | inline bool shaken(float ax, float ay, float az) { |
| 165 | return (abs(ax) >= 1.75) || (abs(ay) >= 1.5) || (abs(az) >= 1.75); |
| 166 | } |
| 167 | |
| 168 | void intro() { |
| 169 | M5.Display.setTextSize(4); |
| 170 | M5.Display.drawCenterString("For Greg", M5.Display.width() / 2, (M5.Display.height() / 2) - 16); |
| 171 | M5.Display.drawCenterString("From Nouveau", M5.Display.width() / 2, (M5.Display.height() / 2) + 16); |
| 172 | M5.Display.setTextColor(random(0, UINT16_MAX), random(0, UINT16_MAX)); |
| 173 | delay(5000); |
| 174 | M5.Display.clear(); |
| 175 | M5.Display.setTextSize(size); |
| 176 | int previous = pixel.run(0, 0, width, height, 0, 0, 0, 0); |
| 177 | for(uint32_t x = 0; x < width; x++) { |
| 178 | for(uint32_t y = 0; y < height; y++) { |
| 179 | const int value = pixel.run(x, y, width, height, t, previous, 0, 0); |
| 180 | const int character = (abs(value % 17)) + 127; |
| 181 | M5.Display.drawChar(character, x * tile_size, y * tile_size); |
| 182 | previous = value; |
| 183 | delay(1); |
| 184 | } |
| 185 | } |
| 186 | delay(1000); |
| 187 | M5.Display.setTextSize(4); |
| 188 | M5.Display.setTextColor(TFT_CYAN, TFT_DARKCYAN); |
| 189 | M5.Display.drawCenterString(" ", M5.Display.width() / 2, (M5.Display.height() / 2) - 48); |
| 190 | M5.Display.drawCenterString(" ALL THESE WORLDS ", M5.Display.width() / 2, (M5.Display.height() / 2) - 16); |
| 191 | M5.Display.drawCenterString(" ARE YOURS ", M5.Display.width() / 2, (M5.Display.height() / 2) + 16); |
| 192 | M5.Display.drawCenterString(" ", M5.Display.width() / 2, (M5.Display.height() / 2) + 48); |
| 193 | delay(5000); |
| 194 | pixel.randomize(); |
| 195 | M5.Display.fillRect(0, 0, M5.Display.width(), M5.Display.height(), TFT_BLACK); |
| 196 | delay(1000); |
| 197 | } |
| 198 | |
| 199 | void setup(void) { |
| 200 | Serial.begin(9600); |
| 201 | M5.begin(); |
| 202 | M5.Display.setRotation(1); |
| 203 | M5.Display.setFont(&fonts::Font8x8C64); |
| 204 | M5.Display.waitDisplay(); |
| 205 | size = 2; |
| 206 | tile_size = size * 8; |
| 207 | width = M5.Display.width() / tile_size; |
| 208 | height = (M5.Display.height() / tile_size) - 1; |
| 209 | intro(); |
| 210 | size = 10; |
| 211 | tile_size = size * 8; |
| 212 | width = M5.Display.width() / tile_size; |
| 213 | height = (M5.Display.height() / tile_size) - 1; |
| 214 | M5.Display.setTextSize(size); |
| 215 | M5.Display.setTextColor(random(), random()); |
| 216 | pixel.print(size); |
| 217 | } |
| 218 | |
| 219 | void loop(void) { |
| 220 | lgfx::touch_point_t point = {}; |
| 221 | float ax = 0, ay = 0, az = 0; |
| 222 | bool touch = false; |
| 223 | M5.Imu.update(); |
| 224 | M5.Imu.getAccel(&ax, &ay, &az); |
| 225 | if(M5.Display.getTouchRaw(&point, 1)) { |
| 226 | M5.Display.convertRawXY(&point, 1); |
| 227 | touch = true; |
| 228 | } |
| 229 | M5.Display.startWrite(); |
| 230 | int previous = pixel.run(0, 0, width, height, 0, 0, 0, 0); |
| 231 | bool alive = false; |
| 232 | for(uint32_t x = 0; x < width; x++) { |
| 233 | for(uint32_t y = 0; y < height; y++) { |
| 234 | const int value = pixel.run(x, y, width, height, t, previous, map(point.x, 0, M5.Display.width(), 0, width), map(point.y, 0, M5.Display.height(), 0, height)); |
| 235 | const int character = (abs(value % 17)) + 127; |
| 236 | M5.Display.drawChar(character, x * tile_size, y * tile_size); |
| 237 | if(((abs(previous % 17)) + 127) != character) { |
| 238 | alive = true; |
| 239 | } |
| 240 | previous = value; |
| 241 | } |
| 242 | } |
| 243 | M5.Display.endWrite(); |
| 244 | t += offset; |
| 245 | if(wait > 0) { |
| 246 | wait--; |
| 247 | } |
| 248 | if(cooldown > 0) { |
| 249 | cooldown--; |
| 250 | } |
| 251 | if(touch) { |
| 252 | cooldown = 100; |
| 253 | } |
| 254 | if(!alive) { |
| 255 | wait = 0; |
| 256 | } |
| 257 | if((shaken(ax, ay, az) && !touch) || (wait == 0 && (!alive || cooldown == 0))) { |
| 258 | pixel.randomize(); |
| 259 | if(alive) { |
| 260 | M5.Display.setTextColor(random(), random()); |
| 261 | } |
| 262 | wait = 50; |
| 263 | pixel.print(size); |
| 264 | t = 0; |
| 265 | } |
| 266 | if(t >= 1000000) { |
| 267 | offset = -1; |
| 268 | } else if(t == 0) { |
| 269 | offset = 1; |
| 270 | } |
| 271 | } |
| 272 |