-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmap.html
More file actions
139 lines (135 loc) · 7.6 KB
/
map.html
File metadata and controls
139 lines (135 loc) · 7.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
<html>
<body>
<!-- Crop the image of the tileset to the tile ; used with object-position below -->
<style>
img {
object-fit:none;
}
#map div.layer {
position:absolute;
top:0;
left:0;
}
</style>
<div id="map" style="position:relative"></div>
<script>
function drawLayer (id, width, height, tileSizeX, tileSizeY, layerContent, tilesetWidth, tilesetHeight, firstGid) {
const DIAG_FLIP_MASK = 0x20000000;
const X_FLIP_MASK = 0x80000000;
const Y_FLIP_MASK = 0x40000000;
let map = document.getElementById ("map");
const mapXSize = width * tileSizeX;
const mapYSize = height * tileSizeY;
var cellIndex = 0;
var layerDiv = document.createElement ("div");
for (var y = 0; y < mapYSize; y += tileSizeY) {
var lineDiv = document.createElement ("div");
for (var x = 0; x < mapXSize; x += tileSizeX) {
// The tile ids start at firstGid and increment over every tile in the tileset
var tileId = layerContent [cellIndex] - firstGid;
const flipFlags = tileId & 0xF0000000;
tileId = tileId & 0xFFFFFFF; // Remove the rotation bits from the tile id
var cellImg = document.createElement ("img");
// We show only one tile from the tileset
cellImg.setAttribute ("width", tileSizeX + "px");
cellImg.setAttribute ("height", tileSizeY + "px");
// Use the Tiled exported tileset as the source for the image
cellImg.setAttribute ("src", "tileset.png");
// Draw the tile appropriately to the rotation
var flipStyle = "";
if (flipFlags !== 0) {
/* Documentation from https://doc.mapeditor.org/en/stable/reference/global-tile-ids/#gid-tile-flipping :
Bit 32 is used for storing whether the tile is horizontally flipped, bit 31 is used for the vertically flipped tiles. In orthogonal and isometric maps, bit 30 indicates whether the tile is flipped (anti) diagonally, which enables tile rotation, and bit 29 can be ignored. In hexagonal maps, bit 30 indicates whether the tile is rotated 60 degrees clockwise, and bit 29 indicates 120 degrees clockwise rotation.
When rendering an orthographic or isometric tile, the order of operations matters. The diagonal flip is done first, followed by the horizontal and vertical flips. The diagonal flip should flip the bottom left and top right corners of the tile, and can be thought of as an x/y axis swap. */
if (flipFlags & DIAG_FLIP_MASK) { // bit 30
flipStyle += " transform-origin: center; transform: scaleX(-1) scaleY(-1) ";
}
if (flipFlags & X_FLIP_MASK) { // bit 32
if (flipStyle === "") {
flipStyle = " transform: scaleX(-1) ";
}
else {
// diagonal flip + x symmetry = rotation 90°
if (flipFlags & DIAG_FLIP_MASK) {
flipStyle = " transform-origin:center; transform: rotate(90deg) ";
}
else {
flipStyle += "scaleX(-1) ";
}
}
}
if (flipFlags & Y_FLIP_MASK) { // bit 31
if (flipStyle === "") {
flipStyle = " transform: scaleY(-1) ";
}
else {
// diagonal flip + y symmetry = rotation -90°
if (flipFlags & DIAG_FLIP_MASK) {
flipStyle = " transform-origin:center; transform: rotate(-90deg) ";
}
else {
flipStyle += " scaleY(-1) ";
}
}
}
flipStyle += ";"
}
if (tileId >= 0) {
// Offset the tileset image so that the part that is visible is the tile which ID we know
const yOffset = tileSizeY * (tileId / tilesetWidth | 0);
const xOffset = tileSizeX * (tileId % tilesetWidth);
cellImg.setAttribute ("style", flipStyle + "object-position:-" + xOffset + "px -" + yOffset + "px" );
}
else {
// Offset the tilset image so that it is not visible (making the tile transparent)
cellImg.setAttribute ("style", "object-position:" + tileSizeX + "px " + tileSizeY + "px");
}
lineDiv.appendChild (cellImg);
cellIndex ++;
}
layerDiv.appendChild (lineDiv);
}
layerDiv.setAttribute ("id", id);
layerDiv.setAttribute ("class", "layer");
map.appendChild (layerDiv);
}
</script>
<!-- Load the js library used for unzipping the layer -->
<!-- You can get pako.js from https://raw.githubusercontent.com/nodeca/pako/master/dist/pako.js -->
<script type="text/javascript" src="pako.js"></script>
<!-- Load the Tiled map -->
<script type="text/javascript" src="map.js"></script>
<!-- Show the layers of the map, using the first tileset -->
<script>
var tileMap;
for (var mapName in TileMaps) {
tileMap = TileMaps [mapName];
}
for (var layer of tileMap.layers) {
if (layer.type !== "tilelayer") {
continue;
}
// Retrieve the layer data by unzipping the layer data
const layerHeight = layer.height;
const layerWidth = layer.width;
// Unzipping the layer data :
// Decode base64 (convert ascii to binary)..
const strData = atob(layer.data);
// Convert binary string to character-number array..
const charData = strData.split('').map(function(x){return x.charCodeAt(0);});
// Turn number array into byte-array..
const binData = new Uint8Array(charData);
// Unzip..
const data = pako.inflate(binData);
// ..and turn into an array of 32 bytes unsigned integers, containing the tile ids.
var layerContent = new Uint32Array(data.buffer);
// Retrieve tileset size and first tile id
const tileSet = tileMap.tilesets [0];
const firstGID = tileSet.firstgid;
const tilesetWidth = tileSet.imagewidth / tileSet.tilewidth;
const tilesetHeight = tileSet.imageheight / tileSet.tileheight;
drawLayer ("layer " + layer.id, layerWidth, layerHeight, tileSet.tilewidth, tileSet.tileheight, layerContent, tilesetWidth, tilesetHeight, firstGID);
}
</script>
</body>
</html>