Skip to content

Commit 9a96ecd

Browse files
authored
Merge pull request #1266 from melonjs/fix/concave-polygon-decomposition
Decompose concave collision polygons into convex triangles
2 parents 588db28 + 94f4b5d commit 9a96ecd

3 files changed

Lines changed: 23 additions & 111 deletions

File tree

packages/examples/public/assets/tiledMapLoader/map/orthogonal-outside.tmx

Lines changed: 1 addition & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -227,59 +227,8 @@
227227
</data>
228228
</layer>
229229
<objectgroup id="3" name="Objects">
230-
<object id="1" name="maggots" type="Location" x="435" y="74" width="155" height="99">
231-
<properties>
232-
<property name="spawncount" type="int" value="5"/>
233-
<property name="spawntype" value="maggot"/>
234-
</properties>
235-
</object>
236-
<object id="2" name="discover chest" type="Trigger" x="201" y="200" width="127" height="127">
237-
<properties>
238-
<property name="script" type="file" value="chest-discovered.lua"/>
239-
</properties>
240-
<ellipse/>
241-
</object>
242-
<object id="3" name="unreachable" type="Fixture" x="2" y="158">
243-
<properties>
244-
<property name="static" type="bool" value="true"/>
245-
</properties>
230+
<object id="3" x="2" y="158">
246231
<polygon points="0,0 55,-23 96,-117 110,-61 104,-42 119,-33 116,6 104,9 100,36 60,43 53,58 43,58 34,74 21,69 18,90 0,89"/>
247232
</object>
248-
<object id="5" name="guard" type="NPC" x="22" y="361">
249-
<polyline points="-3,120 87,91 154,96 181,16 273,-1"/>
250-
</object>
251-
<object id="6" name="guard" type="NPC" x="277" y="18">
252-
<polyline points="0,0 75,78 133,82 176,179 274,183"/>
253-
</object>
254-
<object id="10" gid="282" x="413.333" y="225.333" width="16" height="16"/>
255-
<object id="11" gid="282" x="421.667" y="218" width="16" height="16"/>
256-
<object id="12" gid="2147483930" x="423" y="235.333" width="16" height="16"/>
257-
<object id="13" gid="282" x="5" y="70" width="16" height="16"/>
258-
<object id="14" gid="282" x="-3.66667" y="80.3333" width="16" height="16"/>
259-
<object id="16" gid="283" x="538" y="418.333" width="16" height="16"/>
260-
<object id="17" gid="283" x="407.667" y="462" width="16" height="16"/>
261-
<object id="18" gid="283" x="417" y="473.667" width="16" height="16"/>
262-
<object id="19" gid="283" x="402.667" y="469" width="16" height="16"/>
263-
<object id="21" gid="2147483930" x="683.333" y="260.5" width="16" height="16"/>
264-
<object id="22" gid="282" x="692.167" y="269.167" width="16" height="16"/>
265-
<object id="23" gid="282" x="701.667" y="247.833" width="16" height="16"/>
266-
<object id="24" gid="282" x="688.5" y="242" width="16" height="16"/>
267-
<object id="25" gid="282" x="670.5" y="263.5" width="16" height="16"/>
268-
<object id="26" gid="282" x="680" y="284" width="16" height="16"/>
269-
<object id="27" gid="282" x="643.833" y="283.667" width="16" height="16"/>
270-
<object id="28" gid="282" x="63.4165" y="386" width="16" height="16"/>
271-
<object id="29" gid="282" x="9.0835" y="356.167" width="16" height="16"/>
272-
<object id="30" gid="282" x="11.9165" y="385" width="16" height="16"/>
273-
<object id="31" gid="282" x="54.2495" y="378.5" width="16" height="16"/>
274-
<object id="32" gid="2147483930" x="2.4165" y="364.5" width="16" height="16"/>
275-
<object id="33" gid="2147483930" x="41.5835" y="382.833" width="16" height="16"/>
276-
<object id="34" type="Sign" gid="257" x="670.667" y="87" width="16" height="16">
277-
<properties>
278-
<property name="text" value="East West"/>
279-
</properties>
280-
</object>
281-
<object id="37" name="player-start" type="Location" x="192" y="160">
282-
<point/>
283-
</object>
284233
</objectgroup>
285234
</map>

packages/examples/src/examples/tiledMapLoader/assets/map/orthogonal-outside.tmx

