Merge pull request #31 from kosso/chained-aurora-demos

Updated Aurora demo for chained virtual displays.
This commit is contained in:
mrfaptastic 2020-09-14 10:32:11 +01:00 committed by GitHub
commit beb0c54cc6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
31 changed files with 4535 additions and 0 deletions

View file

@ -0,0 +1,50 @@
/*
* Aurora: https://github.com/pixelmatix/aurora
* Copyright (c) 2014 Jason Coon
*
* Portions of this code are adapted from "Attractor" in "The Nature of Code" by Daniel Shiffman: http://natureofcode.com/
* Copyright (c) 2014 Daniel Shiffman
* http://www.shiffman.net
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "Vector.h"
class Attractor {
public:
float mass; // Mass, tied to size
float G; // Gravitational Constant
PVector location; // Location
Attractor() {
location = PVector(MATRIX_CENTRE_X, MATRIX_CENTRE_Y);
mass = 8;
G = .5;
}
PVector attract(Boid m) {
PVector force = location - m.location; // Calculate direction of force
float d = force.mag(); // Distance between objects
d = constrain(d, 5.0, 32.0); // Limiting the distance to eliminate "extreme" results for very close or very far objects
force.normalize(); // Normalize vector (distance doesn't matter here, we just want this vector for direction)
float strength = (G * mass * m.mass) / (d * d); // Calculate gravitional force magnitude
force *= strength; // Get force vector --> magnitude * direction
return force;
}
};

View file

@ -0,0 +1,326 @@
/*
* Aurora: https://github.com/pixelmatix/aurora
* Copyright (c) 2014 Jason Coon
*
* Portions of this code are adapted from "Flocking" in "The Nature of Code" by Daniel Shiffman: http://natureofcode.com/
* Copyright (c) 2014 Daniel Shiffman
* http://www.shiffman.net
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
// Flocking
// Daniel Shiffman <http://www.shiffman.net>
// The Nature of Code, Spring 2009
// Boid class
// Methods for Separation, Cohesion, Alignment added
class Boid {
public:
PVector location;
PVector velocity;
PVector acceleration;
float maxforce; // Maximum steering force
float maxspeed; // Maximum speed
float desiredseparation = 4;
float neighbordist = 8;
byte colorIndex = 0;
float mass;
boolean enabled = true;
Boid() {}
Boid(float x, float y) {
acceleration = PVector(0, 0);
velocity = PVector(randomf(), randomf());
location = PVector(x, y);
maxspeed = 1.5;
maxforce = 0.05;
}
static float randomf() {
return mapfloat(random(0, 255), 0, 255, -.5, .5);
}
static float mapfloat(float x, float in_min, float in_max, float out_min, float out_max) {
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}
void run(Boid boids [], uint8_t boidCount) {
flock(boids, boidCount);
update();
// wrapAroundBorders();
// render();
}
// Method to update location
void update() {
// Update velocity
velocity += acceleration;
// Limit speed
velocity.limit(maxspeed);
location += velocity;
// Reset acceleration to 0 each cycle
acceleration *= 0;
}
void applyForce(PVector force) {
// We could add mass here if we want A = F / M
acceleration += force;
}
void repelForce(PVector obstacle, float radius) {
//Force that drives boid away from obstacle.
PVector futPos = location + velocity; //Calculate future position for more effective behavior.
PVector dist = obstacle - futPos;
float d = dist.mag();
if (d <= radius) {
PVector repelVec = location - obstacle;
repelVec.normalize();
if (d != 0) { //Don't divide by zero.
// float scale = 1.0 / d; //The closer to the obstacle, the stronger the force.
repelVec.normalize();
repelVec *= (maxforce * 7);
if (repelVec.mag() < 0) { //Don't let the boids turn around to avoid the obstacle.
repelVec.y = 0;
}
}
applyForce(repelVec);
}
}
// We accumulate a new acceleration each time based on three rules
void flock(Boid boids [], uint8_t boidCount) {
PVector sep = separate(boids, boidCount); // Separation
PVector ali = align(boids, boidCount); // Alignment
PVector coh = cohesion(boids, boidCount); // Cohesion
// Arbitrarily weight these forces
sep *= 1.5;
ali *= 1.0;
coh *= 1.0;
// Add the force vectors to acceleration
applyForce(sep);
applyForce(ali);
applyForce(coh);
}
// Separation
// Method checks for nearby boids and steers away
PVector separate(Boid boids [], uint8_t boidCount) {
PVector steer = PVector(0, 0);
int count = 0;
// For every boid in the system, check if it's too close
for (int i = 0; i < boidCount; i++) {
Boid other = boids[i];
if (!other.enabled)
continue;
float d = location.dist(other.location);
// If the distance is greater than 0 and less than an arbitrary amount (0 when you are yourself)
if ((d > 0) && (d < desiredseparation)) {
// Calculate vector pointing away from neighbor
PVector diff = location - other.location;
diff.normalize();
diff /= d; // Weight by distance
steer += diff;
count++; // Keep track of how many
}
}
// Average -- divide by how many
if (count > 0) {
steer /= (float) count;
}
// As long as the vector is greater than 0
if (steer.mag() > 0) {
// Implement Reynolds: Steering = Desired - Velocity
steer.normalize();
steer *= maxspeed;
steer -= velocity;
steer.limit(maxforce);
}
return steer;
}
// Alignment
// For every nearby boid in the system, calculate the average velocity
PVector align(Boid boids [], uint8_t boidCount) {
PVector sum = PVector(0, 0);
int count = 0;
for (int i = 0; i < boidCount; i++) {
Boid other = boids[i];
if (!other.enabled)
continue;
float d = location.dist(other.location);
if ((d > 0) && (d < neighbordist)) {
sum += other.velocity;
count++;
}
}
if (count > 0) {
sum /= (float) count;
sum.normalize();
sum *= maxspeed;
PVector steer = sum - velocity;
steer.limit(maxforce);
return steer;
}
else {
return PVector(0, 0);
}
}
// Cohesion
// For the average location (i.e. center) of all nearby boids, calculate steering vector towards that location
PVector cohesion(Boid boids [], uint8_t boidCount) {
PVector sum = PVector(0, 0); // Start with empty vector to accumulate all locations
int count = 0;
for (int i = 0; i < boidCount; i++) {
Boid other = boids[i];
if (!other.enabled)
continue;
float d = location.dist(other.location);
if ((d > 0) && (d < neighbordist)) {
sum += other.location; // Add location
count++;
}
}
if (count > 0) {
sum /= count;
return seek(sum); // Steer towards the location
}
else {
return PVector(0, 0);
}
}
// A method that calculates and applies a steering force towards a target
// STEER = DESIRED MINUS VELOCITY
PVector seek(PVector target) {
PVector desired = target - location; // A vector pointing from the location to the target
// Normalize desired and scale to maximum speed
desired.normalize();
desired *= maxspeed;
// Steering = Desired minus Velocity
PVector steer = desired - velocity;
steer.limit(maxforce); // Limit to maximum steering force
return steer;
}
// A method that calculates a steering force towards a target
// STEER = DESIRED MINUS VELOCITY
void arrive(PVector target) {
PVector desired = target - location; // A vector pointing from the location to the target
float d = desired.mag();
// Normalize desired and scale with arbitrary damping within 100 pixels
desired.normalize();
if (d < 4) {
float m = map(d, 0, 100, 0, maxspeed);
desired *= m;
}
else {
desired *= maxspeed;
}
// Steering = Desired minus Velocity
PVector steer = desired - velocity;
steer.limit(maxforce); // Limit to maximum steering force
applyForce(steer);
//Serial.println(d);
}
void wrapAroundBorders() {
if (location.x < 0) location.x = VPANEL_W - 1;
if (location.y < 0) location.y = VPANEL_H - 1;
if (location.x >= VPANEL_W) location.x = 0;
if (location.y >= VPANEL_H) location.y = 0;
}
void avoidBorders() {
PVector desired = velocity;
if (location.x < 8) desired = PVector(maxspeed, velocity.y);
if (location.x >= VPANEL_W - 8) desired = PVector(-maxspeed, velocity.y);
if (location.y < 8) desired = PVector(velocity.x, maxspeed);
if (location.y >= VPANEL_H - 8) desired = PVector(velocity.x, -maxspeed);
if (desired != velocity) {
PVector steer = desired - velocity;
steer.limit(maxforce);
applyForce(steer);
}
if (location.x < 0) location.x = 0;
if (location.y < 0) location.y = 0;
if (location.x >= VPANEL_W) location.x = VPANEL_W - 1;
if (location.y >= VPANEL_H) location.y = VPANEL_H - 1;
}
bool bounceOffBorders(float bounce) {
bool bounced = false;
if (location.x >= VPANEL_W) {
location.x = VPANEL_W - 1;
velocity.x *= -bounce;
bounced = true;
}
else if (location.x < 0) {
location.x = 0;
velocity.x *= -bounce;
bounced = true;
}
if (location.y >= VPANEL_H) {
location.y = VPANEL_H - 1;
velocity.y *= -bounce;
bounced = true;
}
else if (location.y < 0) {
location.y = 0;
velocity.y *= -bounce;
bounced = true;
}
return bounced;
}
void render() {
//// Draw a triangle rotated in the direction of velocity
//float theta = velocity.heading2D() + radians(90);
//fill(175);
//stroke(0);
//pushMatrix();
//translate(location.x,location.y);
//rotate(theta);
//beginShape(TRIANGLES);
//vertex(0, -r*2);
//vertex(-r, r*2);
//vertex(r, r*2);
//endShape();
//popMatrix();
//matrix.drawBackgroundPixelRGB888(location.x, location.y, CRGB::Blue);
}
};
static const uint8_t AVAILABLE_BOID_COUNT = 40;
Boid boids[AVAILABLE_BOID_COUNT];

View file

@ -0,0 +1,181 @@
/* ------------------------- CUSTOM GPIO PIN MAPPING ------------------------- */
// Kosso's ESP32 Matrix PCB pins
#define R1_PIN 2
#define G1_PIN 15
#define B1_PIN 4
#define R2_PIN 16
#define G2_PIN 13
#define B2_PIN 17
#define A_PIN 5
#define B_PIN 18
#define C_PIN 19
#define D_PIN 27
#define E_PIN -1
#define LAT_PIN 21
#define OE_PIN 23
#define CLK_PIN 22
/* -------------------------- Display Config Initialisation -------------------- */
#define MATRIX_WIDTH 128 // Overall matrix dimensions if laid out end-to-end.
#define MATRIX_HEIGHT 32
#define PANEL_RES_X 64 // Number of pixels wide of each INDIVIDUAL panel module.
#define PANEL_RES_Y 32 // Number of pixels tall of each INDIVIDUAL panel module.
#define NUM_ROWS 2 // Number of rows of chained INDIVIDUAL PANELS
#define NUM_COLS 1 // Number of INDIVIDUAL PANELS per ROW
// Virtual Panl dimensions
#define VPANEL_W 64 // Kosso: All Pattern files have had the MATRIX_WIDTH and MATRIX_HEIGHT replaced by these.
#define VPANEL_H 64 //
// Kosso added: Button with debounce
#define BTN_PIN 0 // Pattern advance. Using EPS32 Boot button.
int buttonState; // the current reading from the input pin
int lastButtonState = LOW; // the previous reading from the input pin
unsigned long lastDebounceTime = 0; // the last time the output pin was toggled
unsigned long debounceDelay = 50; // the debounce time; increase if the output flickers
// The palettes are set to change every 60 seconds.
// Kosso added: Non-volatile memory to save last pattern index.
#include <Preferences.h>
Preferences preferences;
int lastPattern = 0;
/* -------------------------- Class Initialisation -------------------------- */
//#include <ESP32-RGB64x32MatrixPanel-I2S-DMA.h>
//RGB64x32MatrixPanel_I2S_DMA matrix;
#include <ESP32-VirtualMatrixPanel-I2S-DMA.h>
RGB64x32MatrixPanel_I2S_DMA matrix;
// Added support for 'Chained' virtual panel configurations.
VirtualMatrixPanel virtualDisp(matrix, NUM_ROWS, NUM_COLS, PANEL_RES_X, PANEL_RES_Y, true);
#include <FastLED.h> // Used for some mathematics calculations and effects.
#include "Effects.h"
Effects effects;
#include "Drawable.h"
#include "Playlist.h"
//#include "Geometry.h"
#include "Patterns.h"
Patterns patterns;
/* -------------------------- Some variables -------------------------- */
unsigned long ms_current = 0;
unsigned long ms_previous = 0;
unsigned long ms_animation_max_duration = 60000; // 10 seconds
unsigned long next_frame = 0;
void setup()
{
// Setup serial interface
Serial.begin(115200);
delay(250);
// Added a button to manually advance the pattern index.
pinMode(BTN_PIN, INPUT);
// For saving last pattern index. TO reboot with same.
preferences.begin("RGBMATRIX", false);
lastPattern = preferences.getInt("lastPattern", 0);
matrix.setPanelBrightness(30);
matrix.setMinRefreshRate(200);
matrix.begin(R1_PIN, G1_PIN, B1_PIN, R2_PIN, G2_PIN, B2_PIN, A_PIN, B_PIN, C_PIN, D_PIN, E_PIN, LAT_PIN, OE_PIN, CLK_PIN ); // setup the LED matrix
virtualDisp.fillScreen(virtualDisp.color444(0, 0, 0));
Serial.println("**************** Starting Aurora Effects Demo ****************");
Serial.println("MATRIX_WIDTH " + String(MATRIX_WIDTH));
Serial.println("MATRIX_HEIGHT " + String(MATRIX_HEIGHT));
#ifdef VPANEL_W
Serial.println("VIRTUAL PANEL WIDTH " + String(VPANEL_W));
Serial.println("VIRTUAL PANEL HEIGHT " + String(VPANEL_H));
#endif
// setup the effects generator
effects.Setup();
delay(500);
Serial.println("Effects being loaded: ");
listPatterns();
Serial.println("LastPattern index: " + String(lastPattern));
patterns.setPattern(lastPattern); // // simple noise
patterns.start();
Serial.print("Starting with pattern: ");
Serial.println(patterns.getCurrentPatternName());
preferences.end();
}
void patternAdvance(){
// Go to next pattern in the list (se Patterns.h)
patterns.stop();
patterns.move(1);
patterns.start();
// Select a random palette as well
effects.RandomPalette();
Serial.print("Changing pattern to: ");
Serial.println(patterns.getCurrentPatternName());
Serial.println(patterns.getPatternIndex());
lastPattern = patterns.getPatternIndex();
// Save last index.
preferences.begin("RGBMATRIX", false);
preferences.putInt("lastPattern", lastPattern);
preferences.end();
}
void loop()
{
// Boot button Pattern advance with debounce
int reading = digitalRead(BTN_PIN);
if (reading != lastButtonState) {
lastDebounceTime = millis();
}
if ((millis() - lastDebounceTime) > debounceDelay) {
if (reading != buttonState) {
buttonState = reading;
if (buttonState == LOW) {
Serial.println("NEXT PATTERN ...");
patternAdvance();
}
}
}
lastButtonState = reading;
// end button debounce
ms_current = millis();
if ( (ms_current - ms_previous) > ms_animation_max_duration )
{
// patternAdvance();
// just auto-change the palette
effects.RandomPalette();
ms_previous = ms_current;
}
if ( next_frame < ms_current)
next_frame = patterns.drawFrame() + ms_current;
}
void listPatterns() {
patterns.listPatterns();
}

