diff --git a/demo/src/lib.rs b/demo/src/lib.rs index be8e1bd..00f8817 100644 --- a/demo/src/lib.rs +++ b/demo/src/lib.rs @@ -8,6 +8,7 @@ use mapgen::dungeon::{ starting_point::{AreaStartingPosition, XStart, YStart}, cull_unreachable::CullUnreachable, distant_exit::DistantExit, + rooms_corridors_nearest::NearestCorridors, }; @@ -47,6 +48,7 @@ impl World { pub fn new_random_rooms(width: u32, height: u32, seed: u32) -> World { let mut rng = StdRng::seed_from_u64(seed as u64); let map = MapBuilder::new(Box::new(RandomRoomsGen::new())) + .with(NearestCorridors::new()) .build_map_with_rng(width as usize, height as usize, &mut rng); let tiles = (0..map.tiles.len()) .map(|i| if map.tiles[i] == TileType::Floor {Cell::Floor} else {Cell::Wall}) diff --git a/docs/0.bootstrap.js b/docs/0.bootstrap.js index e0ae0ba..18d39ea 100644 --- a/docs/0.bootstrap.js +++ b/docs/0.bootstrap.js @@ -4,11 +4,11 @@ /*!*****************************!*\ !*** ../pkg/mapgen_demo.js ***! \*****************************/ -/*! exports provided: World, __wbindgen_object_drop_ref, __wbg_getTime_29addd71c7089c47, __wbg_new0_a3af66503e735141, __wbindgen_throw */ +/*! exports provided: Cell, World, __wbindgen_throw */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _mapgen_demo_bg_wasm__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./mapgen_demo_bg.wasm */ \"../pkg/mapgen_demo_bg.wasm\");\n/* harmony import */ var _mapgen_demo_bg_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./mapgen_demo_bg.js */ \"../pkg/mapgen_demo_bg.js\");\n/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, \"World\", function() { return _mapgen_demo_bg_js__WEBPACK_IMPORTED_MODULE_1__[\"World\"]; });\n\n/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, \"__wbindgen_object_drop_ref\", function() { return _mapgen_demo_bg_js__WEBPACK_IMPORTED_MODULE_1__[\"__wbindgen_object_drop_ref\"]; });\n\n/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, \"__wbg_getTime_29addd71c7089c47\", function() { return _mapgen_demo_bg_js__WEBPACK_IMPORTED_MODULE_1__[\"__wbg_getTime_29addd71c7089c47\"]; });\n\n/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, \"__wbg_new0_a3af66503e735141\", function() { return _mapgen_demo_bg_js__WEBPACK_IMPORTED_MODULE_1__[\"__wbg_new0_a3af66503e735141\"]; });\n\n/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, \"__wbindgen_throw\", function() { return _mapgen_demo_bg_js__WEBPACK_IMPORTED_MODULE_1__[\"__wbindgen_throw\"]; });\n\n\n\n\n//# sourceURL=webpack:///../pkg/mapgen_demo.js?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _mapgen_demo_bg_wasm__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./mapgen_demo_bg.wasm */ \"../pkg/mapgen_demo_bg.wasm\");\n/* harmony import */ var _mapgen_demo_bg_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./mapgen_demo_bg.js */ \"../pkg/mapgen_demo_bg.js\");\n/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, \"Cell\", function() { return _mapgen_demo_bg_js__WEBPACK_IMPORTED_MODULE_1__[\"Cell\"]; });\n\n/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, \"World\", function() { return _mapgen_demo_bg_js__WEBPACK_IMPORTED_MODULE_1__[\"World\"]; });\n\n/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, \"__wbindgen_throw\", function() { return _mapgen_demo_bg_js__WEBPACK_IMPORTED_MODULE_1__[\"__wbindgen_throw\"]; });\n\n\n\n\n//# sourceURL=webpack:///../pkg/mapgen_demo.js?"); /***/ }), @@ -16,11 +16,11 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _map /*!********************************!*\ !*** ../pkg/mapgen_demo_bg.js ***! \********************************/ -/*! exports provided: World, __wbindgen_object_drop_ref, __wbg_getTime_29addd71c7089c47, __wbg_new0_a3af66503e735141, __wbindgen_throw */ +/*! exports provided: Cell, World, __wbindgen_throw */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* WEBPACK VAR INJECTION */(function(module) {/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"World\", function() { return World; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"__wbindgen_object_drop_ref\", function() { return __wbindgen_object_drop_ref; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"__wbg_getTime_29addd71c7089c47\", function() { return __wbg_getTime_29addd71c7089c47; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"__wbg_new0_a3af66503e735141\", function() { return __wbg_new0_a3af66503e735141; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"__wbindgen_throw\", function() { return __wbindgen_throw; });\n/* harmony import */ var _mapgen_demo_bg_wasm__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./mapgen_demo_bg.wasm */ \"../pkg/mapgen_demo_bg.wasm\");\n\n\nconst heap = new Array(32).fill(undefined);\n\nheap.push(undefined, null, true, false);\n\nfunction getObject(idx) { return heap[idx]; }\n\nlet heap_next = heap.length;\n\nfunction dropObject(idx) {\n if (idx < 36) return;\n heap[idx] = heap_next;\n heap_next = idx;\n}\n\nfunction takeObject(idx) {\n const ret = getObject(idx);\n dropObject(idx);\n return ret;\n}\n\nconst lTextDecoder = typeof TextDecoder === 'undefined' ? (0, module.require)('util').TextDecoder : TextDecoder;\n\nlet cachedTextDecoder = new lTextDecoder('utf-8', { ignoreBOM: true, fatal: true });\n\ncachedTextDecoder.decode();\n\nlet cachegetUint8Memory0 = null;\nfunction getUint8Memory0() {\n if (cachegetUint8Memory0 === null || cachegetUint8Memory0.buffer !== _mapgen_demo_bg_wasm__WEBPACK_IMPORTED_MODULE_0__[\"memory\"].buffer) {\n cachegetUint8Memory0 = new Uint8Array(_mapgen_demo_bg_wasm__WEBPACK_IMPORTED_MODULE_0__[\"memory\"].buffer);\n }\n return cachegetUint8Memory0;\n}\n\nfunction getStringFromWasm0(ptr, len) {\n return cachedTextDecoder.decode(getUint8Memory0().subarray(ptr, ptr + len));\n}\n\nfunction addHeapObject(obj) {\n if (heap_next === heap.length) heap.push(heap.length + 1);\n const idx = heap_next;\n heap_next = heap[idx];\n\n heap[idx] = obj;\n return idx;\n}\n/**\n*/\nclass World {\n\n static __wrap(ptr) {\n const obj = Object.create(World.prototype);\n obj.ptr = ptr;\n\n return obj;\n }\n\n free() {\n const ptr = this.ptr;\n this.ptr = 0;\n\n _mapgen_demo_bg_wasm__WEBPACK_IMPORTED_MODULE_0__[\"__wbg_world_free\"](ptr);\n }\n /**\n * @param {number} width\n * @param {number} height\n * @returns {World}\n */\n static new(width, height) {\n var ret = _mapgen_demo_bg_wasm__WEBPACK_IMPORTED_MODULE_0__[\"world_new\"](width, height);\n return World.__wrap(ret);\n }\n /**\n * @returns {number}\n */\n width() {\n var ret = _mapgen_demo_bg_wasm__WEBPACK_IMPORTED_MODULE_0__[\"world_width\"](this.ptr);\n return ret >>> 0;\n }\n /**\n * @returns {number}\n */\n height() {\n var ret = _mapgen_demo_bg_wasm__WEBPACK_IMPORTED_MODULE_0__[\"world_height\"](this.ptr);\n return ret >>> 0;\n }\n /**\n * @returns {number}\n */\n tiles() {\n var ret = _mapgen_demo_bg_wasm__WEBPACK_IMPORTED_MODULE_0__[\"world_tiles\"](this.ptr);\n return ret;\n }\n}\n\nconst __wbindgen_object_drop_ref = function(arg0) {\n takeObject(arg0);\n};\n\nconst __wbg_getTime_29addd71c7089c47 = function(arg0) {\n var ret = getObject(arg0).getTime();\n return ret;\n};\n\nconst __wbg_new0_a3af66503e735141 = function() {\n var ret = new Date();\n return addHeapObject(ret);\n};\n\nconst __wbindgen_throw = function(arg0, arg1) {\n throw new Error(getStringFromWasm0(arg0, arg1));\n};\n\n\n/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(/*! ./../www/node_modules/webpack/buildin/harmony-module.js */ \"./node_modules/webpack/buildin/harmony-module.js\")(module)))\n\n//# sourceURL=webpack:///../pkg/mapgen_demo_bg.js?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* WEBPACK VAR INJECTION */(function(module) {/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"Cell\", function() { return Cell; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"World\", function() { return World; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"__wbindgen_throw\", function() { return __wbindgen_throw; });\n/* harmony import */ var _mapgen_demo_bg_wasm__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./mapgen_demo_bg.wasm */ \"../pkg/mapgen_demo_bg.wasm\");\n\n\nconst lTextDecoder = typeof TextDecoder === 'undefined' ? (0, module.require)('util').TextDecoder : TextDecoder;\n\nlet cachedTextDecoder = new lTextDecoder('utf-8', { ignoreBOM: true, fatal: true });\n\ncachedTextDecoder.decode();\n\nlet cachegetUint8Memory0 = null;\nfunction getUint8Memory0() {\n if (cachegetUint8Memory0 === null || cachegetUint8Memory0.buffer !== _mapgen_demo_bg_wasm__WEBPACK_IMPORTED_MODULE_0__[\"memory\"].buffer) {\n cachegetUint8Memory0 = new Uint8Array(_mapgen_demo_bg_wasm__WEBPACK_IMPORTED_MODULE_0__[\"memory\"].buffer);\n }\n return cachegetUint8Memory0;\n}\n\nfunction getStringFromWasm0(ptr, len) {\n return cachedTextDecoder.decode(getUint8Memory0().subarray(ptr, ptr + len));\n}\n/**\n*/\nconst Cell = Object.freeze({ Floor:0,\"0\":\"Floor\",Wall:1,\"1\":\"Wall\", });\n/**\n*/\nclass World {\n\n static __wrap(ptr) {\n const obj = Object.create(World.prototype);\n obj.ptr = ptr;\n\n return obj;\n }\n\n free() {\n const ptr = this.ptr;\n this.ptr = 0;\n\n _mapgen_demo_bg_wasm__WEBPACK_IMPORTED_MODULE_0__[\"__wbg_world_free\"](ptr);\n }\n /**\n * @param {number} width\n * @param {number} height\n * @param {number} seed\n * @returns {World}\n */\n static new_cellular_automata(width, height, seed) {\n var ret = _mapgen_demo_bg_wasm__WEBPACK_IMPORTED_MODULE_0__[\"world_new_cellular_automata\"](width, height, seed);\n return World.__wrap(ret);\n }\n /**\n * @param {number} width\n * @param {number} height\n * @param {number} seed\n * @returns {World}\n */\n static new_random_rooms(width, height, seed) {\n var ret = _mapgen_demo_bg_wasm__WEBPACK_IMPORTED_MODULE_0__[\"world_new_random_rooms\"](width, height, seed);\n return World.__wrap(ret);\n }\n /**\n * @returns {number}\n */\n width() {\n var ret = _mapgen_demo_bg_wasm__WEBPACK_IMPORTED_MODULE_0__[\"world_width\"](this.ptr);\n return ret >>> 0;\n }\n /**\n * @returns {number}\n */\n height() {\n var ret = _mapgen_demo_bg_wasm__WEBPACK_IMPORTED_MODULE_0__[\"world_height\"](this.ptr);\n return ret >>> 0;\n }\n /**\n * @returns {number}\n */\n tiles() {\n var ret = _mapgen_demo_bg_wasm__WEBPACK_IMPORTED_MODULE_0__[\"world_tiles\"](this.ptr);\n return ret;\n }\n}\n\nconst __wbindgen_throw = function(arg0, arg1) {\n throw new Error(getStringFromWasm0(arg0, arg1));\n};\n\n\n/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(/*! ./../www/node_modules/webpack/buildin/harmony-module.js */ \"./node_modules/webpack/buildin/harmony-module.js\")(module)))\n\n//# sourceURL=webpack:///../pkg/mapgen_demo_bg.js?"); /***/ }), @@ -28,7 +28,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* WEBPACK VAR INJECTION */(f /*!**********************************!*\ !*** ../pkg/mapgen_demo_bg.wasm ***! \**********************************/ -/*! exports provided: memory, __wbg_world_free, world_new, world_width, world_height, world_tiles */ +/*! exports provided: memory, __wbg_world_free, world_new_cellular_automata, world_new_random_rooms, world_width, world_height, world_tiles */ /***/ (function(module, exports, __webpack_require__) { eval("\"use strict\";\n// Instantiate WebAssembly module\nvar wasmExports = __webpack_require__.w[module.i];\n__webpack_require__.r(exports);\n// export exports from WebAssembly module\nfor(var name in wasmExports) if(name != \"__webpack_init__\") exports[name] = wasmExports[name];\n// exec imports from WebAssembly module (for esm order)\n/* harmony import */ var m0 = __webpack_require__(/*! ./mapgen_demo_bg.js */ \"../pkg/mapgen_demo_bg.js\");\n\n\n// exec wasm module\nwasmExports[\"__webpack_init__\"]()\n\n//# sourceURL=webpack:///../pkg/mapgen_demo_bg.wasm?"); @@ -43,7 +43,7 @@ eval("\"use strict\";\n// Instantiate WebAssembly module\nvar wasmExports = __we /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var mapgen_demo__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! mapgen-demo */ \"../pkg/mapgen_demo.js\");\n/* harmony import */ var mapgen_demo_mapgen_demo_bg__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! mapgen-demo/mapgen_demo_bg */ \"../pkg/mapgen_demo_bg.wasm\");\n\n\n\nconst CELL_SIZE = 12;\nconst GRID_COLOR = \"#CCCCCC\";\nconst DEAD_COLOR = \"#FFFFFF\";\nconst ALIVE_COLOR = \"#000000\";\n\nconst world = mapgen_demo__WEBPACK_IMPORTED_MODULE_0__[\"World\"].new(80, 50);\nconst width = world.width();\nconst height = world.height();\n\n// Give the canvas room for all of our cells and a 1px border\n// around each of them.\nconst canvas = document.getElementById(\"mapgen-canvas\");\ncanvas.height = (CELL_SIZE + 1) * height + 1;\ncanvas.width = (CELL_SIZE + 1) * width + 1;\n\nconst ctx = canvas.getContext('2d');\n\nconst renderLoop = () => {\n // universe.tick();\n\n drawGrid();\n drawCells();\n\n requestAnimationFrame(renderLoop);\n};\n\nconst drawGrid = () => {\n ctx.beginPath();\n ctx.strokeStyle = GRID_COLOR;\n\n // Vertical lines.\n for (let i = 0; i <= width; i++) {\n ctx.moveTo(i * (CELL_SIZE + 1) + 1, 0);\n ctx.lineTo(i * (CELL_SIZE + 1) + 1, (CELL_SIZE + 1) * height + 1);\n }\n\n // Horizontal lines.\n for (let j = 0; j <= height; j++) {\n ctx.moveTo(0, j * (CELL_SIZE + 1) + 1);\n ctx.lineTo((CELL_SIZE + 1) * width + 1, j * (CELL_SIZE + 1) + 1);\n }\n\n ctx.stroke();\n};\n\nconst getIndex = (row, column) => {\n return row * width + column;\n};\n\nconst drawCells = () => {\n const tilesPtr = world.tiles();\n const tiles = new Uint8Array(mapgen_demo_mapgen_demo_bg__WEBPACK_IMPORTED_MODULE_1__[\"memory\"].buffer, tilesPtr, width * height);\n\n ctx.beginPath();\n\n for (let row = 0; row < height; row++) {\n for (let col = 0; col < width; col++) {\n const idx = getIndex(row, col);\n\n ctx.fillStyle = tiles[idx]\n ? DEAD_COLOR\n : ALIVE_COLOR;\n\n ctx.fillRect(\n col * (CELL_SIZE + 1) + 1,\n row * (CELL_SIZE + 1) + 1,\n CELL_SIZE,\n CELL_SIZE\n );\n }\n }\n\n ctx.stroke();\n};\n\ndrawGrid();\ndrawCells();\nrequestAnimationFrame(renderLoop);\n\n//# sourceURL=webpack:///./index.js?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var mapgen_demo__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! mapgen-demo */ \"../pkg/mapgen_demo.js\");\n/* harmony import */ var mapgen_demo_mapgen_demo_bg__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! mapgen-demo/mapgen_demo_bg */ \"../pkg/mapgen_demo_bg.wasm\");\n\n\n\nconst CELL_SIZE = 12;\nconst GRID_COLOR = \"#CCCCCC\";\nconst DEAD_COLOR = \"#FFFFFF\";\nconst ALIVE_COLOR = \"#000000\";\n\nvar world = null;\nconst width = 80;\nconst height = 50;\n\nconst infoDiv = document.getElementById('map-info');\n// Give the canvas room for all of our cells and a 1px border\n// around each of them.\nconst canvas = document.getElementById(\"mapgen-canvas\");\ncanvas.height = (CELL_SIZE + 1) * height + 1;\ncanvas.width = (CELL_SIZE + 1) * width + 1;\n\nconst ctx = canvas.getContext('2d');\n\n// Map generators\nfunction newCellularAutomata() {\n var seed = Date.now();\n world = mapgen_demo__WEBPACK_IMPORTED_MODULE_0__[\"World\"].new_cellular_automata(width, height, seed);\n requestAnimationFrame(renderLoop);\n infoDiv.textContent = \"Cellular Automata with the seed: \" + seed;\n}\n\nfunction newSimpleRooms() {\n var seed = Date.now();\n world = mapgen_demo__WEBPACK_IMPORTED_MODULE_0__[\"World\"].new_random_rooms(width, height, seed);\n requestAnimationFrame(renderLoop);\n infoDiv.textContent = \"Random Rooms with the seed: \" + seed;\n}\n\nconst renderLoop = () => {\n // universe.tick();\n\n drawGrid();\n drawCells();\n\n requestAnimationFrame(renderLoop);\n};\n\nconst drawGrid = () => {\n ctx.beginPath();\n ctx.strokeStyle = GRID_COLOR;\n\n // Vertical lines.\n for (let i = 0; i <= width; i++) {\n ctx.moveTo(i * (CELL_SIZE + 1) + 1, 0);\n ctx.lineTo(i * (CELL_SIZE + 1) + 1, (CELL_SIZE + 1) * height + 1);\n }\n\n // Horizontal lines.\n for (let j = 0; j <= height; j++) {\n ctx.moveTo(0, j * (CELL_SIZE + 1) + 1);\n ctx.lineTo((CELL_SIZE + 1) * width + 1, j * (CELL_SIZE + 1) + 1);\n }\n\n ctx.stroke();\n};\n\nconst getIndex = (row, column) => {\n return row * width + column;\n};\n\nconst drawCells = () => {\n const tilesPtr = world.tiles();\n const tiles = new Uint8Array(mapgen_demo_mapgen_demo_bg__WEBPACK_IMPORTED_MODULE_1__[\"memory\"].buffer, tilesPtr, width * height);\n\n ctx.beginPath();\n\n for (let row = 0; row < height; row++) {\n for (let col = 0; col < width; col++) {\n const idx = getIndex(row, col);\n\n ctx.fillStyle = tiles[idx] == mapgen_demo__WEBPACK_IMPORTED_MODULE_0__[\"Cell\"].Floor\n ? DEAD_COLOR\n : ALIVE_COLOR;\n\n ctx.fillRect(\n col * (CELL_SIZE + 1) + 1,\n row * (CELL_SIZE + 1) + 1,\n CELL_SIZE,\n CELL_SIZE\n );\n }\n }\n\n ctx.stroke();\n};\n\nnewCellularAutomata();\n\n// Connect UI element\ndocument.getElementById('cellular-automata-option').addEventListener('click', newCellularAutomata);\ndocument.getElementById('simple-rooms-option').addEventListener('click', newSimpleRooms);\n\n\n//# sourceURL=webpack:///./index.js?"); /***/ }), diff --git a/docs/bbf7fe2631d06e11148e.module.wasm b/docs/bbf7fe2631d06e11148e.module.wasm new file mode 100644 index 0000000..9582c05 Binary files /dev/null and b/docs/bbf7fe2631d06e11148e.module.wasm differ diff --git a/docs/bootstrap.js b/docs/bootstrap.js index a792eb6..cbda51c 100644 --- a/docs/bootstrap.js +++ b/docs/bootstrap.js @@ -55,15 +55,6 @@ /******/ "../pkg/mapgen_demo_bg.wasm": function() { /******/ return { /******/ "./mapgen_demo_bg.js": { -/******/ "__wbindgen_object_drop_ref": function(p0i32) { -/******/ return installedModules["../pkg/mapgen_demo_bg.js"].exports["__wbindgen_object_drop_ref"](p0i32); -/******/ }, -/******/ "__wbg_getTime_29addd71c7089c47": function(p0i32) { -/******/ return installedModules["../pkg/mapgen_demo_bg.js"].exports["__wbg_getTime_29addd71c7089c47"](p0i32); -/******/ }, -/******/ "__wbg_new0_a3af66503e735141": function() { -/******/ return installedModules["../pkg/mapgen_demo_bg.js"].exports["__wbg_new0_a3af66503e735141"](); -/******/ }, /******/ "__wbindgen_throw": function(p0i32,p1i32) { /******/ return installedModules["../pkg/mapgen_demo_bg.js"].exports["__wbindgen_throw"](p0i32,p1i32); /******/ } @@ -168,7 +159,7 @@ /******/ promises.push(installedWasmModuleData); /******/ else { /******/ var importObject = wasmImportObjects[wasmModuleId](); -/******/ var req = fetch(__webpack_require__.p + "" + {"../pkg/mapgen_demo_bg.wasm":"bf853f7fb17b7aed38db"}[wasmModuleId] + ".module.wasm"); +/******/ var req = fetch(__webpack_require__.p + "" + {"../pkg/mapgen_demo_bg.wasm":"bbf7fe2631d06e11148e"}[wasmModuleId] + ".module.wasm"); /******/ var promise; /******/ if(importObject instanceof Promise && typeof WebAssembly.compileStreaming === 'function') { /******/ promise = Promise.all([WebAssembly.compileStreaming(req), importObject]).then(function(items) { diff --git a/docs/index.html b/docs/index.html index 80e6e05..07d6fec 100644 --- a/docs/index.html +++ b/docs/index.html @@ -3,11 +3,54 @@ Mapgen demo + + + -

Mapgen demo

+ + - - +
+ + + + diff --git a/src/common/geometry.rs b/src/common/geometry.rs index 9895121..57d8715 100644 --- a/src/common/geometry.rs +++ b/src/common/geometry.rs @@ -14,6 +14,11 @@ impl Point { Point {x, y} } + /// Create new point from i32 coords + pub fn new_i32(x: i32, y: i32) -> Point { + Point::new(x as usize, y as usize) + } + /// Euclidean distance to a given point pub fn distance_to(self, point: &Point) -> f32 { let a = (self.x as f32 - point.x as f32).powf(2.0); @@ -41,8 +46,8 @@ impl Rect { self.x1 <= other.x2 && self.x2 >= other.x1 && self.y1 <= other.y2 && self.y2 >= other.y1 } - pub fn center(&self) -> (i32, i32) { - ((self.x1 + self.x2)/2, (self.y1 + self.y2)/2) + pub fn center(&self) -> Point { + Point::new_i32((self.x1 + self.x2)/2, (self.y1 + self.y2)/2) } } diff --git a/src/dungeon/map.rs b/src/dungeon/map.rs index e0830fc..415fcaf 100644 --- a/src/dungeon/map.rs +++ b/src/dungeon/map.rs @@ -23,7 +23,9 @@ pub struct Map { pub width : usize, pub height : usize, pub starting_point: Option, - pub exit_point: Option + pub exit_point: Option, + pub rooms: Vec, + pub corridors: Vec>, } impl Map { @@ -37,6 +39,8 @@ impl Map { height, starting_point: None, exit_point: None, + rooms: Vec::new(), + corridors: Vec::new() } } @@ -105,12 +109,36 @@ impl Map { /// Create room on the map at given location /// Room is created by setting all tiles in the room to the Floor - pub fn create_room(&mut self, rect: &Rect) { + pub fn add_room(&mut self, rect: Rect) { for x in rect.x1..rect.x2 { for y in rect.y1..rect.y2 { self.set_tile(x as usize, y as usize, TileType::Floor); } } + self.rooms.push(rect); + } + + pub fn add_corridor(&mut self, from: Point, to:Point) { + let mut corridor = Vec::new(); + let mut x = from.x; + let mut y = from.y; + + while x != to.x || y != to.y { + if x < to.x { + x += 1; + } else if x > to.x { + x -= 1; + } else if y < to.y { + y += 1; + } else if y > to.y { + y -= 1; + } + + if self.at(x, y) != TileType::Floor { + corridor.push(Point::new(x, y)); + self.set_tile(x, y, TileType::Floor); + } + } } } @@ -183,7 +211,7 @@ mod tests { #[test] fn test_create_room() { let mut map = Map::new(5, 5); - map.create_room(&Rect::new(1, 1, 3, 3)); + map.add_room(Rect::new(1, 1, 3, 3)); for x in 0..map.width { for y in 0..map.height { if x == 0 || y == 0 || x == 4 || y == 4 { @@ -195,4 +223,23 @@ mod tests { } } + #[test] + fn test_add_corridor() { + let map_str = " + ########## + # # # + ########## + "; + let mut map = Map::from_string(map_str); + let expected_map_str = " + ########## + # # + ########## + "; + let expected_map = Map::from_string(expected_map_str); + + map.add_corridor(Point::new(1, 1), Point::new(8, 1)); + + assert_eq!(map.tiles, expected_map.tiles); + } } \ No newline at end of file diff --git a/src/dungeon/mod.rs b/src/dungeon/mod.rs index b834d88..96ca7a1 100644 --- a/src/dungeon/mod.rs +++ b/src/dungeon/mod.rs @@ -31,6 +31,7 @@ pub mod cellular_automata; pub mod cull_unreachable; pub mod distant_exit; pub mod random_rooms; +pub mod rooms_corridors_nearest; pub mod starting_point; mod dijkstra; diff --git a/src/dungeon/random_rooms.rs b/src/dungeon/random_rooms.rs index 65dc527..0b0e84d 100644 --- a/src/dungeon/random_rooms.rs +++ b/src/dungeon/random_rooms.rs @@ -50,7 +50,6 @@ impl RandomRoomsGen { fn build_rooms(&self, width: usize, height: usize, rng : &mut StdRng) -> Map { let mut map = Map::new(width, height); - let mut rooms : Vec = Vec::new(); // Create room dimensions for _ in 0..self.max_rooms { @@ -59,16 +58,11 @@ impl RandomRoomsGen { let x = random::random_range(rng, 1, width - w); let y = random::random_range(rng, 1, height - h); let new_room = Rect::new(x as i32, y as i32, w as i32, h as i32); - let intersects = rooms.iter().any(|r| new_room.intersect(r)); + let intersects = map.rooms.iter().any(|r| new_room.intersect(r)); if !intersects { - rooms.push(new_room); + map.add_room(new_room); } } - - // Apply rooms to the map - for room in rooms { - map.create_room(&room); - } map } diff --git a/src/dungeon/rooms_corridors_nearest.rs b/src/dungeon/rooms_corridors_nearest.rs new file mode 100644 index 0000000..abdaa46 --- /dev/null +++ b/src/dungeon/rooms_corridors_nearest.rs @@ -0,0 +1,47 @@ +//! Connect nearest rooms on the map with corridors +//! +use rand::prelude::StdRng; +use super::MapModifier; +use super::map::Map; +use std::collections::HashSet; + + +pub struct NearestCorridors {} + +impl MapModifier for NearestCorridors { + fn modify_map(&self, _: &mut StdRng, map: &Map) -> Map { + self.corridors(map) + } +} + +impl NearestCorridors { + + pub fn new() -> Box { + Box::new(NearestCorridors{}) + } + + fn corridors(&self, map: &Map) -> Map { + let mut new_map = map.clone(); + + let mut connected : HashSet = HashSet::new(); + for (i,room) in map.rooms.iter().enumerate() { + let mut room_distance : Vec<(usize, f32)> = Vec::new(); + let room_center = room.center(); + for (j,other_room) in new_map.rooms.iter().enumerate() { + if i != j && !connected.contains(&j) { + let other_center = other_room.center(); + let distance = room_center.distance_to(&other_center); + room_distance.push((j, distance)); + } + } + + if !room_distance.is_empty() { + room_distance.sort_by(|a,b| a.1.partial_cmp(&b.1).unwrap() ); + let dest_center = new_map.rooms[room_distance[0].0].center(); + new_map.add_corridor(room_center, dest_center); + connected.insert(i); + } + } + new_map + } +} \ No newline at end of file