This Trac instance is not used for development anymore!

We migrated our development workflow to git and Gitea.
To test the future redirection, replace trac by ariadne in the page URL.

source: ps/trunk/binaries/data/mods/public/maps/random/rmgen/TileClass.js

Last change on this file was 25622, checked in by wraitii, 4 years ago

Speed up and simplify TileClass implementation

Use a more memory-efficient layout, reducing memory usage and speeding things up considerably.

Patch by: smiley

Reviewed By: wraitii

Differential Revision: https://code.wildfiregames.com/D4021

  • Property svn:eol-style set to native
File size: 3.0 KB
RevLine 
[25622]1/**
2 * Class that can be tagged to any tile. Can be used to constrain placers and entity placement to given areas.
3 */
4class TileClass {
[9096]5
[25622]6 constructor(size)
[9096]7 {
[25622]8 this.size = size;
9 this.width = Math.ceil(size / 16); // Need one entry per 16 tiles as each tile takes a single bit
10 this.inclusionGrid = new Uint16Array(this.size * this.width);
[9096]11 }
12
[25622]13 /**
14 * Returns true if the given position is part of the tileclass.
15 */
16 has(position)
[9096]17 {
[25622]18 if (position.x < 0 || position.x >= this.size || position.y < 0 || position.y >= this.size)
19 return 0;
20 // x >> 4 == Math.floor(x / 16); used to find the integer this x is included in
21 // x & 0xF == x % 16; used to find the bit position of the given x
22 return this.inclusionGrid[position.y * this.width + (position.x >> 4)] & (1 << (position.x & 0xF));
[9096]23 }
[18840]24
[25622]25 /**
26 * Adds the given position to the tileclass.
27 */
28 add(position)
[9096]29 {
[25622]30 if (position.x < 0 || position.x >= this.size || position.y < 0 || position.y >= this.size)
31 return;
32 this.inclusionGrid[position.y * this.width + (position.x >> 4)] |= 1 << (position.x & 0xF);
[9096]33 }
[18840]34
[25622]35 /**
36 * Removes the given position to the tileclass.
37 */
38 remove(position)
[9096]39 {
[25622]40 if (position.x < 0 || position.x >= this.size || position.y < 0 || position.y >= this.size)
41 return;
42 this.inclusionGrid[position.y * this.width + (position.x >> 4)] &= ~(1 << (position.x & 0xF));
[9096]43 }
44
[25622]45 /**
46 * Count the number of tiles in the tileclass within the given radius of the given position.
47 * Can return either the total number of members or nonmembers.
48 */
49 countInRadius(position, radius, returnMembers)
[9096]50 {
[25622]51 let members = 0;
52 let total = 0;
53 const radius2 = radius * radius;
54 const [x, y] = [position.x, position.y];
[18840]55
[25622]56 const yMin = Math.max(Math.ceil(y - radius), 0);
57 const yMax = Math.min(Math.floor(y + radius), this.size - 1);
58 for (let iy = yMin; iy <= yMax; ++iy)
[15621]59 {
[25622]60 const dy = iy - y;
61 const dy2 = dy * dy;
62 const delta = Math.sqrt(radius2 - dy2);
63 const xMin = Math.max(Math.ceil(x - delta), 0);
64 const xMax = Math.min(Math.floor(x + delta), this.size - 1);
[21026]65
[25622]66 const indexXMin = xMin >> 4;
67 const indexXMax = xMax >> 4;
68 const indexY = iy * this.width;
69 for (let indexX = indexXMin; indexX <= indexXMax; ++indexX)
[15621]70 {
[25622]71 const imin = indexX == indexXMin ? xMin & 0xF : 0;
72 const imax = indexX == indexXMax ? xMax & 0xF : 15;
73 total += imax - imin + 1;
74 if (this.inclusionGrid[indexY + indexX])
75 for (let i = imin; i <= imax; ++i)
76 if (this.inclusionGrid[indexY + indexX] & (1 << i))
77 ++members;
[15621]78 }
79 }
[25622]80
81 return returnMembers ? members : total - members;
[9096]82 }
[18840]83
[25622]84 /**
85 * Counts the number of tiles marked in the tileclass within the given radius of the given position.
86 */
87 countMembersInRadius(position, radius)
88 {
89 return this.countInRadius(position, radius, true);
90 }
[9096]91
[25622]92 /**
93 * Counts the number of tiles not marked in the tileclass within the given radius of the given position.
94 */
95 countNonMembersInRadius(position, radius)
96 {
97 return this.countInRadius(position, radius, false);
98 }
99}
Note: See TracBrowser for help on using the repository browser.