From 1e2393637465082fc408e10aab70b409a67315e9 Mon Sep 17 00:00:00 2001 From: Fabian Schlenz Date: Fri, 14 Jun 2019 05:32:17 +0200 Subject: [PATCH] Added effect 'gol': Conway's Game of Life. --- include/Window.h | 3 +- include/config.sample.h | 4 +- include/effect_gol.h | 23 ++++++++++ src/effect_gol.cpp | 98 +++++++++++++++++++++++++++++++++++++++++ src/effects.cpp | 4 ++ 5 files changed, 130 insertions(+), 2 deletions(-) create mode 100644 include/effect_gol.h create mode 100644 src/effect_gol.cpp diff --git a/include/Window.h b/include/Window.h index dc37ddf..6b7b053 100644 --- a/include/Window.h +++ b/include/Window.h @@ -7,11 +7,12 @@ class Window { public: const uint8_t x, y; const uint8_t width, height; + uint16_t count; static Window* getFullWindow(); Window(): Window(0, 0, LED_WIDTH, LED_HEIGHT) {}; Window(uint8_t x, uint8_t y) : Window(x, y, LED_WIDTH-x, LED_HEIGHT-y) {}; - Window(uint8_t x, uint8_t y, uint8_t width, uint8_t height) : x(x), y(y), width(width), height(height) {}; + Window(uint8_t x, uint8_t y, uint8_t width, uint8_t height) : x(x), y(y), width(width), height(height) { count = width*height; }; void clear(); void clear(CRGB* color); diff --git a/include/config.sample.h b/include/config.sample.h index d638b85..2d54758 100644 --- a/include/config.sample.h +++ b/include/config.sample.h @@ -69,7 +69,9 @@ #define EFFECT_FIREWORK_BLUR 200 #define EFFECT_FIREWORK_FADEOUT_SPEED 5 - +#define EFFECT_GOL_START_PERCENTAGE 128 +#define EFFECT_GOL_BLEND_SPEED 5 + // Stop editing here #ifdef DEBUG diff --git a/include/effect_gol.h b/include/effect_gol.h new file mode 100644 index 0000000..c982610 --- /dev/null +++ b/include/effect_gol.h @@ -0,0 +1,23 @@ +#pragma once +#include "Effect.h" + +class GolEffect : public Effect { +private: + uint8_t *_data; + uint8_t *_old; + uint8_t _blend; + uint8_t _hue = 0; + uint8_t _old_hue = 0; + uint16_t _step; + + void _advance(); + void _draw(); + void _initialize(); + +public: + GolEffect(); + void start(); + void stop(); + void loop(); + bool can_be_shown_with_clock(); +}; diff --git a/src/effect_gol.cpp b/src/effect_gol.cpp new file mode 100644 index 0000000..6cc13de --- /dev/null +++ b/src/effect_gol.cpp @@ -0,0 +1,98 @@ +#include "effect_gol.h" +#include "my_fastled.h" + +GolEffect::GolEffect() { + this->window = new Window(0, 0, LED_WIDTH, LED_HEIGHT-6); +} + +bool GolEffect::can_be_shown_with_clock() { return true; } + +void GolEffect::start() { + _data = new uint8_t[this->window->count]; + _old = new uint8_t[this->window->count]; + for(uint16_t i=0; iwindow->count; i++) { + _old[i] = 0; + } + _initialize(); +} + +void GolEffect::_initialize() { + for(uint16_t i=0; iwindow->count; i++) { + _data[i] = random8() < EFFECT_GOL_START_PERCENTAGE ? 1 : 0; + } + _old_hue = _hue; + _hue = random8(); + _step = 0; +} + +void GolEffect::stop() { + delete[] _data; + delete[] _old; +} + +void GolEffect::loop() { + if (EFFECT_GOL_BLEND_SPEED + _blend > 255) { + _blend = 0; + _advance(); + } else { + _blend += EFFECT_GOL_BLEND_SPEED; + } + + _draw(); +} + +void GolEffect::_advance() { + _step++; + _old_hue = _hue; + if (_step >= EFFECT_GOL_RESTART_AFTER_STEPS) { + _initialize(); + } else { + for(uint16_t i=0; iwindow->count; i++) { + _old[i] = _data[i]; + } + uint8_t w = this->window->width; + uint16_t changes = 0; + for(uint8_t x=0; xwindow->width; x++) for(uint8_t y=0; ywindow->height; y++) { + uint16_t index = y*w + x; + uint8_t count = + (x>0 && y>0 && _old[index - w - 1]) + + (y>0 && _old[index - w]) + + (xwindow->width-1 && y>0 && _old[index - w + 1]) + + + (x>0 && _old[index - 1]) + + (xwindow->width-1 && _old[index + 1]) + + + (x>0 && ywindow->height-1 && _old[index + w - 1]) + + (ywindow->height-1 && _old[index + w]) + + (xwindow->width-1 && ywindow->height-1 && _old[index + w + 1]); + if (_old[index]==0 && count==3) { + // birth + _data[index]=1; + changes++; + } + if (_old[index]>0) { + if (count<2 || count>3) { + //death + _data[index]=0; + changes++; + } else if (_data[index] < 255) { + //ageing + _data[index]++; + } + } + } + + if (changes == 0) { + _initialize(); + } + } +} + +void GolEffect::_draw() { + for(uint16_t i=0; iwindow->count; i++) { + CRGB o = _old[i]==0 ? CRGB::Black : (CRGB)CHSV(_old_hue, 180, 255); + CRGB n = _data[i]==0 ? CRGB::Black : (CRGB)CHSV(_hue, 180, 255); + CRGB result = nblend(o, n, _blend); + this->window->setPixelByIndex(i, &result); + } +} diff --git a/src/effects.cpp b/src/effects.cpp index b0ff82c..61d5636 100644 --- a/src/effects.cpp +++ b/src/effects.cpp @@ -16,6 +16,7 @@ #include "effect_snake.h" #include "effect_fire.h" #include "effect_firework.h" +#include "effect_gol.h" SimpleList* effects; SimpleList* cycle_effects; @@ -38,6 +39,7 @@ ConfettiEffect effect_confetti; SnakeEffect effect_snake; FireEffect effect_fire; FireworkEffect effect_firework; +GolEffect effect_gol; Effect* current_effect; @@ -62,6 +64,7 @@ void setup_effects() { effects->add((EffectEntry){"snake", (Effect *)&effect_snake}); effects->add((EffectEntry){"fire", (Effect *)&effect_fire}); effects->add((EffectEntry){"firework", (Effect *)&effect_firework}); + effects->add((EffectEntry){"gol", (Effect *)&effect_gol}); cycle_effects->add(&effect_sinematrix3); cycle_effects->add(&effect_multi_dynamic); @@ -69,6 +72,7 @@ void setup_effects() { cycle_effects->add(&effect_confetti); cycle_effects->add(&effect_single_dynamic); cycle_effects->add(&effect_snake); + cycle_effects->add(&effect_gol); current_effect = &effect_cycle; }