Compare commits
No commits in common. "main" and "20a14de05d89e9360390542cf86f203e4a24eecc" have entirely different histories.
main
...
20a14de05d
40
.drone.yml
40
.drone.yml
|
@ -1,40 +0,0 @@
|
||||||
kind: pipeline
|
|
||||||
type: docker
|
|
||||||
name: default
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: test
|
|
||||||
image: rust
|
|
||||||
pull: always
|
|
||||||
commands:
|
|
||||||
- rustup component add clippy rustfmt
|
|
||||||
- cargo fmt --check
|
|
||||||
- cargo test --all-features
|
|
||||||
- cargo clippy --all-features
|
|
||||||
- name: release
|
|
||||||
image: rust
|
|
||||||
pull: always
|
|
||||||
commands:
|
|
||||||
- cargo publish
|
|
||||||
when:
|
|
||||||
event:
|
|
||||||
- tag
|
|
||||||
environment:
|
|
||||||
CARGO_REGISTRY_TOKEN:
|
|
||||||
from_secret: cargo_registry_token
|
|
||||||
- name: discord notification
|
|
||||||
image: appleboy/drone-discord
|
|
||||||
when:
|
|
||||||
status: [success, failure]
|
|
||||||
settings:
|
|
||||||
webhook_id:
|
|
||||||
from_secret: discord_webhook_id
|
|
||||||
webhook_token:
|
|
||||||
from_secret: discord_webhook_token
|
|
||||||
tts: true
|
|
||||||
message: >
|
|
||||||
{{#success build.status}}
|
|
||||||
{{repo.name}} build {{build.number}} succeeded: <{{build.link}}>
|
|
||||||
{{else}}
|
|
||||||
{{repo.name}} build {{build.number}} failed: <{{build.link}}>
|
|
||||||
{{/success}}
|
|
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -4,4 +4,3 @@ Cargo.lock
|
||||||
.vscode/
|
.vscode/
|
||||||
pkg/
|
pkg/
|
||||||
package-lock.json
|
package-lock.json
|
||||||
.DS_Store
|
|
4
.travis.yml
Normal file
4
.travis.yml
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
language: rust
|
||||||
|
rust:
|
||||||
|
- stable
|
||||||
|
- beta
|
36
CHANGELOG.md
36
CHANGELOG.md
|
@ -1,36 +0,0 @@
|
||||||
# Changelog
|
|
||||||
|
|
||||||
All notable changes to this project will be documented in this file.
|
|
||||||
|
|
||||||
## Version 0.3.0 - 2023-02-22
|
|
||||||
|
|
||||||
### Features
|
|
||||||
|
|
||||||
- Add optional map serialization.
|
|
||||||
|
|
||||||
## Version 0.2.1 - 2023-01-31
|
|
||||||
|
|
||||||
### Miscellaneous Tasks
|
|
||||||
|
|
||||||
- Resolve clippy warnings and add a bounds check.
|
|
||||||
|
|
||||||
## Version 0.2.0 - 2022-08-27
|
|
||||||
|
|
||||||
### Refactor
|
|
||||||
|
|
||||||
- `map.at` now returns `Option<&Tile>` rather than a wall tile when requested coordinates are out-of-bounds.
|
|
||||||
|
|
||||||
## Version 0.1.1 - 2022-03-18
|
|
||||||
|
|
||||||
### Miscellaneous Tasks
|
|
||||||
|
|
||||||
- More automated release configuration.
|
|
||||||
|
|
||||||
## Version 0.1.0 - 2022-03-18
|
|
||||||
|
|
||||||
### Miscellaneous Tasks
|
|
||||||
|
|
||||||
- Rename crate and set up automated releases.
|
|
||||||
- Remove demo.
|
|
||||||
|
|
||||||
<!-- generated by git-cliff -->
|
|
20
Cargo.toml
20
Cargo.toml
|
@ -1,20 +1,14 @@
|
||||||
[package]
|
[package]
|
||||||
name = "here_be_dragons"
|
name = "mapgen"
|
||||||
version = "0.3.0"
|
version = "0.5.2"
|
||||||
authors = ["Nolan Darilek <nolan@thewordnerd.info>", "Krzysztof Langner <klangner@gmail.com>"]
|
authors = ["Krzysztof Langner <klangner@gmail.com>"]
|
||||||
description = "Map generator for games"
|
description = "Map generator for games (dungeons, worlds etc.)"
|
||||||
keywords = ["game", "map", "map-generator"]
|
keywords = ["game", "map", "map-generator"]
|
||||||
license = "MIT OR Apache-2.0"
|
license = "MIT OR Apache-2.0"
|
||||||
repository = "https://labs.lightsout.games/projects/here_be_dragons"
|
repository = "https://github.com/klangner/mapgen.rs"
|
||||||
documentation = "https://docs.rs/here_be_dragons"
|
homepage = "https://github.com/klangner/mapgen.rs"
|
||||||
|
documentation = "https://docs.rs/mapgen"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
rand = "0.8"
|
rand = "0.8"
|
||||||
serde = { version = "1", optional = true, features = ["derive"]}
|
|
||||||
|
|
||||||
[package.metadata.release]
|
|
||||||
publish = false
|
|
||||||
push = false
|
|
||||||
pre-release-hook = ["git-cliff", "-o", "CHANGELOG.md", "--tag", "{{version}}"]
|
|
||||||
pre-release-commit-message = "Release"
|
|
||||||
|
|
35
README.md
35
README.md
|
@ -1,17 +1,15 @@
|
||||||
# Here Be Dragons
|
# Game Map Generator
|
||||||
|
|
||||||
[![Crates.io](https://img.shields.io/crates/v/here_be_dragons.svg)](https://crates.io/crates/here_be_dragons)
|
[![Build Status](https://travis-ci.org/klangner/mapgen.rs.svg?branch=master)](https://travis-ci.org/klangner/mapgen.rs)
|
||||||
[![here_be_dragons](https://docs.rs/here_be_dragons/badge.svg)](https://docs.rs/here_be_dragons/)
|
[![Crates.io](https://img.shields.io/crates/v/mapgen.svg)](https://crates.io/crates/mapgen)
|
||||||
|
[![mapgen.rs](https://docs.rs/mapgen/badge.svg)](https://docs.rs/mapgen/)
|
||||||
|
|
||||||
Generate procedural maps for games.
|
Generate procedural maps for games. [Try it in the browser](https://klangner.github.io/mapgen.rs/) using WebAssembly.
|
||||||
|
|
||||||
## Acknowledgments
|
|
||||||
|
|
||||||
This crate is based on [mapgen.rs](https://github.com/klangner/mapgen.rs). Thanks to Krzysztof Langner for doing the hard work of implementing the many map generation algorithms this crate includes.
|
|
||||||
|
|
||||||
## Map filters
|
## Map filters
|
||||||
|
|
||||||
This library consists of different map filters which can be combined to create custom map generators.
|
This library consists of different map filters which can be combined to create custom map generator.
|
||||||
|
|
||||||
### Implemented filters
|
### Implemented filters
|
||||||
|
|
||||||
|
@ -31,19 +29,20 @@ This library consists of different map filters which can be combined to create c
|
||||||
* [x] Voronoi hive
|
* [x] Voronoi hive
|
||||||
* [ ] Wave Function Collapse
|
* [ ] Wave Function Collapse
|
||||||
|
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
Add the dependency to your project
|
Add dependency to your project
|
||||||
```
|
```
|
||||||
here_be_dragons = "0.1"
|
mapgen = "0.4"
|
||||||
```
|
```
|
||||||
|
|
||||||
Using single map generator:
|
Using single map generator:
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
use rand::prelude::*;
|
use rand::prelude::*;
|
||||||
use here_be_dragons::{Map, MapFilter};
|
use mapgen::{Map, MapFilter};
|
||||||
use here_be_dragons::filter::CellularAutomata;
|
use mapgen::filter::CellularAutomata;
|
||||||
|
|
||||||
let mut rng = StdRng::seed_from_u64(100);
|
let mut rng = StdRng::seed_from_u64(100);
|
||||||
let gen = CellularAutomata::new();
|
let gen = CellularAutomata::new();
|
||||||
|
@ -53,7 +52,7 @@ let map = gen.modify_map(&mut rng, &Map::new(80, 50));
|
||||||
Use MapBuilder for chaining map generator and modifiers
|
Use MapBuilder for chaining map generator and modifiers
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
use here_be_dragons::{
|
use mapgen::{
|
||||||
MapBuilder,
|
MapBuilder,
|
||||||
filter::{
|
filter::{
|
||||||
NoiseGenerator,
|
NoiseGenerator,
|
||||||
|
@ -73,11 +72,14 @@ let map = MapBuilder::new(80, 50)
|
||||||
.build();
|
.build();
|
||||||
```
|
```
|
||||||
|
|
||||||
For more information check the [docs](https://docs.rs/here_be_dragons).
|
For more information check the [doc](https://docs.rs/mapgen)
|
||||||
|
|
||||||
This library is based on the code from the [Roguelike tutorial](https://github.com/thebracket/rustrogueliketutorial). I highly recommend it for learning how to write a Roguelike in Rust.
|
|
||||||
|
|
||||||
## License
|
This library is based on the code from the [Roguelike tutorial](https://github.com/thebracket/rustrogueliketutorial).
|
||||||
|
I highly recommend it for learning how to write Roguelike in Rust.
|
||||||
|
|
||||||
|
|
||||||
|
# License
|
||||||
|
|
||||||
Licensed under either of
|
Licensed under either of
|
||||||
|
|
||||||
|
@ -86,6 +88,7 @@ Licensed under either of
|
||||||
|
|
||||||
at your option.
|
at your option.
|
||||||
|
|
||||||
|
|
||||||
**Contributions**
|
**Contributions**
|
||||||
|
|
||||||
Unless you explicitly state otherwise, any contribution intentionally submitted
|
Unless you explicitly state otherwise, any contribution intentionally submitted
|
||||||
|
|
60
cliff.toml
60
cliff.toml
|
@ -1,60 +0,0 @@
|
||||||
# configuration file for git-cliff (0.1.0)
|
|
||||||
|
|
||||||
[changelog]
|
|
||||||
# changelog header
|
|
||||||
header = """
|
|
||||||
# Changelog\n
|
|
||||||
All notable changes to this project will be documented in this file.\n
|
|
||||||
"""
|
|
||||||
# template for the changelog body
|
|
||||||
# https://tera.netlify.app/docs/#introduction
|
|
||||||
body = """
|
|
||||||
{% if version %}\
|
|
||||||
## Version {{ version | trim_start_matches(pat="v") }} - {{ timestamp | date(format="%Y-%m-%d") }}
|
|
||||||
{% else %}\
|
|
||||||
## Unreleased
|
|
||||||
{% endif %}\
|
|
||||||
{% for group, commits in commits | group_by(attribute="group") %}
|
|
||||||
### {{ group | upper_first }}
|
|
||||||
{% for commit in commits %}
|
|
||||||
- {% if commit.breaking %}[**breaking**] {% endif %}{{ commit.message | upper_first }}\
|
|
||||||
{% endfor %}
|
|
||||||
{% endfor %}\n
|
|
||||||
"""
|
|
||||||
# remove the leading and trailing whitespace from the template
|
|
||||||
trim = true
|
|
||||||
# changelog footer
|
|
||||||
footer = """
|
|
||||||
<!-- generated by git-cliff -->
|
|
||||||
"""
|
|
||||||
|
|
||||||
[git]
|
|
||||||
# parse the commits based on https://www.conventionalcommits.org
|
|
||||||
conventional_commits = true
|
|
||||||
# filter out the commits that are not conventional
|
|
||||||
filter_unconventional = true
|
|
||||||
# regex for parsing and grouping commits
|
|
||||||
commit_parsers = [
|
|
||||||
{ message = "^feat", group = "Features"},
|
|
||||||
{ message = "^fix", group = "Bug Fixes"},
|
|
||||||
{ message = "^doc", group = "Documentation"},
|
|
||||||
{ message = "^perf", group = "Performance"},
|
|
||||||
{ message = "^refactor", group = "Refactor"},
|
|
||||||
{ message = "^style", group = "Styling"},
|
|
||||||
{ message = "^test", group = "Testing"},
|
|
||||||
{ message = "^chore\\(release\\): prepare for", skip = true},
|
|
||||||
{ message = "^chore", group = "Miscellaneous Tasks"},
|
|
||||||
{ body = ".*security", group = "Security"},
|
|
||||||
]
|
|
||||||
# filter out the commits that are not matched by commit parsers
|
|
||||||
filter_commits = false
|
|
||||||
# glob pattern for matching git tags
|
|
||||||
tag_pattern = "v[0-9]*"
|
|
||||||
# regex for skipping tags
|
|
||||||
skip_tags = ""
|
|
||||||
# regex for ignoring tags
|
|
||||||
ignore_tags = ""
|
|
||||||
# sort the tags chronologically
|
|
||||||
date_order = false
|
|
||||||
# sort the commits inside sections by oldest/newest order
|
|
||||||
sort_commits = "oldest"
|
|
BIN
demo/.DS_Store
vendored
Normal file
BIN
demo/.DS_Store
vendored
Normal file
Binary file not shown.
28
demo/Cargo.toml
Normal file
28
demo/Cargo.toml
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
[package]
|
||||||
|
name = "mapgen-demo"
|
||||||
|
version = "0.1.2"
|
||||||
|
authors = ["Krzysztof Langner <klangner@gmail.com>"]
|
||||||
|
description = "Map generator demo"
|
||||||
|
license = "MIT OR Apache-2.0"
|
||||||
|
repository = "https://github.com/klangner/mapgen.rs"
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
crate-type = ["cdylib"]
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
mapgen = {path=".."}
|
||||||
|
getrandom = { version = "0.2", features = ["js"] }
|
||||||
|
rand = "0.8"
|
||||||
|
wasm-bindgen = "0.2"
|
||||||
|
js-sys = "0.3"
|
||||||
|
|
||||||
|
[dependencies.web-sys]
|
||||||
|
version = "0.3.4"
|
||||||
|
features = [
|
||||||
|
'Document',
|
||||||
|
'Element',
|
||||||
|
'HtmlElement',
|
||||||
|
'Node',
|
||||||
|
'Window',
|
||||||
|
]
|
201
demo/LICENSE-APACHE
Normal file
201
demo/LICENSE-APACHE
Normal file
|
@ -0,0 +1,201 @@
|
||||||
|
Apache License
|
||||||
|
Version 2.0, January 2004
|
||||||
|
http://www.apache.org/licenses/
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||||
|
|
||||||
|
1. Definitions.
|
||||||
|
|
||||||
|
"License" shall mean the terms and conditions for use, reproduction,
|
||||||
|
and distribution as defined by Sections 1 through 9 of this document.
|
||||||
|
|
||||||
|
"Licensor" shall mean the copyright owner or entity authorized by
|
||||||
|
the copyright owner that is granting the License.
|
||||||
|
|
||||||
|
"Legal Entity" shall mean the union of the acting entity and all
|
||||||
|
other entities that control, are controlled by, or are under common
|
||||||
|
control with that entity. For the purposes of this definition,
|
||||||
|
"control" means (i) the power, direct or indirect, to cause the
|
||||||
|
direction or management of such entity, whether by contract or
|
||||||
|
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||||
|
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||||
|
|
||||||
|
"You" (or "Your") shall mean an individual or Legal Entity
|
||||||
|
exercising permissions granted by this License.
|
||||||
|
|
||||||
|
"Source" form shall mean the preferred form for making modifications,
|
||||||
|
including but not limited to software source code, documentation
|
||||||
|
source, and configuration files.
|
||||||
|
|
||||||
|
"Object" form shall mean any form resulting from mechanical
|
||||||
|
transformation or translation of a Source form, including but
|
||||||
|
not limited to compiled object code, generated documentation,
|
||||||
|
and conversions to other media types.
|
||||||
|
|
||||||
|
"Work" shall mean the work of authorship, whether in Source or
|
||||||
|
Object form, made available under the License, as indicated by a
|
||||||
|
copyright notice that is included in or attached to the work
|
||||||
|
(an example is provided in the Appendix below).
|
||||||
|
|
||||||
|
"Derivative Works" shall mean any work, whether in Source or Object
|
||||||
|
form, that is based on (or derived from) the Work and for which the
|
||||||
|
editorial revisions, annotations, elaborations, or other modifications
|
||||||
|
represent, as a whole, an original work of authorship. For the purposes
|
||||||
|
of this License, Derivative Works shall not include works that remain
|
||||||
|
separable from, or merely link (or bind by name) to the interfaces of,
|
||||||
|
the Work and Derivative Works thereof.
|
||||||
|
|
||||||
|
"Contribution" shall mean any work of authorship, including
|
||||||
|
the original version of the Work and any modifications or additions
|
||||||
|
to that Work or Derivative Works thereof, that is intentionally
|
||||||
|
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||||
|
or by an individual or Legal Entity authorized to submit on behalf of
|
||||||
|
the copyright owner. For the purposes of this definition, "submitted"
|
||||||
|
means any form of electronic, verbal, or written communication sent
|
||||||
|
to the Licensor or its representatives, including but not limited to
|
||||||
|
communication on electronic mailing lists, source code control systems,
|
||||||
|
and issue tracking systems that are managed by, or on behalf of, the
|
||||||
|
Licensor for the purpose of discussing and improving the Work, but
|
||||||
|
excluding communication that is conspicuously marked or otherwise
|
||||||
|
designated in writing by the copyright owner as "Not a Contribution."
|
||||||
|
|
||||||
|
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||||
|
on behalf of whom a Contribution has been received by Licensor and
|
||||||
|
subsequently incorporated within the Work.
|
||||||
|
|
||||||
|
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
copyright license to reproduce, prepare Derivative Works of,
|
||||||
|
publicly display, publicly perform, sublicense, and distribute the
|
||||||
|
Work and such Derivative Works in Source or Object form.
|
||||||
|
|
||||||
|
3. Grant of Patent License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
(except as stated in this section) patent license to make, have made,
|
||||||
|
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||||
|
where such license applies only to those patent claims licensable
|
||||||
|
by such Contributor that are necessarily infringed by their
|
||||||
|
Contribution(s) alone or by combination of their Contribution(s)
|
||||||
|
with the Work to which such Contribution(s) was submitted. If You
|
||||||
|
institute patent litigation against any entity (including a
|
||||||
|
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||||
|
or a Contribution incorporated within the Work constitutes direct
|
||||||
|
or contributory patent infringement, then any patent licenses
|
||||||
|
granted to You under this License for that Work shall terminate
|
||||||
|
as of the date such litigation is filed.
|
||||||
|
|
||||||
|
4. Redistribution. You may reproduce and distribute copies of the
|
||||||
|
Work or Derivative Works thereof in any medium, with or without
|
||||||
|
modifications, and in Source or Object form, provided that You
|
||||||
|
meet the following conditions:
|
||||||
|
|
||||||
|
(a) You must give any other recipients of the Work or
|
||||||
|
Derivative Works a copy of this License; and
|
||||||
|
|
||||||
|
(b) You must cause any modified files to carry prominent notices
|
||||||
|
stating that You changed the files; and
|
||||||
|
|
||||||
|
(c) You must retain, in the Source form of any Derivative Works
|
||||||
|
that You distribute, all copyright, patent, trademark, and
|
||||||
|
attribution notices from the Source form of the Work,
|
||||||
|
excluding those notices that do not pertain to any part of
|
||||||
|
the Derivative Works; and
|
||||||
|
|
||||||
|
(d) If the Work includes a "NOTICE" text file as part of its
|
||||||
|
distribution, then any Derivative Works that You distribute must
|
||||||
|
include a readable copy of the attribution notices contained
|
||||||
|
within such NOTICE file, excluding those notices that do not
|
||||||
|
pertain to any part of the Derivative Works, in at least one
|
||||||
|
of the following places: within a NOTICE text file distributed
|
||||||
|
as part of the Derivative Works; within the Source form or
|
||||||
|
documentation, if provided along with the Derivative Works; or,
|
||||||
|
within a display generated by the Derivative Works, if and
|
||||||
|
wherever such third-party notices normally appear. The contents
|
||||||
|
of the NOTICE file are for informational purposes only and
|
||||||
|
do not modify the License. You may add Your own attribution
|
||||||
|
notices within Derivative Works that You distribute, alongside
|
||||||
|
or as an addendum to the NOTICE text from the Work, provided
|
||||||
|
that such additional attribution notices cannot be construed
|
||||||
|
as modifying the License.
|
||||||
|
|
||||||
|
You may add Your own copyright statement to Your modifications and
|
||||||
|
may provide additional or different license terms and conditions
|
||||||
|
for use, reproduction, or distribution of Your modifications, or
|
||||||
|
for any such Derivative Works as a whole, provided Your use,
|
||||||
|
reproduction, and distribution of the Work otherwise complies with
|
||||||
|
the conditions stated in this License.
|
||||||
|
|
||||||
|
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||||
|
any Contribution intentionally submitted for inclusion in the Work
|
||||||
|
by You to the Licensor shall be under the terms and conditions of
|
||||||
|
this License, without any additional terms or conditions.
|
||||||
|
Notwithstanding the above, nothing herein shall supersede or modify
|
||||||
|
the terms of any separate license agreement you may have executed
|
||||||
|
with Licensor regarding such Contributions.
|
||||||
|
|
||||||
|
6. Trademarks. This License does not grant permission to use the trade
|
||||||
|
names, trademarks, service marks, or product names of the Licensor,
|
||||||
|
except as required for reasonable and customary use in describing the
|
||||||
|
origin of the Work and reproducing the content of the NOTICE file.
|
||||||
|
|
||||||
|
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||||
|
agreed to in writing, Licensor provides the Work (and each
|
||||||
|
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||||
|
implied, including, without limitation, any warranties or conditions
|
||||||
|
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||||
|
appropriateness of using or redistributing the Work and assume any
|
||||||
|
risks associated with Your exercise of permissions under this License.
|
||||||
|
|
||||||
|
8. Limitation of Liability. In no event and under no legal theory,
|
||||||
|
whether in tort (including negligence), contract, or otherwise,
|
||||||
|
unless required by applicable law (such as deliberate and grossly
|
||||||
|
negligent acts) or agreed to in writing, shall any Contributor be
|
||||||
|
liable to You for damages, including any direct, indirect, special,
|
||||||
|
incidental, or consequential damages of any character arising as a
|
||||||
|
result of this License or out of the use or inability to use the
|
||||||
|
Work (including but not limited to damages for loss of goodwill,
|
||||||
|
work stoppage, computer failure or malfunction, or any and all
|
||||||
|
other commercial damages or losses), even if such Contributor
|
||||||
|
has been advised of the possibility of such damages.
|
||||||
|
|
||||||
|
9. Accepting Warranty or Additional Liability. While redistributing
|
||||||
|
the Work or Derivative Works thereof, You may choose to offer,
|
||||||
|
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||||
|
or other liability obligations and/or rights consistent with this
|
||||||
|
License. However, in accepting such obligations, You may act only
|
||||||
|
on Your own behalf and on Your sole responsibility, not on behalf
|
||||||
|
of any other Contributor, and only if You agree to indemnify,
|
||||||
|
defend, and hold each Contributor harmless for any liability
|
||||||
|
incurred by, or claims asserted against, such Contributor by reason
|
||||||
|
of your accepting any such warranty or additional liability.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
APPENDIX: How to apply the Apache License to your work.
|
||||||
|
|
||||||
|
To apply the Apache License to your work, attach the following
|
||||||
|
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||||
|
replaced with your own identifying information. (Don't include
|
||||||
|
the brackets!) The text should be enclosed in the appropriate
|
||||||
|
comment syntax for the file format. We also recommend that a
|
||||||
|
file or class name and description of purpose be included on the
|
||||||
|
same "printed page" as the copyright notice for easier
|
||||||
|
identification within third-party archives.
|
||||||
|
|
||||||
|
Copyright 2017 Krzysztof Langner
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
18
demo/README.md
Normal file
18
demo/README.md
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
# Demo application for mapgen
|
||||||
|
|
||||||
|
## Build the project:
|
||||||
|
|
||||||
|
```
|
||||||
|
wasm-pack build
|
||||||
|
cd www
|
||||||
|
npm run server
|
||||||
|
```
|
||||||
|
|
||||||
|
Deply application
|
||||||
|
```
|
||||||
|
cd www
|
||||||
|
npm run build
|
||||||
|
```
|
||||||
|
|
||||||
|
This app uses:
|
||||||
|
* [Urizen OneBit Tilesets](https://vurmux.itch.io/urizen-onebit-tilesets)
|
BIN
demo/assets/texture/ascii.png
Normal file
BIN
demo/assets/texture/ascii.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 6.3 KiB |
8
demo/assets/texture/ascii.ron
Normal file
8
demo/assets/texture/ascii.ron
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
#![enable(implicit_some)]
|
||||||
|
|
||||||
|
Grid((
|
||||||
|
texture_width: 320,
|
||||||
|
texture_height: 320,
|
||||||
|
columns: 16,
|
||||||
|
rows: 16,
|
||||||
|
))
|
BIN
demo/assets/texture/basic.png
Normal file
BIN
demo/assets/texture/basic.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 44 KiB |
8
demo/assets/texture/basic.ron
Normal file
8
demo/assets/texture/basic.ron
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
#![enable(implicit_some)]
|
||||||
|
|
||||||
|
Grid((
|
||||||
|
texture_width: 261,
|
||||||
|
texture_height: 261,
|
||||||
|
columns: 20,
|
||||||
|
rows: 20,
|
||||||
|
))
|
203
demo/src/lib.rs
Normal file
203
demo/src/lib.rs
Normal file
|
@ -0,0 +1,203 @@
|
||||||
|
use wasm_bindgen::prelude::*;
|
||||||
|
use web_sys;
|
||||||
|
use rand::prelude::*;
|
||||||
|
use mapgen::{Map, MapBuilder, NoData, geometry::Point};
|
||||||
|
use mapgen::filter::*;
|
||||||
|
use mapgen::metric;
|
||||||
|
|
||||||
|
|
||||||
|
#[wasm_bindgen]
|
||||||
|
#[repr(u8)]
|
||||||
|
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||||
|
pub enum Cell {
|
||||||
|
Floor = 0,
|
||||||
|
Wall = 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub struct World {
|
||||||
|
width: u32,
|
||||||
|
height: u32,
|
||||||
|
tiles: Vec<Cell>,
|
||||||
|
map: Map<NoData>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub struct Position {
|
||||||
|
col: usize,
|
||||||
|
row: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[wasm_bindgen]
|
||||||
|
impl World {
|
||||||
|
|
||||||
|
fn new(width: u32, height: u32, map: Map<NoData>) -> World {
|
||||||
|
let tiles = (0..map.tiles.len())
|
||||||
|
.map(|i| if map.tiles[i].is_walkable() {Cell::Floor} else {Cell::Wall})
|
||||||
|
.collect();
|
||||||
|
World { width, height, tiles, map }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new_cellular_automata(width: u32, height: u32, seed: u32) -> World {
|
||||||
|
World::print_map_info(format!("Cellular Automata with the seed: {}", seed));
|
||||||
|
let mut rng = StdRng::seed_from_u64(seed as u64);
|
||||||
|
let map = MapBuilder::new(width as usize, height as usize)
|
||||||
|
.with(NoiseGenerator::uniform())
|
||||||
|
.with(CellularAutomata::new())
|
||||||
|
.with(AreaStartingPosition::new(XStart::CENTER, YStart::CENTER))
|
||||||
|
.with(CullUnreachable::new())
|
||||||
|
.with(DistantExit::new())
|
||||||
|
.build_with_rng(&mut rng);
|
||||||
|
World::print_map_metrics(&map);
|
||||||
|
World::new(width, height, map)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new_simple_rooms(width: u32, height: u32, seed: u32) -> World {
|
||||||
|
World::print_map_info(format!("Simple Rooms with the seed: {}", seed));
|
||||||
|
let mut rng = StdRng::seed_from_u64(seed as u64);
|
||||||
|
let map = MapBuilder::new(width as usize, height as usize)
|
||||||
|
.with(SimpleRooms::new())
|
||||||
|
.with(NearestCorridors::new())
|
||||||
|
.with(AreaStartingPosition::new(XStart::LEFT, YStart::TOP))
|
||||||
|
.with(DistantExit::new())
|
||||||
|
.build_with_rng(&mut rng);
|
||||||
|
World::print_map_metrics(&map);
|
||||||
|
World::new(width, height, map)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new_bsp_rooms(width: u32, height: u32, seed: u32) -> World {
|
||||||
|
World::print_map_info(format!("BSP Rooms with the seed: {}", seed));
|
||||||
|
let mut rng = StdRng::seed_from_u64(seed as u64);
|
||||||
|
let map = MapBuilder::new(width as usize, height as usize)
|
||||||
|
.with(BspRooms::new())
|
||||||
|
.with(NearestCorridors::new())
|
||||||
|
.with(AreaStartingPosition::new(XStart::LEFT, YStart::BOTTOM))
|
||||||
|
.with(DistantExit::new())
|
||||||
|
.build_with_rng(&mut rng);
|
||||||
|
World::print_map_metrics(&map);
|
||||||
|
World::new(width, height, map)
|
||||||
|
}
|
||||||
|
|
||||||
|
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(width as usize, height as usize)
|
||||||
|
.with(BspInterior::new())
|
||||||
|
.with(AreaStartingPosition::new(XStart::CENTER, YStart::CENTER))
|
||||||
|
.with(CullUnreachable::new())
|
||||||
|
.with(DistantExit::new())
|
||||||
|
.build_with_rng(&mut rng);
|
||||||
|
World::print_map_metrics(&map);
|
||||||
|
World::new(width, height, map)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new_drunkard(width: u32, height: u32, seed: u32) -> World {
|
||||||
|
World::print_map_info(format!("Drunkard with the seed: {}", seed));
|
||||||
|
let mut rng = StdRng::seed_from_u64(seed as u64);
|
||||||
|
let map = MapBuilder::new(width as usize, height as usize)
|
||||||
|
.with(DrunkardsWalk::open_halls())
|
||||||
|
.with(AreaStartingPosition::new(XStart::RIGHT, YStart::BOTTOM))
|
||||||
|
.with(CullUnreachable::new())
|
||||||
|
.with(DistantExit::new())
|
||||||
|
.build_with_rng(&mut rng);
|
||||||
|
World::print_map_metrics(&map);
|
||||||
|
World::new(width, height, map)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new_maze(width: u32, height: u32, seed: u32) -> World {
|
||||||
|
World::print_map_info(format!("Maze with the seed: {}", seed));
|
||||||
|
let mut rng = StdRng::seed_from_u64(seed as u64);
|
||||||
|
let map = MapBuilder::new(width as usize, height as usize)
|
||||||
|
.with(MazeBuilder::new())
|
||||||
|
.with(AreaStartingPosition::new(XStart::LEFT, YStart::TOP))
|
||||||
|
.with(DistantExit::new())
|
||||||
|
.build_with_rng(&mut rng);
|
||||||
|
World::print_map_metrics(&map);
|
||||||
|
World::new(width, height, map)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new_voronoi(width: u32, height: u32, seed: u32) -> World {
|
||||||
|
World::print_map_info(format!("Voronoi Hive with the seed: {}", seed));
|
||||||
|
let mut rng = StdRng::seed_from_u64(seed as u64);
|
||||||
|
let map = MapBuilder::new(width as usize, height as usize)
|
||||||
|
.with(VoronoiHive::new())
|
||||||
|
.with(AreaStartingPosition::new(XStart::LEFT, YStart::TOP))
|
||||||
|
.with(DistantExit::new())
|
||||||
|
.build_with_rng(&mut rng);
|
||||||
|
World::print_map_metrics(&map);
|
||||||
|
World::new(width, height, map)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new_random(width: u32, height: u32, seed: u32) -> World {
|
||||||
|
let mut rng = rand::thread_rng();
|
||||||
|
let px = rng.gen::<f32>();
|
||||||
|
if px < 1.0/6.0 {
|
||||||
|
World::new_cellular_automata(width, height, seed)
|
||||||
|
} else if px < 2.0/6.0 {
|
||||||
|
World::new_simple_rooms(width, height, seed)
|
||||||
|
} else if px < 3.0/6.0 {
|
||||||
|
World::new_drunkard(width, height, seed)
|
||||||
|
} else if px < 4.0/6.0 {
|
||||||
|
World::new_bsp_rooms(width, height, seed)
|
||||||
|
} else if px < 5.0/6.0 {
|
||||||
|
World::new_bsp_rooms(width, height, seed)
|
||||||
|
} else {
|
||||||
|
World::new_maze(width, height, seed)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn width(&self) -> u32 {
|
||||||
|
self.width
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn height(&self) -> u32 {
|
||||||
|
self.height
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn tiles(&self) -> *const Cell {
|
||||||
|
self.tiles.as_ptr()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn player_pos(&self) -> Position {
|
||||||
|
let p = self.map.starting_point.unwrap_or(Point::new(0, 0));
|
||||||
|
Position { col: p.x, row: p.y }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn exit_pos(&self) -> Position {
|
||||||
|
let p = self.map.exit_point.unwrap_or(Point::new(0, 0));
|
||||||
|
Position { col: p.x, row: p.y }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn print_map_info(info: String) {
|
||||||
|
let window = web_sys::window().expect("no global `window` exists");
|
||||||
|
let document = window.document().expect("should have a document on window");
|
||||||
|
let div = document.get_element_by_id("map-info").expect("Need div with id: map-info");
|
||||||
|
div.set_inner_html(&info);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn print_map_metrics(map: &Map<NoData>) {
|
||||||
|
let window = web_sys::window().expect("no global `window` exists");
|
||||||
|
let document = window.document().expect("should have a document on window");
|
||||||
|
let div = document.get_element_by_id("map-metrics").expect("Need div with id: map-metrics");
|
||||||
|
let density = metric::density(map);
|
||||||
|
let path_length = metric::path_length(map);
|
||||||
|
let info = format!("Metrics: density: {}, path length: {}", density, path_length);
|
||||||
|
div.set_inner_html(&info);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[wasm_bindgen]
|
||||||
|
impl Position {
|
||||||
|
pub fn new(col: usize, row: usize) -> Position {
|
||||||
|
Position { col, row }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn col(&self) -> usize {
|
||||||
|
self.col
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn row(&self) -> usize {
|
||||||
|
self.row
|
||||||
|
}
|
||||||
|
}
|
12
demo/src/utils.rs
Normal file
12
demo/src/utils.rs
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
|
||||||
|
pub fn set_panic_hook() {
|
||||||
|
// When the `console_error_panic_hook` feature is enabled, we can call the
|
||||||
|
// `set_panic_hook` function at least once during initialization, and then
|
||||||
|
// we will get better error messages if our code ever panics.
|
||||||
|
//
|
||||||
|
// For more details see
|
||||||
|
// https://github.com/rustwasm/console_error_panic_hook#readme
|
||||||
|
#[cfg(feature = "console_error_panic_hook")]
|
||||||
|
console_error_panic_hook::set_once();
|
||||||
|
}
|
||||||
|
|
BIN
demo/www/.DS_Store
vendored
Normal file
BIN
demo/www/.DS_Store
vendored
Normal file
Binary file not shown.
4
demo/www/.gitignore
vendored
Normal file
4
demo/www/.gitignore
vendored
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
node_modules
|
||||||
|
dist
|
||||||
|
.bin/
|
||||||
|
package-lock.json
|
BIN
demo/www/assets/favicon.ico
Normal file
BIN
demo/www/assets/favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 31 KiB |
BIN
demo/www/assets/tiles.png
Normal file
BIN
demo/www/assets/tiles.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 44 KiB |
5
demo/www/bootstrap.js
vendored
Normal file
5
demo/www/bootstrap.js
vendored
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
// A dependency graph that contains any wasm must all be imported
|
||||||
|
// asynchronously. This `bootstrap.js` file does the single async import, so
|
||||||
|
// that no one else needs to worry about it again.
|
||||||
|
import("./index.js")
|
||||||
|
.catch(e => console.error("Error importing `index.js`:", e));
|
71
demo/www/index.html
Normal file
71
demo/www/index.html
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<link rel="icon" type="image/png" href="assets/favicon.ico" />
|
||||||
|
<title>Mapgen demo</title>
|
||||||
|
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css"
|
||||||
|
integrity="sha384-JcKb8q3iqJ61gNV9KGb8thSsNjpSL0n8PARn9HuZOnIxN0hoP+VmmDGMN5t9UJ0Z" crossorigin="anonymous">
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
background-color: lightgrey;
|
||||||
|
}
|
||||||
|
canvas {
|
||||||
|
padding-left: 0;
|
||||||
|
padding-right: 0;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<script src="./bootstrap.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<nav class="navbar navbar-expand-lg navbar-light bg-light">
|
||||||
|
<a class="navbar-brand" href="#">Mapgen demo</a>
|
||||||
|
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent"
|
||||||
|
aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
|
||||||
|
<span class="navbar-toggler-icon"></span>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<div class="mx-auto" id="navbarSupportedContent">
|
||||||
|
<ul class="navbar-nav">
|
||||||
|
<span class="navbar-text mr-2">Generator</span>
|
||||||
|
<li class="nav-item dropdown">
|
||||||
|
<button class="btn btn-secondary dropdown-toggle mr-2" type="button" id="generatorDropdown"
|
||||||
|
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||||
|
Random
|
||||||
|
</button>
|
||||||
|
<div class="dropdown-menu" aria-labelledby="generatorDropdown">
|
||||||
|
<a class="dropdown-item" id="cellular-automata-option">Cellular Automata</a>
|
||||||
|
<a class="dropdown-item" id="simple-rooms-option">Simple Rooms</a>
|
||||||
|
<a class="dropdown-item" id="bsp-rooms-option">BSP Rooms</a>
|
||||||
|
<a class="dropdown-item" id="bsp-interior-option">BSP Interior</a>
|
||||||
|
<a class="dropdown-item" id="drunkard-option">Drunkard Walk</a>
|
||||||
|
<a class="dropdown-item" id="maze-option">Maze</a>
|
||||||
|
<a class="dropdown-item" id="voronoi-option">Voronoi Hive</a>
|
||||||
|
<a class="dropdown-item" id="random-option">Random</a>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
<span class="navbar-text mr-2">Seed</span>
|
||||||
|
<input class="form-control mr-sm-2 w-25" id="seed" type="search" placeholder="random" aria-label="Seed">
|
||||||
|
<button class="btn btn-outline-success my-2 my-sm-0" type="submit" id="refresh">Refresh</button>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<a class="github-button" href="https://github.com/klangner/mapgen.rs" data-icon="octicon-star"
|
||||||
|
aria-label="Star ntkme/github-buttons on GitHub">Star</a>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<canvas id="mapgen-canvas"></canvas>
|
||||||
|
<div id="map-info" style="text-align: center"></div>
|
||||||
|
<div id="map-metrics" style="text-align: center"></div>
|
||||||
|
|
||||||
|
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"
|
||||||
|
integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js"
|
||||||
|
integrity="sha384-9/reFTGAW83EW2RDu2S0VKaIzap3H66lZH81PoYlFhbGU+6BZp6G7niu735Sk7lN" crossorigin="anonymous"></script>
|
||||||
|
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"
|
||||||
|
integrity="sha384-B4gt1jrGC7Jh4AgTPSdUtOBvfO8shuf57BaghqFfPlYxofvL8/KUEfYiJOMMV+rV" crossorigin="anonymous"></script>
|
||||||
|
<script async defer src="https://buttons.github.io/buttons.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
173
demo/www/index.js
Normal file
173
demo/www/index.js
Normal file
|
@ -0,0 +1,173 @@
|
||||||
|
import {Cell, World} from "mapgen-demo";
|
||||||
|
import { memory } from "mapgen-demo/mapgen_demo_bg";
|
||||||
|
|
||||||
|
const CANVAS_SIZE = 750;
|
||||||
|
const GRID_COLS = 80;
|
||||||
|
const GRID_ROWS = 50;
|
||||||
|
const CELL_SIZE = CANVAS_SIZE/GRID_ROWS;
|
||||||
|
const TILE_SIZE = 39;
|
||||||
|
|
||||||
|
// Init canvas
|
||||||
|
const canvas = document.getElementById("mapgen-canvas");
|
||||||
|
canvas.height = CELL_SIZE * GRID_ROWS;
|
||||||
|
canvas.width = CELL_SIZE * GRID_COLS;
|
||||||
|
const ctx = canvas.getContext('2d');
|
||||||
|
// Info box
|
||||||
|
const infoDiv = document.getElementById('map-info');
|
||||||
|
// API to the WASM
|
||||||
|
let world = null;
|
||||||
|
|
||||||
|
// Load tiles bitmap
|
||||||
|
let tiles_image = new Image();
|
||||||
|
tiles_image.src = 'assets/tiles.png';
|
||||||
|
|
||||||
|
// Take provided seed or generate new one
|
||||||
|
function get_seed() {
|
||||||
|
var seed_text = document.getElementById("seed").value;
|
||||||
|
if( seed_text.length > 0) {
|
||||||
|
return Number(seed_text);
|
||||||
|
}
|
||||||
|
return Date.now();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function setGenerator(e) {
|
||||||
|
document.getElementById("generatorDropdown").innerHTML = e.target.innerText;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Map generators
|
||||||
|
function refreshMap() {
|
||||||
|
var generator_name = document.getElementById("generatorDropdown").innerHTML;
|
||||||
|
|
||||||
|
switch(generator_name){
|
||||||
|
case "Cellular Automata":
|
||||||
|
world = World.new_cellular_automata(GRID_COLS, GRID_ROWS, get_seed());
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "Simple Rooms":
|
||||||
|
world = World.new_simple_rooms(GRID_COLS, GRID_ROWS, get_seed());
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "BSP Rooms":
|
||||||
|
world = World.new_bsp_rooms(GRID_COLS, GRID_ROWS, get_seed());
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "BSP Interior":
|
||||||
|
world = World.new_bsp_interior(GRID_COLS, GRID_ROWS, get_seed());
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "Drunkard Walk":
|
||||||
|
world = World.new_drunkard(GRID_COLS, GRID_ROWS, get_seed());
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "Maze":
|
||||||
|
world = World.new_maze(GRID_COLS, GRID_ROWS, get_seed());
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "Voronoi Hive":
|
||||||
|
world = World.new_voronoi(GRID_COLS, GRID_ROWS, get_seed());
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
world = World.new_random(GRID_COLS, GRID_ROWS, get_seed());
|
||||||
|
}
|
||||||
|
|
||||||
|
requestAnimationFrame(renderLoop);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Main loop
|
||||||
|
function renderLoop() {
|
||||||
|
// universe.tick();
|
||||||
|
drawCells();
|
||||||
|
requestAnimationFrame(renderLoop);
|
||||||
|
};
|
||||||
|
|
||||||
|
const getIndex = (row, column) => {
|
||||||
|
return row * GRID_COLS + column;
|
||||||
|
};
|
||||||
|
|
||||||
|
const is_inner_wall = (tiles, col, row) => {
|
||||||
|
for (let c = Math.max(col - 1, 0); c < Math.min(col + 2, GRID_COLS); c++) {
|
||||||
|
for (let r = Math.max(row - 1, 0); r < Math.min(row + 2, GRID_ROWS); r++) {
|
||||||
|
if ((c != col || r != row) && tiles[getIndex(r, c)] == Cell.Floor) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const draw_tile = (ctx, row, col, tile_type) => {
|
||||||
|
var tile_x = 0;
|
||||||
|
var tile_y = 0;
|
||||||
|
if (tile_type == "floor") {
|
||||||
|
tile_x = 3;
|
||||||
|
tile_y = 2;
|
||||||
|
} else if (tile_type == "wall") {
|
||||||
|
tile_x = 0;
|
||||||
|
tile_y = 3;
|
||||||
|
} else if (tile_type == "player") {
|
||||||
|
tile_x = 0;
|
||||||
|
tile_y = 8;
|
||||||
|
} else if (tile_type == "exit") {
|
||||||
|
tile_x = 10;
|
||||||
|
tile_y = 1;
|
||||||
|
} else {
|
||||||
|
tile_x = 18;
|
||||||
|
tile_y = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.drawImage(
|
||||||
|
tiles_image,
|
||||||
|
tile_x * TILE_SIZE + 3,
|
||||||
|
tile_y * TILE_SIZE + 3,
|
||||||
|
TILE_SIZE - 3,
|
||||||
|
TILE_SIZE - 3,
|
||||||
|
col * CELL_SIZE,
|
||||||
|
row * CELL_SIZE,
|
||||||
|
CELL_SIZE,
|
||||||
|
CELL_SIZE);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
const drawCells = () => {
|
||||||
|
const tilesPtr = world.tiles();
|
||||||
|
const tiles = new Uint8Array(memory.buffer, tilesPtr, GRID_COLS * GRID_ROWS);
|
||||||
|
|
||||||
|
// tiles
|
||||||
|
for (let row = 0; row < GRID_ROWS; row++) {
|
||||||
|
for (let col = 0; col < GRID_COLS; col++) {
|
||||||
|
const idx = getIndex(row, col);
|
||||||
|
if (tiles[idx] == Cell.Floor) {
|
||||||
|
draw_tile(ctx, row, col, "floor");
|
||||||
|
} else if (is_inner_wall(tiles, col, row)){
|
||||||
|
draw_tile(ctx, row, col, "inner-wall");
|
||||||
|
} else {
|
||||||
|
draw_tile(ctx, row, col, "wall");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Player position
|
||||||
|
let player = world.player_pos();
|
||||||
|
draw_tile(ctx, player.row(), player.col(), "player");
|
||||||
|
|
||||||
|
// Exit position
|
||||||
|
let exit = world.exit_pos();
|
||||||
|
draw_tile(ctx, exit.row(), exit.col(), "exit");
|
||||||
|
};
|
||||||
|
|
||||||
|
// Connect UI element
|
||||||
|
document.getElementById('cellular-automata-option').addEventListener('click', setGenerator);
|
||||||
|
document.getElementById('simple-rooms-option').addEventListener('click', setGenerator);
|
||||||
|
document.getElementById('bsp-rooms-option').addEventListener('click', setGenerator);
|
||||||
|
document.getElementById('drunkard-option').addEventListener('click', setGenerator);
|
||||||
|
document.getElementById('bsp-interior-option').addEventListener('click', setGenerator);
|
||||||
|
document.getElementById('maze-option').addEventListener('click', setGenerator);
|
||||||
|
document.getElementById('voronoi-option').addEventListener('click', setGenerator);
|
||||||
|
document.getElementById('random-option').addEventListener('click', setGenerator);
|
||||||
|
|
||||||
|
document.getElementById('refresh').addEventListener('click', refreshMap);
|
||||||
|
|
||||||
|
refreshMap();
|
41
demo/www/package.json
Normal file
41
demo/www/package.json
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
{
|
||||||
|
"name": "create-wasm-app",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"description": "create an app to consume rust-generated wasm packages",
|
||||||
|
"main": "index.js",
|
||||||
|
"bin": {
|
||||||
|
"create-wasm-app": ".bin/create-wasm-app.js"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"build": "webpack --config webpack.config.js",
|
||||||
|
"server": "webpack-dev-server",
|
||||||
|
"deploy": "gh-pages -d dist"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git+https://github.com/rustwasm/create-wasm-app.git"
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"webassembly",
|
||||||
|
"wasm",
|
||||||
|
"rust",
|
||||||
|
"webpack"
|
||||||
|
],
|
||||||
|
"author": "Ashley Williams <ashley666ashley@gmail.com>",
|
||||||
|
"license": "(MIT OR Apache-2.0)",
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/rustwasm/create-wasm-app/issues"
|
||||||
|
},
|
||||||
|
"homepage": "https://github.com/rustwasm/create-wasm-app#readme",
|
||||||
|
"dependencies": {
|
||||||
|
"gh-pages": "^3.1.0",
|
||||||
|
"mapgen-demo": "file:../pkg"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"hello-wasm-pack": "^0.1.0",
|
||||||
|
"webpack": "^4.29.3",
|
||||||
|
"webpack-cli": "^3.1.0",
|
||||||
|
"webpack-dev-server": "^3.1.5",
|
||||||
|
"copy-webpack-plugin": "^5.0.0"
|
||||||
|
}
|
||||||
|
}
|
14
demo/www/webpack.config.js
Normal file
14
demo/www/webpack.config.js
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
const CopyWebpackPlugin = require("copy-webpack-plugin");
|
||||||
|
const path = require('path');
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
entry: "./bootstrap.js",
|
||||||
|
output: {
|
||||||
|
path: path.resolve(__dirname, "../../docs"),
|
||||||
|
filename: "bootstrap.js",
|
||||||
|
},
|
||||||
|
mode: "development",
|
||||||
|
plugins: [
|
||||||
|
new CopyWebpackPlugin(['index.html', { from: 'assets', to: 'assets' }])
|
||||||
|
],
|
||||||
|
};
|
72
docs/0.bootstrap.js
Normal file
72
docs/0.bootstrap.js
Normal file
File diff suppressed because one or more lines are too long
BIN
docs/3450392053799dfed08d.module.wasm
Normal file
BIN
docs/3450392053799dfed08d.module.wasm
Normal file
Binary file not shown.
BIN
docs/3bda724f23e860df0b9c.module.wasm
Normal file
BIN
docs/3bda724f23e860df0b9c.module.wasm
Normal file
Binary file not shown.
BIN
docs/98c7bb1ad7a2b17fcade.module.wasm
Normal file
BIN
docs/98c7bb1ad7a2b17fcade.module.wasm
Normal file
Binary file not shown.
BIN
docs/assets/favicon.ico
Normal file
BIN
docs/assets/favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 31 KiB |
BIN
docs/assets/tiles.png
Normal file
BIN
docs/assets/tiles.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 44 KiB |
348
docs/bootstrap.js
vendored
Normal file
348
docs/bootstrap.js
vendored
Normal file
|
@ -0,0 +1,348 @@
|
||||||
|
/******/ (function(modules) { // webpackBootstrap
|
||||||
|
/******/ // install a JSONP callback for chunk loading
|
||||||
|
/******/ function webpackJsonpCallback(data) {
|
||||||
|
/******/ var chunkIds = data[0];
|
||||||
|
/******/ var moreModules = data[1];
|
||||||
|
/******/
|
||||||
|
/******/
|
||||||
|
/******/ // add "moreModules" to the modules object,
|
||||||
|
/******/ // then flag all "chunkIds" as loaded and fire callback
|
||||||
|
/******/ var moduleId, chunkId, i = 0, resolves = [];
|
||||||
|
/******/ for(;i < chunkIds.length; i++) {
|
||||||
|
/******/ chunkId = chunkIds[i];
|
||||||
|
/******/ if(Object.prototype.hasOwnProperty.call(installedChunks, chunkId) && installedChunks[chunkId]) {
|
||||||
|
/******/ resolves.push(installedChunks[chunkId][0]);
|
||||||
|
/******/ }
|
||||||
|
/******/ installedChunks[chunkId] = 0;
|
||||||
|
/******/ }
|
||||||
|
/******/ for(moduleId in moreModules) {
|
||||||
|
/******/ if(Object.prototype.hasOwnProperty.call(moreModules, moduleId)) {
|
||||||
|
/******/ modules[moduleId] = moreModules[moduleId];
|
||||||
|
/******/ }
|
||||||
|
/******/ }
|
||||||
|
/******/ if(parentJsonpFunction) parentJsonpFunction(data);
|
||||||
|
/******/
|
||||||
|
/******/ while(resolves.length) {
|
||||||
|
/******/ resolves.shift()();
|
||||||
|
/******/ }
|
||||||
|
/******/
|
||||||
|
/******/ };
|
||||||
|
/******/
|
||||||
|
/******/
|
||||||
|
/******/ // The module cache
|
||||||
|
/******/ var installedModules = {};
|
||||||
|
/******/
|
||||||
|
/******/ // object to store loaded and loading chunks
|
||||||
|
/******/ // undefined = chunk not loaded, null = chunk preloaded/prefetched
|
||||||
|
/******/ // Promise = chunk loading, 0 = chunk loaded
|
||||||
|
/******/ var installedChunks = {
|
||||||
|
/******/ "main": 0
|
||||||
|
/******/ };
|
||||||
|
/******/
|
||||||
|
/******/
|
||||||
|
/******/
|
||||||
|
/******/ // script path function
|
||||||
|
/******/ function jsonpScriptSrc(chunkId) {
|
||||||
|
/******/ return __webpack_require__.p + "" + chunkId + ".bootstrap.js"
|
||||||
|
/******/ }
|
||||||
|
/******/
|
||||||
|
/******/ // object to store loaded and loading wasm modules
|
||||||
|
/******/ var installedWasmModules = {};
|
||||||
|
/******/
|
||||||
|
/******/ function promiseResolve() { return Promise.resolve(); }
|
||||||
|
/******/
|
||||||
|
/******/ var wasmImportObjects = {
|
||||||
|
/******/ "../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_c73f06b5ed8b878d": function(p0i32,p1i32) {
|
||||||
|
/******/ return installedModules["../pkg/mapgen_demo_bg.js"].exports["__wbg_getRandomValues_c73f06b5ed8b878d"](p0i32,p1i32);
|
||||||
|
/******/ },
|
||||||
|
/******/ "__wbg_randomFillSync_5fa0a72035c7bfd9": function(p0i32,p1i32,p2i32) {
|
||||||
|
/******/ return installedModules["../pkg/mapgen_demo_bg.js"].exports["__wbg_randomFillSync_5fa0a72035c7bfd9"](p0i32,p1i32,p2i32);
|
||||||
|
/******/ },
|
||||||
|
/******/ "__wbg_self_23b14d60c8dbf9da": function() {
|
||||||
|
/******/ return installedModules["../pkg/mapgen_demo_bg.js"].exports["__wbg_self_23b14d60c8dbf9da"]();
|
||||||
|
/******/ },
|
||||||
|
/******/ "__wbg_static_accessor_MODULE_ff1e47f7076e0ee1": function() {
|
||||||
|
/******/ return installedModules["../pkg/mapgen_demo_bg.js"].exports["__wbg_static_accessor_MODULE_ff1e47f7076e0ee1"]();
|
||||||
|
/******/ },
|
||||||
|
/******/ "__wbg_require_1dab18ea211c4fa1": function(p0i32,p1i32,p2i32) {
|
||||||
|
/******/ return installedModules["../pkg/mapgen_demo_bg.js"].exports["__wbg_require_1dab18ea211c4fa1"](p0i32,p1i32,p2i32);
|
||||||
|
/******/ },
|
||||||
|
/******/ "__wbg_crypto_df96f3577c8a9bae": function(p0i32) {
|
||||||
|
/******/ return installedModules["../pkg/mapgen_demo_bg.js"].exports["__wbg_crypto_df96f3577c8a9bae"](p0i32);
|
||||||
|
/******/ },
|
||||||
|
/******/ "__wbg_msCrypto_331efcdb9be40d7c": function(p0i32) {
|
||||||
|
/******/ return installedModules["../pkg/mapgen_demo_bg.js"].exports["__wbg_msCrypto_331efcdb9be40d7c"](p0i32);
|
||||||
|
/******/ },
|
||||||
|
/******/ "__wbindgen_is_undefined": function(p0i32) {
|
||||||
|
/******/ return installedModules["../pkg/mapgen_demo_bg.js"].exports["__wbindgen_is_undefined"](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"]();
|
||||||
|
/******/ },
|
||||||
|
/******/ "__wbg_buffer_49131c283a06686f": function(p0i32) {
|
||||||
|
/******/ return installedModules["../pkg/mapgen_demo_bg.js"].exports["__wbg_buffer_49131c283a06686f"](p0i32);
|
||||||
|
/******/ },
|
||||||
|
/******/ "__wbg_length_2b13641a9d906653": function(p0i32) {
|
||||||
|
/******/ return installedModules["../pkg/mapgen_demo_bg.js"].exports["__wbg_length_2b13641a9d906653"](p0i32);
|
||||||
|
/******/ },
|
||||||
|
/******/ "__wbg_new_9b295d24cf1d706f": function(p0i32) {
|
||||||
|
/******/ return installedModules["../pkg/mapgen_demo_bg.js"].exports["__wbg_new_9b295d24cf1d706f"](p0i32);
|
||||||
|
/******/ },
|
||||||
|
/******/ "__wbg_set_3bb960a9975f3cd2": function(p0i32,p1i32,p2i32) {
|
||||||
|
/******/ return installedModules["../pkg/mapgen_demo_bg.js"].exports["__wbg_set_3bb960a9975f3cd2"](p0i32,p1i32,p2i32);
|
||||||
|
/******/ },
|
||||||
|
/******/ "__wbg_newwithlength_3c570aeea9a95954": function(p0i32) {
|
||||||
|
/******/ return installedModules["../pkg/mapgen_demo_bg.js"].exports["__wbg_newwithlength_3c570aeea9a95954"](p0i32);
|
||||||
|
/******/ },
|
||||||
|
/******/ "__wbg_subarray_4eaeb3de00cf1955": function(p0i32,p1i32,p2i32) {
|
||||||
|
/******/ return installedModules["../pkg/mapgen_demo_bg.js"].exports["__wbg_subarray_4eaeb3de00cf1955"](p0i32,p1i32,p2i32);
|
||||||
|
/******/ },
|
||||||
|
/******/ "__wbindgen_throw": function(p0i32,p1i32) {
|
||||||
|
/******/ return installedModules["../pkg/mapgen_demo_bg.js"].exports["__wbindgen_throw"](p0i32,p1i32);
|
||||||
|
/******/ },
|
||||||
|
/******/ "__wbindgen_memory": function() {
|
||||||
|
/******/ return installedModules["../pkg/mapgen_demo_bg.js"].exports["__wbindgen_memory"]();
|
||||||
|
/******/ }
|
||||||
|
/******/ }
|
||||||
|
/******/ };
|
||||||
|
/******/ },
|
||||||
|
/******/ };
|
||||||
|
/******/
|
||||||
|
/******/ // The require function
|
||||||
|
/******/ function __webpack_require__(moduleId) {
|
||||||
|
/******/
|
||||||
|
/******/ // Check if module is in cache
|
||||||
|
/******/ if(installedModules[moduleId]) {
|
||||||
|
/******/ return installedModules[moduleId].exports;
|
||||||
|
/******/ }
|
||||||
|
/******/ // Create a new module (and put it into the cache)
|
||||||
|
/******/ var module = installedModules[moduleId] = {
|
||||||
|
/******/ i: moduleId,
|
||||||
|
/******/ l: false,
|
||||||
|
/******/ exports: {}
|
||||||
|
/******/ };
|
||||||
|
/******/
|
||||||
|
/******/ // Execute the module function
|
||||||
|
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
|
||||||
|
/******/
|
||||||
|
/******/ // Flag the module as loaded
|
||||||
|
/******/ module.l = true;
|
||||||
|
/******/
|
||||||
|
/******/ // Return the exports of the module
|
||||||
|
/******/ return module.exports;
|
||||||
|
/******/ }
|
||||||
|
/******/
|
||||||
|
/******/ // This file contains only the entry chunk.
|
||||||
|
/******/ // The chunk loading function for additional chunks
|
||||||
|
/******/ __webpack_require__.e = function requireEnsure(chunkId) {
|
||||||
|
/******/ var promises = [];
|
||||||
|
/******/
|
||||||
|
/******/
|
||||||
|
/******/ // JSONP chunk loading for javascript
|
||||||
|
/******/
|
||||||
|
/******/ var installedChunkData = installedChunks[chunkId];
|
||||||
|
/******/ if(installedChunkData !== 0) { // 0 means "already installed".
|
||||||
|
/******/
|
||||||
|
/******/ // a Promise means "currently loading".
|
||||||
|
/******/ if(installedChunkData) {
|
||||||
|
/******/ promises.push(installedChunkData[2]);
|
||||||
|
/******/ } else {
|
||||||
|
/******/ // setup Promise in chunk cache
|
||||||
|
/******/ var promise = new Promise(function(resolve, reject) {
|
||||||
|
/******/ installedChunkData = installedChunks[chunkId] = [resolve, reject];
|
||||||
|
/******/ });
|
||||||
|
/******/ promises.push(installedChunkData[2] = promise);
|
||||||
|
/******/
|
||||||
|
/******/ // start chunk loading
|
||||||
|
/******/ var script = document.createElement('script');
|
||||||
|
/******/ var onScriptComplete;
|
||||||
|
/******/
|
||||||
|
/******/ script.charset = 'utf-8';
|
||||||
|
/******/ script.timeout = 120;
|
||||||
|
/******/ if (__webpack_require__.nc) {
|
||||||
|
/******/ script.setAttribute("nonce", __webpack_require__.nc);
|
||||||
|
/******/ }
|
||||||
|
/******/ script.src = jsonpScriptSrc(chunkId);
|
||||||
|
/******/
|
||||||
|
/******/ // create error before stack unwound to get useful stacktrace later
|
||||||
|
/******/ var error = new Error();
|
||||||
|
/******/ onScriptComplete = function (event) {
|
||||||
|
/******/ // avoid mem leaks in IE.
|
||||||
|
/******/ script.onerror = script.onload = null;
|
||||||
|
/******/ clearTimeout(timeout);
|
||||||
|
/******/ var chunk = installedChunks[chunkId];
|
||||||
|
/******/ if(chunk !== 0) {
|
||||||
|
/******/ if(chunk) {
|
||||||
|
/******/ var errorType = event && (event.type === 'load' ? 'missing' : event.type);
|
||||||
|
/******/ var realSrc = event && event.target && event.target.src;
|
||||||
|
/******/ error.message = 'Loading chunk ' + chunkId + ' failed.\n(' + errorType + ': ' + realSrc + ')';
|
||||||
|
/******/ error.name = 'ChunkLoadError';
|
||||||
|
/******/ error.type = errorType;
|
||||||
|
/******/ error.request = realSrc;
|
||||||
|
/******/ chunk[1](error);
|
||||||
|
/******/ }
|
||||||
|
/******/ installedChunks[chunkId] = undefined;
|
||||||
|
/******/ }
|
||||||
|
/******/ };
|
||||||
|
/******/ var timeout = setTimeout(function(){
|
||||||
|
/******/ onScriptComplete({ type: 'timeout', target: script });
|
||||||
|
/******/ }, 120000);
|
||||||
|
/******/ script.onerror = script.onload = onScriptComplete;
|
||||||
|
/******/ document.head.appendChild(script);
|
||||||
|
/******/ }
|
||||||
|
/******/ }
|
||||||
|
/******/
|
||||||
|
/******/ // Fetch + compile chunk loading for webassembly
|
||||||
|
/******/
|
||||||
|
/******/ var wasmModules = {"0":["../pkg/mapgen_demo_bg.wasm"]}[chunkId] || [];
|
||||||
|
/******/
|
||||||
|
/******/ wasmModules.forEach(function(wasmModuleId) {
|
||||||
|
/******/ var installedWasmModuleData = installedWasmModules[wasmModuleId];
|
||||||
|
/******/
|
||||||
|
/******/ // a Promise means "currently loading" or "already loaded".
|
||||||
|
/******/ if(installedWasmModuleData)
|
||||||
|
/******/ promises.push(installedWasmModuleData);
|
||||||
|
/******/ else {
|
||||||
|
/******/ var importObject = wasmImportObjects[wasmModuleId]();
|
||||||
|
/******/ var req = fetch(__webpack_require__.p + "" + {"../pkg/mapgen_demo_bg.wasm":"98c7bb1ad7a2b17fcade"}[wasmModuleId] + ".module.wasm");
|
||||||
|
/******/ var promise;
|
||||||
|
/******/ if(importObject instanceof Promise && typeof WebAssembly.compileStreaming === 'function') {
|
||||||
|
/******/ promise = Promise.all([WebAssembly.compileStreaming(req), importObject]).then(function(items) {
|
||||||
|
/******/ return WebAssembly.instantiate(items[0], items[1]);
|
||||||
|
/******/ });
|
||||||
|
/******/ } else if(typeof WebAssembly.instantiateStreaming === 'function') {
|
||||||
|
/******/ promise = WebAssembly.instantiateStreaming(req, importObject);
|
||||||
|
/******/ } else {
|
||||||
|
/******/ var bytesPromise = req.then(function(x) { return x.arrayBuffer(); });
|
||||||
|
/******/ promise = bytesPromise.then(function(bytes) {
|
||||||
|
/******/ return WebAssembly.instantiate(bytes, importObject);
|
||||||
|
/******/ });
|
||||||
|
/******/ }
|
||||||
|
/******/ promises.push(installedWasmModules[wasmModuleId] = promise.then(function(res) {
|
||||||
|
/******/ return __webpack_require__.w[wasmModuleId] = (res.instance || res).exports;
|
||||||
|
/******/ }));
|
||||||
|
/******/ }
|
||||||
|
/******/ });
|
||||||
|
/******/ return Promise.all(promises);
|
||||||
|
/******/ };
|
||||||
|
/******/
|
||||||
|
/******/ // expose the modules object (__webpack_modules__)
|
||||||
|
/******/ __webpack_require__.m = modules;
|
||||||
|
/******/
|
||||||
|
/******/ // expose the module cache
|
||||||
|
/******/ __webpack_require__.c = installedModules;
|
||||||
|
/******/
|
||||||
|
/******/ // define getter function for harmony exports
|
||||||
|
/******/ __webpack_require__.d = function(exports, name, getter) {
|
||||||
|
/******/ if(!__webpack_require__.o(exports, name)) {
|
||||||
|
/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter });
|
||||||
|
/******/ }
|
||||||
|
/******/ };
|
||||||
|
/******/
|
||||||
|
/******/ // define __esModule on exports
|
||||||
|
/******/ __webpack_require__.r = function(exports) {
|
||||||
|
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
|
||||||
|
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
||||||
|
/******/ }
|
||||||
|
/******/ Object.defineProperty(exports, '__esModule', { value: true });
|
||||||
|
/******/ };
|
||||||
|
/******/
|
||||||
|
/******/ // create a fake namespace object
|
||||||
|
/******/ // mode & 1: value is a module id, require it
|
||||||
|
/******/ // mode & 2: merge all properties of value into the ns
|
||||||
|
/******/ // mode & 4: return value when already ns object
|
||||||
|
/******/ // mode & 8|1: behave like require
|
||||||
|
/******/ __webpack_require__.t = function(value, mode) {
|
||||||
|
/******/ if(mode & 1) value = __webpack_require__(value);
|
||||||
|
/******/ if(mode & 8) return value;
|
||||||
|
/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
|
||||||
|
/******/ var ns = Object.create(null);
|
||||||
|
/******/ __webpack_require__.r(ns);
|
||||||
|
/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value });
|
||||||
|
/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
|
||||||
|
/******/ return ns;
|
||||||
|
/******/ };
|
||||||
|
/******/
|
||||||
|
/******/ // getDefaultExport function for compatibility with non-harmony modules
|
||||||
|
/******/ __webpack_require__.n = function(module) {
|
||||||
|
/******/ var getter = module && module.__esModule ?
|
||||||
|
/******/ function getDefault() { return module['default']; } :
|
||||||
|
/******/ function getModuleExports() { return module; };
|
||||||
|
/******/ __webpack_require__.d(getter, 'a', getter);
|
||||||
|
/******/ return getter;
|
||||||
|
/******/ };
|
||||||
|
/******/
|
||||||
|
/******/ // Object.prototype.hasOwnProperty.call
|
||||||
|
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
|
||||||
|
/******/
|
||||||
|
/******/ // __webpack_public_path__
|
||||||
|
/******/ __webpack_require__.p = "";
|
||||||
|
/******/
|
||||||
|
/******/ // on error function for async loading
|
||||||
|
/******/ __webpack_require__.oe = function(err) { console.error(err); throw err; };
|
||||||
|
/******/
|
||||||
|
/******/ // object with all WebAssembly.instance exports
|
||||||
|
/******/ __webpack_require__.w = {};
|
||||||
|
/******/
|
||||||
|
/******/ var jsonpArray = window["webpackJsonp"] = window["webpackJsonp"] || [];
|
||||||
|
/******/ var oldJsonpFunction = jsonpArray.push.bind(jsonpArray);
|
||||||
|
/******/ jsonpArray.push = webpackJsonpCallback;
|
||||||
|
/******/ jsonpArray = jsonpArray.slice();
|
||||||
|
/******/ for(var i = 0; i < jsonpArray.length; i++) webpackJsonpCallback(jsonpArray[i]);
|
||||||
|
/******/ var parentJsonpFunction = oldJsonpFunction;
|
||||||
|
/******/
|
||||||
|
/******/
|
||||||
|
/******/ // Load entry module and return exports
|
||||||
|
/******/ return __webpack_require__(__webpack_require__.s = "./bootstrap.js");
|
||||||
|
/******/ })
|
||||||
|
/************************************************************************/
|
||||||
|
/******/ ({
|
||||||
|
|
||||||
|
/***/ "./bootstrap.js":
|
||||||
|
/*!**********************!*\
|
||||||
|
!*** ./bootstrap.js ***!
|
||||||
|
\**********************/
|
||||||
|
/*! no static exports found */
|
||||||
|
/***/ (function(module, exports, __webpack_require__) {
|
||||||
|
|
||||||
|
eval("// A dependency graph that contains any wasm must all be imported\n// asynchronously. This `bootstrap.js` file does the single async import, so\n// that no one else needs to worry about it again.\n__webpack_require__.e(/*! import() */ 0).then(__webpack_require__.bind(null, /*! ./index.js */ \"./index.js\"))\n .catch(e => console.error(\"Error importing `index.js`:\", e));\n\n\n//# sourceURL=webpack:///./bootstrap.js?");
|
||||||
|
|
||||||
|
/***/ })
|
||||||
|
|
||||||
|
/******/ });
|
BIN
docs/f22182091a16774e383e.module.wasm
Normal file
BIN
docs/f22182091a16774e383e.module.wasm
Normal file
Binary file not shown.
BIN
docs/fa6c9d72e1d9a518ed31.module.wasm
Normal file
BIN
docs/fa6c9d72e1d9a518ed31.module.wasm
Normal file
Binary file not shown.
71
docs/index.html
Normal file
71
docs/index.html
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<link rel="icon" type="image/png" href="assets/favicon.ico" />
|
||||||
|
<title>Mapgen demo</title>
|
||||||
|
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css"
|
||||||
|
integrity="sha384-JcKb8q3iqJ61gNV9KGb8thSsNjpSL0n8PARn9HuZOnIxN0hoP+VmmDGMN5t9UJ0Z" crossorigin="anonymous">
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
background-color: lightgrey;
|
||||||
|
}
|
||||||
|
canvas {
|
||||||
|
padding-left: 0;
|
||||||
|
padding-right: 0;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<script src="./bootstrap.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<nav class="navbar navbar-expand-lg navbar-light bg-light">
|
||||||
|
<a class="navbar-brand" href="#">Mapgen demo</a>
|
||||||
|
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent"
|
||||||
|
aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
|
||||||
|
<span class="navbar-toggler-icon"></span>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<div class="mx-auto" id="navbarSupportedContent">
|
||||||
|
<ul class="navbar-nav">
|
||||||
|
<span class="navbar-text mr-2">Generator</span>
|
||||||
|
<li class="nav-item dropdown">
|
||||||
|
<button class="btn btn-secondary dropdown-toggle mr-2" type="button" id="generatorDropdown"
|
||||||
|
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||||
|
Random
|
||||||
|
</button>
|
||||||
|
<div class="dropdown-menu" aria-labelledby="generatorDropdown">
|
||||||
|
<a class="dropdown-item" id="cellular-automata-option">Cellular Automata</a>
|
||||||
|
<a class="dropdown-item" id="simple-rooms-option">Simple Rooms</a>
|
||||||
|
<a class="dropdown-item" id="bsp-rooms-option">BSP Rooms</a>
|
||||||
|
<a class="dropdown-item" id="bsp-interior-option">BSP Interior</a>
|
||||||
|
<a class="dropdown-item" id="drunkard-option">Drunkard Walk</a>
|
||||||
|
<a class="dropdown-item" id="maze-option">Maze</a>
|
||||||
|
<a class="dropdown-item" id="voronoi-option">Voronoi Hive</a>
|
||||||
|
<a class="dropdown-item" id="random-option">Random</a>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
<span class="navbar-text mr-2">Seed</span>
|
||||||
|
<input class="form-control mr-sm-2 w-25" id="seed" type="search" placeholder="random" aria-label="Seed">
|
||||||
|
<button class="btn btn-outline-success my-2 my-sm-0" type="submit" id="refresh">Refresh</button>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<a class="github-button" href="https://github.com/klangner/mapgen.rs" data-icon="octicon-star"
|
||||||
|
aria-label="Star ntkme/github-buttons on GitHub">Star</a>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<canvas id="mapgen-canvas"></canvas>
|
||||||
|
<div id="map-info" style="text-align: center"></div>
|
||||||
|
<div id="map-metrics" style="text-align: center"></div>
|
||||||
|
|
||||||
|
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"
|
||||||
|
integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js"
|
||||||
|
integrity="sha384-9/reFTGAW83EW2RDu2S0VKaIzap3H66lZH81PoYlFhbGU+6BZp6G7niu735Sk7lN" crossorigin="anonymous"></script>
|
||||||
|
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"
|
||||||
|
integrity="sha384-B4gt1jrGC7Jh4AgTPSdUtOBvfO8shuf57BaghqFfPlYxofvL8/KUEfYiJOMMV+rV" crossorigin="anonymous"></script>
|
||||||
|
<script async defer src="https://buttons.github.io/buttons.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -1,4 +1,4 @@
|
||||||
use here_be_dragons::*;
|
use mapgen::*;
|
||||||
use rand::prelude::*;
|
use rand::prelude::*;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use here_be_dragons::*;
|
use mapgen::*;
|
||||||
use rand::prelude::*;
|
use rand::prelude::*;
|
||||||
use std::time::{SystemTime, UNIX_EPOCH};
|
use std::time::{SystemTime, UNIX_EPOCH};
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use here_be_dragons::{
|
use mapgen::{
|
||||||
filter::{
|
filter::{
|
||||||
AreaStartingPosition, CellularAutomata, CullUnreachable, NoiseGenerator, XStart, YStart,
|
AreaStartingPosition, CellularAutomata, CullUnreachable, NoiseGenerator, XStart, YStart,
|
||||||
},
|
},
|
||||||
|
@ -16,8 +16,8 @@ impl MapFilter<MyData> for IncrementData {
|
||||||
fn modify_map(
|
fn modify_map(
|
||||||
&self,
|
&self,
|
||||||
_rng: &mut rand::prelude::StdRng,
|
_rng: &mut rand::prelude::StdRng,
|
||||||
map: &here_be_dragons::Map<MyData>,
|
map: &mapgen::Map<MyData>,
|
||||||
) -> here_be_dragons::Map<MyData> {
|
) -> mapgen::Map<MyData> {
|
||||||
let mut map = map.clone();
|
let mut map = map.clone();
|
||||||
map.data.value += 1;
|
map.data.value += 1;
|
||||||
map
|
map
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use here_be_dragons::{
|
use mapgen::{
|
||||||
filter::{
|
filter::{
|
||||||
AreaStartingPosition, CellularAutomata, CullUnreachable, NoiseGenerator, XStart, YStart,
|
AreaStartingPosition, CellularAutomata, CullUnreachable, NoiseGenerator, XStart, YStart,
|
||||||
},
|
},
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
//! ---
|
//! ---
|
||||||
//! use rand::prelude::*;
|
//! use rand::prelude::*;
|
||||||
//! use crate::common::geometry::Point;
|
//! use crate::common::geometry::Point;
|
||||||
//! use here_be_dragons::dungeon::{
|
//! use mapgen::dungeon::{
|
||||||
//! MapModifier,
|
//! MapModifier,
|
||||||
//! map::{Map, TileType},
|
//! map::{Map, TileType},
|
||||||
//! starting_point::{AreaStartingPosition, XStart, YStart}
|
//! starting_point::{AreaStartingPosition, XStart, YStart}
|
||||||
|
@ -63,7 +63,7 @@ impl<D: Clone + Default> DijkstraMap<D> {
|
||||||
/// WARNING: Will give incorrect results when used with non-uniform exit costs. Much slower
|
/// WARNING: Will give incorrect results when used with non-uniform exit costs. Much slower
|
||||||
/// algorithm required to support that.
|
/// algorithm required to support that.
|
||||||
fn build(&mut self, map: &Map<D>) {
|
fn build(&mut self, map: &Map<D>) {
|
||||||
let mapsize = self.size_x * self.size_y;
|
let mapsize: usize = (self.size_x * self.size_y) as usize;
|
||||||
let mut open_list: VecDeque<((usize, usize), f32)> = VecDeque::with_capacity(mapsize);
|
let mut open_list: VecDeque<((usize, usize), f32)> = VecDeque::with_capacity(mapsize);
|
||||||
|
|
||||||
if let Some(pos) = map.starting_point {
|
if let Some(pos) = map.starting_point {
|
||||||
|
|
|
@ -6,8 +6,8 @@
|
||||||
//! Example generator usage:
|
//! Example generator usage:
|
||||||
//! ```
|
//! ```
|
||||||
//! use rand::prelude::*;
|
//! use rand::prelude::*;
|
||||||
//! use here_be_dragons::{Map, MapFilter, NoData};
|
//! use mapgen::{Map, MapFilter, NoData};
|
||||||
//! use here_be_dragons::filter::{
|
//! use mapgen::filter::{
|
||||||
//! BspInterior
|
//! BspInterior
|
||||||
//! };
|
//! };
|
||||||
//!
|
//!
|
||||||
|
@ -130,12 +130,12 @@ mod tests {
|
||||||
let gen = BspInterior::<NoData>::new();
|
let gen = BspInterior::<NoData>::new();
|
||||||
let map = gen.modify_map(&mut rng, &Map::new(80, 50));
|
let map = gen.modify_map(&mut rng, &Map::new(80, 50));
|
||||||
for i in 0..80 {
|
for i in 0..80 {
|
||||||
assert!(map.at(i, 0).unwrap().is_blocked());
|
assert!(map.at(i, 0).is_blocked());
|
||||||
assert!(map.at(i, 49).unwrap().is_blocked());
|
assert!(map.at(i, 49).is_blocked());
|
||||||
}
|
}
|
||||||
for j in 0..50 {
|
for j in 0..50 {
|
||||||
assert!(map.at(0, j).unwrap().is_blocked());
|
assert!(map.at(0, j).is_blocked());
|
||||||
assert!(map.at(79, j).unwrap().is_blocked());
|
assert!(map.at(79, j).is_blocked());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,8 +6,8 @@
|
||||||
//! Example generator usage:
|
//! Example generator usage:
|
||||||
//! ```
|
//! ```
|
||||||
//! use rand::prelude::*;
|
//! use rand::prelude::*;
|
||||||
//! use here_be_dragons::{Map, MapFilter, NoData};
|
//! use mapgen::{Map, MapFilter, NoData};
|
||||||
//! use here_be_dragons::filter::BspRooms;
|
//! use mapgen::filter::BspRooms;
|
||||||
//!
|
//!
|
||||||
//! let mut rng = StdRng::seed_from_u64(100);
|
//! let mut rng = StdRng::seed_from_u64(100);
|
||||||
//! let gen = BspRooms::<NoData>::new();
|
//! let gen = BspRooms::<NoData>::new();
|
||||||
|
@ -110,8 +110,8 @@ impl<D: Clone + Default> BspRooms<D> {
|
||||||
let rect_width = rect.width();
|
let rect_width = rect.width();
|
||||||
let rect_height = rect.height();
|
let rect_height = rect.height();
|
||||||
|
|
||||||
let w = usize::max(3, rng.random_range(1, usize::min(rect_width, 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, 20))) + 1;
|
let h = usize::max(3, rng.random_range(1, usize::min(rect_height as usize, 20))) + 1;
|
||||||
|
|
||||||
result.x1 += rng.random_range(0, 6);
|
result.x1 += rng.random_range(0, 6);
|
||||||
result.y1 += rng.random_range(0, 6);
|
result.y1 += rng.random_range(0, 6);
|
||||||
|
@ -150,15 +150,11 @@ impl<D: Clone + Default> BspRooms<D> {
|
||||||
if y < 1 {
|
if y < 1 {
|
||||||
can_build = false;
|
can_build = false;
|
||||||
}
|
}
|
||||||
if can_build {
|
if can_build && map.at(x as usize, y as usize).is_walkable() {
|
||||||
if let Some(tile) = map.at(x, y) {
|
|
||||||
if tile.is_walkable() {
|
|
||||||
can_build = false;
|
can_build = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
can_build
|
can_build
|
||||||
}
|
}
|
||||||
|
@ -178,12 +174,12 @@ mod tests {
|
||||||
let gen = BspRooms::<NoData>::new();
|
let gen = BspRooms::<NoData>::new();
|
||||||
let map = gen.modify_map(&mut rng, &Map::new(80, 50));
|
let map = gen.modify_map(&mut rng, &Map::new(80, 50));
|
||||||
for i in 0..80 {
|
for i in 0..80 {
|
||||||
assert!(map.at(i, 0).unwrap().is_blocked());
|
assert!(map.at(i, 0).is_blocked());
|
||||||
assert!(map.at(i, 49).unwrap().is_blocked());
|
assert!(map.at(i, 49).is_blocked());
|
||||||
}
|
}
|
||||||
for j in 0..50 {
|
for j in 0..50 {
|
||||||
assert!(map.at(0, j).unwrap().is_blocked());
|
assert!(map.at(0, j).is_blocked());
|
||||||
assert!(map.at(79, j).unwrap().is_blocked());
|
assert!(map.at(79, j).is_blocked());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,8 +9,8 @@
|
||||||
//! Example usage:
|
//! Example usage:
|
||||||
//! ```
|
//! ```
|
||||||
//! use rand::prelude::*;
|
//! use rand::prelude::*;
|
||||||
//! use here_be_dragons::{Map, MapFilter, NoData};
|
//! use mapgen::{Map, MapFilter, NoData};
|
||||||
//! use here_be_dragons::filter::CellularAutomata;
|
//! use mapgen::filter::CellularAutomata;
|
||||||
//!
|
//!
|
||||||
//! let mut rng = StdRng::seed_from_u64(100);
|
//! let mut rng = StdRng::seed_from_u64(100);
|
||||||
//! let gen = CellularAutomata::<NoData>::new();
|
//! let gen = CellularAutomata::<NoData>::new();
|
||||||
|
@ -76,7 +76,7 @@ fn apply_iteration<D: Clone + Default>(map: &Map<D>) -> Map<D> {
|
||||||
];
|
];
|
||||||
let neighbors = idxs
|
let neighbors = idxs
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|(x, y)| map.at(*x, *y).unwrap().is_blocked())
|
.filter(|(x, y)| map.at(*x, *y).is_blocked())
|
||||||
.count();
|
.count();
|
||||||
|
|
||||||
if neighbors > 4 || neighbors == 0 {
|
if neighbors > 4 || neighbors == 0 {
|
||||||
|
@ -103,7 +103,7 @@ mod tests {
|
||||||
fn test_iteration_wal() {
|
fn test_iteration_wal() {
|
||||||
let map = Map::<NoData>::new(3, 3);
|
let map = Map::<NoData>::new(3, 3);
|
||||||
let new_map = apply_iteration(&map);
|
let new_map = apply_iteration(&map);
|
||||||
assert!(new_map.at(1, 1).unwrap().is_blocked());
|
assert!(new_map.at(1, 1).is_blocked());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -115,6 +115,6 @@ mod tests {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let new_map = apply_iteration(&map);
|
let new_map = apply_iteration(&map);
|
||||||
assert!(new_map.at(1, 1).unwrap().is_walkable());
|
assert!(new_map.at(1, 1).is_walkable());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
//! Example generator usage:
|
//! Example generator usage:
|
||||||
//! ```
|
//! ```
|
||||||
//! use rand::prelude::*;
|
//! use rand::prelude::*;
|
||||||
//! use here_be_dragons::{Map, MapFilter, NoData};
|
//! use mapgen::{Map, MapFilter, NoData};
|
||||||
//! use here_be_dragons::filter::DrunkardsWalk;
|
//! use mapgen::filter::DrunkardsWalk;
|
||||||
//!
|
//!
|
||||||
//! let mut rng = StdRng::seed_from_u64(100);
|
//! let mut rng = StdRng::seed_from_u64(100);
|
||||||
//! let gen = DrunkardsWalk::<NoData>::open_area();
|
//! let gen = DrunkardsWalk::<NoData>::open_area();
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
//! Example generator usage:
|
//! Example generator usage:
|
||||||
//! ```
|
//! ```
|
||||||
//! use rand::prelude::*;
|
//! use rand::prelude::*;
|
||||||
//! use here_be_dragons::{Map, MapFilter, NoData};
|
//! use mapgen::{Map, MapFilter, NoData};
|
||||||
//! use here_be_dragons::filter::MazeBuilder;
|
//! use mapgen::filter::MazeBuilder;
|
||||||
//!
|
//!
|
||||||
//! let mut rng = StdRng::seed_from_u64(100);
|
//! let mut rng = StdRng::seed_from_u64(100);
|
||||||
//! let gen = MazeBuilder::<NoData>::new();
|
//! let gen = MazeBuilder::<NoData>::new();
|
||||||
|
@ -160,7 +160,7 @@ impl<'a, D: Clone + Default> Grid<'a, D> {
|
||||||
if neighbors.len() == 1 {
|
if neighbors.len() == 1 {
|
||||||
return Some(neighbors[0]);
|
return Some(neighbors[0]);
|
||||||
} else {
|
} else {
|
||||||
return Some(neighbors[(self.rng.roll_dice(1, neighbors.len()) - 1)]);
|
return Some(neighbors[(self.rng.roll_dice(1, neighbors.len()) - 1) as usize]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
|
|
|
@ -4,8 +4,8 @@
|
||||||
//! Example usage:
|
//! Example usage:
|
||||||
//! ```
|
//! ```
|
||||||
//! use rand::prelude::*;
|
//! use rand::prelude::*;
|
||||||
//! use here_be_dragons::{Map, MapFilter, NoData};
|
//! use mapgen::{Map, MapFilter, NoData};
|
||||||
//! use here_be_dragons::filter::NoiseGenerator;
|
//! use mapgen::filter::NoiseGenerator;
|
||||||
//!
|
//!
|
||||||
//! let mut rng = StdRng::seed_from_u64(100);
|
//! let mut rng = StdRng::seed_from_u64(100);
|
||||||
//! let gen = NoiseGenerator::<NoData>::uniform();
|
//! let gen = NoiseGenerator::<NoData>::uniform();
|
||||||
|
|
|
@ -6,8 +6,8 @@
|
||||||
//! Example generator usage:
|
//! Example generator usage:
|
||||||
//! ```
|
//! ```
|
||||||
//! use rand::prelude::*;
|
//! use rand::prelude::*;
|
||||||
//! use here_be_dragons::{MapFilter, Map, NoData};
|
//! use mapgen::{MapFilter, Map, NoData};
|
||||||
//! use here_be_dragons::filter::SimpleRooms;
|
//! use mapgen::filter::SimpleRooms;
|
||||||
//!
|
//!
|
||||||
//! let mut rng = StdRng::seed_from_u64(100);
|
//! let mut rng = StdRng::seed_from_u64(100);
|
||||||
//! let gen = SimpleRooms::<NoData>::new();
|
//! let gen = SimpleRooms::<NoData>::new();
|
||||||
|
|
|
@ -6,9 +6,9 @@
|
||||||
//! Example modifier usage:
|
//! Example modifier usage:
|
||||||
//! ```
|
//! ```
|
||||||
//! use rand::prelude::*;
|
//! use rand::prelude::*;
|
||||||
//! use here_be_dragons::{MapFilter, Map, NoData, Tile};
|
//! use mapgen::{MapFilter, Map, NoData, Tile};
|
||||||
//! use here_be_dragons::filter::starting_point::{AreaStartingPosition, XStart, YStart};
|
//! use mapgen::filter::starting_point::{AreaStartingPosition, XStart, YStart};
|
||||||
//! use here_be_dragons::geometry::Point;
|
//! use mapgen::geometry::Point;
|
||||||
//!
|
//!
|
||||||
//! let mut rng = StdRng::seed_from_u64(100);
|
//! let mut rng = StdRng::seed_from_u64(100);
|
||||||
//! let mut map = Map::<NoData>::new(80, 50);
|
//! let mut map = Map::<NoData>::new(80, 50);
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
//! Example generator usage:
|
//! Example generator usage:
|
||||||
//! ```
|
//! ```
|
||||||
//! use rand::prelude::*;
|
//! use rand::prelude::*;
|
||||||
//! use here_be_dragons::{Map, MapFilter, NoData};
|
//! use mapgen::{Map, MapFilter, NoData};
|
||||||
//! use here_be_dragons::filter::VoronoiHive;
|
//! use mapgen::filter::VoronoiHive;
|
||||||
//!
|
//!
|
||||||
//! let mut rng = StdRng::seed_from_u64(100);
|
//! let mut rng = StdRng::seed_from_u64(100);
|
||||||
//! let gen = VoronoiHive::<NoData>::new();
|
//! let gen = VoronoiHive::<NoData>::new();
|
||||||
|
@ -47,7 +47,7 @@ impl<D: Clone + Default> VoronoiHive<D> {
|
||||||
let seeds = self.generate_seeds(rng, map.width, map.height);
|
let seeds = self.generate_seeds(rng, map.width, map.height);
|
||||||
|
|
||||||
let mut voronoi_distance = vec![(0, 0.0f32); self.n_seeds];
|
let mut voronoi_distance = vec![(0, 0.0f32); self.n_seeds];
|
||||||
let mut voronoi_membership: Vec<i32> = vec![0; map.width * map.height];
|
let mut voronoi_membership: Vec<i32> = vec![0; map.width as usize * map.height as usize];
|
||||||
for (i, vid) in voronoi_membership.iter_mut().enumerate() {
|
for (i, vid) in voronoi_membership.iter_mut().enumerate() {
|
||||||
let x = i % map.width;
|
let x = i % map.width;
|
||||||
let y = i / map.width;
|
let y = i / map.width;
|
||||||
|
|
|
@ -1,12 +1,8 @@
|
||||||
//! Support function for 2D geometry
|
//! Support function for 2D geometry
|
||||||
//!
|
//!
|
||||||
|
|
||||||
#[cfg(feature = "serde")]
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
|
|
||||||
/// Position on the map
|
/// Position on the map
|
||||||
#[derive(Default, PartialEq, Copy, Clone, Debug, Eq, Hash)]
|
#[derive(Default, PartialEq, Copy, Clone, Debug, Eq, Hash)]
|
||||||
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
|
|
||||||
pub struct Point {
|
pub struct Point {
|
||||||
pub x: usize,
|
pub x: usize,
|
||||||
pub y: usize,
|
pub y: usize,
|
||||||
|
@ -33,7 +29,6 @@ impl Point {
|
||||||
|
|
||||||
/// Rectangle region on the map
|
/// Rectangle region on the map
|
||||||
#[derive(Hash, PartialEq, Eq, Copy, Clone, Debug)]
|
#[derive(Hash, PartialEq, Eq, Copy, Clone, Debug)]
|
||||||
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
|
|
||||||
pub struct Rect {
|
pub struct Rect {
|
||||||
pub x1: usize,
|
pub x1: usize,
|
||||||
pub x2: usize,
|
pub x2: usize,
|
||||||
|
@ -89,7 +84,7 @@ impl Rect {
|
||||||
/// Calculate abs value between 2 usize values
|
/// Calculate abs value between 2 usize values
|
||||||
/// Example:
|
/// Example:
|
||||||
/// ```
|
/// ```
|
||||||
/// use here_be_dragons::geometry::usize_abs;
|
/// use mapgen::geometry::usize_abs;
|
||||||
///
|
///
|
||||||
/// assert_eq!(usize_abs(5, 3), 2);
|
/// assert_eq!(usize_abs(5, 3), 2);
|
||||||
/// assert_eq!(usize_abs(3, 5), 2);
|
/// assert_eq!(usize_abs(3, 5), 2);
|
||||||
|
|
|
@ -8,13 +8,13 @@
|
||||||
//!
|
//!
|
||||||
//! Example
|
//! Example
|
||||||
//! ```
|
//! ```
|
||||||
//! use here_be_dragons::{MapFilter, MapBuilder, Map, NoData, Tile};
|
//! use mapgen::{MapFilter, MapBuilder, Map, NoData, Tile};
|
||||||
//! use here_be_dragons::filter::{
|
//! use mapgen::filter::{
|
||||||
//! NoiseGenerator,
|
//! NoiseGenerator,
|
||||||
//! CellularAutomata,
|
//! CellularAutomata,
|
||||||
//! starting_point::{AreaStartingPosition, XStart, YStart}
|
//! starting_point::{AreaStartingPosition, XStart, YStart}
|
||||||
//! };
|
//! };
|
||||||
//! use here_be_dragons::geometry::Point;
|
//! use mapgen::geometry::Point;
|
||||||
//!
|
//!
|
||||||
//! let map = MapBuilder::<NoData>::new(80, 50)
|
//! let map = MapBuilder::<NoData>::new(80, 50)
|
||||||
//! .with(NoiseGenerator::uniform())
|
//! .with(NoiseGenerator::uniform())
|
||||||
|
|
50
src/map.rs
50
src/map.rs
|
@ -7,15 +7,10 @@
|
||||||
//! specific game.
|
//! specific game.
|
||||||
//!
|
//!
|
||||||
|
|
||||||
|
use super::geometry::{usize_abs, Point, Rect};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
#[cfg(feature = "serde")]
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
|
|
||||||
use crate::geometry::{usize_abs, Point, Rect};
|
|
||||||
|
|
||||||
#[derive(PartialEq, Copy, Clone, Debug, Eq, Hash)]
|
#[derive(PartialEq, Copy, Clone, Debug, Eq, Hash)]
|
||||||
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
|
|
||||||
pub struct Tile {
|
pub struct Tile {
|
||||||
is_blocked: bool,
|
is_blocked: bool,
|
||||||
index: usize,
|
index: usize,
|
||||||
|
@ -35,7 +30,6 @@ pub struct NoData;
|
||||||
|
|
||||||
/// Map data
|
/// Map data
|
||||||
#[derive(Default, Clone)]
|
#[derive(Default, Clone)]
|
||||||
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
|
|
||||||
pub struct Map<D: Clone + Default> {
|
pub struct Map<D: Clone + Default> {
|
||||||
pub tiles: Vec<Tile>,
|
pub tiles: Vec<Tile>,
|
||||||
pub width: usize,
|
pub width: usize,
|
||||||
|
@ -118,12 +112,12 @@ impl<D: Clone + Default> Map<D> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get TileType at the given location
|
/// Get TileType at the given location
|
||||||
pub fn at(&self, x: usize, y: usize) -> Option<&Tile> {
|
pub fn at(&self, x: usize, y: usize) -> Tile {
|
||||||
if x < self.width && y < self.height {
|
if x >= self.width || y >= self.height {
|
||||||
let idx = y * self.width + x;
|
Tile::wall()
|
||||||
self.tiles.get(idx)
|
|
||||||
} else {
|
} else {
|
||||||
None
|
let idx = (y as usize) * self.width + (x as usize);
|
||||||
|
self.tiles[idx]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -164,17 +158,13 @@ impl<D: Clone + Default> Map<D> {
|
||||||
|
|
||||||
// Check if given tile can be accessed
|
// Check if given tile can be accessed
|
||||||
fn is_exit_valid(&self, x: usize, y: usize) -> bool {
|
fn is_exit_valid(&self, x: usize, y: usize) -> bool {
|
||||||
if let Some(tile) = self.at(x, y) {
|
!self.at(x, y).is_blocked
|
||||||
!tile.is_blocked
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Modify tile at the given location
|
/// Modify tile at the given location
|
||||||
pub fn set_tile(&mut self, x: usize, y: usize, tile: Tile) {
|
pub fn set_tile(&mut self, x: usize, y: usize, tile: Tile) {
|
||||||
if x < self.width && y < self.height {
|
if x < self.width && y < self.height {
|
||||||
let idx = self.xy_idx(x, y);
|
let idx = self.xy_idx(x as usize, y as usize);
|
||||||
self.tiles[idx] = tile;
|
self.tiles[idx] = tile;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -188,7 +178,7 @@ impl<D: Clone + Default> Map<D> {
|
||||||
pub fn add_room(&mut self, rect: Rect) {
|
pub fn add_room(&mut self, rect: Rect) {
|
||||||
for x in rect.x1..rect.x2 {
|
for x in rect.x1..rect.x2 {
|
||||||
for y in rect.y1..rect.y2 {
|
for y in rect.y1..rect.y2 {
|
||||||
self.set_tile(x, y, Tile::floor());
|
self.set_tile(x as usize, y as usize, Tile::floor());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.rooms.push(rect);
|
self.rooms.push(rect);
|
||||||
|
@ -210,14 +200,12 @@ impl<D: Clone + Default> Map<D> {
|
||||||
y -= 1;
|
y -= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(tile) = self.at(x, y) {
|
if self.at(x, y).is_blocked {
|
||||||
if tile.is_blocked {
|
|
||||||
corridor.push(Point::new(x, y));
|
corridor.push(Point::new(x, y));
|
||||||
self.set_tile(x, y, Tile::floor());
|
self.set_tile(x, y, Tile::floor());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
pub fn paint(&mut self, mode: Symmetry, brush_size: usize, x: usize, y: usize) {
|
pub fn paint(&mut self, mode: Symmetry, brush_size: usize, x: usize, y: usize) {
|
||||||
match mode {
|
match mode {
|
||||||
|
@ -286,10 +274,10 @@ impl<D: Clone + Default> fmt::Display for Map<D> {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
for y in 0..self.height {
|
for y in 0..self.height {
|
||||||
let bytes: Vec<u8> = (0..self.width)
|
let bytes: Vec<u8> = (0..self.width)
|
||||||
.map(|x| if self.at(x, y).unwrap().is_blocked { '#' } else { ' ' } as u8)
|
.map(|x| if self.at(x, y).is_blocked { '#' } else { ' ' } as u8)
|
||||||
.collect();
|
.collect();
|
||||||
let line = String::from_utf8(bytes).expect("Can't convert map to string");
|
let line = String::from_utf8(bytes).expect("Can't convert map to string");
|
||||||
let _ = writeln!(f, "{line}");
|
let _ = writeln!(f, "{}", line);
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -307,7 +295,7 @@ mod tests {
|
||||||
let map = Map::<NoData>::new(10, 10);
|
let map = Map::<NoData>::new(10, 10);
|
||||||
for i in 0..10 {
|
for i in 0..10 {
|
||||||
for j in 0..10 {
|
for j in 0..10 {
|
||||||
assert!(map.at(i, j).unwrap().is_blocked);
|
assert!(map.at(i, j).is_blocked);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -324,12 +312,12 @@ mod tests {
|
||||||
assert_eq!(map.width, 10);
|
assert_eq!(map.width, 10);
|
||||||
assert_eq!(map.height, 3);
|
assert_eq!(map.height, 3);
|
||||||
for i in 0..10 {
|
for i in 0..10 {
|
||||||
assert!(map.at(i, 0).unwrap().is_blocked);
|
assert!(map.at(i, 0).is_blocked);
|
||||||
assert!(map.at(i, 2).unwrap().is_blocked);
|
assert!(map.at(i, 2).is_blocked);
|
||||||
if i == 0 || i == 9 {
|
if i == 0 || i == 9 {
|
||||||
assert!(map.at(i, 1).unwrap().is_blocked);
|
assert!(map.at(i, 1).is_blocked);
|
||||||
} else {
|
} else {
|
||||||
assert!(map.at(i, 1).unwrap().is_walkable());
|
assert!(map.at(i, 1).is_walkable());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -355,9 +343,9 @@ mod tests {
|
||||||
for x in 0..map.width {
|
for x in 0..map.width {
|
||||||
for y in 0..map.height {
|
for y in 0..map.height {
|
||||||
if x == 0 || y == 0 || x == 4 || y == 4 {
|
if x == 0 || y == 0 || x == 4 || y == 4 {
|
||||||
assert!(map.at(x, y).unwrap().is_blocked);
|
assert!(map.at(x, y).is_blocked);
|
||||||
} else {
|
} else {
|
||||||
assert!(map.at(x, y).unwrap().is_walkable());
|
assert!(map.at(x, y).is_walkable());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user