View file

@ -0,0 +1,50 @@
/*
* Aurora: https://github.com/pixelmatix/aurora
* Copyright (c) 2014 Jason Coon
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef Drawable_H
#define Drawable_H
class Drawable{
public:
char* name;
virtual bool isRunnable() {
return false;
}
virtual bool isPlaylist() {
return false;
}
// a single frame should be drawn as fast as possible, without any delay or blocking
// return how many millisecond delay is requested before the next call to drawFrame()
virtual unsigned int drawFrame() {
matrix.fillScreen(0);
//backgroundLayer.fillScreen({ 0, 0, 0 });
return 0;
};
virtual void start() {};
virtual void stop() {};
};
#endif

View file

@ -0,0 +1,914 @@
/*
Aurora: https://github.com/pixelmatix/aurora
Copyright (c) 2014 Jason Coon
Portions of this code are adapted from "Funky Clouds" by Stefan Petrick: https://gist.github.com/anonymous/876f908333cd95315c35
Portions of this code are adapted from "NoiseSmearing" by Stefan Petrick: https://gist.github.com/StefanPetrick/9ee2f677dbff64e3ba7a
Copyright (c) 2014 Stefan Petrick
http://www.stefan-petrick.de/wordpress_beta
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef Effects_H
#define Effects_H
/* ---------------------------- GLOBAL CONSTANTS ----------------------------- */
//const int MATRIX_CENTER_X = MATRIX_WIDTH / 2;
//const int MATRIX_CENTER_Y = MATRIX_HEIGHT / 2;
//const byte MATRIX_CENTRE_X = MATRIX_CENTER_X - 1;
//const byte MATRIX_CENTRE_Y = MATRIX_CENTER_Y - 1;
const int MATRIX_CENTER_X = VPANEL_W / 2;
const int MATRIX_CENTER_Y = VPANEL_H / 2;
const byte MATRIX_CENTRE_X = MATRIX_CENTER_X - 1;
const byte MATRIX_CENTRE_Y = MATRIX_CENTER_Y - 1;
const uint16_t NUM_LEDS = (VPANEL_W * VPANEL_H) + 1; // one led spare to capture out of bounds
/* Convert x,y co-ordinate to flat array index.
x and y positions start from 0, so must not be >= 'real' panel width or height
(i.e. 64 pixels or 32 pixels.). Max value: MATRIX_WIDTH-1 etc.
*/
uint16_t XY( uint8_t x, uint8_t y)
{
if ( x >= VPANEL_W || x < 0) return 0;
if ( y >= VPANEL_H || y < 0) return 0;
return (y * VPANEL_W) + x + 1; // everything offset by one to capture out of bounds stuff - never displayed by ShowFrame()
}
/// Some mathematics provided by FastLED
uint8_t beatcos8(accum88 beats_per_minute, uint8_t lowest = 0, uint8_t highest = 255, uint32_t timebase = 0, uint8_t phase_offset = 0)
{
uint8_t beat = beat8(beats_per_minute, timebase);
uint8_t beatcos = cos8(beat + phase_offset);
uint8_t rangewidth = highest - lowest;
uint8_t scaledbeat = scale8(beatcos, rangewidth);
uint8_t result = lowest + scaledbeat;
return result;
}
uint8_t mapsin8(uint8_t theta, uint8_t lowest = 0, uint8_t highest = 255) {
uint8_t beatsin = sin8(theta);
uint8_t rangewidth = highest - lowest;
uint8_t scaledbeat = scale8(beatsin, rangewidth);
uint8_t result = lowest + scaledbeat;
return result;
}
uint8_t mapcos8(uint8_t theta, uint8_t lowest = 0, uint8_t highest = 255) {
uint8_t beatcos = cos8(theta);
uint8_t rangewidth = highest - lowest;
uint8_t scaledbeat = scale8(beatcos, rangewidth);
uint8_t result = lowest + scaledbeat;
return result;
}
// Array of temperature readings at each simulation cell
byte heat[NUM_LEDS];
uint32_t noise_x;
uint32_t noise_y;
uint32_t noise_z;
uint32_t noise_scale_x;
uint32_t noise_scale_y;
uint8_t noise[VPANEL_W][VPANEL_H];
uint8_t noisesmoothing;
class Effects {
public:
//CRGB *leds;
CRGB leds[NUM_LEDS];
CRGB leds2[NUM_LEDS]; // Faptastic: getting rid of this and any dependant effects or algos. to save memory 24*64*32 bytes of ram (50k).
/* The only 'framebuffer' we have is what is contained in the leds and leds2 variables.
We don't store what the color a particular pixel might be, other than when it's turned
into raw electrical signal output gobbly-gook (i.e. the DMA matrix buffer), but this * is not reversible.
As such, any time these effects want to write a pixel color, we first have to update
the leds or leds2 array, and THEN write it to the RGB panel. This enables us to 'look up' the array to see what a pixel color was previously, each drawFrame().
*/
void drawBackgroundFastLEDPixelCRGB(int16_t x, int16_t y, CRGB color)
{
leds[XY(x, y)] = color;
virtualDisp.drawPixelRGB888(x, y, color.r, color.g, color.b);
}
// write one pixel with the specified color from the current palette to coordinates
void Pixel(int x, int y, uint8_t colorIndex) {
CRGB temp = ColorFromCurrentPalette(colorIndex);
leds[XY(x, y)] = temp;
virtualDisp.drawPixelRGB888(x, y, temp.r, temp.g, temp.b); // now draw it?
}
void PrepareFrame() {
// leds = (CRGB*) backgroundLayer.backBuffer();
}
void ShowFrame() {
#if (FASTLED_VERSION >= 3001000)
nblendPaletteTowardPalette(currentPalette, targetPalette, 24);
#else
currentPalette = targetPalette;
#endif
// backgroundLayer.swapBuffers();
// leds = (CRGB*) backgroundLayer.backBuffer();
// LEDS.countFPS();
for (int y = 0; y < VPANEL_H; y++) {
for (int x = 0; x < VPANEL_W; x++)
{
CRGB tmp_led = leds[XY(x, y)];
virtualDisp.drawPixelRGB888( x, y, tmp_led.r, tmp_led.g, tmp_led.b);
} // end loop to copy fast led to the dma matrix
}
}
// scale the brightness of the screenbuffer down
void DimAll(byte value)
{
for (int i = 0; i < NUM_LEDS; i++)
{
leds[i].nscale8(value);
}
}
void ClearFrame()
{
memset(leds, 0x00, sizeof(leds)); // flush
}
void CircleStream(uint8_t value) {
DimAll(value); ShowFrame();
for (uint8_t offset = 0; offset < MATRIX_CENTER_X; offset++) {
boolean hasprev = false;
uint16_t prevxy = 0;
for (uint8_t theta = 0; theta < 255; theta++) {
uint8_t x = mapcos8(theta, offset, (VPANEL_W - 1) - offset);
uint8_t y = mapsin8(theta, offset, (VPANEL_H - 1) - offset);
uint16_t xy = XY(x, y);
if (hasprev) {
leds[prevxy] += leds[xy];
}
prevxy = xy;
hasprev = true;
}
}
for (uint8_t x = 0; x < VPANEL_W; x++) {
for (uint8_t y = 0; y < VPANEL_H; y++) {
uint16_t xy = XY(x, y);
leds[xy] = leds2[xy];
leds[xy].nscale8(value);
leds2[xy].nscale8(value);
}
}
}
// palettes
static const int paletteCount = 10;
int paletteIndex = -1;
TBlendType currentBlendType = LINEARBLEND;
CRGBPalette16 currentPalette;
CRGBPalette16 targetPalette;
char* currentPaletteName;
static const int HeatColorsPaletteIndex = 6;
static const int RandomPaletteIndex = 9;
void Setup() {
currentPalette = RainbowColors_p;
loadPalette(0);
NoiseVariablesSetup();
}
void CyclePalette(int offset = 1) {
loadPalette(paletteIndex + offset);
}
void RandomPalette() {
loadPalette(RandomPaletteIndex);
}
void loadPalette(int index) {
paletteIndex = index;
if (paletteIndex >= paletteCount)
paletteIndex = 0;
else if (paletteIndex < 0)
paletteIndex = paletteCount - 1;
switch (paletteIndex) {
case 0:
targetPalette = RainbowColors_p;
currentPaletteName = (char *)"Rainbow";
break;
case 1:
targetPalette = OceanColors_p;
currentPaletteName = (char *)"Ocean";
break;
case 2:
targetPalette = CloudColors_p;
currentPaletteName = (char *)"Cloud";
break;
case 3:
targetPalette = ForestColors_p;
currentPaletteName = (char *)"Forest";
break;
case 4:
targetPalette = PartyColors_p;
currentPaletteName = (char *)"Party";
break;
case 5:
setupGrayscalePalette();
currentPaletteName = (char *)"Grey";
break;
case HeatColorsPaletteIndex:
targetPalette = HeatColors_p;
currentPaletteName = (char *)"Heat";
break;
case 7:
targetPalette = LavaColors_p;
currentPaletteName = (char *)"Lava";
break;
case 8:
setupIcePalette();
currentPaletteName = (char *)"Ice";
break;
case RandomPaletteIndex:
loadPalette(random(0, paletteCount - 1));
paletteIndex = RandomPaletteIndex;
currentPaletteName = (char *)"Random";
break;
}
}
void setPalette(String paletteName) {
if (paletteName == "Rainbow")
loadPalette(0);
else if (paletteName == "Ocean")
loadPalette(1);
else if (paletteName == "Cloud")
loadPalette(2);
else if (paletteName == "Forest")
loadPalette(3);
else if (paletteName == "Party")
loadPalette(4);
else if (paletteName == "Grayscale")
loadPalette(5);
else if (paletteName == "Heat")
loadPalette(6);
else if (paletteName == "Lava")
loadPalette(7);
else if (paletteName == "Ice")
loadPalette(8);
else if (paletteName == "Random")
RandomPalette();
}
void listPalettes() {
Serial.println(F("{"));
Serial.print(F(" \"count\": "));
Serial.print(paletteCount);
Serial.println(",");
Serial.println(F(" \"results\": ["));
String paletteNames [] = {
"Rainbow",
// "RainbowStripe",
"Ocean",
"Cloud",
"Forest",
"Party",
"Grayscale",
"Heat",
"Lava",
"Ice",
"Random"
};
for (int i = 0; i < paletteCount; i++) {
Serial.print(F(" \""));
Serial.print(paletteNames[i]);
if (i == paletteCount - 1)
Serial.println(F("\""));
else
Serial.println(F("\","));
}
Serial.println(" ]");
Serial.println("}");
}
void setupGrayscalePalette() {
targetPalette = CRGBPalette16(CRGB::Black, CRGB::White);
}
void setupIcePalette() {
targetPalette = CRGBPalette16(CRGB::Black, CRGB::Blue, CRGB::Aqua, CRGB::White);
}
// Oscillators and Emitters
// the oscillators: linear ramps 0-255
byte osci[6];
// sin8(osci) swinging between 0 to MATRIX_WIDTH - 1
byte p[6];
// set the speeds (and by that ratios) of the oscillators here
void MoveOscillators() {
osci[0] = osci[0] + 5;
osci[1] = osci[1] + 2;
osci[2] = osci[2] + 3;
osci[3] = osci[3] + 4;
osci[4] = osci[4] + 1;
if (osci[4] % 2 == 0)
osci[5] = osci[5] + 1; // .5
for (int i = 0; i < 4; i++) {
p[i] = map8(sin8(osci[i]), 0, VPANEL_W - 1); //why? to keep the result in the range of 0-MATRIX_WIDTH (matrix size)
}
}
// All the caleidoscope functions work directly within the screenbuffer (leds array).
// Draw whatever you like in the area x(0-15) and y (0-15) and then copy it arround.
// rotates the first 16x16 quadrant 3 times onto a 32x32 (+90 degrees rotation for each one)
void Caleidoscope1() {
for (int x = 0; x < MATRIX_CENTER_X; x++) {
for (int y = 0; y < MATRIX_CENTER_Y; y++) {
leds[XY(VPANEL_W - 1 - x, y)] = leds[XY(x, y)];
leds[XY(VPANEL_W - 1 - x, VPANEL_H - 1 - y)] = leds[XY(x, y)];
leds[XY(x, VPANEL_H - 1 - y)] = leds[XY(x, y)];
}
}
}
// mirror the first 16x16 quadrant 3 times onto a 32x32
void Caleidoscope2() {
for (int x = 0; x < MATRIX_CENTER_X; x++) {
for (int y = 0; y < MATRIX_CENTER_Y; y++) {
leds[XY(VPANEL_W - 1 - x, y)] = leds[XY(y, x)];
leds[XY(x, VPANEL_H - 1 - y)] = leds[XY(y, x)];
leds[XY(VPANEL_W - 1 - x, VPANEL_H - 1 - y)] = leds[XY(x, y)];
}
}
}
// copy one diagonal triangle into the other one within a 16x16
void Caleidoscope3() {
for (int x = 0; x <= MATRIX_CENTRE_X; x++) {
for (int y = 0; y <= x; y++) {
leds[XY(x, y)] = leds[XY(y, x)];
}
}
}
// copy one diagonal triangle into the other one within a 16x16 (90 degrees rotated compared to Caleidoscope3)
void Caleidoscope4() {
for (int x = 0; x <= MATRIX_CENTRE_X; x++) {
for (int y = 0; y <= MATRIX_CENTRE_Y - x; y++) {
leds[XY(MATRIX_CENTRE_Y - y, MATRIX_CENTRE_X - x)] = leds[XY(x, y)];
}
}
}
// copy one diagonal triangle into the other one within a 8x8
void Caleidoscope5() {
for (int x = 0; x < VPANEL_W / 4; x++) {
for (int y = 0; y <= x; y++) {
leds[XY(x, y)] = leds[XY(y, x)];
}
}
for (int x = VPANEL_W / 4; x < VPANEL_W / 2; x++) {
for (int y = VPANEL_H / 4; y >= 0; y--) {
leds[XY(x, y)] = leds[XY(y, x)];
}
}
}
void Caleidoscope6() {
for (int x = 1; x < MATRIX_CENTER_X; x++) {
leds[XY(7 - x, 7)] = leds[XY(x, 0)];
} //a
for (int x = 2; x < MATRIX_CENTER_X; x++) {
leds[XY(7 - x, 6)] = leds[XY(x, 1)];
} //b
for (int x = 3; x < MATRIX_CENTER_X; x++) {
leds[XY(7 - x, 5)] = leds[XY(x, 2)];
} //c
for (int x = 4; x < MATRIX_CENTER_X; x++) {
leds[XY(7 - x, 4)] = leds[XY(x, 3)];
} //d
for (int x = 5; x < MATRIX_CENTER_X; x++) {
leds[XY(7 - x, 3)] = leds[XY(x, 4)];
} //e
for (int x = 6; x < MATRIX_CENTER_X; x++) {
leds[XY(7 - x, 2)] = leds[XY(x, 5)];
} //f
for (int x = 7; x < MATRIX_CENTER_X; x++) {
leds[XY(7 - x, 1)] = leds[XY(x, 6)];
} //g
}
// create a square twister to the left or counter-clockwise
// x and y for center, r for radius
void SpiralStream(int x, int y, int r, byte dimm) {
for (int d = r; d >= 0; d--) { // from the outside to the inside
for (int i = x - d; i <= x + d; i++) {
leds[XY(i, y - d)] += leds[XY(i + 1, y - d)]; // lowest row to the right
leds[XY(i, y - d)].nscale8(dimm);
}
for (int i = y - d; i <= y + d; i++) {
leds[XY(x + d, i)] += leds[XY(x + d, i + 1)]; // right colum up
leds[XY(x + d, i)].nscale8(dimm);
}
for (int i = x + d; i >= x - d; i--) {
leds[XY(i, y + d)] += leds[XY(i - 1, y + d)]; // upper row to the left
leds[XY(i, y + d)].nscale8(dimm);
}
for (int i = y + d; i >= y - d; i--) {
leds[XY(x - d, i)] += leds[XY(x - d, i - 1)]; // left colum down
leds[XY(x - d, i)].nscale8(dimm);
}
}
}
// expand everything within a circle
void Expand(int centerX, int centerY, int radius, byte dimm) {
if (radius == 0)
return;
int currentRadius = radius;
while (currentRadius > 0) {
int a = radius, b = 0;
int radiusError = 1 - a;
int nextRadius = currentRadius - 1;
int nextA = nextRadius - 1, nextB = 0;
int nextRadiusError = 1 - nextA;
while (a >= b)
{
// move them out one pixel on the radius
leds[XY(a + centerX, b + centerY)] = leds[XY(nextA + centerX, nextB + centerY)];
leds[XY(b + centerX, a + centerY)] = leds[XY(nextB + centerX, nextA + centerY)];
leds[XY(-a + centerX, b + centerY)] = leds[XY(-nextA + centerX, nextB + centerY)];
leds[XY(-b + centerX, a + centerY)] = leds[XY(-nextB + centerX, nextA + centerY)];
leds[XY(-a + centerX, -b + centerY)] = leds[XY(-nextA + centerX, -nextB + centerY)];
leds[XY(-b + centerX, -a + centerY)] = leds[XY(-nextB + centerX, -nextA + centerY)];
leds[XY(a + centerX, -b + centerY)] = leds[XY(nextA + centerX, -nextB + centerY)];
leds[XY(b + centerX, -a + centerY)] = leds[XY(nextB + centerX, -nextA + centerY)];
// dim them
leds[XY(a + centerX, b + centerY)].nscale8(dimm);
leds[XY(b + centerX, a + centerY)].nscale8(dimm);
leds[XY(-a + centerX, b + centerY)].nscale8(dimm);
leds[XY(-b + centerX, a + centerY)].nscale8(dimm);
leds[XY(-a + centerX, -b + centerY)].nscale8(dimm);
leds[XY(-b + centerX, -a + centerY)].nscale8(dimm);
leds[XY(a + centerX, -b + centerY)].nscale8(dimm);
leds[XY(b + centerX, -a + centerY)].nscale8(dimm);
b++;
if (radiusError < 0)
radiusError += 2 * b + 1;
else
{
a--;
radiusError += 2 * (b - a + 1);
}
nextB++;
if (nextRadiusError < 0)
nextRadiusError += 2 * nextB + 1;
else
{
nextA--;
nextRadiusError += 2 * (nextB - nextA + 1);
}
}
currentRadius--;
}
}
// give it a linear tail to the right
void StreamRight(byte scale, int fromX = 0, int toX = VPANEL_W, int fromY = 0, int toY = VPANEL_H)
{
for (int x = fromX + 1; x < toX; x++) {
for (int y = fromY; y < toY; y++) {
leds[XY(x, y)] += leds[XY(x - 1, y)];
leds[XY(x, y)].nscale8(scale);
}
}
for (int y = fromY; y < toY; y++)
leds[XY(0, y)].nscale8(scale);
}
// give it a linear tail to the left
void StreamLeft(byte scale, int fromX = VPANEL_W, int toX = 0, int fromY = 0, int toY = VPANEL_H)
{
for (int x = toX; x < fromX; x++) {
for (int y = fromY; y < toY; y++) {
leds[XY(x, y)] += leds[XY(x + 1, y)];
leds[XY(x, y)].nscale8(scale);
}
}
for (int y = fromY; y < toY; y++)
leds[XY(0, y)].nscale8(scale);
}
// give it a linear tail downwards
void StreamDown(byte scale)
{
for (int x = 0; x < VPANEL_W; x++) {
for (int y = 1; y < VPANEL_H; y++) {
leds[XY(x, y)] += leds[XY(x, y - 1)];
leds[XY(x, y)].nscale8(scale);
}
}
for (int x = 0; x < VPANEL_W; x++)
leds[XY(x, 0)].nscale8(scale);
}
// give it a linear tail upwards
void StreamUp(byte scale)
{
for (int x = 0; x < VPANEL_W; x++) {
for (int y = VPANEL_H - 2; y >= 0; y--) {
leds[XY(x, y)] += leds[XY(x, y + 1)];
leds[XY(x, y)].nscale8(scale);
}
}
for (int x = 0; x < VPANEL_W; x++)
leds[XY(x, VPANEL_H - 1)].nscale8(scale);
}
// give it a linear tail up and to the left
void StreamUpAndLeft(byte scale)
{
for (int x = 0; x < VPANEL_W - 1; x++) {
for (int y = VPANEL_H - 2; y >= 0; y--) {
leds[XY(x, y)] += leds[XY(x + 1, y + 1)];
leds[XY(x, y)].nscale8(scale);
}
}
for (int x = 0; x < VPANEL_W; x++)
leds[XY(x, VPANEL_H - 1)].nscale8(scale);
for (int y = 0; y < VPANEL_H; y++)
leds[XY(VPANEL_W - 1, y)].nscale8(scale);
}
// give it a linear tail up and to the right
void StreamUpAndRight(byte scale)
{
for (int x = 0; x < VPANEL_W - 1; x++) {
for (int y = VPANEL_H - 2; y >= 0; y--) {
leds[XY(x + 1, y)] += leds[XY(x, y + 1)];
leds[XY(x, y)].nscale8(scale);
}
}
// fade the bottom row
for (int x = 0; x < VPANEL_W; x++)
leds[XY(x, VPANEL_H - 1)].nscale8(scale);
// fade the right column
for (int y = 0; y < VPANEL_H; y++)
leds[XY(VPANEL_W - 1, y)].nscale8(scale);
}
// just move everything one line down
void MoveDown() {
for (int y = VPANEL_H - 1; y > 0; y--) {
for (int x = 0; x < VPANEL_W; x++) {
leds[XY(x, y)] = leds[XY(x, y - 1)];
}
}
}
// just move everything one line down
void VerticalMoveFrom(int start, int end) {
for (int y = end; y > start; y--) {
for (int x = 0; x < VPANEL_W; x++) {
leds[XY(x, y)] = leds[XY(x, y - 1)];
}
}
}
// copy the rectangle defined with 2 points x0, y0, x1, y1
// to the rectangle beginning at x2, x3
void Copy(byte x0, byte y0, byte x1, byte y1, byte x2, byte y2) {
for (int y = y0; y < y1 + 1; y++) {
for (int x = x0; x < x1 + 1; x++) {
leds[XY(x + x2 - x0, y + y2 - y0)] = leds[XY(x, y)];
}
}
}
// rotate + copy triangle (MATRIX_CENTER_X*MATRIX_CENTER_X)
void RotateTriangle() {
for (int x = 1; x < MATRIX_CENTER_X; x++) {
for (int y = 0; y < x; y++) {
leds[XY(x, 7 - y)] = leds[XY(7 - x, y)];
}
}
}
// mirror + copy triangle (MATRIX_CENTER_X*MATRIX_CENTER_X)
void MirrorTriangle() {
for (int x = 1; x < MATRIX_CENTER_X; x++) {
for (int y = 0; y < x; y++) {
leds[XY(7 - y, x)] = leds[XY(7 - x, y)];
}
}
}
// draw static rainbow triangle pattern (MATRIX_CENTER_XxWIDTH / 2)
// (just for debugging)
void RainbowTriangle() {
for (int i = 0; i < MATRIX_CENTER_X; i++) {
for (int j = 0; j <= i; j++) {
Pixel(7 - i, j, i * j * 4);
}
}
}
void BresenhamLine(int x0, int y0, int x1, int y1, byte colorIndex)
{
BresenhamLine(x0, y0, x1, y1, ColorFromCurrentPalette(colorIndex));
}
void BresenhamLine(int x0, int y0, int x1, int y1, CRGB color)
{
int dx = abs(x1 - x0), sx = x0 < x1 ? 1 : -1;
int dy = -abs(y1 - y0), sy = y0 < y1 ? 1 : -1;
int err = dx + dy, e2;
for (;;) {
leds[XY(x0, y0)] += color;
if (x0 == x1 && y0 == y1) break;
e2 = 2 * err;
if (e2 > dy) {
err += dy;
x0 += sx;
}
if (e2 < dx) {
err += dx;
y0 += sy;
}
}
}
// write one pixel with the specified color from the current palette to coordinates
/*
void Pixel(int x, int y, uint8_t colorIndex) {
leds[XY(x, y)] = ColorFromCurrentPalette(colorIndex);
matrix.drawBackgroundPixelRGB888(x,y, leds[XY(x, y)]); // now draw it?
}
*/
CRGB ColorFromCurrentPalette(uint8_t index = 0, uint8_t brightness = 255, TBlendType blendType = LINEARBLEND) {
return ColorFromPalette(currentPalette, index, brightness, currentBlendType);
}
CRGB HsvToRgb(uint8_t h, uint8_t s, uint8_t v) {
CHSV hsv = CHSV(h, s, v);
CRGB rgb;
hsv2rgb_spectrum(hsv, rgb);
return rgb;
}
void NoiseVariablesSetup() {
noisesmoothing = 200;
noise_x = random16();
noise_y = random16();
noise_z = random16();
noise_scale_x = 6000;
noise_scale_y = 6000;
}
void FillNoise() {
for (uint8_t i = 0; i < VPANEL_W; i++) {
uint32_t ioffset = noise_scale_x * (i - MATRIX_CENTRE_Y);
for (uint8_t j = 0; j < VPANEL_H; j++) {
uint32_t joffset = noise_scale_y * (j - MATRIX_CENTRE_Y);
byte data = inoise16(noise_x + ioffset, noise_y + joffset, noise_z) >> 8;
uint8_t olddata = noise[i][j];
uint8_t newdata = scale8(olddata, noisesmoothing) + scale8(data, 256 - noisesmoothing);
data = newdata;
noise[i][j] = data;
}
}
}
// non leds2 memory version.
void MoveX(byte delta)
{
CRGB tmp = 0;
for (int y = 0; y < VPANEL_H; y++)
{
// Shift Left: https://codedost.com/c/arraypointers-in-c/c-program-shift-elements-array-left-direction/
// Computationally heavier but doesn't need an entire leds2 array
tmp = leds[XY(0, y)];
for (int m = 0; m < delta; m++)
{
// Do this delta time for each row... computationally expensive potentially.
for (int x = 0; x < VPANEL_H; x++)
{
leds[XY(x, y)] = leds [XY(x + 1, y)];
}
leds[XY(VPANEL_W - 1, y)] = tmp;
}
/*
// Shift
for (int x = 0; x < VPANEL_W - delta; x++) {
leds2[XY(x, y)] = leds[XY(x + delta, y)];
}
// Wrap around
for (int x = VPANEL_W - delta; x < VPANEL_W; x++) {
leds2[XY(x, y)] = leds[XY(x + delta - VPANEL_H, y)];
}
*/
} // end row loop
/*
// write back to leds
for (uint8_t y = 0; y < VPANEL_H; y++) {
for (uint8_t x = 0; x < VPANEL_W; x++) {
leds[XY(x, y)] = leds2[XY(x, y)];
}
}
*/
}
void MoveY(byte delta)
{
CRGB tmp = 0;
for (int x = 0; x < VPANEL_W; x++)
{
tmp = leds[XY(x, 0)];
for (int m = 0; m < delta; m++) // moves
{
// Do this delta time for each row... computationally expensive potentially.
for (int y = 0; y < VPANEL_H; y++)
{
leds[XY(x, y)] = leds [XY(x, y + 1)];
}
leds[XY(x, VPANEL_H - 1)] = tmp;
}
} // end column loop
} /// MoveY
void MoveFractionalNoiseX(byte amt = 16) {
// move delta pixelwise
for (int y = 0; y < VPANEL_H; y++) {
uint16_t amount = noise[0][y] * amt;
byte delta = 31 - (amount / 256);
for (int x = 0; x < VPANEL_W - delta; x++) {
leds2[XY(x, y)] = leds[XY(x + delta, y)];
}
for (int x = VPANEL_H - delta; x < VPANEL_W; x++) {
leds2[XY(x, y)] = leds[XY(x + delta - VPANEL_W, y)];
}
}
//move fractions
CRGB PixelA;
CRGB PixelB;
for (uint8_t y = 0; y < VPANEL_H; y++) {
uint16_t amount = noise[0][y] * amt;
byte delta = 31 - (amount / 256);
byte fractions = amount - (delta * 256);
for (uint8_t x = 1; x < VPANEL_W; x++) {
PixelA = leds2[XY(x, y)];
PixelB = leds2[XY(x - 1, y)];
PixelA %= 255 - fractions;
PixelB %= fractions;
leds[XY(x, y)] = PixelA + PixelB;
}
PixelA = leds2[XY(0, y)];
PixelB = leds2[XY(VPANEL_W - 1, y)];
PixelA %= 255 - fractions;
PixelB %= fractions;
leds[XY(0, y)] = PixelA + PixelB;
}
}
void MoveFractionalNoiseY(byte amt = 16) {
// move delta pixelwise
for (int x = 0; x < VPANEL_W; x++) {
uint16_t amount = noise[x][0] * amt;
byte delta = 31 - (amount / 256);
for (int y = 0; y < VPANEL_W - delta; y++) {
leds2[XY(x, y)] = leds[XY(x, y + delta)];
}
for (int y = VPANEL_W - delta; y < VPANEL_W; y++) {
leds2[XY(x, y)] = leds[XY(x, y + delta - VPANEL_W)];
}
}
//move fractions
CRGB PixelA;
CRGB PixelB;
for (uint8_t x = 0; x < VPANEL_H; x++) {
uint16_t amount = noise[x][0] * amt;
byte delta = 31 - (amount / 256);
byte fractions = amount - (delta * 256);
for (uint8_t y = 1; y < VPANEL_W; y++) {
PixelA = leds2[XY(x, y)];
PixelB = leds2[XY(x, y - 1)];
PixelA %= 255 - fractions;
PixelB %= fractions;
leds[XY(x, y)] = PixelA + PixelB;
}
PixelA = leds2[XY(x, 0)];
PixelB = leds2[XY(x, VPANEL_W - 1)];
PixelA %= 255 - fractions;
PixelB %= fractions;
leds[XY(x, 0)] = PixelA + PixelB;
}
}
void standardNoiseSmearing() {
noise_x += 1000;
noise_y += 1000;
noise_scale_x = 4000;
noise_scale_y = 4000;
FillNoise();
MoveX(3);
MoveFractionalNoiseY(4);
MoveY(3);
MoveFractionalNoiseX(4);
}
};
#endif

