njin
Engine 2D gọn nhẹ để tự tay làm game theo ý mình. Vibe coding cũng ổn luôn
Loading...
Searching...
No Matches
njin_procgen.h
1#pragma once
2#include "_tilemap.h"
3#include "_types.h"
4#include <functional>
5#include <initializer_list>
6#include <string_view>
7#include <vector>
8
9namespace njin {
12
13// ---------------------------------------------------------------------------
14// Lưới ô tạm để sinh bản đồ
15// ---------------------------------------------------------------------------
16
24struct tile_grid {
25 i32 width = 0;
26 i32 height = 0;
27 std::vector<i32> cells{};
28
30 bool inside(i32 x, i32 y) const { return x >= 0 && y >= 0 && x < width && y < height; }
32 i32 get(i32 x, i32 y) const { return inside(x, y) ? cells[(usize)(y * width + x)] : -1; }
34 void set(i32 x, i32 y, i32 tile) {
35 if (inside(x, y))
36 cells[(usize)(y * width + x)] = tile;
37 }
38};
39
43tile_grid tile_grid_make(i32 width, i32 height, i32 fill = -1);
44
50tile_grid tile_grid_from_text(std::string_view text, std::initializer_list<tile_key> legend);
51
55void tilemap_from_grid(tilemap &map, const tile_grid &grid, cell origin = {});
56
59i32 grid_count(const tile_grid &grid, i32 tile);
60
61// ---------------------------------------------------------------------------
62// Nhiễu
63// ---------------------------------------------------------------------------
64
70
78
95
100f32 noise_2d(const noise_desc &desc, f32 x, f32 y);
101
104f32 noise_1d(const noise_desc &desc, f32 x);
105
106// ---------------------------------------------------------------------------
107// Luật: làm bản đồ trông tự nhiên
108// ---------------------------------------------------------------------------
109
118
122void grid_majority(tile_grid &grid, i32 iterations = 1, i32 threshold = 5);
123
129void grid_smooth(tile_grid &grid, i32 solid, i32 open, i32 iterations = 3, i32 threshold = 5);
130
135i32 grid_remove_small(tile_grid &grid, i32 tile, i32 min_size, i32 replace);
136
140
145i32 grid_keep_largest(tile_grid &grid, std::initializer_list<i32> walkable, i32 replace);
146
152i32 grid_border(tile_grid &grid, i32 tile, i32 touching, i32 replace, u8 sides = side_all, i32 distance = 1);
153
159i32 grid_scatter(tile_grid &grid, i32 on, i32 place, f32 chance, u32 seed, i32 min_distance = 0);
160
171i32 grid_scatter(tile_grid &grid, i32 place, f32 chance, u32 seed,
172 const std::function<bool(const tile_grid &, i32, i32)> &where, i32 min_distance = 0);
173
174// ---------------------------------------------------------------------------
175// Bo góc tự nhiên: autotile
176// ---------------------------------------------------------------------------
177
186
199
202
210
214 std::vector<i32> tiles{};
216 std::vector<i32> joins{};
217 i32 base = 0;
222};
223
237i32 grid_autotile(tile_grid &grid, const std::vector<autotile_rule> &rules);
238
239// ---------------------------------------------------------------------------
240// Top-down: vùng đất theo độ cao và độ ẩm
241// ---------------------------------------------------------------------------
242
245struct biome {
249};
250
257 i32 width = 64;
258 i32 height = 64;
261 noise_desc moisture_noise{.seed = 7919, .frequency = 0.03f, .octaves = 3};
262 std::vector<biome> biomes{};
263 f32 island = 0.0f;
267 bool normalize = true;
272 std::vector<i32> walkable{};
275};
276
280 std::vector<f32> heights{};
282};
283
286
287// ---------------------------------------------------------------------------
288// Platformer: mặt đất, hang, hố, bục
289// ---------------------------------------------------------------------------
290
333
337 std::vector<i32> surface{};
340};
341
344
345// ---------------------------------------------------------------------------
346// Wave Function Collapse
347// ---------------------------------------------------------------------------
348
350enum wfc_dir { wfc_right, wfc_down, wfc_left, wfc_up };
351
354struct wfc_rules {
355 std::vector<i32> tiles{};
356 std::vector<f32> weights{};
359 std::vector<u64> allow{};
360 i32 words = 0;
361};
362
365i32 wfc_add_tile(wfc_rules &rules, i32 tile, f32 weight = 1.0f);
366
370void wfc_allow(wfc_rules &rules, i32 a, wfc_dir dir, i32 b);
371
377wfc_rules wfc_learn(const tile_grid &sample, bool periodic = false);
378
380struct wfc_desc {
381 i32 width = 32;
382 i32 height = 32;
383 u32 seed = 1;
385 bool periodic = false;
388 std::function<bool(i32 x, i32 y, i32 tile)> allowed{};
389};
390
395bool wfc_generate(const wfc_rules &rules, const wfc_desc &desc, tile_grid &out);
396
398} // namespace njin
f32 distance(vec2 a, vec2 b)
Khoảng cách giữa hai điểm.
Definition _math.h:69
f32 noise_1d(const noise_desc &desc, f32 x)
Nhiễu một chiều, từ 0 đến 1: đường mặt đất của platformer, độ cao theo cột.
topdown_gen_result generate_topdown(const topdown_gen_desc &desc)
Sinh bản đồ top-down từ nhiễu.
void tilemap_from_grid(tilemap &map, const tile_grid &grid, cell origin={})
Đặt lưới vào tilemap, góc trên trái ở ô origin.
wfc_dir
Hướng từ một ô sang ô bên cạnh, dùng cho luật kề của WFC.
Definition njin_procgen.h:350
noise_fractal
Cách chồng nhiều lớp nhiễu (octave) lên nhau.
Definition njin_procgen.h:72
bool wfc_generate(const wfc_rules &rules, const wfc_desc &desc, tile_grid &out)
Sinh một lưới thoả mọi luật kề, bằng Wave Function Collapse (mô hình ô, không quay lui: gặp mâu thuẫn...
grid_side
Các phía của một ô, cộng lại được: side_up | side_down.
Definition njin_procgen.h:111
autotile_neighbor
Các ô kề, cộng lại thành mặt nạ (mask) của một ô.
Definition njin_procgen.h:189
i32 grid_border(tile_grid &grid, i32 tile, i32 touching, i32 replace, u8 sides=side_all, i32 distance=1)
Viền: ô tile nằm cách touching không quá distance ô (theo các phía trong sides) thì thành replace.
i32 grid_count(const tile_grid &grid, i32 tile)
Số ô có giá trị tile.
void wfc_allow(wfc_rules &rules, i32 a, wfc_dir dir, i32 b)
Cho phép b đứng ở hướng dir của a, và (đối xứng) a đứng ở hướng ngược lại của b.
i32 grid_scatter(tile_grid &grid, i32 on, i32 place, f32 chance, u32 seed, i32 min_distance=0)
Rải ngẫu nhiên: mỗi ô on có xác suất chance thành place, và hai ô được rải cách nhau ít nhất min_dist...
autotile_layout
Bộ ô dùng để nối một loại địa hình với chính nó.
Definition njin_procgen.h:179
i32 grid_keep_largest(tile_grid &grid, std::initializer_list< i32 > walkable, i32 replace)
Giữ mọi chỗ đi được liền một khối: trong các ô thuộc walkable, chỉ vùng liền nhau (4 hướng) lớn nhất ...
noise_type
Loại nhiễu cơ bản.
Definition njin_procgen.h:66
tile_grid tile_grid_make(i32 width, i32 height, i32 fill=-1)
Tạo một lưới width x height, mọi ô là fill.
i32 autotile_count(autotile_layout layout)
Số ô của một bộ.
platformer_gen_result generate_platformer(const platformer_gen_desc &desc)
Sinh màn platformer từ nhiễu.
wfc_rules wfc_learn(const tile_grid &sample, bool periodic=false)
Học luật từ một mẫu: mọi cặp ô cạnh nhau trong mẫu thành luật kề, số lần xuất hiện thành độ hay gặp.
i32 grid_merge_small(tile_grid &grid, i32 min_size)
Như grid_remove_small() cho mọi loại ô: vùng nhỏ hơn min_size hoà vào loại ô bao quanh nó nhiều nhất.
tile_grid tile_grid_from_text(std::string_view text, std::initializer_list< tile_key > legend)
Dựng lưới từ bản đồ chữ, cùng quy tắc với tilemap_from_text(): mỗi ký tự một ô, legend cho biết ký tự...
f32 noise_2d(const noise_desc &desc, f32 x, f32 y)
Giá trị nhiễu tại một điểm, từ 0 đến 1.
i32 grid_autotile(tile_grid &grid, const std::vector< autotile_rule > &rules)
Thay mọi ô thuộc rules[i].tiles bằng ô của bộ tương ứng, chọn theo các ô kề: chỗ nào địa hình hở ra t...
void grid_smooth(tile_grid &grid, i32 solid, i32 open, i32 iterations=3, i32 threshold=5)
Làm mượt hai loại ô kiểu hang động (automat tế bào): một ô thành solid nếu ít nhất threshold trong 8 ...
i32 wfc_add_tile(wfc_rules &rules, i32 tile, f32 weight=1.0f)
Thêm một ô vào luật (hoặc đổi độ hay gặp nếu đã có).
i32 autotile_index(u8 mask, autotile_layout layout=autotile_blob)
Số thứ tự ô (trong bộ, từ 0) ứng với một mặt nạ.
i32 grid_remove_small(tile_grid &grid, i32 tile, i32 min_size, i32 replace)
Xoá các vùng nhỏ của một loại ô: mỗi vùng liền nhau (theo 4 hướng) của tile có ít hơn min_size ô thì ...
void grid_majority(tile_grid &grid, i32 iterations=1, i32 threshold=5)
Làm mượt: mỗi ô thành loại ô xuất hiện nhiều nhất trong ô 3 x 3 quanh nó, nếu loại đó có ít nhất thre...
@ fractal_none
Một lớp. Hình to, trơn.
Definition njin_procgen.h:73
@ fractal_ridged
Gờ nhọn: dãy núi, sống đá, dòng sông khi lấy vùng thấp.
Definition njin_procgen.h:75
@ fractal_fbm
Cộng các lớp càng lúc càng nhỏ và nhạt: địa hình tự nhiên. Mặc định.
Definition njin_procgen.h:74
@ fractal_billow
Gợn tròn phồng lên: mây, đồi thấp, đá cuội.
Definition njin_procgen.h:76
@ side_left
Ô bên trái.
Definition njin_procgen.h:114
@ side_down
Ô phía dưới.
Definition njin_procgen.h:113
@ side_all
Cả bốn phía.
Definition njin_procgen.h:116
@ side_right
Ô bên phải.
Definition njin_procgen.h:115
@ side_up
Ô phía trên.
Definition njin_procgen.h:112
@ neighbor_down_left
Ô chéo trái dưới.
Definition njin_procgen.h:195
@ neighbor_left
Ô bên trái.
Definition njin_procgen.h:196
@ neighbor_right
Ô bên phải.
Definition njin_procgen.h:192
@ neighbor_up
Ô phía trên.
Definition njin_procgen.h:190
@ neighbor_up_left
Ô chéo trái trên.
Definition njin_procgen.h:197
@ neighbor_up_right
Ô chéo phải trên.
Definition njin_procgen.h:191
@ neighbor_down
Ô phía dưới.
Definition njin_procgen.h:194
@ neighbor_down_right
Ô chéo phải dưới.
Definition njin_procgen.h:193
@ autotile_blob
47 ô, nhìn cả tám ô kề. Có cả góc lồi lẫn góc lõm: đất, nước, mặt đá liền tự nhiên....
Definition njin_procgen.h:184
@ autotile_edges
16 ô, nhìn bốn ô kề (trên, phải, dưới, trái).
Definition njin_procgen.h:182
@ noise_perlin
Nhiễu gradient (Perlin): mượt, tròn trịa. Mặc định, hợp cho địa hình.
Definition njin_procgen.h:67
@ noise_value
Nhiễu giá trị: rẻ hơn, hơi vuông vức. Hợp cho vết, đốm.
Definition njin_procgen.h:68
std::uint8_t u8
Số nguyên không dấu 8 bit.
Definition _types.h:20
std::int32_t i32
Số nguyên có dấu 32 bit.
Definition _types.h:14
std::size_t usize
Số nguyên không dấu cỡ con trỏ, dùng cho kích thước và chỉ số.
Definition _types.h:34
float f32
Số thực 32 bit.
Definition _types.h:28
std::uint32_t u32
Số nguyên không dấu 32 bit.
Definition _types.h:22
Một luật bo góc: những ô nào là cùng một địa hình và vẽ bằng bộ ô nào.
Definition njin_procgen.h:212
std::vector< i32 > joins
Ô khác vẫn được tính là nối liền (không tạo mép), nhưng không bị thay: đá dưới đất,...
Definition njin_procgen.h:216
autotile_layout layout
Kiểu bộ.
Definition njin_procgen.h:218
i32 base
Số thứ tự của ô đầu tiên của bộ trong tileset. Bộ là các ô liền nhau.
Definition njin_procgen.h:217
u8 outside
Những phía mà ngoài lưới coi như cùng loại (các bit njin::grid_side).
Definition njin_procgen.h:221
std::vector< i32 > tiles
Các ô của lưới mà luật này thay bằng ô của bộ (ví dụ cỏ và đất cùng là "mặt đất").
Definition njin_procgen.h:214
Một vùng đất của bản đồ top-down: ô nào đặt ở chỗ có độ cao và độ ẩm nào.
Definition njin_procgen.h:245
i32 tile
Ô đặt cho vùng này.
Definition njin_procgen.h:246
f32 max_height
Độ cao tối đa (0 đến 1).
Definition njin_procgen.h:247
f32 max_moisture
Độ ẩm tối đa (0 đến 1). Để 1 nếu không dùng độ ẩm.
Definition njin_procgen.h:248
Vị trí một ô trong lưới. Có thể âm.
Definition _tilemap.h:43
Tham số của một nguồn nhiễu.
Definition njin_procgen.h:84
noise_type type
Loại nhiễu.
Definition njin_procgen.h:86
f32 gain
Mỗi lớp sau có độ mạnh nhân với số này. Lớn: gồ ghề.
Definition njin_procgen.h:91
f32 warp
Uốn cong toạ độ, tính bằng ô. 0 là tắt, 4 đến 20 cho viền tự nhiên.
Definition njin_procgen.h:92
f32 warp_frequency
Tần số của nhiễu dùng để uốn.
Definition njin_procgen.h:93
noise_fractal fractal
Cách chồng lớp.
Definition njin_procgen.h:88
f32 lacunarity
Mỗi lớp sau có tần số nhân với số này.
Definition njin_procgen.h:90
u32 seed
Hạt giống. Đổi số này là có bản đồ khác.
Definition njin_procgen.h:85
i32 octaves
Số lớp (1 đến 8). Nhiều lớp: mép chi tiết hơn, tốn hơn.
Definition njin_procgen.h:89
f32 frequency
Tần số theo ô. Nhỏ: vùng to; lớn: vùng vụn. 0.02 đến 0.1 là thường.
Definition njin_procgen.h:87
Tham số sinh màn platformer, nhìn ngang, đi từ trái sang phải.
Definition njin_procgen.h:296
i32 platform_max
Bục dài nhất.
Definition njin_procgen.h:330
i32 deep_tile
Ô ở sâu (đá). -1 là dùng dirt_tile.
Definition njin_procgen.h:306
i32 ground_max
Hàng thấp nhất mặt đất được xuống.
Definition njin_procgen.h:302
i32 platform_tile
Ô của bục (thường là bục một chiều, njin::tile_one_way).
Definition njin_procgen.h:328
i32 cave_margin
Số hàng ngay dưới mặt đất không bị đục hang.
Definition njin_procgen.h:319
i32 pit_min
Hố hẹp nhất, tính bằng ô.
Definition njin_procgen.h:321
i32 dirt_tile
Ô dưới mặt đất.
Definition njin_procgen.h:305
i32 platform_height
Bục cao hơn mặt đất bấy nhiêu ô. Giữ không quá độ cao nhảy.
Definition njin_procgen.h:331
i32 slope_r_tile
Ô dốc cao bên phải và cao bên trái (njin::tile_slope_r, njin::tile_slope_l), đặt ở chỗ mặt đất lên ho...
Definition njin_procgen.h:310
i32 deep_depth
Từ độ sâu này (ô tính từ mặt đất) trở xuống là deep_tile.
Definition njin_procgen.h:307
i32 height
Số hàng.
Definition njin_procgen.h:298
noise_desc cave_noise
Nhiễu của hang.
Definition njin_procgen.h:313
i32 surface_tile
Ô mặt đất (cỏ).
Definition njin_procgen.h:304
i32 slope_l_tile
Xem slope_r_tile.
Definition njin_procgen.h:311
i32 ground_min
Hàng cao nhất mặt đất được lên (hàng tính từ trên xuống).
Definition njin_procgen.h:301
f32 pit_chance
Xác suất bắt đầu một hố ở mỗi cột. 0 là không có hố.
Definition njin_procgen.h:320
i32 platform_min
Bục ngắn nhất.
Definition njin_procgen.h:329
f32 caves
Tỉ lệ diện tích ngầm được đục thành hang, 0 (tắt) đến 0.9.
Definition njin_procgen.h:318
i32 width
Số cột.
Definition njin_procgen.h:297
noise_desc surface_noise
Nhiễu của mặt đất, theo cột.
Definition njin_procgen.h:300
i32 pit_max
Hố rộng nhất.
Definition njin_procgen.h:325
i32 safe_columns
Số cột bằng phẳng, không hố, ở mỗi đầu màn (chỗ xuất phát và đích).
Definition njin_procgen.h:326
f32 platform_chance
Xác suất đặt một bục lơ lửng ở mỗi cột. 0 là không có bục.
Definition njin_procgen.h:327
i32 max_step
Chênh lệch tối đa giữa hai cột cạnh nhau, tính bằng ô.
Definition njin_procgen.h:303
Kết quả của generate_platformer().
Definition njin_procgen.h:335
cell spawn
Ô trống ngay trên mặt đất, ở đầu trái: chỗ đặt nhân vật.
Definition njin_procgen.h:338
cell goal
Ô trống ngay trên mặt đất, ở đầu phải: chỗ đặt đích.
Definition njin_procgen.h:339
std::vector< i32 > surface
Hàng của mặt đất ở từng cột, -1 ở cột là hố.
Definition njin_procgen.h:337
tile_grid grid
Màn chơi.
Definition njin_procgen.h:336
Một lưới ô hình chữ nhật, kích thước cố định, để sinh và sửa bản đồ trước khi đưa vào njin::tilemap.
Definition njin_procgen.h:24
void set(i32 x, i32 y, i32 tile)
Đặt một ô; ngoài lưới thì bỏ qua.
Definition njin_procgen.h:34
bool inside(i32 x, i32 y) const
Ô có nằm trong lưới không.
Definition njin_procgen.h:30
i32 width
Số cột.
Definition njin_procgen.h:25
i32 get(i32 x, i32 y) const
Giá trị một ô.
Definition njin_procgen.h:32
i32 height
Số hàng.
Definition njin_procgen.h:26
std::vector< i32 > cells
Các ô theo hàng, từ trên xuống. cells[y * width + x].
Definition njin_procgen.h:27
Lưới ô vuông không giới hạn kích thước, vẽ từ một tileset, chia thành chunk.
Definition _tilemap.h:128
Tham số sinh bản đồ top-down.
Definition njin_procgen.h:256
i32 smooth
Số lần grid_majority(). 0 là tắt.
Definition njin_procgen.h:268
noise_desc height_noise
Nhiễu độ cao.
Definition njin_procgen.h:259
noise_desc moisture_noise
Nhiễu độ ẩm. Chỉ dùng khi có vùng đặt max_moisture dưới 1.
Definition njin_procgen.h:261
std::vector< biome > biomes
Các vùng, xét theo thứ tự. Ô không khớp vùng nào dùng vùng cuối.
Definition njin_procgen.h:262
std::vector< i32 > walkable
Các ô đi được.
Definition njin_procgen.h:272
i32 height
Số hàng.
Definition njin_procgen.h:258
i32 blocked_tile
Ô thay cho vùng đi được bị bỏ, khi có walkable.
Definition njin_procgen.h:273
i32 min_region
grid_merge_small(): vùng nhỏ hơn số ô này bị hoà vào xung quanh.
Definition njin_procgen.h:269
i32 width
Số cột.
Definition njin_procgen.h:257
i32 border_tile
Ô cho vòng tường bao quanh bản đồ. -1 là không có.
Definition njin_procgen.h:274
f32 island
0 là tắt.
Definition njin_procgen.h:263
bool normalize
Kéo giãn độ cao (và độ ẩm) để ô thấp nhất của bản đồ là 0 và ô cao nhất là 1.
Definition njin_procgen.h:267
Kết quả của generate_topdown().
Definition njin_procgen.h:278
tile_grid grid
Bản đồ.
Definition njin_procgen.h:279
cell spawn
Điểm xuất phát: ô đi được gần tâm nhất (tâm bản đồ nếu không có walkable).
Definition njin_procgen.h:281
std::vector< f32 > heights
Độ cao (0 đến 1) của từng ô, cùng thứ tự với grid.cells. Dùng cho luật riêng.
Definition njin_procgen.h:280
Tham số của wfc_generate().
Definition njin_procgen.h:380
bool periodic
Kết quả lặp lại được: mép phải khớp mép trái, mép dưới khớp mép trên.
Definition njin_procgen.h:385
std::function< bool(i32 x, i32 y, i32 tile)> allowed
Ràng buộc: ô tile có được đặt ở (x, y) không.
Definition njin_procgen.h:388
i32 height
Số hàng.
Definition njin_procgen.h:382
u32 seed
Hạt giống.
Definition njin_procgen.h:383
i32 attempts
Số lần thử lại khi đi vào ngõ cụt (mâu thuẫn), mỗi lần một dãy ngẫu nhiên mới.
Definition njin_procgen.h:384
i32 width
Số cột.
Definition njin_procgen.h:381
Luật của Wave Function Collapse: có những ô nào, mỗi ô hay gặp đến đâu, và ô nào được đứng cạnh ô nào...
Definition njin_procgen.h:354
std::vector< i32 > tiles
Các ô (số thứ tự trong tileset; -1 là ô trống cũng là một ô).
Definition njin_procgen.h:355
std::vector< f32 > weights
Độ hay gặp của từng ô.
Definition njin_procgen.h:356
std::vector< u64 > allow
Luật kề, dạng bit: allow[(i * 4 + dir) * words + j / 64] có bit j % 64 nếu ô thứ j được đứng ở hướng ...
Definition njin_procgen.h:359
i32 words
Số từ 64 bit cho mỗi tập ô.
Definition njin_procgen.h:360