@adatechnology/game-urban 0.0.0-stage → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +80 -2
- package/dist/index.d.ts +1428 -0
- package/dist/index.global.js +31313 -0
- package/dist/index.global.js.map +1 -0
- package/dist/index.js +1087 -0
- package/dist/index.js.map +1 -0
- package/package.json +55 -3
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Anderson Fernandes
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,81 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @adatechnology/game-urban
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
The urban pattern as data, with no three.js: the five street poles with a light budget, roads with a dashed centre line, sidewalks, street grids, blocks filled with city buildings, and the props of a street. A literal port of the pieces of the team's Galeria do Vale Cinzento (`poleLED`, `poleConcrete`, `poleIron`, `poleWood`, `floodTower`, `road`, `walk`, `streetGrid`, `fillBlock`, `fence`, `tent`, `pine`, `tree`, `container`, `watchtower`, `sandbags`, `stripLabel`, `wires`).
|
|
4
|
+
|
|
5
|
+
Everything is a **part** on the silhouette vocabulary of `@adatechnology/game-floorplan` (boxes with the rounded edge, cylinders, prisms, lines, signs, groups), plus the few the street needs (cones, crowns, planes, labels, lights). A drawer such as `@adatechnology/game-urban-three` turns the parts into meshes. The package knows no game and no place: the named valley, the neighbourhood of the zombie checkpoint and the like belong to the game that uses it.
|
|
6
|
+
|
|
7
|
+
```ts
|
|
8
|
+
import { createUrban } from '@adatechnology/game-urban'
|
|
9
|
+
|
|
10
|
+
const urban = createUrban({ lights: { budget: 16 } })
|
|
11
|
+
const b = urban.builder({ seed: 7 }) // the page's generator, mulberry32(7)
|
|
12
|
+
|
|
13
|
+
urban.streets.grid(b, { block: 36, count: 2, width: 10 })
|
|
14
|
+
urban.block.fill(b, { cx: 0, cz: 0, size: 26, minHeight: 12, maxHeight: 36, lit: 0.05, shop: 0.5 })
|
|
15
|
+
urban.poles.get('led_double').build(b, { x: 18, z: 5, on: true })
|
|
16
|
+
urban.props.watchtower(b, 40, 0, true)
|
|
17
|
+
|
|
18
|
+
const scene = b.scene() // { parts, items, windows: { lit, dark } }
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Poles
|
|
22
|
+
|
|
23
|
+
| id | shape | what it is |
|
|
24
|
+
|---|---|---|
|
|
25
|
+
| `led_double` | `double_arm` | 9 m mast, two arms with white LED heads (avenue) |
|
|
26
|
+
| `concrete_arm` | `single_arm` | 8 m concrete mast, one arm, sodium lamp, optional transformer drum (`dir` -1 mirrors the arm) |
|
|
27
|
+
| `cast_iron` | `lantern` | 4 m iron post, lantern box and pointed cap |
|
|
28
|
+
| `wood_crossarm` | `crossarm` | 7 m wooden pole with a crossarm and a hanging lamp |
|
|
29
|
+
| `flood_tower` | `flood_tower` | 12 m four-legged tower with three floodlights |
|
|
30
|
+
|
|
31
|
+
A pole that is `on` has a glowing lens and, while the **light budget** lasts, a real point light (white LED 1.3 / 24 m, sodium 1.3 / 20 m, lantern 1 / 14 m, crossarm 0.9 / 16 m, floodlight 1.6 / 34 m). The budget is the Galeria's counter: 16 by default, `take()` is `left-- > 0`, so `left` keeps falling below zero when more lamps ask than the budget had, and the lamps that did not get a light keep their lens. `flicker: true` marks the light of a failing lamp; the drawer animates it.
|
|
32
|
+
|
|
33
|
+
Every number of a pole is data. A game patches one by id, adds a pole or takes one out, and a pole of a new shape brings its builder:
|
|
34
|
+
|
|
35
|
+
```ts
|
|
36
|
+
createUrban({
|
|
37
|
+
patch: { poles: { led_double: { spec: { light: { distance: 30 } } } } },
|
|
38
|
+
packs: { poles: [{ id: 'banner', shape: 'banner', spec: { height: 5 } }] },
|
|
39
|
+
shapes: { banner: (b, spec, o) => b.box(o.x, 0, o.z, 0.2, spec.height, 0.2, 0xffffff) },
|
|
40
|
+
remove: { poles: ['wood_crossarm'] },
|
|
41
|
+
facades: [0x777777, 0x998877], // colours of the city buildings
|
|
42
|
+
streets: { road: { color: 0x303030, dash: { every: 4 } } },
|
|
43
|
+
})
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Streets, blocks and props
|
|
47
|
+
|
|
48
|
+
- `streets.road(b, x, z, w, l, 'x' | 'z')`: a plane at 2 cm with a dash (1.8 x 0.16 m) every 5 m from 2 m after the start, as instances. `walk`, `ground` and `grid({ block, count, width })` (2n+1 roads each way and a sidewalk slab on each of the 2n x 2n blocks).
|
|
49
|
+
- `block.fill(b, { cx, cz, size, minHeight, maxHeight, k, gap, lit, shop })`: a `k x k` split of the block less 2 m of street; a building a little smaller than its lot, as tall as `lerp(min, max, random^1.6)` (more low buildings than tall ones), drawn by `createCityBuilding` of game-floorplan with the shared generator. Returns the buildings for the game's bookkeeping. `block.building` places one.
|
|
50
|
+
- `props`: `fence`, `tent`, `pine`, `tree`, `container`, `watchtower` (with a searchlight whose beam circles the ground), `sandbags` (instances), `label` (two lines on a 22 x 4.4 m board) and `wires`.
|
|
51
|
+
|
|
52
|
+
## Neighbourhood patterns
|
|
53
|
+
|
|
54
|
+
`urban.neighbourhoods` has the ten patterns of the Galeria's sample sheet: `downtown`, `suburb`, `working_class`, `historic_street`, `industrial_port`, `railway_village`, `mountain_resort`, `stilt_village`, `military` and `rural`. A pattern is data (`streetWidth`, `walkWidth`, `typologies`, `pole`, `lightColor`, `spacing`, `lit` = the share of lamps on and the rest burnt out, `marker`, `text` in `pt-BR` and `en`, and the `params` of its composer) plus a `compose` key into the registry of composers, which draw the street. A game changes a number with `patch`, adds a pattern with `packs` and a composer with `composers`, or takes one out with `remove`.
|
|
55
|
+
|
|
56
|
+
```ts
|
|
57
|
+
const plan = urban.neighbourhoods.get('suburb').compose(b, { x: 0, z: 0 }, {
|
|
58
|
+
locale: 'en',
|
|
59
|
+
providers: {
|
|
60
|
+
house: (typology, request, b) => myHouse(typology, request, b), // default: the far-away silhouettes of game-floorplan
|
|
61
|
+
vehicle: createVehicleProvider(), // default: none (the page's box car is not shipped)
|
|
62
|
+
plant: createPlantProvider(), // default: the cone pine and the ball tree of the props
|
|
63
|
+
},
|
|
64
|
+
})
|
|
65
|
+
// plan: { id, origin, houses, buildings, poles, vehicles, plants } (what was put where)
|
|
66
|
+
urban.neighbourhoods.composeSampleSheet(b) // the ground and the ten cells, in the order the page builds them
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### Vehicles and plants from the other packages
|
|
70
|
+
|
|
71
|
+
`createVehicleProvider({ ids?, pick?, paint? })` parks a vehicle of `game-vehicles-fleet` (cars, SUVs, pickups and vans by default) where a pattern parks one, and `createPlantProvider({ region?, contexts?, seed?, pick? })` plants a species of `game-vegetation-species` where a pattern plants (a tree from the region's `sidewalk_tree` table, a pine from `square`). They do not draw: they add a `placement` part (`b.place(kind, id, x, z, { ry, scale, color, seed })`) that says what to put and where. The choice depends on the spot and not on `b.random`, so the scene around it keeps the same draw order. The drawer (`game-urban-three`) asks a resolver for each kind and leaves the spot empty when it has none.
|
|
72
|
+
|
|
73
|
+
## Terrain
|
|
74
|
+
|
|
75
|
+
`urban.terrain(options)` is a ground made of layers, as the Galeria's Vale: a rolling base (waves), masked relief (mountains, hills: `mask · (level + waves)`), cities levelled flat, rivers carved to a bed, lakes carved to a level, a forest density, and a colour for every point by ordered rules (low ground, ellipses such as a bog, city rectangles, high rock, forest, then open fields picked by a hash of the map cell). It answers `heightAt(px, py)`, `forestAt`, `colorAt`, `nearRiver` and `toWorld`/`fromWorld` (the frame maps the plan to metres: `world = plan · scale + origin`), and hands a drawer `grid(segments)`: the 32-bit coordinates, heights and colours of the square mesh, rows along z. `urban.drawTerrain(b, terrain)` adds the mesh part and the water plane. `custom(px, py, h)` has the last word on a height.
|
|
76
|
+
|
|
77
|
+
The numbers of a place are the game's: the Vale Cinzento (4 rivers, 4 lakes, 5 cities, the Serra, the Mata Funda) is `game-slice/urban/valley-terrain.json` in the spec folder, and a copy of it is the fixture of the tests.
|
|
78
|
+
|
|
79
|
+
## Same seed, same city
|
|
80
|
+
|
|
81
|
+
The page keeps one generator for everything it draws and draws from it in call order. The builder does the same: the facade colour, the shop signs, the lit windows and the heights come from `b.random`, in the page's order, so a scene drawn with the same seed and the same calls has the same parts. The golden test in `game-urban-three` compares 34 parts, the terrain mesh (181 x 181 vertices, heights and colours) and the whole sample sheet (1029 objects, the lists of instances and windows, the light budget left, the next number of the random and the map markers) with the page's scene hash, the lists the page keeps before its flush and the surface of each material.
|