From 3b081668678f54934b945a0a65af44d4265b08e5 Mon Sep 17 00:00:00 2001 From: klangner Date: Tue, 15 Sep 2020 22:33:18 +0200 Subject: [PATCH] bsp interior --- Cargo.toml | 2 +- README.md | 2 +- demo/src/lib.rs | 11 ++- demo/www/index.html | 2 +- demo/www/index.js | 6 +- docs/0.bootstrap.js | 23 ++++-- docs/bootstrap.js | 65 +++++++++++++++- docs/cbb67d3121ca19dbc9af.module.wasm | Bin 0 -> 94179 bytes docs/index.html | 4 +- src/common/geometry.rs | 40 ++++++++-- src/common/random.rs | 59 +++++++++++--- src/dungeon/bsp_interior.rs | 108 ++++++++++++++++++++++++++ src/dungeon/bsp_rooms.rs | 34 ++++---- src/dungeon/mod.rs | 1 + src/dungeon/simple_rooms.rs | 12 +-- 15 files changed, 308 insertions(+), 61 deletions(-) create mode 100644 docs/cbb67d3121ca19dbc9af.module.wasm create mode 100644 src/dungeon/bsp_interior.rs diff --git a/Cargo.toml b/Cargo.toml index ff44a43..98116ac 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mapgen" -version = "0.2.1" +version = "0.3.0" authors = ["Krzysztof Langner "] description = "Map generator for games (dungeons, worlds etc.)" keywords = ["game", "map", "map-generator"] diff --git a/README.md b/README.md index a3ee855..0320b6e 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ Generate procedural maps for games. [Try it in the browser](https://klangner.git ### Dungeons * Map generators - * [ ] BSP Interior + * [x] BSP Interior * [x] BSP Rooms * [x] Cellular automata * [ ] Diffusion-Limited Aggregation (DLA) diff --git a/demo/src/lib.rs b/demo/src/lib.rs index 3e25a78..d3cc4d8 100644 --- a/demo/src/lib.rs +++ b/demo/src/lib.rs @@ -6,7 +6,7 @@ use mapgen::dungeon::{ map::TileType, cellular_automata::CellularAutomataGen, simple_rooms::SimpleRoomsGen, - bsp_rooms::BspRoomsGen, + bsp_interior::BspInteriorGen, starting_point::{AreaStartingPosition, XStart, YStart}, cull_unreachable::CullUnreachable, distant_exit::DistantExit, @@ -64,11 +64,10 @@ impl World { tiles } } - pub fn new_bsp_rooms(width: u32, height: u32, seed: u32) -> World { - World::print_map_info(format!("BSP Rooms with the seed: {}", seed)); + pub fn new_bsp_interior(width: u32, height: u32, seed: u32) -> World { + World::print_map_info(format!("BSP Interior with the seed: {}", seed)); let mut rng = StdRng::seed_from_u64(seed as u64); - let map = MapBuilder::new(BspRoomsGen::new()) - .with(NearestCorridors::new()) + let map = MapBuilder::new(BspInteriorGen::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}) @@ -87,7 +86,7 @@ impl World { } else if px < 0.6666 { World::new_simple_rooms(width, height, seed) } else { - World::new_bsp_rooms(width, height, seed) + World::new_bsp_interior(width, height, seed) } } diff --git a/demo/www/index.html b/demo/www/index.html index 0b9200a..2426dee 100644 --- a/demo/www/index.html +++ b/demo/www/index.html @@ -37,7 +37,7 @@ diff --git a/demo/www/index.js b/demo/www/index.js index d1ff6f2..5b973b9 100644 --- a/demo/www/index.js +++ b/demo/www/index.js @@ -32,9 +32,9 @@ function newSimpleRooms() { requestAnimationFrame(renderLoop); } -function newBspRooms() { +function newBspInterior() { var seed = Date.now(); - world = World.new_bsp_rooms(width, height, seed); + world = World.new_bsp_interior(width, height, seed); requestAnimationFrame(renderLoop); } @@ -107,5 +107,5 @@ newRandomGen(); // Connect UI element document.getElementById('cellular-automata-option').addEventListener('click', newCellularAutomata); document.getElementById('simple-rooms-option').addEventListener('click', newSimpleRooms); -document.getElementById('bsp-rooms-option').addEventListener('click', newBspRooms); +document.getElementById('bsp-interior-option').addEventListener('click', newBspInterior); document.getElementById('random-option').addEventListener('click', newRandomGen); diff --git a/docs/0.bootstrap.js b/docs/0.bootstrap.js index 18d39ea..3024424 100644 --- a/docs/0.bootstrap.js +++ b/docs/0.bootstrap.js @@ -4,11 +4,11 @@ /*!*****************************!*\ !*** ../pkg/mapgen_demo.js ***! \*****************************/ -/*! exports provided: Cell, World, __wbindgen_throw */ +/*! exports provided: Cell, World, __wbindgen_object_drop_ref, __wbg_getRandomValues_3ac1b33c90b52596, __wbg_randomFillSync_6f956029658662ec, __wbg_self_1c83eb4471d9eb9b, __wbg_static_accessor_MODULE_abf5ae284bffdf45, __wbg_require_5b2b5b594d809d9f, __wbg_crypto_c12f14e810edcaa2, __wbg_msCrypto_679be765111ba775, __wbindgen_is_undefined, __wbg_getRandomValues_05a60bf171bfc2be, __wbg_instanceof_Window_adf3196bdc02b386, __wbg_document_6cc8d0b87c0a99b9, __wbg_getElementById_0cb6ad9511b1efc0, __wbg_setinnerHTML_4ff235db1a3cb4d8, __wbg_call_8e95613cc6524977, __wbindgen_object_clone_ref, __wbg_newnoargs_f3b8a801d5d4b079, __wbg_self_07b2f89e82ceb76d, __wbg_window_ba85d88572adc0dc, __wbg_globalThis_b9277fc37e201fe5, __wbg_global_e16303fe83e1d57f, __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__, \"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?"); +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_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_getRandomValues_3ac1b33c90b52596\", function() { return _mapgen_demo_bg_js__WEBPACK_IMPORTED_MODULE_1__[\"__wbg_getRandomValues_3ac1b33c90b52596\"]; });\n\n/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, \"__wbg_randomFillSync_6f956029658662ec\", function() { return _mapgen_demo_bg_js__WEBPACK_IMPORTED_MODULE_1__[\"__wbg_randomFillSync_6f956029658662ec\"]; });\n\n/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, \"__wbg_self_1c83eb4471d9eb9b\", function() { return _mapgen_demo_bg_js__WEBPACK_IMPORTED_MODULE_1__[\"__wbg_self_1c83eb4471d9eb9b\"]; });\n\n/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, \"__wbg_static_accessor_MODULE_abf5ae284bffdf45\", function() { return _mapgen_demo_bg_js__WEBPACK_IMPORTED_MODULE_1__[\"__wbg_static_accessor_MODULE_abf5ae284bffdf45\"]; });\n\n/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, \"__wbg_require_5b2b5b594d809d9f\", function() { return _mapgen_demo_bg_js__WEBPACK_IMPORTED_MODULE_1__[\"__wbg_require_5b2b5b594d809d9f\"]; });\n\n/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, \"__wbg_crypto_c12f14e810edcaa2\", function() { return _mapgen_demo_bg_js__WEBPACK_IMPORTED_MODULE_1__[\"__wbg_crypto_c12f14e810edcaa2\"]; });\n\n/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, \"__wbg_msCrypto_679be765111ba775\", function() { return _mapgen_demo_bg_js__WEBPACK_IMPORTED_MODULE_1__[\"__wbg_msCrypto_679be765111ba775\"]; });\n\n/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, \"__wbindgen_is_undefined\", function() { return _mapgen_demo_bg_js__WEBPACK_IMPORTED_MODULE_1__[\"__wbindgen_is_undefined\"]; });\n\n/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, \"__wbg_getRandomValues_05a60bf171bfc2be\", function() { return _mapgen_demo_bg_js__WEBPACK_IMPORTED_MODULE_1__[\"__wbg_getRandomValues_05a60bf171bfc2be\"]; });\n\n/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, \"__wbg_instanceof_Window_adf3196bdc02b386\", function() { return _mapgen_demo_bg_js__WEBPACK_IMPORTED_MODULE_1__[\"__wbg_instanceof_Window_adf3196bdc02b386\"]; });\n\n/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, \"__wbg_document_6cc8d0b87c0a99b9\", function() { return _mapgen_demo_bg_js__WEBPACK_IMPORTED_MODULE_1__[\"__wbg_document_6cc8d0b87c0a99b9\"]; });\n\n/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, \"__wbg_getElementById_0cb6ad9511b1efc0\", function() { return _mapgen_demo_bg_js__WEBPACK_IMPORTED_MODULE_1__[\"__wbg_getElementById_0cb6ad9511b1efc0\"]; });\n\n/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, \"__wbg_setinnerHTML_4ff235db1a3cb4d8\", function() { return _mapgen_demo_bg_js__WEBPACK_IMPORTED_MODULE_1__[\"__wbg_setinnerHTML_4ff235db1a3cb4d8\"]; });\n\n/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, \"__wbg_call_8e95613cc6524977\", function() { return _mapgen_demo_bg_js__WEBPACK_IMPORTED_MODULE_1__[\"__wbg_call_8e95613cc6524977\"]; });\n\n/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, \"__wbindgen_object_clone_ref\", function() { return _mapgen_demo_bg_js__WEBPACK_IMPORTED_MODULE_1__[\"__wbindgen_object_clone_ref\"]; });\n\n/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, \"__wbg_newnoargs_f3b8a801d5d4b079\", function() { return _mapgen_demo_bg_js__WEBPACK_IMPORTED_MODULE_1__[\"__wbg_newnoargs_f3b8a801d5d4b079\"]; });\n\n/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, \"__wbg_self_07b2f89e82ceb76d\", function() { return _mapgen_demo_bg_js__WEBPACK_IMPORTED_MODULE_1__[\"__wbg_self_07b2f89e82ceb76d\"]; });\n\n/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, \"__wbg_window_ba85d88572adc0dc\", function() { return _mapgen_demo_bg_js__WEBPACK_IMPORTED_MODULE_1__[\"__wbg_window_ba85d88572adc0dc\"]; });\n\n/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, \"__wbg_globalThis_b9277fc37e201fe5\", function() { return _mapgen_demo_bg_js__WEBPACK_IMPORTED_MODULE_1__[\"__wbg_globalThis_b9277fc37e201fe5\"]; });\n\n/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, \"__wbg_global_e16303fe83e1d57f\", function() { return _mapgen_demo_bg_js__WEBPACK_IMPORTED_MODULE_1__[\"__wbg_global_e16303fe83e1d57f\"]; });\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: Cell, World, __wbindgen_throw */ +/*! exports provided: Cell, World, __wbindgen_object_drop_ref, __wbg_getRandomValues_3ac1b33c90b52596, __wbg_randomFillSync_6f956029658662ec, __wbg_self_1c83eb4471d9eb9b, __wbg_static_accessor_MODULE_abf5ae284bffdf45, __wbg_require_5b2b5b594d809d9f, __wbg_crypto_c12f14e810edcaa2, __wbg_msCrypto_679be765111ba775, __wbindgen_is_undefined, __wbg_getRandomValues_05a60bf171bfc2be, __wbg_instanceof_Window_adf3196bdc02b386, __wbg_document_6cc8d0b87c0a99b9, __wbg_getElementById_0cb6ad9511b1efc0, __wbg_setinnerHTML_4ff235db1a3cb4d8, __wbg_call_8e95613cc6524977, __wbindgen_object_clone_ref, __wbg_newnoargs_f3b8a801d5d4b079, __wbg_self_07b2f89e82ceb76d, __wbg_window_ba85d88572adc0dc, __wbg_globalThis_b9277fc37e201fe5, __wbg_global_e16303fe83e1d57f, __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__, \"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?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* WEBPACK VAR INJECTION */(function(module, global) {/* 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_object_drop_ref\", function() { return __wbindgen_object_drop_ref; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"__wbg_getRandomValues_3ac1b33c90b52596\", function() { return __wbg_getRandomValues_3ac1b33c90b52596; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"__wbg_randomFillSync_6f956029658662ec\", function() { return __wbg_randomFillSync_6f956029658662ec; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"__wbg_self_1c83eb4471d9eb9b\", function() { return __wbg_self_1c83eb4471d9eb9b; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"__wbg_static_accessor_MODULE_abf5ae284bffdf45\", function() { return __wbg_static_accessor_MODULE_abf5ae284bffdf45; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"__wbg_require_5b2b5b594d809d9f\", function() { return __wbg_require_5b2b5b594d809d9f; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"__wbg_crypto_c12f14e810edcaa2\", function() { return __wbg_crypto_c12f14e810edcaa2; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"__wbg_msCrypto_679be765111ba775\", function() { return __wbg_msCrypto_679be765111ba775; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"__wbindgen_is_undefined\", function() { return __wbindgen_is_undefined; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"__wbg_getRandomValues_05a60bf171bfc2be\", function() { return __wbg_getRandomValues_05a60bf171bfc2be; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"__wbg_instanceof_Window_adf3196bdc02b386\", function() { return __wbg_instanceof_Window_adf3196bdc02b386; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"__wbg_document_6cc8d0b87c0a99b9\", function() { return __wbg_document_6cc8d0b87c0a99b9; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"__wbg_getElementById_0cb6ad9511b1efc0\", function() { return __wbg_getElementById_0cb6ad9511b1efc0; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"__wbg_setinnerHTML_4ff235db1a3cb4d8\", function() { return __wbg_setinnerHTML_4ff235db1a3cb4d8; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"__wbg_call_8e95613cc6524977\", function() { return __wbg_call_8e95613cc6524977; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"__wbindgen_object_clone_ref\", function() { return __wbindgen_object_clone_ref; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"__wbg_newnoargs_f3b8a801d5d4b079\", function() { return __wbg_newnoargs_f3b8a801d5d4b079; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"__wbg_self_07b2f89e82ceb76d\", function() { return __wbg_self_07b2f89e82ceb76d; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"__wbg_window_ba85d88572adc0dc\", function() { return __wbg_window_ba85d88572adc0dc; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"__wbg_globalThis_b9277fc37e201fe5\", function() { return __wbg_globalThis_b9277fc37e201fe5; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"__wbg_global_e16303fe83e1d57f\", function() { return __wbg_global_e16303fe83e1d57f; });\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\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\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 handleError(f) {\n return function () {\n try {\n return f.apply(this, arguments);\n\n } catch (e) {\n _mapgen_demo_bg_wasm__WEBPACK_IMPORTED_MODULE_0__[\"__wbindgen_exn_store\"](addHeapObject(e));\n }\n };\n}\n\nfunction getArrayU8FromWasm0(ptr, len) {\n return getUint8Memory0().subarray(ptr / 1, ptr / 1 + len);\n}\n\nfunction isLikeNone(x) {\n return x === undefined || x === null;\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_simple_rooms(width, height, seed) {\n var ret = _mapgen_demo_bg_wasm__WEBPACK_IMPORTED_MODULE_0__[\"world_new_simple_rooms\"](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_bsp_interior(width, height, seed) {\n var ret = _mapgen_demo_bg_wasm__WEBPACK_IMPORTED_MODULE_0__[\"world_new_bsp_interior\"](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(width, height, seed) {\n var ret = _mapgen_demo_bg_wasm__WEBPACK_IMPORTED_MODULE_0__[\"world_new_random\"](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_object_drop_ref = function(arg0) {\n takeObject(arg0);\n};\n\nconst __wbg_getRandomValues_3ac1b33c90b52596 = function(arg0, arg1, arg2) {\n getObject(arg0).getRandomValues(getArrayU8FromWasm0(arg1, arg2));\n};\n\nconst __wbg_randomFillSync_6f956029658662ec = function(arg0, arg1, arg2) {\n getObject(arg0).randomFillSync(getArrayU8FromWasm0(arg1, arg2));\n};\n\nconst __wbg_self_1c83eb4471d9eb9b = handleError(function() {\n var ret = self.self;\n return addHeapObject(ret);\n});\n\nconst __wbg_static_accessor_MODULE_abf5ae284bffdf45 = function() {\n var ret = module;\n return addHeapObject(ret);\n};\n\nconst __wbg_require_5b2b5b594d809d9f = function(arg0, arg1, arg2) {\n var ret = getObject(arg0).require(getStringFromWasm0(arg1, arg2));\n return addHeapObject(ret);\n};\n\nconst __wbg_crypto_c12f14e810edcaa2 = function(arg0) {\n var ret = getObject(arg0).crypto;\n return addHeapObject(ret);\n};\n\nconst __wbg_msCrypto_679be765111ba775 = function(arg0) {\n var ret = getObject(arg0).msCrypto;\n return addHeapObject(ret);\n};\n\nconst __wbindgen_is_undefined = function(arg0) {\n var ret = getObject(arg0) === undefined;\n return ret;\n};\n\nconst __wbg_getRandomValues_05a60bf171bfc2be = function(arg0) {\n var ret = getObject(arg0).getRandomValues;\n return addHeapObject(ret);\n};\n\nconst __wbg_instanceof_Window_adf3196bdc02b386 = function(arg0) {\n var ret = getObject(arg0) instanceof Window;\n return ret;\n};\n\nconst __wbg_document_6cc8d0b87c0a99b9 = function(arg0) {\n var ret = getObject(arg0).document;\n return isLikeNone(ret) ? 0 : addHeapObject(ret);\n};\n\nconst __wbg_getElementById_0cb6ad9511b1efc0 = function(arg0, arg1, arg2) {\n var ret = getObject(arg0).getElementById(getStringFromWasm0(arg1, arg2));\n return isLikeNone(ret) ? 0 : addHeapObject(ret);\n};\n\nconst __wbg_setinnerHTML_4ff235db1a3cb4d8 = function(arg0, arg1, arg2) {\n getObject(arg0).innerHTML = getStringFromWasm0(arg1, arg2);\n};\n\nconst __wbg_call_8e95613cc6524977 = handleError(function(arg0, arg1) {\n var ret = getObject(arg0).call(getObject(arg1));\n return addHeapObject(ret);\n});\n\nconst __wbindgen_object_clone_ref = function(arg0) {\n var ret = getObject(arg0);\n return addHeapObject(ret);\n};\n\nconst __wbg_newnoargs_f3b8a801d5d4b079 = function(arg0, arg1) {\n var ret = new Function(getStringFromWasm0(arg0, arg1));\n return addHeapObject(ret);\n};\n\nconst __wbg_self_07b2f89e82ceb76d = handleError(function() {\n var ret = self.self;\n return addHeapObject(ret);\n});\n\nconst __wbg_window_ba85d88572adc0dc = handleError(function() {\n var ret = window.window;\n return addHeapObject(ret);\n});\n\nconst __wbg_globalThis_b9277fc37e201fe5 = handleError(function() {\n var ret = globalThis.globalThis;\n return addHeapObject(ret);\n});\n\nconst __wbg_global_e16303fe83e1d57f = handleError(function() {\n var ret = global.global;\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), __webpack_require__(/*! ./../www/node_modules/webpack/buildin/global.js */ \"./node_modules/webpack/buildin/global.js\")))\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_cellular_automata, world_new_random_rooms, world_width, world_height, world_tiles */ +/*! exports provided: memory, __wbg_world_free, world_new_cellular_automata, world_new_simple_rooms, world_new_bsp_interior, world_new_random, world_width, world_height, world_tiles, __wbindgen_exn_store */ /***/ (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,18 @@ 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\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?"); +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}\n\nfunction newSimpleRooms() {\n var seed = Date.now();\n world = mapgen_demo__WEBPACK_IMPORTED_MODULE_0__[\"World\"].new_simple_rooms(width, height, seed);\n requestAnimationFrame(renderLoop);\n}\n\nfunction newBspInterior() {\n var seed = Date.now();\n world = mapgen_demo__WEBPACK_IMPORTED_MODULE_0__[\"World\"].new_bsp_interior(width, height, seed);\n requestAnimationFrame(renderLoop);\n}\n\nfunction newRandomGen() {\n var seed = Date.now();\n world = mapgen_demo__WEBPACK_IMPORTED_MODULE_0__[\"World\"].new_random(width, height, seed);\n requestAnimationFrame(renderLoop);\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\nnewRandomGen();\n\n// Connect UI element\ndocument.getElementById('cellular-automata-option').addEventListener('click', newCellularAutomata);\ndocument.getElementById('simple-rooms-option').addEventListener('click', newSimpleRooms);\ndocument.getElementById('bsp-interior-option').addEventListener('click', newBspInterior);\ndocument.getElementById('random-option').addEventListener('click', newRandomGen);\n\n\n//# sourceURL=webpack:///./index.js?"); + +/***/ }), + +/***/ "./node_modules/webpack/buildin/global.js": +/*!***********************************!*\ + !*** (webpack)/buildin/global.js ***! + \***********************************/ +/*! no static exports found */ +/***/ (function(module, exports) { + +eval("var g;\n\n// This works in non-strict mode\ng = (function() {\n\treturn this;\n})();\n\ntry {\n\t// This works if eval is allowed (see CSP)\n\tg = g || new Function(\"return this\")();\n} catch (e) {\n\t// This works if the window reference is available\n\tif (typeof window === \"object\") g = window;\n}\n\n// g can still be undefined, but nothing to do about it...\n// We return undefined, instead of nothing here, so it's\n// easier to handle this case. if(!global) { ...}\n\nmodule.exports = g;\n\n\n//# sourceURL=webpack:///(webpack)/buildin/global.js?"); /***/ }), diff --git a/docs/bootstrap.js b/docs/bootstrap.js index cbda51c..6cf36c6 100644 --- a/docs/bootstrap.js +++ b/docs/bootstrap.js @@ -55,6 +55,69 @@ /******/ "../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_getRandomValues_3ac1b33c90b52596": function(p0i32,p1i32,p2i32) { +/******/ return installedModules["../pkg/mapgen_demo_bg.js"].exports["__wbg_getRandomValues_3ac1b33c90b52596"](p0i32,p1i32,p2i32); +/******/ }, +/******/ "__wbg_randomFillSync_6f956029658662ec": function(p0i32,p1i32,p2i32) { +/******/ return installedModules["../pkg/mapgen_demo_bg.js"].exports["__wbg_randomFillSync_6f956029658662ec"](p0i32,p1i32,p2i32); +/******/ }, +/******/ "__wbg_self_1c83eb4471d9eb9b": function() { +/******/ return installedModules["../pkg/mapgen_demo_bg.js"].exports["__wbg_self_1c83eb4471d9eb9b"](); +/******/ }, +/******/ "__wbg_static_accessor_MODULE_abf5ae284bffdf45": function() { +/******/ return installedModules["../pkg/mapgen_demo_bg.js"].exports["__wbg_static_accessor_MODULE_abf5ae284bffdf45"](); +/******/ }, +/******/ "__wbg_require_5b2b5b594d809d9f": function(p0i32,p1i32,p2i32) { +/******/ return installedModules["../pkg/mapgen_demo_bg.js"].exports["__wbg_require_5b2b5b594d809d9f"](p0i32,p1i32,p2i32); +/******/ }, +/******/ "__wbg_crypto_c12f14e810edcaa2": function(p0i32) { +/******/ return installedModules["../pkg/mapgen_demo_bg.js"].exports["__wbg_crypto_c12f14e810edcaa2"](p0i32); +/******/ }, +/******/ "__wbg_msCrypto_679be765111ba775": function(p0i32) { +/******/ return installedModules["../pkg/mapgen_demo_bg.js"].exports["__wbg_msCrypto_679be765111ba775"](p0i32); +/******/ }, +/******/ "__wbindgen_is_undefined": function(p0i32) { +/******/ return installedModules["../pkg/mapgen_demo_bg.js"].exports["__wbindgen_is_undefined"](p0i32); +/******/ }, +/******/ "__wbg_getRandomValues_05a60bf171bfc2be": function(p0i32) { +/******/ return installedModules["../pkg/mapgen_demo_bg.js"].exports["__wbg_getRandomValues_05a60bf171bfc2be"](p0i32); +/******/ }, +/******/ "__wbg_instanceof_Window_adf3196bdc02b386": function(p0i32) { +/******/ return installedModules["../pkg/mapgen_demo_bg.js"].exports["__wbg_instanceof_Window_adf3196bdc02b386"](p0i32); +/******/ }, +/******/ "__wbg_document_6cc8d0b87c0a99b9": function(p0i32) { +/******/ return installedModules["../pkg/mapgen_demo_bg.js"].exports["__wbg_document_6cc8d0b87c0a99b9"](p0i32); +/******/ }, +/******/ "__wbg_getElementById_0cb6ad9511b1efc0": function(p0i32,p1i32,p2i32) { +/******/ return installedModules["../pkg/mapgen_demo_bg.js"].exports["__wbg_getElementById_0cb6ad9511b1efc0"](p0i32,p1i32,p2i32); +/******/ }, +/******/ "__wbg_setinnerHTML_4ff235db1a3cb4d8": function(p0i32,p1i32,p2i32) { +/******/ return installedModules["../pkg/mapgen_demo_bg.js"].exports["__wbg_setinnerHTML_4ff235db1a3cb4d8"](p0i32,p1i32,p2i32); +/******/ }, +/******/ "__wbg_call_8e95613cc6524977": function(p0i32,p1i32) { +/******/ return installedModules["../pkg/mapgen_demo_bg.js"].exports["__wbg_call_8e95613cc6524977"](p0i32,p1i32); +/******/ }, +/******/ "__wbindgen_object_clone_ref": function(p0i32) { +/******/ return installedModules["../pkg/mapgen_demo_bg.js"].exports["__wbindgen_object_clone_ref"](p0i32); +/******/ }, +/******/ "__wbg_newnoargs_f3b8a801d5d4b079": function(p0i32,p1i32) { +/******/ return installedModules["../pkg/mapgen_demo_bg.js"].exports["__wbg_newnoargs_f3b8a801d5d4b079"](p0i32,p1i32); +/******/ }, +/******/ "__wbg_self_07b2f89e82ceb76d": function() { +/******/ return installedModules["../pkg/mapgen_demo_bg.js"].exports["__wbg_self_07b2f89e82ceb76d"](); +/******/ }, +/******/ "__wbg_window_ba85d88572adc0dc": function() { +/******/ return installedModules["../pkg/mapgen_demo_bg.js"].exports["__wbg_window_ba85d88572adc0dc"](); +/******/ }, +/******/ "__wbg_globalThis_b9277fc37e201fe5": function() { +/******/ return installedModules["../pkg/mapgen_demo_bg.js"].exports["__wbg_globalThis_b9277fc37e201fe5"](); +/******/ }, +/******/ "__wbg_global_e16303fe83e1d57f": function() { +/******/ return installedModules["../pkg/mapgen_demo_bg.js"].exports["__wbg_global_e16303fe83e1d57f"](); +/******/ }, /******/ "__wbindgen_throw": function(p0i32,p1i32) { /******/ return installedModules["../pkg/mapgen_demo_bg.js"].exports["__wbindgen_throw"](p0i32,p1i32); /******/ } @@ -159,7 +222,7 @@ /******/ promises.push(installedWasmModuleData); /******/ else { /******/ var importObject = wasmImportObjects[wasmModuleId](); -/******/ var req = fetch(__webpack_require__.p + "" + {"../pkg/mapgen_demo_bg.wasm":"bbf7fe2631d06e11148e"}[wasmModuleId] + ".module.wasm"); +/******/ var req = fetch(__webpack_require__.p + "" + {"../pkg/mapgen_demo_bg.wasm":"cbb67d3121ca19dbc9af"}[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/cbb67d3121ca19dbc9af.module.wasm b/docs/cbb67d3121ca19dbc9af.module.wasm new file mode 100644 index 0000000000000000000000000000000000000000..a0d00bd6ea9d4fda8176f736257f6f1994321d62 GIT binary patch literal 94179 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 diff --git a/src/common/geometry.rs b/src/common/geometry.rs index 57d8715..86295b2 100644 --- a/src/common/geometry.rs +++ b/src/common/geometry.rs @@ -30,24 +30,44 @@ impl Point { /// Rectangle region on the map #[derive(PartialEq, Copy, Clone)] pub struct Rect { - pub x1 : i32, - pub x2 : i32, - pub y1 : i32, - pub y2 : i32 + pub x1 : usize, + pub x2 : usize, + pub y1 : usize, + pub y2 : usize } impl Rect { - pub fn new(x:i32, y: i32, width:i32, height:i32) -> Rect { + pub fn new(x: usize, y: usize, width: usize, height: usize) -> Rect { Rect{x1:x, y1:y, x2:x+width, y2:y+height} } + pub fn new_i32(x:i32, y: i32, width:i32, height:i32) -> Rect { + Rect::new(x as usize, y as usize, width as usize, height as usize) + } + /// Returns true if this overlaps with other pub fn intersect(&self, other:&Rect) -> bool { self.x1 <= other.x2 && self.x2 >= other.x1 && self.y1 <= other.y2 && self.y2 >= other.y1 } pub fn center(&self) -> Point { - Point::new_i32((self.x1 + self.x2)/2, (self.y1 + self.y2)/2) + Point::new((self.x1 + self.x2)/2, (self.y1 + self.y2)/2) + } + + pub fn width(&self) -> usize { + if self.x2 >= self.x1 { + self.x2 - self.x1 + } else { + self.x1 - self.x2 + } + } + + pub fn height(&self) -> usize { + if self.y2 >= self.y1 { + self.y2 - self.y1 + } else { + self.y1 - self.y2 + } } } @@ -72,4 +92,12 @@ mod tests { let rect2 = Rect::new(30, 30, 60, 60); assert!(rect1.intersect(&rect2)); } + + #[test] + fn test_size() { + let rect1 = Rect::new(10, 10, 40, 30); + assert_eq!(rect1.width(), 40); + assert_eq!(rect1.height(), 30); + } + } \ No newline at end of file diff --git a/src/common/random.rs b/src/common/random.rs index 047d01f..9ebd257 100644 --- a/src/common/random.rs +++ b/src/common/random.rs @@ -2,14 +2,25 @@ //! use rand::prelude::*; +pub trait Rng { + /// Generate random number between start and end (bot inclusive). + fn roll_dice(&mut self, min: usize, max: usize) -> usize; + /// Generate random number between start (inclusive) and end (exclusive). + fn random_range(&mut self, start: usize, end: usize) -> usize; +} -/// Generate random number between start (inclusive) and end (exclusive). -pub fn random_range(rng: &mut StdRng, start: usize, end: usize) -> usize { - let max = (end - start) as u32; - if max == 0 { - start - } else { - ((rng.next_u32() % max) + start as u32) as usize +impl Rng for StdRng { + fn roll_dice(&mut self, min: usize, max: usize) -> usize { + self.random_range(min, max+1) + } + + fn random_range(&mut self, start: usize, end: usize) -> usize { + let max = (end - start) as u32; + if max == 0 { + start + } else { + ((self.next_u32() % max) + start as u32) as usize + } } } @@ -18,16 +29,40 @@ pub fn random_range(rng: &mut StdRng, start: usize, end: usize) -> usize { /// ------------------------------------------------------------------------------------------------ #[cfg(test)] mod tests { - use std::time::{SystemTime, UNIX_EPOCH}; use rand::prelude::*; - use super::*; + use super::Rng; #[test] fn test_range() { - let system_time = SystemTime::now().duration_since(UNIX_EPOCH).expect("Can't access system time"); - let mut rng = StdRng::seed_from_u64(system_time.as_millis() as u64); - let x = random_range(&mut rng, 5, 8); + let mut rng = StdRng::seed_from_u64(100); + let x = rng.random_range(5, 8); assert!(x >= 5 && x < 8); } + #[test] + fn test_range_average() { + let num_op = 1000; + let mut rng = StdRng::seed_from_u64(1000); + let xs: Vec = (0..num_op).map(|_| rng.random_range(5, 10)).collect(); + let mean = xs.iter().sum::() / num_op; + let min = *xs.iter().min().expect("no min"); + let max = *xs.iter().max().expect("no max"); + assert_eq!(mean, 7); + assert_eq!(min, 5); + assert_eq!(max, 9); + } + + #[test] + fn test_roll_dice() { + let num_op = 1000; + let mut rng = StdRng::seed_from_u64(2000); + let xs: Vec = (0..num_op).map(|_| rng.roll_dice(1, 7)).collect(); + let mean = xs.iter().sum::() as f32 / num_op as f32 + 0.5; + let min = *xs.iter().min().expect("no min"); + let max = *xs.iter().max().expect("no max"); + assert_eq!(mean as usize, 4); + assert_eq!(min, 1); + assert_eq!(max, 7); + } + } \ No newline at end of file diff --git a/src/dungeon/bsp_interior.rs b/src/dungeon/bsp_interior.rs new file mode 100644 index 0000000..e4b2574 --- /dev/null +++ b/src/dungeon/bsp_interior.rs @@ -0,0 +1,108 @@ +//! Random rooms map generator. +//! +//! Try to generate rooms of different size to fill the map area. +//! Rooms will not overlap. +//! +//! Example generator usage: +//! ``` +//! use rand::prelude::*; +//! use mapgen::dungeon::{ +//! MapGenerator, +//! bsp_interior::BspInteriorGen +//! }; +//! +//! let mut rng = StdRng::seed_from_u64(100); +//! let gen = BspInteriorGen::new(); +//! let map = gen.generate_map(80, 50, &mut rng); +//! +//! assert_eq!(map.width, 80); +//! assert_eq!(map.height, 50); +//! ``` +//! + +use rand::prelude::*; +use super::MapGenerator; +use crate::common::geometry::{Point, Rect}; +use crate::common::random::Rng; +use super::map::Map; + + +pub struct BspInteriorGen { + min_room_size: usize, +} + +impl MapGenerator for BspInteriorGen { + fn generate_map(&self, width: usize, height: usize, rng : &mut StdRng) -> Map { + self.build(rng, width, height) + } +} + +impl BspInteriorGen { + + pub fn new() -> Box { + Box::new(BspInteriorGen{ + min_room_size: 8, + }) + } + + fn build(&self, rng: &mut StdRng, width: usize, height: usize) -> Map { + let mut map = Map::new(width, height); + let mut rects: Vec = Vec::new(); + rects.push( Rect::new(1, 1, map.width-2, map.height-2) ); + let first_room = rects[0]; + // Divide the first room + self.add_subrects(first_room, rng, &mut rects); + + let rooms_copy = rects.clone(); + for r in rooms_copy.iter() { + let room = *r; + map.add_room(room); + } + + // Now we want corridors + for i in 0..map.rooms.len()-1 { + let room = map.rooms[i]; + let next_room = map.rooms[i+1]; + let start_x = room.x1 + rng.random_range(1, room.width()); + let start_y = room.y1 + rng.random_range(1, room.height()); + let end_x = next_room.x1 + (rng.random_range(1, next_room.width())); + let end_y = next_room.y1 + (rng.random_range(1, next_room.width())); + map.add_corridor(Point::new(start_x, start_y), Point::new(end_x, end_y)); + } + + map + } + + fn add_subrects(&self, rect: Rect, rng: &mut StdRng, rects: &mut Vec) { + // Remove the last rect from the list + if !rects.is_empty() { + rects.remove(rects.len() - 1); + } + + // Calculate boundaries + let width = rect.x2 - rect.x1; + let height = rect.y2 - rect.y1; + let half_width = width / 2; + let half_height = height / 2; + + let split = rng.roll_dice(1, 4); + + if split <= 2 { + // Horizontal split + let h1 = Rect::new( rect.x1, rect.y1, half_width-1, height ); + rects.push( h1 ); + if half_width > self.min_room_size { self.add_subrects(h1, rng, rects); } + let h2 = Rect::new( rect.x1 + half_width, rect.y1, half_width, height ); + rects.push( h2 ); + if half_width > self.min_room_size { self.add_subrects(h2, rng, rects); } + } else { + // Vertical split + let v1 = Rect::new( rect.x1, rect.y1, width, half_height-1 ); + rects.push(v1); + if half_height > self.min_room_size { self.add_subrects(v1, rng, rects); } + let v2 = Rect::new( rect.x1, rect.y1 + half_height, width, half_height ); + rects.push(v2); + if half_height > self.min_room_size { self.add_subrects(v2, rng, rects); } + } + } +} \ No newline at end of file diff --git a/src/dungeon/bsp_rooms.rs b/src/dungeon/bsp_rooms.rs index 042ced9..e9b6618 100644 --- a/src/dungeon/bsp_rooms.rs +++ b/src/dungeon/bsp_rooms.rs @@ -23,7 +23,7 @@ use rand::prelude::*; use super::MapGenerator; use crate::common::geometry::Rect; -use crate::common::random; +use crate::common::random::Rng; use super::map::{Map, TileType}; @@ -48,7 +48,7 @@ impl BspRoomsGen { let mut map = Map::new(width, height); let mut rects: Vec = Vec::new(); // Start with a single map-sized rectangle - rects.push( Rect::new(2, 2, (width-5) as i32, (height-5) as i32) ); + rects.push( Rect::new(2, 2, width-5, height-5) ); let first_room = rects[0]; rects.append(&mut self.split_into_subrects(first_room)); // Divide the first room @@ -71,10 +71,10 @@ impl BspRoomsGen { fn split_into_subrects(&self, rect: Rect) -> Vec { let mut rects: Vec = Vec::new(); - let width = i32::abs(rect.x1 - rect.x2); - let height = i32::abs(rect.y1 - rect.y2); - let half_width = i32::max(width / 2, 1); - let half_height = i32::max(height / 2, 1); + let width = rect.width(); + let height = rect.height(); + let half_width = usize::max(width / 2, 1); + let half_height = usize::max(height / 2, 1); rects.push(Rect::new( rect.x1, rect.y1, half_width, half_height )); rects.push(Rect::new( rect.x1, rect.y1 + half_height, half_width, half_height )); @@ -86,22 +86,22 @@ impl BspRoomsGen { fn get_random_rect(&self, rng : &mut StdRng, rects: &Vec) -> Rect { if rects.len() == 1 { return rects[0]; } - let idx = random::random_range(rng, 0, rects.len()); + let idx = rng.random_range(0, rects.len()); rects[idx] } fn get_random_sub_rect(&self, rect: Rect, rng: &mut StdRng) -> Rect { let mut result = rect; - let rect_width = i32::abs(rect.x1 - rect.x2); - let rect_height = i32::abs(rect.y1 - rect.y2); + let rect_width = rect.width(); + let rect_height = rect.height(); - let w = usize::max(3, random::random_range(rng, 1, usize::min(rect_width as usize, 20))) + 1; - let h = usize::max(3, random::random_range(rng, 1, usize::min(rect_height as usize, 20))) + 1; + let w = usize::max(3, rng.random_range(1, usize::min(rect_width as usize, 20))) + 1; + let h = usize::max(3, rng.random_range(1, usize::min(rect_height as usize, 20))) + 1; - result.x1 += random::random_range(rng, 0, 6) as i32; - result.y1 += random::random_range(rng, 0, 6) as i32; - result.x2 = result.x1 + w as i32; - result.y2 = result.y1 + h as i32; + result.x1 += rng.random_range(0, 6); + result.y1 += rng.random_range(0, 6); + result.x2 = result.x1 + w; + result.y2 = result.y1 + h; result } @@ -121,8 +121,8 @@ impl BspRoomsGen { for y in expanded.y1 ..= expanded.y2 { for x in expanded.x1 ..= expanded.x2 { - if x > map.width as i32 -2 { can_build = false; } - if y > map.height as i32 -2 { can_build = false; } + if x > map.width - 2 { can_build = false; } + if y > map.height - 2 { can_build = false; } if x < 1 { can_build = false; } if y < 1 { can_build = false; } if can_build { diff --git a/src/dungeon/mod.rs b/src/dungeon/mod.rs index 1ccd797..d1ef8de 100644 --- a/src/dungeon/mod.rs +++ b/src/dungeon/mod.rs @@ -29,6 +29,7 @@ pub mod map; pub mod cellular_automata; pub mod cull_unreachable; +pub mod bsp_interior; pub mod bsp_rooms; pub mod distant_exit; pub mod simple_rooms; diff --git a/src/dungeon/simple_rooms.rs b/src/dungeon/simple_rooms.rs index 7792fee..84d245a 100644 --- a/src/dungeon/simple_rooms.rs +++ b/src/dungeon/simple_rooms.rs @@ -23,7 +23,7 @@ use rand::prelude::*; use super::MapGenerator; use crate::common::geometry::Rect; -use crate::common::random; +use crate::common::random::Rng; use super::map::{Map}; @@ -54,11 +54,11 @@ impl SimpleRoomsGen { // Create room dimensions for _ in 0..self.max_rooms { - let w = random::random_range(rng, self.min_room_size, self.max_room_size); - let h = random::random_range(rng, self.min_room_size, self.max_room_size); - 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 w = rng.random_range(self.min_room_size, self.max_room_size); + let h = rng.random_range(self.min_room_size, self.max_room_size); + let x = rng.random_range(1, width - w); + let y = rng.random_range(1, height - h); + let new_room = Rect::new(x, y, w, h); let intersects = map.rooms.iter().any(|r| new_room.intersect(r)); if !intersects { map.add_room(new_room);