Close

Processing on the Pi - Snow

A project log for Networked Low Resolution DMD Projectors

WiFi networked electro-mechanical 7x7 pixel flip-dot displays as giant DMDs (Digital Micromirror Devices) for low resolution projection

michael-shaubMichael Shaub 02/24/2016 at 04:190 Comments

Date: 2/3/2016

Before I even received the flip-dot display I started working on some pixelated content. My first idea was to create a simple simulation of snowfall, creating some random dots at the top of the display, moving them down a row each frame, slightly shifting them left or right, and then collecting a few frames worth at the bottom of the screen. I quickly found out that I needed to keep space between the dots left and right and vertically, easily handled by skipping every other row when drawing new "snow flakes."

The canvas size is 28 pixels wide by 7 pixels tall, assuming that the images would span across the 4 7x7 pixel displays.

Processing sketch code below:

// Pixelated Snow V9
// 
// For LinkSprite V3 and AlfaZeta flip-dot display
// by Michael Shaub 2016

int dotSize = 50; //diameter of the dots - for preview
PImage pix = createImage(28,7, RGB); //PImage to hold the actual size image
int pixLength = pix.width*pix.height; //total amount of pixels
boolean drawRow = false; //use to alternate drawing a row of dots or skipping

void setup(){
  size(1400,350);
  ellipseMode(CORNER);
  noStroke();
  frameRate(3);
  
  //preset the PImage
  pix.loadPixels();
  for(int i=0; i<pixLength; i++){
    pix.pixels[i] = color(0); //set each pixel to black
  }
  pix.updatePixels();
}

void draw(){
  background(35);
  
  //Copy each row of pixels down to the next row
  pix.loadPixels();
  for(int j=6; j>0; j--){ //step through every row but the top one, in reverse
    int wind = round( random(-1,1) ); //set a value to blow the snow to the left, right, or none
    println(wind);
    for(int i=0; i<28; i++){
      if(!drawRow && j==6){ //only if this is the bottom row and on a frame when the snow isn't drawn on the top row 
        //skip drawing over the last row this frame
      }else{
        //draw this frame
        int targetPix;
        //test boundaries for values
        if( (i+j*pix.width+wind) < 0){
          targetPix = 0;
        }else{
          if( (i+j*pix.width+wind) > 7*pix.width-1){
            targetPix = (i+j*pix.width); 
          }else{
            targetPix = (i+j*pix.width+wind);
          }
        }
          
        pix.pixels[targetPix] = pix.pixels[i+(j-1)*pix.width]; //read pixel values, set fill color to the row above
      }
    }
  }
  
  //Draw the first row of pixels with random values
  //pix.loadPixels();
  int lastRand = 0;
  for(int i=0; i<pix.width; i++){
    int randValue = 0;
    if(drawRow){
      randValue = round(random(.8))*255; //randomly black or white
      if(i>0 && lastRand==255){
        randValue = 0; //never have 2 white dots in a row
      }
    }
    pix.pixels[i] = color(randValue); //set each pixel to black or white
    lastRand = randValue;
  }
  
  drawRow = !drawRow; //toggle the variable
  
  pix.updatePixels();
  
  pix.loadPixels();
  for(int j=0; j<7; j++){
    for(int i=0; i<28; i++){
      fill( pix.pixels[i+j*pix.width] ); //read pixel values, set fill color to that
      ellipse(i*dotSize,j*dotSize,dotSize,dotSize);
    }
  }
}

Discussions