Random_Rect_Edges_mapgenerator.c 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  1. //
  2. // This map generator works by first creating one random rectangle in the room. This rectangle has walls.
  3. // We then create more rectangles randomly on the map and when one of these its edges touches another
  4. // edge we create another room there.
  5. //
  6. // We only draw walls on empty map places so there will be a floor area created.
  7. //
  8. #include "raylib.h"
  9. #include <math.h> // For the ceil function
  10. const int screenWidth = 800;
  11. const int screenHeight = 450;
  12. static int map[100][100];
  13. static int mapWidth = 100;
  14. static int mapHeight = 100;
  15. static int tileWidth = 100;
  16. static int tileHeight = 100;
  17. static void drawmap();
  18. static void makemap();
  19. static void makerect(int x,int y,int w,int h,bool force);
  20. static bool maprectcheck(int x,int y,int w,int h);
  21. static void edgeenhance();
  22. static float edistance(float x1,float y1,float x2,float y2);
  23. int main(void)
  24. {
  25. // Initialization
  26. //--------------------------------------------------------------------------------------
  27. InitWindow(screenWidth, screenHeight, "raylib example.");
  28. // Get the tile width and height based on the amount of tiles hor and vertical on the screen.
  29. tileWidth = ceil((float)screenWidth/(float)mapWidth);
  30. tileHeight = ceil((float)screenHeight/(float)mapHeight);
  31. makemap();
  32. SetTargetFPS(60); // Set our game to run at 60 frames-per-second
  33. //--------------------------------------------------------------------------------------
  34. // Main game loop
  35. while (!WindowShouldClose()) // Detect window close button or ESC key
  36. {
  37. // Update
  38. //----------------------------------------------------------------------------------
  39. if(IsKeyReleased(KEY_SPACE)){
  40. makemap();
  41. }
  42. //----------------------------------------------------------------------------------
  43. // Draw
  44. //----------------------------------------------------------------------------------
  45. BeginDrawing();
  46. ClearBackground((Color){20,20,20,255});
  47. drawmap();
  48. edgeenhance();
  49. DrawRectangle(0,0,screenWidth,20,DARKGRAY);
  50. DrawText("Press space to generate new map.",3,0,20,WHITE);
  51. EndDrawing();
  52. //----------------------------------------------------------------------------------
  53. }
  54. // De-Initialization
  55. //--------------------------------------------------------------------------------------
  56. CloseWindow(); // Close window and OpenGL context
  57. //--------------------------------------------------------------------------------------
  58. return 0;
  59. }
  60. static void makemap(){
  61. // Clear anything that was inside the map array.
  62. for(int y=0;y<mapHeight;y++){
  63. for(int x=0;x<mapWidth;x++){
  64. map[x][y]=0;
  65. }}
  66. // Place the first rectangle.
  67. makerect(mapWidth/2,mapHeight/2,10,10,true);
  68. for(int i=0;i<1500;i++){
  69. int x=GetRandomValue(4,mapWidth-4);
  70. int y=GetRandomValue(4,mapHeight-4);
  71. makerect(x,y,GetRandomValue(5,18),GetRandomValue(5,18),false);
  72. }
  73. };
  74. static void makerect(int x,int y,int w,int h,bool force){
  75. // Check if the rects is inside the map area.
  76. if(x<0 || x+w>=mapWidth-10 || y<0 || y+h>=mapHeight-10)return;
  77. //
  78. if(force==false){
  79. int edge=0;
  80. int cnt=0;
  81. bool good1=false;
  82. // Check if top is inside another rect and one below is nothing.
  83. for(int x1=x;x1<x+w;x1++){
  84. if(map[x1][y]==2){
  85. good1=true;
  86. cnt++;
  87. }
  88. }
  89. if(good1==true && maprectcheck(x,y+1,w,h) && cnt>3)edge++;
  90. good1=false;
  91. cnt=0;
  92. // Check if bottom is inside another rect and one above is nothing.
  93. for(int x1=x;x1<x+w;x1++){
  94. if(map[x1][y+h-1]==2){
  95. good1=true;
  96. cnt++;
  97. }
  98. }
  99. if(good1==true && maprectcheck(x,y,w,h-1) && cnt>3)edge++;
  100. good1=false;
  101. cnt=0;
  102. // Check if left side is inside another rect and one lefter is nothing.
  103. for(int y1=y;y1<y+h;y1++){
  104. if(map[x][y1]==2){
  105. good1=true;
  106. cnt++;
  107. }
  108. }
  109. if(good1==true && maprectcheck(x+1,y,w,h) && cnt>3)edge++;
  110. good1=false;
  111. cnt=0;
  112. // Check if right side is inside another rect and one righter is nothing.
  113. for(int y1=y;y1<y+h;y1++){
  114. if(map[x+w-1][y1]==2){
  115. good1=true;
  116. cnt++;
  117. }
  118. }
  119. if(good1==true && maprectcheck(x,y,w-1,h) && cnt>3)edge++;
  120. if(edge!=1)return;
  121. }
  122. //Draw walls
  123. for(int y1=y;y1<y+h;y1++){
  124. for(int x1=x;x1<x+w;x1++){
  125. if(map[x1][y1]==2)map[x1][y1]=1;
  126. if(map[x1][y1]==0)map[x1][y1]=2;
  127. }
  128. }
  129. //Draw floor
  130. for(int y1=y+1;y1<y+h-1;y1++){
  131. for(int x1=x+1;x1<x+w-1;x1++){
  132. map[x1][y1]=1;
  133. }
  134. }
  135. // bugremoval - it appears there can be holes in the walls. removed here
  136. for(int y1=y;y1<y+h;y1++){
  137. for(int x1=x;x1<x+w;x1++){
  138. if(map[x1][y1]==1){
  139. if(map[x1+1][y1]==0||map[x1-1][y1]==0||map[x1][y1-1]==0||map[x1][y1+1]==0){
  140. map[x1][y1]=2;
  141. }
  142. if(map[x1+1][y1+1]==0||map[x1-1][y1-1]==0||map[x1+1][y1-1]==0||map[x1-1][y1+1]==0){
  143. map[x1][y1]=2;
  144. }
  145. }
  146. }}
  147. };
  148. static bool maprectcheck(int x,int y,int w,int h){
  149. for(int y1=y;y1<y+h;y1++){
  150. for(int x1=x;x1<x+w;x1++){
  151. if(map[x1][y1]!=0)return false;
  152. }
  153. }
  154. return true;
  155. }
  156. static void drawmap(){
  157. int swx=0;
  158. for(int y=0;y<mapHeight;y++){
  159. for(int x=0;x<mapWidth;x++){
  160. int dx=x*tileWidth;
  161. int dy=y*tileHeight;
  162. if(map[x][y]==0){// Nothing on the map here
  163. }
  164. if(map[x][y]==1){// Floor tile
  165. int z=edistance(screenWidth/2,screenHeight/2,dx,dy)/5;
  166. if(swx==0)DrawRectangle(dx,dy,tileWidth,tileHeight,(Color){150-z,150-z,150-z,255});
  167. else DrawRectangle(dx,dy,tileWidth,tileHeight,(Color){120-z,120-z,120-z,255});
  168. }
  169. if(map[x][y]==2){// Wall tile
  170. DrawRectangle(dx,dy,tileWidth,tileHeight,BROWN);
  171. }
  172. swx++;
  173. if(swx>1)swx=0;
  174. }
  175. swx++;
  176. if(swx>1)swx=0;
  177. }
  178. };
  179. static void edgeenhance(){
  180. for(int y=0;y<mapHeight;y++){
  181. for(int x=0;x<mapWidth;x++){
  182. int dx=x*tileWidth;
  183. int dy=y*tileHeight;
  184. //outer edges
  185. if(map[x][y]==2 && map[x-1][y]==0){
  186. DrawRectangle(dx-tileWidth/2,dy,tileWidth/2,tileHeight,(Color){200,150,0,255});
  187. }
  188. if(map[x][y]==2 && map[x][y-1]==0){
  189. DrawRectangle(dx,dy-tileHeight/2,tileWidth,tileHeight/2,(Color){200,150,0,255});
  190. }
  191. if(map[x][y]==2 && map[x+1][y]==0){
  192. DrawRectangle(dx+tileWidth,dy,tileWidth/2,tileHeight,(Color){80,50,50,255});
  193. }
  194. if(map[x][y]==2 && map[x][y+1]==0){
  195. DrawRectangle(dx,dy+tileHeight,tileWidth,tileHeight/2,(Color){80,50,50,255});
  196. }
  197. //inner edges
  198. if(map[x][y]==2 && map[x][y+1]==1){
  199. DrawRectangle(dx,dy+tileHeight,tileWidth,tileHeight/2,DARKGRAY);
  200. }
  201. if(map[x][y]==2 && map[x+1][y]==1){
  202. DrawRectangle(dx+tileWidth,dy,tileWidth/2,tileHeight,DARKGRAY);
  203. }
  204. if(map[x][y]==2 && map[x-1][y]==1){
  205. DrawRectangle(dx-tileWidth/2,dy,tileWidth/2,tileHeight,(Color){200,150,0,255});
  206. }
  207. if(map[x][y]==2 && map[x][y-1]==1){
  208. DrawRectangle(dx,dy-tileHeight/2,tileWidth,tileHeight/2,(Color){200,150,0,255});
  209. }
  210. }}
  211. }
  212. // Euclidean distance (more precise)
  213. float edistance(float x1,float y1,float x2,float y2){
  214. return sqrt( (x1-x2)*(x1-x2)+(y1-y2)*(y1-y2) );
  215. }