// // Wave Function Collapse - sort of... // // I barely understand how this works. It has taken me a number of tries and a whack load of hours // top get to this current point. The tutorials and explanations on the internet are not that clear and easy // to understand. // // In the example here I have a number of tiles. I pick a random tile from the valid ones and place it on the grid. // I then fix the neighbour tiles to fit this current position. Connected/unconnected. I keep placing random tiles // for a x amount of times. // There is a array that contains a list of all possible tiles. There are functions that check if a position on the grid // has connections to another position on the grid. This is used to unflag the tiles that are on the list to get // selected(one random) as a tile to be placed. // // The MAX_TILES is the amount of tiles that I have created to create the map with. I check the middle top/left/right/bottom // tile value to see if there is a connection(1). Experiment with making different tiles. // // I might(should) add comments to the code later. // #include "raylib.h" #define MAP_WIDTH 14 #define MAP_HEIGHT 12 #define MAX_TILES 15 static void newmap(void); static void resetmap(void); // If the selected map position has a connection the l/r/u/d side than return true/false static bool domainhasleftsidedconnections(int x,int y); static bool domainhasrightsidedconnections(int x,int y); static bool domainhastopsidedconnections(int x,int y); static bool domainhasbottomsidedconnections(int x,int y); // Remove every tile flag from l/r/u/d. static void removeleftsidedconnections(int x,int y); static void removerightsidedconnections(int x,int y); static void removetopsidedconnections(int x,int y); static void removebottomsidedconnections(int x,int y); // Select a random tile from the list of available tiles. static void setrandomtile(int x,int y); // Update the current map position checking l/r/u/d for connections and setting // the flag for can use or can not use with setrandomtile. static void updatedomain(int x,int y); // create our final tilemap. static void finishmap(void); // Our tile array. 3by3 grid of x amount of tiles static int tile[3][3][MAX_TILES] = {0}; // Our work map. We have every tile set up there. -1 if not usable or 1 if usable. static int map[MAP_WIDTH][MAP_HEIGHT][MAX_TILES] = {0}; // This is a array we use to draw the map on the screen static int tilemap[MAP_WIDTH][MAP_HEIGHT] = {0}; int main(void) { // Initialization //-------------------------------------------------------------------------------------- const int screenWidth = 800; const int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib example."); // // These are the tiles with which the map will be generated. You can set the amount you want to use in the // define MAX_TILES x // The code checks the connections between these tiles by reading if a 1 is on the center top/left/right/bottom. // Also the draw routine draws the 1's as black. // // You could change(experiment!) and for instance use maybe 4 tiles and see the output. You can change the depth in the // newmap() function for how many times a tile is going to be selected and fit into the map. int tile1[3][3] = { {0,0,0}, {1,1,1}, {0,0,0}}; int tile2[3][3] = { {0,1,0}, {0,1,0}, {0,1,0}}; int tile3[3][3] = { {1,1,1}, {1,1,1}, {1,1,1}}; int tile4[3][3] = { {0,1,0}, {1,1,1}, {0,1,0}}; int tile5[3][3] = { {0,1,0}, {1,1,0}, {0,0,0}}; int tile6[3][3] = { {0,1,0}, {0,1,1}, {0,0,0}}; int tile7[3][3] = { {0,0,0}, {1,1,0}, {0,1,0}}; int tile8[3][3] = { {0,0,0}, {0,1,1}, {0,1,0}}; int tile9[3][3] = { {0,1,0}, {1,1,1}, {0,0,0}}; int tile10[3][3] = { {0,1,0}, {0,1,1}, {0,1,0}}; int tile11[3][3] = { {0,0,0}, {1,1,1}, {0,1,0}}; int tile12[3][3] = { {0,1,0}, {1,1,0}, {0,1,0}}; int tile13[3][3] = { {1,1,0}, {1,1,0}, {1,1,0}}; int tile14[3][3] = { {0,1,1}, {0,1,1}, {0,1,1}}; int tile15[3][3] = { {1,1,1}, {1,1,1}, {1,1,1}}; // // Here we copy each individual tile into a single array that we will // use in the code. for(int i=0;i4){ newmap(); cnt=0; } // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); for (int y = 0; y< MAP_HEIGHT ; y++) { for (int x = 0; x< MAP_WIDTH ; x++) { int x3 = x*48; int y3 = y*32; for(int y2=0;y2<3;y2++){ for(int x2=0;x2<3;x2++){ if( tile[x2][y2][tilemap[x][y]]==1 )DrawRectangle(x3+x2*16,y3+y2*12,16,12,BLACK); } } } } DrawText("Press space for new map.", 100, screenHeight-40, 40, LIGHTGRAY); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } void newmap(){ // Here we reset the map. Meaning nothing will be in the memory. resetmap(); // here we generate the new map. I have set the depth to a number where it generates // output that I thought was ok! int depth=GetRandomValue(100,400); for(int i=0;i-1){ tilemap[x][y] = i; } } }} }; void resetmap(){ for(int y=0;y=MAP_WIDTH || y>=MAP_HEIGHT)return false; for(int i=0;i=MAP_WIDTH || y>=MAP_HEIGHT)return false; for(int i=0;i=MAP_WIDTH || y>=MAP_HEIGHT)return false; for(int i=0;i=MAP_WIDTH || y>=MAP_HEIGHT)return false; for(int i=0;i=MAP_WIDTH || y>=MAP_HEIGHT)return; for(int i=0;i=MAP_WIDTH || y>=MAP_HEIGHT)return; for(int i=0;i=MAP_WIDTH || y>=MAP_HEIGHT)return; for(int i=0;i=MAP_WIDTH || y>=MAP_HEIGHT)return; for(int i=0;i-1){ //if the random number inside the map flag position is enabled(on the list!) for(int i=0;i500)exitloop=true;//if anything goes wrong than exit } // Update around the new tile so that the connections make sense updatedomain(x-1,y); updatedomain(x+1,y); updatedomain(x,y-1); updatedomain(x,y+1); }; void updatedomain(int x,int y){ if(x<0 || y<0 || x>=MAP_WIDTH || y>=MAP_HEIGHT)return; // Enable every tile flag for(int i=0;i