Fireball

Team Fireball
Patrick

Computer Science Spring 2011 Project

Hope Charter High School (wiki, blog, official site)

Mr. Bujak


fireball2.first_frame.png
movie:

code:
/**
 * Fire Cube demo effect
 * by luis2048.
 *
 * A rotating wireframe cube with flames rising up the screen.
 * The fire effect has been used quite often for oldskool demos.
 * First you create a palette of 256 colors ranging from red to
 * yellow (including black). For every frame, calculate each row
 * of pixels based on the two rows below it: The value of each pixel,
 * becomes the sum of the 3 pixels below it (one directly below, one
 * to the left, and one to the right), and one pixel directly two
 * rows below it. Then divide the sum so that the fire dies out as
 * it rises.
 */
 
// This will contain the pixels used to calculate the fire effect
int[][] fire;
 
// Flame colors
color[] palette;
float angle;
int[] calc1,calc2,calc3,calc4,calc5;
 
PGraphics pg;
 
float beginX = 20.0;  // Initial x-coordinate
float beginY = 10.0;  // Initial y-coordinate
float endX = 570.0;   // Final x-coordinate
float endY = 320.0;   // Final y-coordinate
float distX;          // X-axis distance to move
float distY;          // Y-axis distance to move
float exponent = 4;   // Determines the curve
float x = 0.0;        // Current x-coordinate
float y = 0.0;        // Current y-coordinate
float step = 0.01;    // Size of each step along the path
float pct = 0.0;      // Percentage traveled (0.0 to 1.0)
 
 
void setup() {
  size(640, 360, P3D);
  noStroke();
  smooth();
  distX= endX-beginX;
  distY= endY-beginY;
 
 
  // Create buffered image for 3d sphere
  pg = createGraphics(width, height, P3D);
 
  calc1 = new int[width];
  calc3 = new int[width];
  calc4 = new int[width];
  calc2 = new int[height];
  calc5 = new int[height];
 
  colorMode(HSB);
 
  fire = new int[width][height];
  palette = new color[655];
 
  // Generate the palette
  for(int x = 0; x < palette.length; x++) {
    //Hue goes from 0 to 85: red to yellow
    //Saturation is always the maximum: 255
    //Lightness is 0..255 for x=0..128, and 255 for x=128..255
    palette[x] = color(x/3, 255, constrain(x*3, 0, 255));
  }
 
  // Precalculate which pixel values to add during animation loop
  // this speeds up the effect by 10fps
  for (int x = 0; x < width; x++) {
    calc1[x] = x % width;
    calc3[x] = (x - 1 + width) % width;
    calc4[x] = (x + 1) % width;
  }
 
  for(int y = 0; y < height; y++) {
    calc2[y] = (y + 1) % height;
    calc5[y] = (y + 2) % height;
  }
}
 
void draw() {
  angle = 9.5;
 
  // Rotating wireframe sphere
  pg.beginDraw();
  pg.translate(130, height/2, 0);
  pg.rotateX(-0.4);
  pg.rotateY(1.25);
  pg.background(0);
  pg.pushMatrix();
  pg.popMatrix();
  pg.stroke(128);
  pg.scale(25);
  pg.noFill();
  pg.sphere(3);
  pg.endDraw();
 
  pct += step;
  if (pct < 1.0) {
    x = beginX + (pct * distX);
    y = beginY + (pow(pct, exponent) * distY);
  }
 
 
 
 
  // Randomize the bottom row of the fire buffer
  for(int x = 0; x < width; x++)
  {
    fire[x][height-1] = int(random(0,190)) ;
  }
 
  loadPixels();
 
  int counter = 0;
  // Do the fire calculations for every pixel, from top to bottom
  for (int y = 0; y < height; y++) {
    for(int x = 0; x < width; x++) {
      // Add pixel values around current pixel
 
      fire[x][y] =
        ((fire[calc3[x]][calc2[y]]
        + fire[calc1[x]][calc2[y]]
        + fire[calc4[x]][calc2[y]]
        + fire[calc1[x]][calc5[y]]) << 5) / 129;
 
      // Output everything to screen using our palette colors
      pixels[counter] = palette[fire[x][y]];
 
      // Extract the red value using right shift and bit mask
      // equivalent of red(pg.pixels[x+y*w])
      if ((pg.pixels[counter++] >> 16 & 0xFF) == 128) {
        // Only map 3D cube 'lit' pixels onto fire array needed for next frame
        fire[x][y] = 128;
      }
    }
  }
  updatePixels();
}