Blame onefile/gen-dungeon3.c

a5e8d6
a5e8d6
#include <math.h></math.h>
a5e8d6
#include <stdlib.h></stdlib.h>
a5e8d6
#include <string.h></string.h>
a5e8d6
#include <helianthus.h></helianthus.h>
a5e8d6
a5e8d6
a5e8d6
#define WIDTH     285.0
a5e8d6
#define HEIGHT    200.0
a5e8d6
#define RES        10.0
a5e8d6
#define THIKNESS    0.5
a5e8d6
#define ALPHA       0.1
a5e8d6
a5e8d6
#define CELLSIZE   22.5
a5e8d6
#define ITEMSIZE   10.0
a5e8d6
#define WALLSIZE   15.0
a5e8d6
#define WALLJITTER  0.5
a5e8d6
#define WALLWIDTH   1.0
a5e8d6
a5e8d6
#define SRCRES    10.0
a5e8d6
a5e8d6
#define SCALE      1.0
a5e8d6
a5e8d6
a5e8d6
double itemScale;
a5e8d6
double cellScale;
a5e8d6
a5e8d6
a5e8d6
Animation itemTiles[1024];
a5e8d6
Animation cellTiles[1024];
a5e8d6
int map[256][256];
a5e8d6
a5e8d6
int itemTilesCount = 0;
a5e8d6
int cellTilesCount = 0;
a5e8d6
a5e8d6
int rows;
a5e8d6
int cols;
a5e8d6
unsigned int jitterSeed;
a5e8d6
a5e8d6
a5e8d6
Framebuffer framebuffer;
a5e8d6
Animation fbAnim;
a5e8d6
a5e8d6
a5e8d6
void shuffle(int *numbers, int count) {
a5e8d6
  for(int i = 0; i < count; ++i)
a5e8d6
    numbers[i] = i;
a5e8d6
  for(int i = 0; i < 2*count; ++i) {
a5e8d6
    int a = randomNumber(0, count-1);
a5e8d6
    int b = randomNumber(0, count-1);
a5e8d6
    int n = numbers[a];
a5e8d6
    numbers[a] = numbers[b];
a5e8d6
    numbers[b] = n;
a5e8d6
  }
a5e8d6
}
a5e8d6
a5e8d6
a5e8d6
int lastItem = 1000000;
a5e8d6
int itemNumbers[1024];
a5e8d6
int genItem() {
a5e8d6
  if (lastItem >= itemTilesCount)
a5e8d6
    { shuffle(itemNumbers, itemTilesCount); lastItem = 0; }
a5e8d6
  return itemNumbers[lastItem++];
a5e8d6
}
a5e8d6
a5e8d6
a5e8d6
int lastCell = 1000000;
a5e8d6
int cellNumbers[1024];
a5e8d6
int genCell() {
a5e8d6
  if (lastCell >= cellTilesCount)
a5e8d6
    { shuffle(cellNumbers, cellTilesCount); lastCell = 0; }
a5e8d6
  return cellNumbers[lastCell++];
a5e8d6
}
a5e8d6
a5e8d6
a5e8d6
void generateMap() {
a5e8d6
  for(int y = 0; y < rows; ++y)
a5e8d6
    for(int x = 0; x < cols; ++x)
a5e8d6
      map[y][x] = 1000 + genItem();
a5e8d6
a5e8d6
  if (rows >= 2 && cols >= 2 && cellTilesCount > 0) {
a5e8d6
    int cnt = (rows-1)*(cols-1)/4/10;
a5e8d6
    cnt += randomNumber(0, cnt/2) - cnt/4;
a5e8d6
    for(int i = 0; i < cnt; ++i) {
a5e8d6
      int x = randomNumber(0, cols-2);
a5e8d6
      int y = randomNumber(0, rows-2);
a5e8d6
      if ( map[y][x] < 2000
a5e8d6
        && map[y][x+1] < 2000
a5e8d6
        && map[y+1][x] < 2000
a5e8d6
        && map[y+1][x+1] < 2000 )
a5e8d6
      {
a5e8d6
        map[y][x] = 2000 + genCell();
a5e8d6
        map[y][x+1] = map[y+1][x] = map[y+1][x+1] = 3000;
a5e8d6
      }
a5e8d6
    }
a5e8d6
  }
a5e8d6
}
a5e8d6
a5e8d6
a5e8d6
void jitter(double x, double y, double k, double *outX, double *outY) {
a5e8d6
  unsigned int ix = (unsigned int)(int)round(x*2*RES);
a5e8d6
  unsigned int iy = (unsigned int)(int)round(y*2*RES);
a5e8d6
  unsigned int random = ix ^ ((iy << 16) | (iy >> 16));
a5e8d6
  random ^= jitterSeed;
a5e8d6
a5e8d6
	random = (unsigned int)((unsigned long long)random * 48271 % 0x7fffffff);
a5e8d6
  double randomX = random/(double)0x7fffffff;
a5e8d6
	random = (unsigned int)((unsigned long long)random * 48271 % 0x7fffffff);
a5e8d6
  double randomY = random/(double)0x7fffffff;
a5e8d6
a5e8d6
	*outX = x + (randomX*2 - 1)*k;
a5e8d6
	*outY = y + (randomY*2 - 1)*k;
a5e8d6
}
a5e8d6
a5e8d6
a5e8d6
void jitterLine(double x0, double y0, double x1, double y1, double kl, double k) {
a5e8d6
  double dx = x1 - x0;
a5e8d6
  double dy = y1 - y0;
a5e8d6
  double len = sqrt(dx*dx + dy*dy);
a5e8d6
  int count = round(len/kl) + 1;
a5e8d6
  if (count < 2) count = 2;
a5e8d6
  double kx = dx/(count-1);
a5e8d6
  double ky = dy/(count-1);
a5e8d6
  for(int i = 0; i < count; ++i) {
a5e8d6
    double x = x0 + i*kx;
a5e8d6
    double y = y0 + i*ky;
a5e8d6
    jitter(x, y, k, &x, &y);
a5e8d6
    if (i) lineTo(x, y); else moveTo(x, y);
a5e8d6
  }
a5e8d6
  strokePath();
a5e8d6
}
a5e8d6
a5e8d6
a5e8d6
void drawMap() {
a5e8d6
  int fw = framebufferGetWidth(framebuffer);
a5e8d6
  int fh = framebufferGetHeight(framebuffer);
a5e8d6
a5e8d6
  saveState();
a5e8d6
  target(framebuffer);
a5e8d6
  background(COLOR_TRANSPARENT);
a5e8d6
  clear();
a5e8d6
a5e8d6
  translate(fw/2, fh/2);
a5e8d6
  zoom(RES);
a5e8d6
a5e8d6
  double step = WALLSIZE;
a5e8d6
  translate(-(cols-1)*step/2, -(rows-1)*step/2);
a5e8d6
a5e8d6
  double cellSize = CELLSIZE*cellScale;
a5e8d6
  double itemSize = ITEMSIZE*itemScale;
a5e8d6
  fill(COLOR_WHITE);
a5e8d6
  noStroke();
a5e8d6
  for(int y = 0; y < rows; ++y) {
a5e8d6
    for(int x = 0; x < cols; ++x) {
a5e8d6
      int m = map[y][x];
a5e8d6
      if (m < 1000) {
a5e8d6
      } else
a5e8d6
      if (m < 2000) {
a5e8d6
        double xx = x*step - itemSize/2;
a5e8d6
        double yy = y*step - itemSize/2;
a5e8d6
        rectTextured(itemTiles[m - 1000], xx, yy, itemSize, itemSize);
a5e8d6
      } else
a5e8d6
      if (m < 3000) {
a5e8d6
        double xx = x*step + step/2 - cellSize/2;
a5e8d6
        double yy = y*step + step/2 - cellSize/2;
a5e8d6
        rectTextured(cellTiles[m - 2000], xx, yy, cellSize, cellSize);
a5e8d6
      }
a5e8d6
    }
a5e8d6
  }
a5e8d6
a5e8d6
  noFill();
a5e8d6
  stroke(COLOR_BLACK);
a5e8d6
  strokeWidth(THIKNESS);
a5e8d6
  jitterSeed = randomNumber(0, 0x7fffffff);
a5e8d6
  double t = WALLWIDTH/2.0;
a5e8d6
  double k = WALLJITTER;
a5e8d6
  double kl = 2*k;
a5e8d6
  for(int y = 0; y < rows; ++y) {
a5e8d6
    for(int x = 0; x <= cols; ++x) {
a5e8d6
      if (x > 0 && x < cols) {
a5e8d6
        if (map[y][x-1] >= 2000 && map[y][x-1] < 3000) continue;
a5e8d6
        if (y > 0 && map[y][x-1] >= 3000 && map[y-1][x-1] >= 2000 && map[y-1][x-1] < 3000) continue;
a5e8d6
      }
a5e8d6
      double xx = (x - 0.5)*step;
a5e8d6
      double yy = (y - 0.5)*step;
a5e8d6
      jitterLine(xx-t, yy, xx-t, yy+step, kl, k);
a5e8d6
      jitterLine(xx+t, yy, xx+t, yy+step, kl, k);
a5e8d6
    }
a5e8d6
  }
a5e8d6
  for(int x = 0; x < cols; ++x) {
a5e8d6
    for(int y = 0; y <= rows; ++y) {
a5e8d6
      if (y > 0 && y < rows) {
a5e8d6
        if (map[y-1][x] >= 2000 && map[y-1][x] < 3000) continue;
a5e8d6
        if (x > 0 && map[y-1][x] >= 3000 && map[y-1][x-1] >= 2000 && map[y-1][x-1] < 3000) continue;
a5e8d6
      }
a5e8d6
      double xx = (x - 0.5)*step;
a5e8d6
      double yy = (y - 0.5)*step;
a5e8d6
      jitterLine(xx, yy-t, xx+step, yy-t, kl, k);
a5e8d6
      jitterLine(xx, yy+t, xx+step, yy+t, kl, k);
a5e8d6
    }
a5e8d6
  }
a5e8d6
a5e8d6
  viewportSave("data/output/generated-dungeon3.png");
a5e8d6
  restoreState();
a5e8d6
}
a5e8d6
a5e8d6
a5e8d6
void generate() {
a5e8d6
  generateMap();
a5e8d6
  drawMap();
a5e8d6
}
a5e8d6
a5e8d6
a5e8d6
Animation subImage(int width, int height, unsigned char *pixels, int x, int y, int w, int h) {
a5e8d6
  if (x < 0 || y < 0 || x + w > width || y + h > height || !pixels)
a5e8d6
    return NULL;
a5e8d6
  unsigned char *px = calloc(4, w*h);
a5e8d6
  for(int i = 0; i < h; ++i)
a5e8d6
    memcpy(px + i*w*4, pixels + ((y+i)*width + x)*4, w*4);
a5e8d6
  Animation anim = createAnimationFromImage(w, h, px, FALSE);
a5e8d6
  free(px);
a5e8d6
  return anim;
a5e8d6
}
a5e8d6
a5e8d6
a5e8d6
void init() {
a5e8d6
  int w = 0;
a5e8d6
  int h = 0;
a5e8d6
  unsigned char *px = NULL;
a5e8d6
  imageLoad("data/dungeon3.png", &w, &h, &px);
a5e8d6
a5e8d6
  int is = 128;
a5e8d6
  int cs = 256;
a5e8d6
  itemScale = is/(ITEMSIZE*SRCRES);
a5e8d6
  cellScale = cs/(CELLSIZE*SRCRES);
a5e8d6
a5e8d6
  int ix0 = (int)round((1*ITEMSIZE + (1 - itemScale)*ITEMSIZE/2)*SRCRES);
a5e8d6
  int iy0 = ix0;
a5e8d6
  int idx = (int)round(2*ITEMSIZE*SRCRES);
a5e8d6
  int idy = idx;
a5e8d6
a5e8d6
  int cx0 = (int)round((1*ITEMSIZE + (1 - cellScale)*CELLSIZE/2)*SRCRES);
a5e8d6
  int cy0 = (int)round((5*ITEMSIZE + (1 - cellScale)*CELLSIZE/2)*SRCRES);
a5e8d6
  int cdx = (int)round(3*ITEMSIZE*SRCRES);
a5e8d6
a5e8d6
  int y = iy0;
a5e8d6
  for(int i = 0; i < 6; ++i)
a5e8d6
      if ((itemTiles[itemTilesCount] = subImage(w, h, px, ix0 + i*idx, y, is, is)))
a5e8d6
        ++itemTilesCount;
a5e8d6
  y += idy;
a5e8d6
  for(int i = 0; i < 6; ++i)
a5e8d6
      if ((itemTiles[itemTilesCount] = subImage(w, h, px, ix0 + i*idx, y, is, is)))
a5e8d6
        ++itemTilesCount;
a5e8d6
  y = cy0;
a5e8d6
  for(int i = 0; i < 3; ++i)
a5e8d6
      if ((cellTiles[cellTilesCount] = subImage(w, h, px, cx0 + i*cdx, y, cs, cs)))
a5e8d6
        ++cellTilesCount;
a5e8d6
  free(px);
a5e8d6
a5e8d6
  cols = (int)floor(WIDTH/WALLSIZE + 0.001) - 1;
a5e8d6
  rows = (int)floor(HEIGHT/WALLSIZE + 0.001) - 1;
a5e8d6
a5e8d6
  int fw = ceil(WIDTH*RES - 0.001);
a5e8d6
  int fh = ceil(HEIGHT*RES - 0.001);
a5e8d6
  framebuffer = createFramebuffer(fw, fh);
a5e8d6
  fbAnim = createAnimationFromFramebuffer(framebuffer);
a5e8d6
a5e8d6
  generate();
a5e8d6
}
a5e8d6
a5e8d6
a5e8d6
void draw() {
a5e8d6
  background(COLOR_WHITE);
a5e8d6
a5e8d6
  double w = windowGetWidth();
a5e8d6
  double h = windowGetHeight();
a5e8d6
a5e8d6
  if (keyWentDown("space")) generate();
a5e8d6
a5e8d6
  saveState();
a5e8d6
  translate(w/2, h/2);
a5e8d6
  zoom(w/WIDTH);
a5e8d6
  fill(COLOR_WHITE);
a5e8d6
  noStroke();
a5e8d6
  rectTextured(fbAnim, -WIDTH/2.0, -HEIGHT/2.0, WIDTH, HEIGHT);
a5e8d6
  restoreState();
a5e8d6
}
a5e8d6
a5e8d6
a5e8d6
int main() {
a5e8d6
  windowSetVariableFrameRate();
a5e8d6
  windowSetResizable(TRUE);
a5e8d6
  windowSetInit(&init);
a5e8d6
  windowSetDraw(&draw);
a5e8d6
  windowRun();
a5e8d6
}
a5e8d6