Blob Blame Raw

#include <math.h>
#include <stdlib.h>
#include <string.h>
#include <helianthus.h>


#define TILESIZE     512
#define ROWS           8
#define COLS          12


const double cellRatio = 1.0;
const double genRatio  = 0.5;

Animation tiles[1024];

int tilesCount = 0;

Framebuffer framebuffer;
Animation fbAnim;


void groundLine(double len) {
  double ky = 0.02;
  double x = 0;
  double y = 0;
  moveTo(x, y);
  while(x < len) {
    double ny;
    do { ny = (randomFloat()*2 - 1)*ky; } while(fabs(y + ny) > ky);
    y += ny;
    x += (1 + (randomFloat()*2 - 1)*0.5)*ky;
    if (x >= len) { x = len; y = 0; }
    lineTo(x, y);
  }
  strokePath();
}


void generate() {
  saveState();

  target(framebuffer);
  background(COLOR_TRANSPARENT);
  clear();
  zoom(TILESIZE*cellRatio*genRatio);

  fill(colorByRGBA(1, 1, 1, 1));
  noStroke();
  double thikness  = 0.02/cellRatio*genRatio;
  strokeWidth(thikness);

  saveState();
  translate(0.5, 0.5);
  if (tilesCount > 0)
    for(int y = 0; y < ROWS; ++y)
      for(int x = 0; x < COLS; ++x) {
        saveState();
        translate(x, y);
        zoom(1/cellRatio);
        rectTextured(tiles[rand()%tilesCount], -0.5, -0.5, 1, 1);
        restoreState();
      }
  restoreState();

  saveState();
  stroke(COLOR_BLACK);
  double k = 1/3.0;
  saveState();
    translate(0.5 - k, 0.5);
    for(int i = 0; i < ROWS; ++i) {
      saveState();
      translate(0, i - k);
      groundLine(COLS + 2*k - 1);
      restoreState();
      saveState();
      translate(0, i + k);
      groundLine(COLS + 2*k - 1);
      restoreState();
    }
  restoreState();
  saveState();
    rotate(90);
    scale(1, -1);
    translate(0.5 - k, 0.5);
    for(int i = 0; i < COLS; ++i) {
      saveState();
      translate(0, i - k);
      groundLine(ROWS + 2*k - 1);
      restoreState();
      saveState();
      translate(0, i + k);
      groundLine(ROWS + 2*k -  1);
      restoreState();
    }
  restoreState();
  restoreState();

  viewportSave("data/output/generated-dungeon.png");
  restoreState();
}


Animation subImage(int width, int height, unsigned char *pixels, int x, int y, int w, int h) {
  if (x < 0 || y < 0 || x + w > width || y + h > height || !pixels)
    return NULL;
  unsigned char *px = calloc(4, w*h);
  for(int i = 0; i < h; ++i)
    memcpy(px + i*w*4, pixels + ((y+i)*width + x)*4, w*4);
  Animation anim = createAnimationFromImage(w, h, px, FALSE);
  free(px);
  return anim;
}


void init() {
  int w = 0;
  int h = 0;
  unsigned char *px = NULL;
  imageLoad("data/dungeon.png", &w, &h, &px);
  int s = TILESIZE + TILESIZE/2;
  for(int y = 0; y < 2; ++y)
    for(int x = 0; x < 6; ++x)
      if ((tiles[tilesCount] = subImage(w, h, px, x*TILESIZE + TILESIZE/4, y*TILESIZE + TILESIZE/4, TILESIZE, TILESIZE)))
        ++tilesCount;
  free(px);

  w = ceil(TILESIZE*COLS*cellRatio*genRatio - 0.001);
  h = ceil(TILESIZE*ROWS*cellRatio*genRatio - 0.001);
  framebuffer = createFramebuffer(w, h);
  fbAnim = createAnimationFromFramebuffer(framebuffer);

  generate();
}


void draw() {
  background(COLOR_WHITE);

  double w = windowGetWidth();
  double h = windowGetHeight();

  if (keyWentDown("space")) generate();

  saveState();
  translate(w/2, h/2);
  zoom(w/COLS);
  fill(COLOR_WHITE);
  noStroke();
  rectTextured(fbAnim, -COLS/2.0, -ROWS/2.0, COLS, ROWS);
  restoreState();
}


int main() {
  windowSetVariableFrameRate();
  windowSetResizable(TRUE);
  windowSetInit(&init);
  windowSetDraw(&draw);
  windowRun();
}