View file

@ -0,0 +1,150 @@
/*
* Aurora: https://github.com/pixelmatix/aurora
* Copyright (c) 2014 Jason Coon
*
* Portions of this code are adapted from Noel Bundy's work: https://github.com/TwystNeko/Object3d
* Copyright (c) 2014 Noel Bundy
*
* Portions of this code are adapted from the Petty library: https://code.google.com/p/peggy/
* Copyright (c) 2008 Windell H Oskay. All right reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef Geometry_H
#define Geometry_H
struct Vertex
{
float x, y, z;
Vertex()
{
this->set(0, 0, 0);
}
Vertex(float x, float y, float z)
{
this->set(x, y, z);
}
void set(float x, float y, float z)
{
this->x = x;
this->y = y;
this->z = z;
}
};
struct EdgePoint
{
int x, y;
boolean visible;
EdgePoint()
{
this->set(0, 0);
this->visible = false;
}
void set(int a, int b)
{
this->x = a;
this->y = b;
}
};
struct Point
{
float x, y;
Point()
{
set(0, 0);
}
Point(float x, float y)
{
set(x, y);
}
void set(float x, float y)
{
this->x = x;
this->y = y;
}
};
struct squareFace
{
int length;
int sommets[4];
int ed[4];
squareFace()
{
set(-1, -1, -1, -1);
}
squareFace(int a, int b, int c, int d)
{
this->length = 4;
this->sommets[0] = a;
this->sommets[1] = b;
this->sommets[2] = c;
this->sommets[3] = d;
}
void set(int a, int b, int c, int d)
{
this->length = 4;
this->sommets[0] = a;
this->sommets[1] = b;
this->sommets[2] = c;
this->sommets[3] = d;
}
};
struct triFace
{
int length;
int sommets[3];
int ed[3];
triFace()
{
set(-1,-1,-1);
}
triFace(int a, int b, int c)
{
this->length =3;
this->sommets[0]=a;
this->sommets[1]=b;
this->sommets[2]=c;
}
void set(int a, int b, int c)
{
this->length =3;
this->sommets[0]=a;
this->sommets[1]=b;
this->sommets[2]=c;
}
};
#endif

View file

@ -0,0 +1,3 @@
const uint8_t PROGMEM palette_fire[] = {/* RGB888 R,G,B,R,G,B,R,G,B,... */
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x05,0x00,0x00,0x0a,0x00,0x00,0x10,0x00,0x00,0x15,0x00,0x00,0x1b,0x00,0x00,0x20,0x00,0x00,0x25,0x00,0x00,0x2b,0x00,0x00,0x31,0x00,0x00,0x36,0x00,0x00,0x3c,0x00,0x00,0x41,0x00,0x00,0x46,0x00,0x00,0x4c,0x00,0x00,0x52,0x00,0x00,0x57,0x00,0x00,0x5d,0x00,0x00,0x62,0x00,0x00,0x68,0x00,0x00,0x6d,0x00,0x00,0x73,0x00,0x00,0x79,0x00,0x00,0x7e,0x00,0x00,0x83,0x00,0x00,0x89,0x00,0x00,0x8e,0x00,0x00,0x94,0x00,0x00,0x9a,0x00,0x00,0x9f,0x00,0x00,0xa5,0x00,0x00,0xaa,0x00,0x00,0xb0,0x00,0x00,0xb5,0x00,0x00,0xbb,0x00,0x00,0xc0,0x00,0x00,0xc6,0x00,0x00,0xcb,0x00,0x00,0xd1,0x00,0x00,0xd7,0x00,0x00,0xdc,0x00,0x00,0xe1,0x00,0x00,0xe6,0x00,0x00,0xe8,0x02,0x00,0xe9,0x08,0x00,0xe9,0x0f,0x00,0xe9,0x13,0x00,0xe9,0x16,0x00,0xe9,0x1b,0x00,0xe9,0x21,0x00,0xe9,0x26,0x00,0xe9,0x2a,0x00,0xe9,0x2e,0x00,0xe9,0x32,0x00,0xe9,0x37,0x00,0xe9,0x3b,0x00,0xe9,0x3f,0x00,0xe9,0x44,0x00,0xe9,0x4a,0x00,0xe9,0x4e,0x00,0xe9,0x52,0x00,0xe9,0x56,0x00,0xe9,0x5a,0x00,0xe9,0x5d,0x00,0xe9,0x63,0x00,0xe9,0x67,0x00,0xe9,0x6b,0x00,0xe9,0x71,0x00,0xe9,0x77,0x00,0xe9,0x78,0x00,0xe9,0x7c,0x00,0xe9,0x81,0x00,0xe9,0x86,0x00,0xe9,0x8b,0x00,0xe9,0x8f,0x00,0xe9,0x93,0x00,0xe9,0x99,0x00,0xe9,0x9d,0x00,0xe9,0xa0,0x00,0xe9,0xa4,0x00,0xe9,0xaa,0x00,0xe9,0xb0,0x00,0xe9,0xb4,0x00,0xe9,0xb5,0x00,0xe9,0xb9,0x00,0xe9,0xbe,0x00,0xe9,0xc3,0x00,0xe9,0xc9,0x00,0xe9,0xce,0x00,0xe9,0xd2,0x00,0xe9,0xd6,0x00,0xe9,0xd9,0x00,0xe9,0xdd,0x00,0xe9,0xe2,0x00,0xe9,0xe7,0x02,0xe9,0xe9,0x0e,0xe9,0xe9,0x1c,0xe9,0xe9,0x28,0xe9,0xe9,0x38,0xe9,0xe9,0x48,0xe9,0xe9,0x57,0xe9,0xe9,0x67,0xe9,0xe9,0x73,0xe9,0xe9,0x81,0xe9,0xe9,0x90,0xe9,0xe9,0xa1,0xe9,0xe9,0xb1,0xe9,0xe9,0xbf,0xe9,0xe9,0xcb,0xe9,0xe9,0xcb,0xe9,0xe9,0xcd,0xe9,0xe9,0xd9,0xe9,0xe9,0xe5,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe8,0xe8,0xe8,0xe8,0xe8,0xe8,0xe8,0xe8,0xe8,0xe8,0xe8,0xe8,0xe7,0xe7,0xe7,0xe7,0xe7,0xe7,0xe6,0xe6,0xe6,0xe4,0xe4,0xe4,0xe3,0xe3,0xe3,0xe0,0xe0,0xe0,0xdc,0xdc,0xdc,0xd8,0xd8,0xd8,0xd2,0xd2,0xd2,0xca,0xca,0xca,0xc1,0xc1,0xc1,0xb7,0xb7,0xb7,0xab,0xab,0xab,0x9d,0x9d,0x9d,0x8f,0x8f,0x8f,0x81,0x81,0x81,0x72,0x72,0x72,0x64,0x64,0x64,0x56,0x56,0x56,0x4a,0x4a,0x4a,0x3e,0x3e,0x3e,0x33,0x33,0x33,0x2a,0x2a,0x2a,0x22,0x22,0x22,0x1b,0x1b,0x1b,0x16,0x16,0x16,0x11,0x11,0x11,0x0d,0x0d,0x0d,0x0b,0x0b,0x0b,0x08,0x08,0x08,0x07,0x07,0x07,0x06,0x06,0x06,0x05,0x05,0x05,0x04,0x04,0x04,0x03,0x03,0x03,0x03,0x03,0x03,0x02,0x02,0x02,0x02,0x02,0x02,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
};

