Quick answer: Augment each element with its original index. Sort by primary key, then by index as a tiebreaker. Stable sort even on old browsers.
A high score table sorts by score descending. Players with identical scores swap positions every refresh — sort isn’t stable. The display feels random.
Augmented Array
Maintain a parallel index in the array data:
[
{ score: 100, name: "A", idx: 0 },
{ score: 200, name: "B", idx: 1 },
{ score: 100, name: "C", idx: 2 }
]
Sort comparator: score desc, then idx asc:
function(a, b) {
if (a.score != b.score) return b.score - a.score;
return a.idx - b.idx;
}
In Construct Events
Construct’s Sort action calls a JS expression or uses a custom event. For complex sorts, use the JavaScript module:
scoreArray.sort((a, b) => {
const s = b.score - a.score;
return s !== 0 ? s : a.idx - b.idx;
});
Run via Browser → Execute JavaScript or in a JS file imported via the script project property.
Why Indices Help
Without tiebreaker, the sort algorithm freely swaps equal elements. With idx tiebreaker, ordering is deterministic: equal-score players always show in the same relative order.
Stable Sort Helper Function
Reuse across the project:
function stableSort(arr, cmp) {
return arr
.map((v, i) => [v, i])
.sort(([a, i], [b, j]) => cmp(a, b) || i - j)
.map(([v]) => v);
}
Decorates with index, sorts, undecorates. Stable on any JS runtime.
Verifying
Sort score table repeatedly. Equal-score entries always in the same order. Add a new tied entry; it slots after existing same-score entries (matching insertion order).
“Stable sort = predictable display. Pair sort key with index, problem solved everywhere.”
For leaderboards specifically, also add timestamp tiebreaker — earlier scorers rank ahead, motivating early competition.