Lines changed: 1 addition & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -227,59 +227,8 @@
227227
</data>
228228
</layer>
229229
<objectgroup id="3" name="Objects">
230-
<object id="1" name="maggots" type="Location" x="435" y="74" width="155" height="99">
231-
<properties>
232-
<property name="spawncount" type="int" value="5"/>
233-
<property name="spawntype" value="maggot"/>
234-
</properties>
235-
</object>
236-
<object id="2" name="discover chest" type="Trigger" x="201" y="200" width="127" height="127">
237-
<properties>
238-
<property name="script" type="file" value="chest-discovered.lua"/>
239-
</properties>
240-
<ellipse/>
241-
</object>
242-
<object id="3" name="unreachable" type="Fixture" x="2" y="158">
243-
<properties>
244-
<property name="static" type="bool" value="true"/>
245-
</properties>
230+
<object id="3" x="2" y="158">
246231
<polygon points="0,0 55,-23 96,-117 110,-61 104,-42 119,-33 116,6 104,9 100,36 60,43 53,58 43,58 34,74 21,69 18,90 0,89"/>
247232
</object>
248-
<object id="5" name="guard" type="NPC" x="22" y="361">
249-
<polyline points="-3,120 87,91 154,96 181,16 273,-1"/>
250-
</object>
251-
<object id="6" name="guard" type="NPC" x="277" y="18">
252-
<polyline points="0,0 75,78 133,82 176,179 274,183"/>
253-
</object>
254-
<object id="10" gid="282" x="413.333" y="225.333" width="16" height="16"/>
255-
<object id="11" gid="282" x="421.667" y="218" width="16" height="16"/>
256-
<object id="12" gid="2147483930" x="423" y="235.333" width="16" height="16"/>
257-
<object id="13" gid="282" x="5" y="70" width="16" height="16"/>
258-
<object id="14" gid="282" x="-3.66667" y="80.3333" width="16" height="16"/>
259-
<object id="16" gid="283" x="538" y="418.333" width="16" height="16"/>
260-
<object id="17" gid="283" x="407.667" y="462" width="16" height="16"/>
261-
<object id="18" gid="283" x="417" y="473.667" width="16" height="16"/>
262-
<object id="19" gid="283" x="402.667" y="469" width="16" height="16"/>
263-
<object id="21" gid="2147483930" x="683.333" y="260.5" width="16" height="16"/>
264-
<object id="22" gid="282" x="692.167" y="269.167" width="16" height="16"/>
265-
<object id="23" gid="282" x="701.667" y="247.833" width="16" height="16"/>
266-
<object id="24" gid="282" x="688.5" y="242" width="16" height="16"/>
267-
<object id="25" gid="282" x="670.5" y="263.5" width="16" height="16"/>
268-
<object id="26" gid="282" x="680" y="284" width="16" height="16"/>
269-
<object id="27" gid="282" x="643.833" y="283.667" width="16" height="16"/>
270-
<object id="28" gid="282" x="63.4165" y="386" width="16" height="16"/>
271-
<object id="29" gid="282" x="9.0835" y="356.167" width="16" height="16"/>
272-
<object id="30" gid="282" x="11.9165" y="385" width="16" height="16"/>
273-
<object id="31" gid="282" x="54.2495" y="378.5" width="16" height="16"/>
274-
<object id="32" gid="2147483930" x="2.4165" y="364.5" width="16" height="16"/>
275-
<object id="33" gid="2147483930" x="41.5835" y="382.833" width="16" height="16"/>
276-
<object id="34" type="Sign" gid="257" x="670.667" y="87" width="16" height="16">
277-
<properties>
278-
<property name="text" value="East West"/>
279-
</properties>
280-
</object>
281-
<object id="37" name="player-start" type="Location" x="192" y="160">
282-
<point/>
283-
</object>
284233
</objectgroup>
285234
</map>

packages/melonjs/src/level/tiled/TMXObject.js

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -226,15 +226,29 @@ export default class TMXObject {
226226
if (this.isPolygon === true) {
227227
const _polygon = polygonPool.get(0, 0, this.points);
228228
const isConvex = _polygon.isConvex();
229-
// make sure it's a convex polygon
230-
if (isConvex === false) {
231-
throw new Error(
232-
"collision polygones in Tiled should be defined as Convex",
229+
230+
if (isConvex === true) {
231+
shapes.push(_polygon.rotate(this.rotation));
232+
} else if (isConvex === false) {
233+
// decompose concave polygon into convex triangles
234+
console.warn(
235+
"melonJS: concave collision polygon detected, decomposing into convex triangles",
233236
);
234-
} else if (isConvex === null) {
235-
throw new Error("invalid polygone");
237+
const indices = _polygon.getIndices();
238+
const pts = _polygon.points;
239+
for (let t = 0; t < indices.length; t += 3) {
240+
const tri = polygonPool.get(0, 0, [
241+
vector2dPool.get(pts[indices[t]].x, pts[indices[t]].y),
242+
vector2dPool.get(pts[indices[t + 1]].x, pts[indices[t + 1]].y),
243+
vector2dPool.get(pts[indices[t + 2]].x, pts[indices[t + 2]].y),
244+
]);
245+
shapes.push(tri.rotate(this.rotation));
246+
}
247+
polygonPool.release(_polygon);
248+
} else {
249+
console.warn("melonJS: invalid polygon definition, skipping");
250+
polygonPool.release(_polygon);
236251
}
237-
shapes.push(_polygon.rotate(this.rotation));
238252
} else if (this.isPolyLine === true) {
239253
const p = this.points;
240254
let p1;

0 commit comments

Comments
 (0)