View file

@ -0,0 +1,73 @@
/*
* Aurora: https://github.com/pixelmatix/aurora
* Copyright (c) 2014 Jason Coon
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef PatternAttract_H
class PatternAttract : public Drawable {
private:
const int count = 8;
Attractor attractor;
public:
PatternAttract() {
name = (char *)"Attract";
}
void start() {
int direction = random(0, 2);
if (direction == 0)
direction = -1;
for (int i = 0; i < count; i++) {
Boid boid = Boid(15, 31 - i);
boid.mass = 1; // random(0.1, 2);
boid.velocity.x = ((float) random(40, 50)) / 100.0;
boid.velocity.x *= direction;
boid.velocity.y = 0;
boid.colorIndex = i * 32;
boids[i] = boid;
//dim = random(170, 250);
}
}
unsigned int drawFrame() {
// dim all pixels on the display
uint8_t dim = beatsin8(2, 170, 250);
effects.DimAll(dim); effects.ShowFrame();
for (int i = 0; i < count; i++) {
Boid boid = boids[i];
PVector force = attractor.attract(boid);
boid.applyForce(force);
boid.update();
effects.drawBackgroundFastLEDPixelCRGB(boid.location.x, boid.location.y, effects.ColorFromCurrentPalette(boid.colorIndex));
boids[i] = boid;
}
return 15;
}
};
#endif

View file

@ -0,0 +1,116 @@
/*
* Aurora: https://github.com/pixelmatix/aurora
* Copyright (c) 2014 Jason Coon
*
* Portions of this code are adapted from "Funky Noise" by Stefan Petrick: https://github.com/StefanPetrick/FunkyNoise
* Copyright (c) 2014 Stefan Petrick
* http://www.stefan-petrick.de/wordpress_beta
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef PatternElectricMandala_H
class PatternElectricMandala : public Drawable {
private:
// The coordinates for 16-bit noise spaces.
#define NUM_LAYERS 1
// used for the random based animations
int16_t dx;
int16_t dy;
int16_t dz;
int16_t dsx;
int16_t dsy;
public:
PatternElectricMandala() {
name = (char *)"ElectricMandala";
}
void start() {
// set to reasonable values to avoid a black out
noisesmoothing = 200;
// just any free input pin
//random16_add_entropy(analogRead(18));
// fill coordinates with random values
// set zoom levels
noise_x = random16();
noise_y = random16();
noise_z = random16();
noise_scale_x = 6000;
noise_scale_y = 6000;
// for the random movement
dx = random8();
dy = random8();
dz = random8();
dsx = random8();
dsy = random8();
}
unsigned int drawFrame() {
#if FASTLED_VERSION >= 3001000
// a new parameter set every 15 seconds
EVERY_N_SECONDS(25) {
//SetupRandomPalette3();
dy = random16(500) - 250; // random16(2000) - 1000 is pretty fast but works fine, too
dx = random16(500) - 250;
dz = random16(500) - 250;
noise_scale_x = random16(10000) + 2000;
noise_scale_y = random16(10000) + 2000;
}
#endif
noise_y += dy;
noise_x += dx;
noise_z += dz;
effects.FillNoise();
ShowNoiseLayer(0, 1, 0);
effects.Caleidoscope3();
effects.Caleidoscope1();
effects.ShowFrame();
return 0;
}
// show just one layer
void ShowNoiseLayer(byte layer, byte colorrepeat, byte colorshift) {
for (uint8_t i = 0; i < VPANEL_W; i++) {
for (uint8_t j = 0; j < VPANEL_H; j++) {
uint8_t color = noise[i][j];
uint8_t bri = color;
// assign a color depending on the actual palette
CRGB pixel = ColorFromPalette(effects.currentPalette, colorrepeat * (color + colorshift), bri);
effects.leds[XY(i, j)] = pixel;
}
}
}
};
#endif

View file

@ -0,0 +1,121 @@
/*
Aurora: https://github.com/pixelmatix/aurora
Copyright (c) 2014 Jason Coon
Portions of this code are adapted from FastLED Fire2012 example by Mark Kriegsman: https://github.com/FastLED/FastLED/tree/master/examples/Fire2012WithPalette
Copyright (c) 2013 FastLED
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
// Note: (Kosso) : Doesn't look good with certain palettes.
#ifndef PatternFire_H
#define PatternFire_H
#ifndef Effects_H
#include "Effects.h"
#endif
class PatternFire : public Drawable {
private:
public:
PatternFire() {
name = (char *)"Fire";
}
// There are two main parameters you can play with to control the look and
// feel of your fire: COOLING (used in step 1 above), and SPARKING (used
// in step 3 above).
//
// cooling: How much does the air cool as it rises?
// Less cooling = taller flames. More cooling = shorter flames.
// Default 55, suggested range 20-100
int cooling = 100;
// sparking: What chance (out of 255) is there that a new spark will be lit?
// Higher chance = more roaring fire. Lower chance = more flickery fire.
// Default 120, suggested range 50-200.
unsigned int sparking = 100;
unsigned int drawFrame() {
// Add entropy to random number generator; we use a lot of it.
random16_add_entropy( random16());
effects.DimAll(235);
for (int x = 0; x < VPANEL_W; x++) {
// Step 1. Cool down every cell a little
for (int y = 0; y < VPANEL_H; y++) {
int xy = XY(x, y);
heat[xy] = qsub8(heat[xy], random8(0, ((cooling * 10) / VPANEL_H) + 2));
}
// Step 2. Heat from each cell drifts 'up' and diffuses a little
for (int y = 0; y < VPANEL_H; y++) {
heat[XY(x, y)] = (heat[XY(x, y + 1)] + heat[XY(x, y + 2)] + heat[XY(x, y + 2)]) / 3;
}
// Step 2. Randomly ignite new 'sparks' of heat
if (random8() < sparking) {
// int x = (p[0] + p[1] + p[2]) / 3;
int xy = XY(x, VPANEL_H - 1);
heat[xy] = qadd8(heat[xy], random8(160, 255));
}
// Step 4. Map from heat cells to LED colors
for (int y = 0; y < VPANEL_H; y++) {
int xy = XY(x, y);
byte colorIndex = heat[xy];
// Recommend that you use values 0-240 rather than
// the usual 0-255, as the last 15 colors will be
// 'wrapping around' from the hot end to the cold end,
// which looks wrong.
colorIndex = scale8(colorIndex, 200);
// override color 0 to ensure a black background?
//if (colorIndex != 0) {
// effects.leds[xy] = CRGB::Black;
//}
//else {
effects.leds[xy] = effects.ColorFromCurrentPalette(colorIndex);
//}
}
}
// Noise
noise_x += 1000;
noise_y += 1000;
noise_z += 1000;
noise_scale_x = 4000;
noise_scale_y = 4000;
effects.FillNoise();
// effects.MoveX(2);
effects.MoveFractionalNoiseX(2);
effects.ShowFrame();
return 15;
}
};
#endif

View file

@ -0,0 +1,109 @@
/*
Aurora: https://github.com/pixelmatix/aurora
Copyright (c) 2014 Jason Coon
Added by @Kosso. Cobbled together from various places which I can't remember. I'll update this when I track it down.
Requires PaletteFireKoz.h
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef PatternFireKoz_H
#define PatternFireKoz_H
class PatternFireKoz : public Drawable {
private:
const int FIRE_HEIGHT = 800;
int Bit = 0, NBit = 1;
float fire_c;
// might not need this buffer here... there some led buffers set up in Effects.h
uint8_t fireBuffer[VPANEL_W][VPANEL_H][2];
public:
PatternFireKoz() {
name = (char *)"FireKoz";
}
unsigned int drawFrame() {
for (int x = 1; x < VPANEL_W - 1; x++)
{
fireBuffer[x][VPANEL_H - 2][Bit] = random(0, FIRE_HEIGHT);
if (random(0, 100) > 80)
{
fireBuffer[x][VPANEL_H - 2][Bit] = 0;
fireBuffer[x][VPANEL_H - 3][Bit] = 0;
}
}
for (int y = 1; y < VPANEL_H - 1; y++)
{
for (int x = 1; x < VPANEL_W - 1; x++)
{
fire_c = (fireBuffer[x - 1][y][Bit] +
fireBuffer[x + 1][y][Bit] +
fireBuffer[x][y - 1][Bit] +
fireBuffer[x][y + 1][Bit] +
fireBuffer[x][y][Bit]) /
5.0;
fire_c = (fireBuffer[x - 1][y][Bit] +
fireBuffer[x + 1][y][Bit] +
fireBuffer[x][y - 1][Bit] +
fireBuffer[x][y + 1][Bit] +
fireBuffer[x][y][Bit]) /
5.0;
if (fire_c > (FIRE_HEIGHT / 2) && fire_c < FIRE_HEIGHT) {
fire_c -= 0.2;
} else if (fire_c > (FIRE_HEIGHT / 4) && fire_c < (FIRE_HEIGHT / 2)) {
fire_c -= 0.4;
} else if (fire_c <= (FIRE_HEIGHT / 8)) {
fire_c -= 0.7;
} else {
fire_c -= 1;
}
if (fire_c < 0)
fire_c = 0;
if (fire_c >= FIRE_HEIGHT + 1)
fire_c = FIRE_HEIGHT - 1;
fireBuffer[x][y - 1][NBit] = fire_c;
int index = (int)fire_c * 3;
if (fire_c == 0)
{
effects.drawBackgroundFastLEDPixelCRGB(x, y, CRGB(0, 0, 0));
}
else
{
effects.drawBackgroundFastLEDPixelCRGB(x, y, CRGB(palette_fire[index], palette_fire[index + 1], palette_fire[index + 2]));
}
}
}
//display.drawRect(0, 0, VPANEL_W, VPANEL_H, display.color565(25, 25, 25));
NBit = Bit;
Bit = 1 - Bit;
effects.ShowFrame();
return 30; // no idea what this is for...
}
};
#endif

View file

@ -0,0 +1,125 @@
/*
* Aurora: https://github.com/pixelmatix/aurora
* Copyright (c) 2014 Jason Coon
*
* Portions of this code are adapted from "Flocking" in "The Nature of Code" by Daniel Shiffman: http://natureofcode.com/
* Copyright (c) 2014 Daniel Shiffman
* http://www.shiffman.net
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
// Flocking
// Daniel Shiffman <http://www.shiffman.net>
// The Nature of Code, Spring 2009
// Demonstration of Craig Reynolds' "Flocking" behavior
// See: http://www.red3d.com/cwr/
// Rules: Cohesion, Separation, Alignment
#ifndef PatternFlock_H
#define PatternFlock_H
class PatternFlock : public Drawable {
public:
PatternFlock() {
name = (char *)"Flock";
}
static const int boidCount = 10;
Boid predator;
PVector wind;
byte hue = 0;
bool predatorPresent = true;
void start() {
for (int i = 0; i < boidCount; i++) {
boids[i] = Boid(15, 15);
boids[i].maxspeed = 0.380;
boids[i].maxforce = 0.015;
}
predatorPresent = random(0, 2) >= 1;
if (predatorPresent) {
predator = Boid(31, 31);
predatorPresent = true;
predator.maxspeed = 0.385;
predator.maxforce = 0.020;
predator.neighbordist = 16.0;
predator.desiredseparation = 0.0;
}
}
unsigned int drawFrame() {
effects.DimAll(230); effects.ShowFrame();
bool applyWind = random(0, 255) > 250;
if (applyWind) {
wind.x = Boid::randomf() * .015;
wind.y = Boid::randomf() * .015;
}
CRGB color = effects.ColorFromCurrentPalette(hue);
for (int i = 0; i < boidCount; i++) {
Boid * boid = &boids[i];
if (predatorPresent) {
// flee from predator
boid->repelForce(predator.location, 10);
}
boid->run(boids, boidCount);
boid->wrapAroundBorders();
PVector location = boid->location;
// PVector velocity = boid->velocity;
// backgroundLayer.drawLine(location.x, location.y, location.x - velocity.x, location.y - velocity.y, color);
// effects.leds[XY(location.x, location.y)] += color;
effects.drawBackgroundFastLEDPixelCRGB(location.x, location.y, color);
if (applyWind) {
boid->applyForce(wind);
applyWind = false;
}
}
if (predatorPresent) {
predator.run(boids, boidCount);
predator.wrapAroundBorders();
color = effects.ColorFromCurrentPalette(hue + 128);
PVector location = predator.location;
// PVector velocity = predator.velocity;
// backgroundLayer.drawLine(location.x, location.y, location.x - velocity.x, location.y - velocity.y, color);
// effects.leds[XY(location.x, location.y)] += color;
effects.drawBackgroundFastLEDPixelCRGB(location.x, location.y, color);
}
EVERY_N_MILLIS(200) {
hue++;
}
EVERY_N_SECONDS(30) {
predatorPresent = !predatorPresent;
}
return 0;
}
};
#endif

View file

@ -0,0 +1,92 @@
/*
* Aurora: https://github.com/pixelmatix/aurora
* Copyright (c) 2014 Jason Coon
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef PatternFlowField_H
class PatternFlowField : public Drawable {
public:
PatternFlowField() {
name = (char *)"FlowField";
}
uint16_t x;
uint16_t y;
uint16_t z;
uint16_t speed = 1;
uint16_t scale = 26;
static const int count = 40;
byte hue = 0;
void start() {
x = random16();
y = random16();
z = random16();
for (int i = 0; i < count; i++) {
boids[i] = Boid(random(VPANEL_W), 0);
}
}
unsigned int drawFrame() {
effects.DimAll(240);
// CRGB color = effects.ColorFromCurrentPalette(hue);
for (int i = 0; i < count; i++) {
Boid * boid = &boids[i];
int ioffset = scale * boid->location.x;
int joffset = scale * boid->location.y;
byte angle = inoise8(x + ioffset, y + joffset, z);
boid->velocity.x = (float) sin8(angle) * 0.0078125 - 1.0;
boid->velocity.y = -((float)cos8(angle) * 0.0078125 - 1.0);
boid->update();
effects.drawBackgroundFastLEDPixelCRGB(boid->location.x, boid->location.y, effects.ColorFromCurrentPalette(angle + hue)); // color
if (boid->location.x < 0 || boid->location.x >= VPANEL_W ||
boid->location.y < 0 || boid->location.y >= VPANEL_H) {
boid->location.x = random(VPANEL_W);
boid->location.y = 0;
}
}
EVERY_N_MILLIS(200) {
hue++;
}
x += speed;
y += speed;
z += speed;
effects.ShowFrame();
return 50;
}
};
#endif

View file

@ -0,0 +1,51 @@
/*
*
* Aurora: https://github.com/pixelmatix/aurora
* Copyright (c) 2014 Jason Coon
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef PatternIncrementalDrift_H
#define PatternIncrementalDrift_H
class PatternIncrementalDrift : public Drawable {
public:
PatternIncrementalDrift() {
name = (char *)"Incremental Drift";
}
unsigned int drawFrame() {
uint8_t dim = beatsin8(2, 230, 250);
effects.DimAll(dim); effects.ShowFrame();
for (int i = 2; i <= VPANEL_W / 2; i++)
{
CRGB color = effects.ColorFromCurrentPalette((i - 2) * (240 / (VPANEL_W / 2)));
uint8_t x = beatcos8((17 - i) * 2, MATRIX_CENTER_X - i, MATRIX_CENTER_X + i);
uint8_t y = beatsin8((17 - i) * 2, MATRIX_CENTER_Y - i, MATRIX_CENTER_Y + i);
effects.drawBackgroundFastLEDPixelCRGB(x, y, color);
}
return 0;
}
};
#endif

View file

@ -0,0 +1,58 @@
/*
* Aurora: https://github.com/pixelmatix/aurora
* Copyright (c) 2014 Jason Coon
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef PatternInfinity_H
class PatternInfinity : public Drawable {
public:
PatternInfinity() {
name = (char *)"Infinity";
}
unsigned int drawFrame() {
// dim all pixels on the display slightly
// to 250/255 (98%) of their current brightness
effects.DimAll(250); effects.ShowFrame();
// the Effects class has some sample oscillators
// that move from 0 to 255 at different speeds
effects.MoveOscillators();
// the horizontal position of the head of the infinity sign
// oscillates from 0 to the maximum horizontal and back
int x = (VPANEL_W - 1) - effects.p[1];
// the vertical position of the head oscillates
// from 8 to 23 and back (hard-coded for a 32x32 matrix)
int y = map8(sin8(effects.osci[3]), 8, 23);
// the hue oscillates from 0 to 255, overflowing back to 0
byte hue = sin8(effects.osci[5]);
// draw a pixel at x,y using a color from the current palette
effects.Pixel(x, y, hue);
return 15;
}
};
#endif

View file

@ -0,0 +1,129 @@
/*
* Aurora: https://github.com/pixelmatix/aurora
* Copyright (c) 2014 Jason Coon
*
* Portions of this code are adapted from Andrew: http://pastebin.com/f22bfe94d
* which, in turn, was "Adapted from the Life example on the Processing.org site"
*
* Made much more colorful by J.B. Langston: https://github.com/jblang/aurora/commit/6db5a884e3df5d686445c4f6b669f1668841929b
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef PatternLife_H
#define PatternLife_H
class Cell {
public:
byte alive : 1;
byte prev : 1;
byte hue: 6;
byte brightness;
};
class PatternLife : public Drawable {
private:
Cell world[VPANEL_W][VPANEL_H];
unsigned int density = 50;
int generation = 0;
void randomFillWorld() {
for (int i = 0; i < VPANEL_W; i++) {
for (int j = 0; j < VPANEL_H; j++) {
if (random(100) < density) {
world[i][j].alive = 1;
world[i][j].brightness = 255;
}
else {
world[i][j].alive = 0;
world[i][j].brightness = 0;
}
world[i][j].prev = world[i][j].alive;
world[i][j].hue = 0;
}
}
}
int neighbours(int x, int y) {
return (world[(x + 1) % VPANEL_W][y].prev) +
(world[x][(y + 1) % VPANEL_H].prev) +
(world[(x + VPANEL_W - 1) % VPANEL_W][y].prev) +
(world[x][(y + VPANEL_H - 1) % VPANEL_H].prev) +
(world[(x + 1) % VPANEL_W][(y + 1) % VPANEL_H].prev) +
(world[(x + VPANEL_W - 1) % VPANEL_W][(y + 1) % VPANEL_H].prev) +
(world[(x + VPANEL_W - 1) % VPANEL_W][(y + VPANEL_H - 1) % VPANEL_H].prev) +
(world[(x + 1) % VPANEL_W][(y + VPANEL_H - 1) % VPANEL_H].prev);
}
public:
PatternLife() {
name = (char *)"Life";
}
unsigned int drawFrame() {
if (generation == 0) {
effects.ClearFrame();
randomFillWorld();
}
// Display current generation
for (int i = 0; i < VPANEL_W; i++) {
for (int j = 0; j < VPANEL_H; j++) {
effects.leds[XY(i, j)] = effects.ColorFromCurrentPalette(world[i][j].hue * 4, world[i][j].brightness);
}
}
// Birth and death cycle
for (int x = 0; x < VPANEL_W; x++) {
for (int y = 0; y < VPANEL_H; y++) {
// Default is for cell to stay the same
if (world[x][y].brightness > 0 && world[x][y].prev == 0)
world[x][y].brightness *= 0.9;
int count = neighbours(x, y);
if (count == 3 && world[x][y].prev == 0) {
// A new cell is born
world[x][y].alive = 1;
world[x][y].hue += 2;
world[x][y].brightness = 255;
} else if ((count < 2 || count > 3) && world[x][y].prev == 1) {
// Cell dies
world[x][y].alive = 0;
}
}
}
// Copy next generation into place
for (int x = 0; x < VPANEL_W; x++) {
for (int y = 0; y < VPANEL_H; y++) {
world[x][y].prev = world[x][y].alive;
}
}
generation++;
if (generation >= 256)
generation = 0;
effects.ShowFrame();
return 60;
}
};
#endif

View file

@ -0,0 +1,264 @@
/*
* Aurora: https://github.com/pixelmatix/aurora
* Copyright (c) 2014 Jason Coon
*
* Many thanks to Jamis Buck for the documentation of the Growing Tree maze generation algorithm: http://weblog.jamisbuck.org/2011/1/27/maze-generation-growing-tree-algorithm
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef PatternMaze_H
#define PatternMaze_H
class PatternMaze : public Drawable {
private:
enum Directions {
None = 0,
Up = 1,
Down = 2,
Left = 4,
Right = 8,
};
struct Point{
int x;
int y;
static Point New(int x, int y) {
Point point;
point.x = x;
point.y = y;
return point;
}
Point Move(Directions direction) {
switch (direction)
{
case Up:
return New(x, y - 1);
case Down:
return New(x, y + 1);
case Left:
return New(x - 1, y);
case Right:
default:
return New(x + 1, y);
}
}
static Directions Opposite(Directions direction) {
switch (direction) {
case Up:
return Down;
case Down:
return Up;
case Left:
return Right;
case Right:
default:
return Left;
}
}
};
// int width = 16;
// int height = 16;
static const int width = VPANEL_W / 2;
static const int height = VPANEL_H / 2;
Directions grid[width][height];
Point point;
Point cells[256];
int cellCount = 0;
int algorithm = 0;
int algorithmCount = 1;
byte hue = 0;
byte hueOffset = 0;
Directions directions[4] = { Up, Down, Left, Right };
void removeCell(int index) {// shift cells after index down one
for (int i = index; i < cellCount - 1; i++) {
cells[i] = cells[i + 1];
}
cellCount--;
}
void shuffleDirections() {
for (int a = 0; a < 4; a++)
{
int r = random(a, 4);
Directions temp = directions[a];
directions[a] = directions[r];
directions[r] = temp;
}
}
Point createPoint(int x, int y) {
Point point;
point.x = x;
point.y = y;
return point;
}
CRGB chooseColor(int index) {
byte h = index + hueOffset;
switch (algorithm) {
case 0:
default:
return effects.ColorFromCurrentPalette(h);
case 1:
return effects.ColorFromCurrentPalette(hue++);
}
}
int chooseIndex(int max) {
switch (algorithm) {
case 0:
default:
// choose newest (recursive backtracker)
return max - 1;
case 1:
// choose random(Prim's)
return random(max);
// case 2:
// // choose oldest (not good, so disabling)
// return 0;
}
}
void generateMaze() {
while (cellCount > 1) {
drawNextCell();
}
}
void drawNextCell() {
int index = chooseIndex(cellCount);
if (index < 0)
return;
point = cells[index];
Point imagePoint = createPoint(point.x * 2, point.y * 2);
//effects.drawBackgroundFastLEDPixelCRGB(imagePoint.x, imagePoint.y, CRGB(CRGB::Gray));
shuffleDirections();
CRGB color = chooseColor(index);
for (int i = 0; i < 4; i++) {
Directions direction = directions[i];
Point newPoint = point.Move(direction);
if (newPoint.x >= 0 && newPoint.y >= 0 && newPoint.x < width && newPoint.y < height && grid[newPoint.y][newPoint.x] == None) {
grid[point.y][point.x] = (Directions) ((int) grid[point.y][point.x] | (int) direction);
grid[newPoint.y][newPoint.x] = (Directions) ((int) grid[newPoint.y][newPoint.x] | (int) point.Opposite(direction));
Point newImagePoint = imagePoint.Move(direction);
effects.drawBackgroundFastLEDPixelCRGB(newImagePoint.x, newImagePoint.y, color);
cellCount++;
cells[cellCount - 1] = newPoint;
index = -1;
break;
}
}
if (index > -1) {
Point finishedPoint = cells[index];
imagePoint = createPoint(finishedPoint.x * 2, finishedPoint.y * 2);
effects.drawBackgroundFastLEDPixelCRGB(imagePoint.x, imagePoint.y, color);
removeCell(index);
}
}
public:
PatternMaze() {
name = (char *)"Maze";
}
unsigned int drawFrame() {
if (cellCount < 1) {
effects.ClearFrame();
// reset the maze grid
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
grid[y][x] = None;
}
}
int x = random(width);
int y = random(height);
cells[0] = createPoint(x, y);
cellCount = 1;
hue = 0;
hueOffset = random(0, 256);
}
drawNextCell();
if (cellCount < 1) {
algorithm++;
if (algorithm >= algorithmCount)
algorithm = 0;
return 1000;
}
effects.ShowFrame();
return 0;
}
void start() {
matrix.fillScreen(0);
cellCount = 0;
hue = 0;
}
};
#endif

View file

@ -0,0 +1,74 @@
/*
* Aurora: https://github.com/pixelmatix/aurora
* Copyright (c) 2014 Jason Coon
*
* Munch pattern created by J.B. Langston: https://github.com/jblang/aurora/blob/master/PatternMunch.h
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef PatternMunch_H
#define PatternMunch_H
class PatternMunch : public Drawable {
private:
byte count = 0;
byte dir = 1;
byte flip = 0;
byte generation = 0;
public:
PatternMunch() {
name = (char *)"Munch";
}
unsigned int drawFrame() {
for (byte x = 0; x < VPANEL_W; x++) {
for (byte y = 0; y < VPANEL_H; y++) {
effects.leds[XY(x, y)] = (x ^ y ^ flip) < count ? effects.ColorFromCurrentPalette(((x ^ y) << 2) + generation) : CRGB::Black;
// The below is more pleasant
// effects.leds[XY(x, y)] = effects.ColorFromCurrentPalette(((x ^ y) << 2) + generation) ;
}
}
count += dir;
if (count <= 0 || count >= VPANEL_W) {
dir = -dir;
}
if (count <= 0) {
if (flip == 0)
flip = VPANEL_W-1;
else
flip = 0;
}
generation++;
// show it ffs!
effects.ShowFrame();
return 60;
}
};
#endif

View file

@ -0,0 +1,338 @@
/*
* Aurora: https://github.com/pixelmatix/aurora
* Copyright (c) 2014 Jason Coon
*
* Portions of this code are adapted from "Noise Smearing" by Stefan Petrick: https://gist.githubusercontent.com/embedded-creations/5cd47d83cb0e04f4574d/raw/ebf6a82b4755d55cfba3bf6598f7b19047f89daf/NoiseSmearing.ino
* Copyright (c) 2014 Stefan Petrick
* http://www.stefan-petrick.de/wordpress_beta
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef PatternNoiseSmearing_H
#define PatternNoiseSmearing_H
byte patternNoiseSmearingHue = 0;
class PatternMultipleStream : public Drawable {
public:
PatternMultipleStream() {
name = (char *)"MultipleStream";
}
// this pattern draws two points to the screen based on sin/cos if a counter
// (comment out NoiseSmearWithRadius to see pattern of pixels)
// these pixels are smeared by a large radius, giving a lot of movement
// the image is dimmed before each drawing to not saturate the screen with color
// the smear has an offset so the pixels usually have a trail leading toward the upper left
unsigned int drawFrame() {
static unsigned long counter = 0;
#if 0
// this counter lets put delays between each frame and still get the same animation
counter++;
#else
// this counter updates in real time and can't be slowed down for debugging
counter = millis() / 10;
#endif
byte x1 = 4 + sin8(counter * 2) / 10;
byte x2 = 8 + sin8(counter * 2) / 16;
byte y2 = 8 + cos8((counter * 2) / 3) / 16;
effects.leds[XY(x1, x2)] = effects.ColorFromCurrentPalette(patternNoiseSmearingHue);
effects.leds[XY(x2, y2)] = effects.ColorFromCurrentPalette(patternNoiseSmearingHue + 128);
// Noise
noise_x += 1000;
noise_y += 1000;
noise_scale_x = 4000;
noise_scale_y = 4000;
effects.FillNoise();
effects.MoveX(8);
// effects.MoveFractionalNoiseX();
effects.MoveY(8);
// effects.MoveFractionalNoiseY();
patternNoiseSmearingHue++;
return 0;
}
};
class PatternMultipleStream2 : public Drawable {
public:
PatternMultipleStream2() {
name = (char *)"MultipleStream2";
}
unsigned int drawFrame() {
effects.DimAll(230); effects.ShowFrame();
byte xx = 4 + sin8(millis() / 9) / 10;
byte yy = 4 + cos8(millis() / 10) / 10;
effects.leds[XY(xx, yy)] += effects.ColorFromCurrentPalette(patternNoiseSmearingHue);
xx = 8 + sin8(millis() / 10) / 16;
yy = 8 + cos8(millis() / 7) / 16;
effects.leds[XY(xx, yy)] += effects.ColorFromCurrentPalette(patternNoiseSmearingHue + 80);
effects.leds[XY(15, 15)] += effects.ColorFromCurrentPalette(patternNoiseSmearingHue + 160);
noise_x += 1000;
noise_y += 1000;
noise_z += 1000;
noise_scale_x = 4000;
noise_scale_y = 4000;
effects.FillNoise();
effects.MoveX(3);
// effects.MoveFractionalNoiseY(4);
effects.MoveY(3);
//effects.MoveFractionalNoiseX(4);
patternNoiseSmearingHue++;
return 0;
}
};
class PatternMultipleStream3 : public Drawable {
public:
PatternMultipleStream3() {
name = (char *)"MultipleStream3";
}
unsigned int drawFrame() {
//CLS();
effects.DimAll(235); effects.ShowFrame();
for (uint8_t i = 3; i < 32; i = i + 4) {
effects.leds[XY(i, 15)] += effects.ColorFromCurrentPalette(i * 8);
}
// Noise
noise_x += 1000;
noise_y += 1000;
noise_z += 1000;
noise_scale_x = 4000;
noise_scale_y = 4000;
effects.FillNoise();
effects.MoveX(3);
// effects.MoveFractionalNoiseY(4);
effects.MoveY(3);
// effects.MoveFractionalNoiseX(4);
effects.ShowFrame();
return 1;
}
};
class PatternMultipleStream4 : public Drawable {
public:
PatternMultipleStream4() {
name = (char *)"MultipleStream4";
}
unsigned int drawFrame() {
//CLS();
effects.DimAll(235); effects.ShowFrame();
effects.leds[XY(15, 15)] += effects.ColorFromCurrentPalette(patternNoiseSmearingHue);
// Noise
noise_x += 1000;
noise_y += 1000;
noise_scale_x = 4000;
noise_scale_y = 4000;
effects.FillNoise();
effects.MoveX(8);
// effects.MoveFractionalNoiseX();
effects.MoveY(8);
// effects.MoveFractionalNoiseY();
patternNoiseSmearingHue++;
return 0;
}
};
class PatternMultipleStream5 : public Drawable {
public:
PatternMultipleStream5() {
name = (char *)"MultipleStream5";
}
unsigned int drawFrame() {
//CLS();
effects.DimAll(235); effects.ShowFrame();
for (uint8_t i = 3; i < 32; i = i + 4) {
effects.leds[XY(i, 31)] += effects.ColorFromCurrentPalette(i * 8);
}
// Noise
noise_x += 1000;
noise_y += 1000;
noise_z += 1000;
noise_scale_x = 4000;
noise_scale_y = 4000;
effects.FillNoise();
effects.MoveX(3);
// effects.MoveFractionalNoiseY(4);
effects.MoveY(4);
// effects.MoveFractionalNoiseX(4);
return 0;
}
};
class PatternMultipleStream8 : public Drawable {
public:
PatternMultipleStream8() {
name = (char *)"MultipleStream8";
}
unsigned int drawFrame() {
effects.DimAll(230); effects.ShowFrame();
// draw grid of rainbow dots on top of the dimmed image
for (uint8_t y = 1; y < 32; y = y + 6) {
for (uint8_t x = 1; x < 32; x = x + 6) {
effects.leds[XY(x, y)] += effects.ColorFromCurrentPalette((x * y) / 4);
}
}
// Noise
noise_x += 1000;
noise_y += 1000;
noise_z += 1000;
noise_scale_x = 4000;
noise_scale_y = 4000;
effects.FillNoise();
effects.MoveX(3);
// effects.MoveFractionalNoiseX(4);
effects.MoveY(3);
//effects.MoveFractionalNoiseY(4);
return 0;
}
};
class PatternPaletteSmear : public Drawable {
public:
PatternPaletteSmear() {
name = (char *)"PaletteSmear";
}
unsigned int drawFrame() {
effects.DimAll(170); effects.ShowFrame();
// draw a rainbow color palette
for (uint8_t y = 0; y < MATRIX_HEIGHT; y++) {
for (uint8_t x = 0; x < MATRIX_WIDTH; x++) {
effects.leds[XY(x, y)] += effects.ColorFromCurrentPalette(x * 8, y * 8 + 7);
}
}
// Noise
noise_x += 1000;
noise_y += 1000;
noise_scale_x = 4000;
noise_scale_y = 4000;
effects.FillNoise();
effects.MoveX(3);
//effects.MoveFractionalNoiseY(4);
effects.MoveY(3);
// effects.MoveFractionalNoiseX(4);
effects.ShowFrame();
return 0;
}
};
class PatternRainbowFlag : public Drawable {
public:
PatternRainbowFlag() {
name = (char *)"RainbowFlag";
}
unsigned int drawFrame() {
effects.DimAll(10); effects.ShowFrame();
CRGB rainbow[7] = {
CRGB::Red,
CRGB::Orange,
CRGB::Yellow,
CRGB::Green,
CRGB::Blue,
CRGB::Violet
};
uint8_t y = 2;
for (uint8_t c = 0; c < 6; c++) {
for (uint8_t j = 0; j < 5; j++) {
for (uint8_t x = 0; x < VPANEL_W; x++) {
effects.leds[XY(x, y)] += rainbow[c];
}
y++;
if (y >= VPANEL_H)
break;
}
}
// Noise
noise_x += 1000;
noise_y += 1000;
noise_scale_x = 4000;
noise_scale_y = 4000;
effects.FillNoise();
effects.MoveX(3);
// effects.MoveFractionalNoiseY(4);
effects.MoveY(3);
// effects.MoveFractionalNoiseX(4);
return 0;
}
};
#endif

View file

@ -0,0 +1,56 @@
/*
*
* Inspired by and based on a loading animation for Prismata by Lunarch Studios:
* http://www.reddit.com/r/gifs/comments/2on8si/connecting_to_server_so_mesmerizing/cmow0sz
*
* Lunarch Studios Inc. hereby publishes the Actionscript 3 source code pasted in this
* comment under the Creative Commons CC0 1.0 Universal Public Domain Dedication.
* Lunarch Studios Inc. waives all rights to the work worldwide under copyright law,
* including all related and neighboring rights, to the extent allowed by law.
* You can copy, modify, distribute and perform the work, even for commercial purposes,
* all without asking permission.
*
* Aurora: https://github.com/pixelmatix/aurora
* Copyright (c) 2014 Jason Coon
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef PatternPendulumWave_H
#define PatternPendulumWave_H
class PatternPendulumWave : public Drawable {
public:
PatternPendulumWave() {
name = (char *)"Pendulum Wave";
}
unsigned int drawFrame() {
effects.DimAll(170); effects.ShowFrame();
for (int x = 0; x < VPANEL_W; x++)
{
uint8_t y = beatsin8(x + VPANEL_W, 0, VPANEL_H);
effects.drawBackgroundFastLEDPixelCRGB(x, y, effects.ColorFromCurrentPalette(x * 7));
}
return 15;
}
};
#endif

View file

@ -0,0 +1,66 @@
/*
* Aurora: https://github.com/pixelmatix/aurora
* Copyright (c) 2014 Jason Coon
*
* Portions of this code are adapted from LedEffects Plasma by Robert Atkins: https://bitbucket.org/ratkins/ledeffects/src/26ed3c51912af6fac5f1304629c7b4ab7ac8ca4b/Plasma.cpp?at=default
* Copyright (c) 2013 Robert Atkins
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef PatternPlasma_H
#define PatternPlasma_H
class PatternPlasma : public Drawable {
private:
int time = 0;
int cycles = 0;
public:
PatternPlasma() {
name = (char *)"Plasma";
}
unsigned int drawFrame() {
for (int x = 0; x < VPANEL_W; x++) {
for (int y = 0; y < VPANEL_H; y++) {
int16_t v = 0;
uint8_t wibble = sin8(time);
v += sin16(x * wibble * 6 + time);
v += cos16(y * (128 - wibble) * 6 + time);
v += sin16(y * x * cos8(-time) / 8);
effects.Pixel(x, y, (v >> 8) + 127);
}
}
time += 1;
cycles++;
if (cycles >= 2048) {
time = 0;
cycles = 0;
}
effects.ShowFrame();
return 30;
}
};
#endif

View file

@ -0,0 +1,56 @@
/*
* Aurora: https://github.com/pixelmatix/aurora
* Copyright (c) 2014 Jason Coon
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef PatternRadar_H
class PatternRadar : public Drawable {
private:
byte theta = 0;
byte hueoffset = 0;
public:
PatternRadar() {
name = (char *)"Radar";
}
unsigned int drawFrame() {
effects.DimAll(254); effects.ShowFrame();
for (int offset = 0; offset < MATRIX_CENTER_X; offset++) {
byte hue = 255 - (offset * 16 + hueoffset);
CRGB color = effects.ColorFromCurrentPalette(hue);
uint8_t x = mapcos8(theta, offset, (VPANEL_W - 1) - offset);
uint8_t y = mapsin8(theta, offset, (VPANEL_H - 1) - offset);
uint16_t xy = XY(x, y);
effects.leds[xy] = color;
EVERY_N_MILLIS(25) {
theta += 2;
hueoffset += 1;
}
}
return 0;
}
};
#endif

View file

@ -0,0 +1,79 @@
/*
* Aurora: https://github.com/pixelmatix/aurora
* Copyright (c) 2014 Jason Coon
*
* Portions of this code are adapted from FastLED Fire2012 example by Mark Kriegsman: https://github.com/FastLED/FastLED/blob/master/examples/Noise/Noise.ino
* Copyright (c) 2013 FastLED
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef PatternSimplexNoise_H
#define PatternSimplexNoise_H
class PatternSimplexNoise : public Drawable {
public:
PatternSimplexNoise() {
name = (char *)"Noise";
}
void start() {
// Initialize our coordinates to some random values
noise_x = random16();
noise_y = random16();
noise_z = random16();
}
unsigned int drawFrame() {
#if FASTLED_VERSION >= 3001000
// a new parameter set every 15 seconds
EVERY_N_SECONDS(15) {
noise_x = random16();
noise_y = random16();
noise_z = random16();
}
#endif
uint32_t speed = 100;
effects.FillNoise();
ShowNoiseLayer(0, 1, 0);
// noise_x += speed;
noise_y += speed;
noise_z += speed;
effects.ShowFrame();
return 0;
}
// show just one layer
void ShowNoiseLayer(byte layer, byte colorrepeat, byte colorshift) {
for (uint8_t i = 0; i < VPANEL_W; i++) {
for (uint8_t j = 0; j < VPANEL_H; j++) {
uint8_t pixel = noise[i][j];
// assign a color depending on the actual palette
effects.leds[XY(i, j)] = effects.ColorFromCurrentPalette(colorrepeat * (pixel + colorshift), pixel);
}
}
}
};
#endif

View file

@ -0,0 +1,145 @@
/*
* Aurora: https://github.com/pixelmatix/aurora
* Copyright (c) 2014 Jason Coon
*
* Portions of this code are adapted from LedEffects Snake by Robert Atkins: https://bitbucket.org/ratkins/ledeffects/src/26ed3c51912af6fac5f1304629c7b4ab7ac8ca4b/Snake.cpp?at=default
* Copyright (c) 2013 Robert Atkins
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef PatternSnake_H
#define PatternSnake_H
class PatternSnake : public Drawable {
private:
static const byte SNAKE_LENGTH = 16;
CRGB colors[SNAKE_LENGTH];
uint8_t initialHue;
enum Direction {
UP, DOWN, LEFT, RIGHT
};
struct Pixel {
uint8_t x;
uint8_t y;
};
struct Snake {
Pixel pixels[SNAKE_LENGTH];
Direction direction;
void newDirection() {
switch (direction) {
case UP:
case DOWN:
direction = random(0, 2) == 1 ? RIGHT : LEFT;
break;
case LEFT:
case RIGHT:
direction = random(0, 2) == 1 ? DOWN : UP;
default:
break;
}
}
void shuffleDown() {
for (byte i = SNAKE_LENGTH - 1; i > 0; i--) {
pixels[i] = pixels[i - 1];
}
}
void reset() {
direction = UP;
for (int i = 0; i < SNAKE_LENGTH; i++) {
pixels[i].x = 0;
pixels[i].y = 0;
}
}
void move() {
switch (direction) {
case UP:
pixels[0].y = (pixels[0].y + 1) % VPANEL_H;
break;
case LEFT:
pixels[0].x = (pixels[0].x + 1) % VPANEL_W;
break;
case DOWN:
pixels[0].y = pixels[0].y == 0 ? VPANEL_H - 1 : pixels[0].y - 1;
break;
case RIGHT:
pixels[0].x = pixels[0].x == 0 ? VPANEL_W - 1 : pixels[0].x - 1;
break;
}
}
void draw(CRGB colors[SNAKE_LENGTH]) {
for (byte i = 0; i < SNAKE_LENGTH; i++) {
effects.leds[XY(pixels[i].x, pixels[i].y)] = colors[i] %= (255 - i * (255 / SNAKE_LENGTH));
}
}
};
static const int snakeCount = 40;
Snake snakes[snakeCount];
public:
PatternSnake() {
name = (char *)"Snake";
for (int i = 0; i < snakeCount; i++) {
Snake* snake = &snakes[i];
snake->reset();
}
}
void start()
{
effects.ClearFrame();
}
unsigned int drawFrame() {
fill_palette(colors, SNAKE_LENGTH, initialHue++, 5, effects.currentPalette, 255, LINEARBLEND);
for (int i = 0; i < snakeCount; i++) {
Snake* snake = &snakes[i];
snake->shuffleDown();
if (random(10) > 7) {
snake->newDirection();
}
snake->move();
snake->draw(colors);
}
effects.ShowFrame();
return 30;
}
};
#endif

View file

@ -0,0 +1,138 @@
/*
* Portions of this code are adapted from "Funky Clouds" by Stefan Petrick:
* https://gist.github.com/anonymous/876f908333cd95315c35
*
* Copyright (c) 2014 Stefan Petrick
* http://www.stefan-petrick.de/wordpress_beta
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef PatternSpiral_H
#define PatternSpiral_H
class PatternSpiral : public Drawable {
private:
// Timer stuff (Oszillators)
struct timer {
unsigned long takt;
unsigned long lastMillis;
unsigned long count;
int delta;
byte up;
byte down;
};
timer multiTimer[5];
int timers = sizeof(multiTimer) / sizeof(multiTimer[0]);
// counts all variables with different speeds linear up and down
void UpdateTimers()
{
unsigned long now = millis();
for (int i = 0; i < timers; i++)
{
while (now - multiTimer[i].lastMillis >= multiTimer[i].takt)
{
multiTimer[i].lastMillis += multiTimer[i].takt;
multiTimer[i].count = multiTimer[i].count + multiTimer[i].delta;
if ((multiTimer[i].count == multiTimer[i].up) || (multiTimer[i].count == multiTimer[i].down))
{
multiTimer[i].delta = -multiTimer[i].delta;
}
}
}
}
public:
PatternSpiral() {
name = (char *)"Spiral";
}
void start() {
// set all counting directions positive for the beginning
for (int i = 0; i < timers; i++) multiTimer[i].delta = 1;
// set range (up/down), speed (takt=ms between steps) and starting point of all oszillators
unsigned long now = millis();
multiTimer[0].lastMillis = now;
multiTimer[0].takt = 42; //x1
multiTimer[0].up = VPANEL_W - 1;
multiTimer[0].down = 0;
multiTimer[0].count = 0;
multiTimer[1].lastMillis = now;
multiTimer[1].takt = 55; //y1
multiTimer[1].up = VPANEL_H - 1;
multiTimer[1].down = 0;
multiTimer[1].count = 0;
multiTimer[2].lastMillis = now;
multiTimer[2].takt = 3; //color
multiTimer[2].up = 255;
multiTimer[2].down = 0;
multiTimer[2].count = 0;
multiTimer[3].lastMillis = now;
multiTimer[3].takt = 71; //x2
multiTimer[3].up = VPANEL_W - 1;
multiTimer[3].down = 0;
multiTimer[3].count = 0;
multiTimer[4].lastMillis = now;
multiTimer[4].takt = 89; //y2
multiTimer[4].up = VPANEL_H - 1;
multiTimer[4].down = 0;
multiTimer[4].count = 0;
}
unsigned int drawFrame() {
// manage the Oszillators
UpdateTimers();
// draw just a line defined by 5 oszillators
effects.BresenhamLine(
multiTimer[3].count, // x1
multiTimer[4].count, // y1
multiTimer[0].count, // x2
multiTimer[1].count, // y2
multiTimer[2].count); // color
// manipulate the screen buffer
// with fixed parameters (could be oszillators too)
// Params: center x, y, radius, scale color down
// --> NOTE: Affects always a SQUARE with an odd length
// effects.SpiralStream(15, 15, 10, 128);
effects.SpiralStream(31, 15, 64, 128); // for 64 pixel wide matrix!
// effects.SpiralStream(47, 15, 10, 128); // for 64 pixel wide matrix!
// why not several times?!
// effects.SpiralStream(16, 6, 6, 128);
// effects.SpiralStream(10, 24, 10, 128);
// increase the contrast
effects.DimAll(250); effects.ShowFrame();
return 0;
}
};
#endif

View file

@ -0,0 +1,107 @@
/*
* Aurora: https://github.com/pixelmatix/aurora
* Copyright (c) 2014 Jason Coon
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef PatternSpiro_H
class PatternSpiro : public Drawable {
private:
byte theta1 = 0;
byte theta2 = 0;
byte hueoffset = 0;
uint8_t radiusx = VPANEL_W / 4;
uint8_t radiusy = VPANEL_H / 4;
uint8_t minx = MATRIX_CENTER_X - radiusx;
uint8_t maxx = MATRIX_CENTER_X + radiusx + 1;
uint8_t miny = MATRIX_CENTER_Y - radiusy;
uint8_t maxy = MATRIX_CENTER_Y + radiusy + 1;
uint8_t spirocount = 1;
uint8_t spirooffset = 256 / spirocount;
boolean spiroincrement = false;
boolean handledChange = false;
public:
PatternSpiro() {
name = (char *)"Spiro";
}
unsigned int drawFrame() {
effects.DimAll(254); effects.ShowFrame();
boolean change = false;
for (int i = 0; i < spirocount; i++) {
uint8_t x = mapsin8(theta1 + i * spirooffset, minx, maxx);
uint8_t y = mapcos8(theta1 + i * spirooffset, miny, maxy);
uint8_t x2 = mapsin8(theta2 + i * spirooffset, x - radiusx, x + radiusx);
uint8_t y2 = mapcos8(theta2 + i * spirooffset, y - radiusy, y + radiusy);
CRGB color = effects.ColorFromCurrentPalette(hueoffset + i * spirooffset, 128);
effects.leds[XY(x2, y2)] += color;
if((x2 == MATRIX_CENTER_X && y2 == MATRIX_CENTER_Y) ||
(x2 == MATRIX_CENTRE_X && y2 == MATRIX_CENTRE_Y)) change = true;
}
theta2 += 1;
EVERY_N_MILLIS(25) {
theta1 += 1;
}
EVERY_N_MILLIS(100) {
if (change && !handledChange) {
handledChange = true;
if (spirocount >= VPANEL_W || spirocount == 1) spiroincrement = !spiroincrement;
if (spiroincrement) {
if(spirocount >= 4)
spirocount *= 2;
else
spirocount += 1;
}
else {
if(spirocount > 4)
spirocount /= 2;
else
spirocount -= 1;
}
spirooffset = 256 / spirocount;
}
if(!change) handledChange = false;
}
EVERY_N_MILLIS(33) {
hueoffset += 1;
}
return 0;
}
};
#endif

View file

@ -0,0 +1,77 @@
/*
* Aurora: https://github.com/pixelmatix/aurora
* Copyright (c) 2014 Jason Coon
*
* Portions of this code are adapted from SmartMatrixSwirl by Mark Kriegsman: https://gist.github.com/kriegsman/5adca44e14ad025e6d3b
* https://www.youtube.com/watch?v=bsGBT-50cts
* Copyright (c) 2014 Mark Kriegsman
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef PatternSwirl_H
class PatternSwirl : public Drawable {
private:
const uint8_t borderWidth = 2;
public:
PatternSwirl() {
name = (char *)"Swirl";
}
void start() {
}
unsigned int drawFrame() {
// Apply some blurring to whatever's already on the matrix
// Note that we never actually clear the matrix, we just constantly
// blur it repeatedly. Since the blurring is 'lossy', there's
// an automatic trend toward black -- by design.
uint8_t blurAmount = beatsin8(2, 10, 255);
#if FASTLED_VERSION >= 3001000
blur2d(effects.leds, VPANEL_W, VPANEL_H, blurAmount);
#else
effects.DimAll(blurAmount);
#endif
// Use two out-of-sync sine waves
uint8_t i = beatsin8(27, borderWidth, VPANEL_H - borderWidth);
uint8_t j = beatsin8(41, borderWidth, VPANEL_W - borderWidth);
// Also calculate some reflections
uint8_t ni = (VPANEL_W - 1) - i;
uint8_t nj = (VPANEL_W - 1) - j;
// The color of each point shifts over time, each at a different speed.
uint16_t ms = millis();
effects.leds[XY(i, j)] += effects.ColorFromCurrentPalette(ms / 11);
effects.leds[XY(j, i)] += effects.ColorFromCurrentPalette(ms / 13);
effects.leds[XY(ni, nj)] += effects.ColorFromCurrentPalette(ms / 17);
effects.leds[XY(nj, ni)] += effects.ColorFromCurrentPalette(ms / 29);
effects.leds[XY(i, nj)] += effects.ColorFromCurrentPalette(ms / 37);
effects.leds[XY(ni, j)] += effects.ColorFromCurrentPalette(ms / 41);
effects.ShowFrame();
return 0;
}
};
#endif

View file

@ -0,0 +1,120 @@
/*
* Aurora: https://github.com/pixelmatix/aurora
* Copyright (c) 2014 Jason Coon
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef PatternWave_H
#define PatternWave_H
class PatternWave : public Drawable {
private:
byte thetaUpdate = 0;
byte thetaUpdateFrequency = 0;
byte theta = 0;
byte hueUpdate = 0;
byte hueUpdateFrequency = 0;
byte hue = 0;
byte rotation = 0;
uint8_t scale = 256 / VPANEL_W;
uint8_t maxX = VPANEL_W - 1;
uint8_t maxY = VPANEL_H - 1;
uint8_t waveCount = 1;
public:
PatternWave() {
name = (char *)"Wave";
}
void start() {
rotation = random(0, 4);
waveCount = random(1, 3);
}
unsigned int drawFrame() {
int n = 0;
switch (rotation) {
case 0:
for (int x = 0; x < VPANEL_W; x++) {
n = quadwave8(x * 2 + theta) / scale;
effects.drawBackgroundFastLEDPixelCRGB(x, n, effects.ColorFromCurrentPalette(x + hue));
if (waveCount == 2)
effects.drawBackgroundFastLEDPixelCRGB(x, maxY - n, effects.ColorFromCurrentPalette(x + hue));
}
break;
case 1:
for (int y = 0; y < VPANEL_H; y++) {
n = quadwave8(y * 2 + theta) / scale;
effects.drawBackgroundFastLEDPixelCRGB(n, y, effects.ColorFromCurrentPalette(y + hue));
if (waveCount == 2)
effects.drawBackgroundFastLEDPixelCRGB(maxX - n, y, effects.ColorFromCurrentPalette(y + hue));
}
break;
case 2:
for (int x = 0; x < VPANEL_W; x++) {
n = quadwave8(x * 2 - theta) / scale;
effects.drawBackgroundFastLEDPixelCRGB(x, n, effects.ColorFromCurrentPalette(x + hue));
if (waveCount == 2)
effects.drawBackgroundFastLEDPixelCRGB(x, maxY - n, effects.ColorFromCurrentPalette(x + hue));
}
break;
case 3:
for (int y = 0; y < VPANEL_H; y++) {
n = quadwave8(y * 2 - theta) / scale;
effects.drawBackgroundFastLEDPixelCRGB(n, y, effects.ColorFromCurrentPalette(y + hue));
if (waveCount == 2)
effects.drawBackgroundFastLEDPixelCRGB(maxX - n, y, effects.ColorFromCurrentPalette(y + hue));
}
break;
}
effects.DimAll(254);
effects.ShowFrame();
if (thetaUpdate >= thetaUpdateFrequency) {
thetaUpdate = 0;
theta++;
}
else {
thetaUpdate++;
}
if (hueUpdate >= hueUpdateFrequency) {
hueUpdate = 0;
hue++;
}
else {
hueUpdate++;
}
return 0;
}
};
#endif

View file

@ -0,0 +1,259 @@
/*
* Aurora: https://github.com/pixelmatix/aurora
* Copyright (c) 2014 Jason Coon
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef Patterns_H
#define Patterns_H
#define ARRAY_SIZE(A) (sizeof(A) / sizeof((A)[0]))
#include "Vector.h"
#include "Boid.h"
#include "Attractor.h"
/*
* Note from mrfaptastic:
*
* Commented out patterns are due to the fact they either didn't work properly with a non-square display,
* or from my personal opinion, are crap.
*
* Kosso: I have removed the crappy ones and added a less crappy (and working!) Fire demo ;)
*
*/
#include "PaletteFireKoz.h" // Added by Kosso
#include "PatternFireKoz.h" // Added by Kosso
#include "PatternSpiro.h"
#include "PatternRadar.h"
#include "PatternSwirl.h"
#include "PatternPendulumWave.h"
#include "PatternFlowField.h"
#include "PatternIncrementalDrift.h"
#include "PatternMunch.h"
#include "PatternElectricMandala.h"
#include "PatternSimplexNoise.h"
#include "PatternWave.h"
#include "PatternAttract.h"
#include "PatternFlock.h"
#include "PatternInfinity.h"
#include "PatternPlasma.h"
#include "PatternSnake.h"
#include "PatternFire.h" // Not very good.
#include "PatternLife.h"
#include "PatternMaze.h"
#include "PatternSpiral.h"
class Patterns : public Playlist {
private:
PatternFireKoz fireKoz;
PatternSpiro spiro;
PatternSwirl swirl;
PatternPendulumWave pendulumWave;
PatternFlowField flowField;
PatternIncrementalDrift incrementalDrift;
PatternMunch munch;
PatternElectricMandala electricMandala;
PatternSimplexNoise simplexNoise;
PatternWave wave;
PatternAttract attract;
PatternFlock flock;
PatternPlasma plasma;
PatternSnake snake;
PatternFire fire;
PatternLife life;
PatternMaze maze;
PatternSpiral spiral;
int currentIndex = 0;
Drawable* currentItem;
int getCurrentIndex() {
return currentIndex;
}
const static int PATTERN_COUNT = 18;
Drawable* shuffledItems[PATTERN_COUNT];
Drawable* items[PATTERN_COUNT] = {
&fireKoz, // added by Kosso
&spiro,
&life,
&flowField,
&pendulumWave,
&incrementalDrift,
&munch,
&electricMandala,
&simplexNoise,
&wave,
&attract,
&swirl,
&flock,
&plasma,
&snake,
&fire,
&maze,
&spiral,
};
public:
Patterns() {
// add the items to the shuffledItems array
for (int a = 0; a < PATTERN_COUNT; a++) {
shuffledItems[a] = items[a];
}
shuffleItems();
this->currentItem = items[0];
this->currentItem->start();
}
char* Drawable::name = (char *)"Patterns";
void stop() {
if (currentItem)
currentItem->stop();
}
void start() {
if (currentItem)
currentItem->start();
}
void move(int step) {
currentIndex += step;
if (currentIndex >= PATTERN_COUNT) currentIndex = 0;
else if (currentIndex < 0) currentIndex = PATTERN_COUNT - 1;
if (effects.paletteIndex == effects.RandomPaletteIndex)
effects.RandomPalette();
moveTo(currentIndex);
//if (!isTimeAvailable && currentItem == &analogClock)
// move(step);
}
void moveRandom(int step) {
currentIndex += step;
if (currentIndex >= PATTERN_COUNT) currentIndex = 0;
else if (currentIndex < 0) currentIndex = PATTERN_COUNT - 1;
if (effects.paletteIndex == effects.RandomPaletteIndex)
effects.RandomPalette();
if (currentItem)
currentItem->stop();
currentItem = shuffledItems[currentIndex];
if (currentItem)
currentItem->start();
// if (!isTimeAvailable && currentItem == &analogClock)
// moveRandom(step);
}
void shuffleItems() {
for (int a = 0; a < PATTERN_COUNT; a++)
{
int r = random(a, PATTERN_COUNT);
Drawable* temp = shuffledItems[a];
shuffledItems[a] = shuffledItems[r];
shuffledItems[r] = temp;
}
}
unsigned int drawFrame() {
return currentItem->drawFrame();
}
void listPatterns() {
Serial.println(F("{"));
Serial.print(F(" \"count\": "));
Serial.print(PATTERN_COUNT);
Serial.println(",");
Serial.println(F(" \"results\": ["));
for (int i = 0; i < PATTERN_COUNT; i++) {
Serial.print(F(" \""));
Serial.print(i, DEC);
Serial.print(F(": "));
Serial.print(items[i]->name);
if (i == PATTERN_COUNT - 1)
Serial.println(F("\""));
else
Serial.println(F("\","));
}
Serial.println(" ]");
Serial.println("}");
}
int getPatternIndex()
{
return currentIndex;
}
char * getCurrentPatternName()
{
return currentItem->name;
}
void moveTo(int index) {
if (currentItem)
currentItem->stop();
currentIndex = index;
currentItem = items[currentIndex];
if (currentItem)
currentItem->start();
}
bool setPattern(String name) {
for (int i = 0; i < PATTERN_COUNT; i++) {
if (name.compareTo(items[i]->name) == 0) {
moveTo(i);
return true;
}
}
return false;
}
bool setPattern(int index) {
if (index >= PATTERN_COUNT || index < 0)
return false;
moveTo(index);
return true;
}
};
#endif

