|
|
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 10.0
|
|
|
a5e8d6 |
#define WALLJITTER 1.0
|
|
|
a5e8d6 |
#define WALLBORDER 2.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 |
|
|
|
a5e8d6 |
int itemTilesCount = 0;
|
|
|
a5e8d6 |
int cellTilesCount = 0;
|
|
|
a5e8d6 |
|
|
|
a5e8d6 |
int rows;
|
|
|
a5e8d6 |
int cols;
|
|
|
a5e8d6 |
|
|
|
a5e8d6 |
Framebuffer framebuffer;
|
|
|
a5e8d6 |
Animation fbAnim;
|
|
|
a5e8d6 |
|
|
|
a5e8d6 |
|
|
|
a5e8d6 |
void shuffle(Animation *anims, int count) {
|
|
|
a5e8d6 |
for(int i = 0; i < 2*count; ++i) {
|
|
|
a5e8d6 |
int a = randomNumber(0, count-1);
|
|
|
a5e8d6 |
int b = randomNumber(0, count-1);
|
|
|
a5e8d6 |
if (a != b) {
|
|
|
a5e8d6 |
Animation anim = anims[a];
|
|
|
a5e8d6 |
anims[a] = anims[b];
|
|
|
a5e8d6 |
anims[b] = anim;
|
|
|
a5e8d6 |
}
|
|
|
a5e8d6 |
}
|
|
|
a5e8d6 |
}
|
|
|
a5e8d6 |
|
|
|
a5e8d6 |
|
|
|
a5e8d6 |
void groundLine(double len, double k) {
|
|
|
a5e8d6 |
double x = 0;
|
|
|
a5e8d6 |
double y = 0;
|
|
|
a5e8d6 |
moveTo(x, y);
|
|
|
a5e8d6 |
while(x < len) {
|
|
|
a5e8d6 |
double ny;
|
|
|
a5e8d6 |
do { ny = (randomFloat()*2 - 1)*k; } while(fabs(y + ny) > k);
|
|
|
a5e8d6 |
y += ny;
|
|
|
a5e8d6 |
x += (1 + (randomFloat()*2 - 1)*0.5)*2*k;
|
|
|
a5e8d6 |
if (x >= len) { x = len; y = 0; }
|
|
|
a5e8d6 |
lineTo(x, y);
|
|
|
a5e8d6 |
}
|
|
|
a5e8d6 |
strokePath();
|
|
|
a5e8d6 |
}
|
|
|
a5e8d6 |
|
|
|
a5e8d6 |
|
|
|
a5e8d6 |
void generate() {
|
|
|
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 |
fill(COLOR_WHITE);
|
|
|
a5e8d6 |
noStroke();
|
|
|
a5e8d6 |
|
|
|
a5e8d6 |
double step = CELLSIZE + WALLSIZE;
|
|
|
a5e8d6 |
translate(-(cols-1)*step/2, -(rows-1)*step/2);
|
|
|
a5e8d6 |
|
|
|
a5e8d6 |
double itemStep = (CELLSIZE - ITEMSIZE)/2;
|
|
|
a5e8d6 |
double cellSize = CELLSIZE*cellScale;
|
|
|
a5e8d6 |
double itemSize = ITEMSIZE*itemScale;
|
|
|
a5e8d6 |
|
|
|
a5e8d6 |
int cellId = cellTilesCount;
|
|
|
a5e8d6 |
int itemId = itemTilesCount;
|
|
|
a5e8d6 |
for(int y = 0; y < rows; ++y) {
|
|
|
a5e8d6 |
for(int x = 0; x < cols; ++x) {
|
|
|
a5e8d6 |
saveState();
|
|
|
a5e8d6 |
translate(x*step, y*step);
|
|
|
a5e8d6 |
if (cellTilesCount > 0 && randomFloat()*100 < 10) {
|
|
|
a5e8d6 |
if (cellId >= cellTilesCount) {
|
|
|
a5e8d6 |
shuffle(cellTiles, cellTilesCount);
|
|
|
a5e8d6 |
cellId = 0;
|
|
|
a5e8d6 |
}
|
|
|
a5e8d6 |
rectTextured(cellTiles[cellId++], -cellSize/2, -cellSize/2, cellSize, cellSize);
|
|
|
a5e8d6 |
} else
|
|
|
a5e8d6 |
if (itemTilesCount > 0) {
|
|
|
a5e8d6 |
int cnt = 4;
|
|
|
a5e8d6 |
if (cnt < itemTilesCount) cnt = rand()%itemTilesCount;
|
|
|
a5e8d6 |
for(int i = 0; i < 4; ++i) {
|
|
|
a5e8d6 |
saveState();
|
|
|
a5e8d6 |
translate(i%2 ? itemStep : -itemStep, i/2 ? itemStep : -itemStep);
|
|
|
a5e8d6 |
if (itemId >= itemTilesCount) {
|
|
|
a5e8d6 |
shuffle(itemTiles, itemTilesCount);
|
|
|
a5e8d6 |
itemId = 0;
|
|
|
a5e8d6 |
}
|
|
|
a5e8d6 |
rectTextured(itemTiles[itemId++], -itemSize/2, -itemSize/2, itemSize, itemSize);
|
|
|
a5e8d6 |
restoreState();
|
|
|
a5e8d6 |
}
|
|
|
a5e8d6 |
}
|
|
|
a5e8d6 |
restoreState();
|
|
|
a5e8d6 |
}
|
|
|
a5e8d6 |
}
|
|
|
a5e8d6 |
|
|
|
a5e8d6 |
noFill();
|
|
|
a5e8d6 |
stroke(COLOR_BLACK);
|
|
|
a5e8d6 |
strokeWidth(THIKNESS);
|
|
|
a5e8d6 |
double k = WALLJITTER;
|
|
|
a5e8d6 |
double wallStep = CELLSIZE/2 + k + WALLBORDER;
|
|
|
a5e8d6 |
saveState();
|
|
|
a5e8d6 |
translate(-wallStep, 0);
|
|
|
a5e8d6 |
double len = (cols-1)*step + 2*wallStep;
|
|
|
a5e8d6 |
for(int i = 0; i < rows; ++i) {
|
|
|
a5e8d6 |
saveState();
|
|
|
a5e8d6 |
translate(0, i*step - wallStep);
|
|
|
a5e8d6 |
groundLine(len, k);
|
|
|
a5e8d6 |
translate(0, 2*wallStep);
|
|
|
a5e8d6 |
groundLine(len, k);
|
|
|
a5e8d6 |
restoreState();
|
|
|
a5e8d6 |
}
|
|
|
a5e8d6 |
restoreState();
|
|
|
a5e8d6 |
saveState();
|
|
|
a5e8d6 |
rotate(90);
|
|
|
a5e8d6 |
scale(1, -1);
|
|
|
a5e8d6 |
translate(-wallStep, 0);
|
|
|
a5e8d6 |
len = (rows-1)*step + 2*wallStep;
|
|
|
a5e8d6 |
for(int i = 0; i < cols; ++i) {
|
|
|
a5e8d6 |
saveState();
|
|
|
a5e8d6 |
translate(0, i*step - wallStep);
|
|
|
a5e8d6 |
groundLine(len, k);
|
|
|
a5e8d6 |
translate(0, 2*wallStep);
|
|
|
a5e8d6 |
groundLine(len, k);
|
|
|
a5e8d6 |
restoreState();
|
|
|
a5e8d6 |
}
|
|
|
a5e8d6 |
restoreState();
|
|
|
a5e8d6 |
|
|
|
a5e8d6 |
viewportSave("data/output/generated-dungeon2.png");
|
|
|
a5e8d6 |
restoreState();
|
|
|
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/dungeon2.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 < 5; ++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 |
rows = HEIGHT/(CELLSIZE + WALLSIZE);
|
|
|
a5e8d6 |
cols = WIDTH/(CELLSIZE + WALLSIZE);
|
|
|
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 |
|