I have a canvas that is 1000x600px. I want to spawn sprites outside the canvas (but evenly distributed). What is the best way to retrieve random values between (-500, -500) and (1500, 1100) but not between (0, 0) and (1000, 600)? I understand a while loop could be used to generate numbers until they are in range but that seems superfluous. Thanks.
If you want to generate a number between -500 and 1500, excluding 0 to 1000, you can just generate a number between 0 and 1000 ( 0 - -500 + 1500 - 1000).
If the number is less than 500, you subtract 500; if the number is greater or equal to 500, add 500.
Or, more generically:
function randomInt(outerMin, outerMax, innerMin, innerMax)
{
var usableRange = innerMin - outerMin + outerMax - innerMax,
threshold = innerMin - outerMin,
num = Math.floor(Math.random() * (usableRange + 1));
if (num < threshold) {
return num - threshold;
} else {
return num - threshold + innerMax;
}
}
randomInt(-500, 1500, 0, 1000);
For two-dimensional points you have to get more creative. First, you generate two points that ARE inside the forbidden area and then spread those values to the good areas:
function randomVector(outer, inner)
{
var innerWidth = inner.right - inner.left,
innerHeight = inner.bottom - inner.top,
x = Math.floor(Math.random() * (innerWidth + 1)),
y = Math.floor(Math.random() * (innerHeight + 1)),
midx = Math.floor(innerWidth / 2),
midy = Math.floor(innerHeight / 2);
if (x < midx) { // left side of forbidden area, spread left
x = x / midx * (inner.left - outer.left) - inner.left;
} else { // right side of forbidden area, spread right
x = (x - midx) / midx * (outer.right - inner.right) + inner.right;
}
if (y < midy) { // top side of forbidden area, spread top
y = y / midy * (inner.top - outer.top) - inner.top;
} else { // bottom side of forbidden area, spread bottom
y = (y - midy) / midy * (outer.bottom - inner.bottom) + inner.bottom;
}
// at this point I'm not sure how to round them
// but it probably should have happened one step above :)
return {
x: Math.floor(x),
y: Math.floor(y)
}
}
randomVector({
left: -500,
top: -500,
right: 1500,
bottom: 1100
}, {
left: 0,
top: 0,
right: 1000,
bottom: 600
});
Important
This works because the areas outside of your "forbidden" area are equal in their respective dimension, i.e. padding-top == padding-bottom && padding-left == padding-right.
If this will be different, the distribution is no longer uniform.
Generate a random number between 0 and 1000, if its over 500 add 500 (or 600 respectivly) if not negate it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With