View file

@ -0,0 +1,39 @@
/*
* Aurora: https://github.com/pixelmatix/aurora
* Copyright (c) 2014 Jason Coon
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef Playlist_H
#define Playlist_H
class Playlist : public Drawable {
public:
virtual bool isPlaylist() {
return true;
}
boolean isCurrentItemFinished = true;
virtual void move(int step) = 0;
virtual void moveRandom(int step) = 0;
virtual int getCurrentIndex();
};
#endif

View file

@ -0,0 +1,169 @@
/*
* Aurora: https://github.com/pixelmatix/aurora
* Copyright (c) 2014 Jason Coon
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef Vector_H
#define Vector_H
template <class T>
class Vector2 {
public:
T x, y;
Vector2() :x(0), y(0) {}
Vector2(T x, T y) : x(x), y(y) {}
Vector2(const Vector2& v) : x(v.x), y(v.y) {}
Vector2& operator=(const Vector2& v) {
x = v.x;
y = v.y;
return *this;
}
bool isEmpty() {
return x == 0 && y == 0;
}
bool operator==(Vector2& v) {
return x == v.x && y == v.y;
}
bool operator!=(Vector2& v) {
return !(x == y);
}
Vector2 operator+(Vector2& v) {
return Vector2(x + v.x, y + v.y);
}
Vector2 operator-(Vector2& v) {
return Vector2(x - v.x, y - v.y);
}
Vector2& operator+=(Vector2& v) {
x += v.x;
y += v.y;
return *this;
}
Vector2& operator-=(Vector2& v) {
x -= v.x;
y -= v.y;
return *this;
}
Vector2 operator+(double s) {
return Vector2(x + s, y + s);
}
Vector2 operator-(double s) {
return Vector2(x - s, y - s);
}
Vector2 operator*(double s) {
return Vector2(x * s, y * s);
}
Vector2 operator/(double s) {
return Vector2(x / s, y / s);
}
Vector2& operator+=(double s) {
x += s;
y += s;
return *this;
}
Vector2& operator-=(double s) {
x -= s;
y -= s;
return *this;
}
Vector2& operator*=(double s) {
x *= s;
y *= s;
return *this;
}
Vector2& operator/=(double s) {
x /= s;
y /= s;
return *this;
}
void set(T x, T y) {
this->x = x;
this->y = y;
}
void rotate(double deg) {
double theta = deg / 180.0 * M_PI;
double c = cos(theta);
double s = sin(theta);
double tx = x * c - y * s;
double ty = x * s + y * c;
x = tx;
y = ty;
}
Vector2& normalize() {
if (length() == 0) return *this;
*this *= (1.0 / length());
return *this;
}
float dist(Vector2 v) const {
Vector2 d(v.x - x, v.y - y);
return d.length();
}
float length() const {
return sqrt(x * x + y * y);
}
float mag() const {
return length();
}
float magSq() {
return (x * x + y * y);
}
void truncate(double length) {
double angle = atan2f(y, x);
x = length * cos(angle);
y = length * sin(angle);
}
Vector2 ortho() const {
return Vector2(y, -x);
}
static float dot(Vector2 v1, Vector2 v2) {
return v1.x * v2.x + v1.y * v2.y;
}
static float cross(Vector2 v1, Vector2 v2) {
return (v1.x * v2.y) - (v1.y * v2.x);
}
void limit(float max) {
if (magSq() > max*max) {
normalize();
*this *= max;
}
}
};
typedef Vector2<float> PVector;
#endif