@Gajet's answer is impossible to follow (so I'm not even convinced it will work), and what I think @The Communist Duck meant his solution to be...
block_y = ground_y + random() % (previousBlock_y + playerJumpHeight)
...will be heavily biased towards creating blocks with y-values centered around ground_y + playerJumpHeight
.
The easiest way to produce more satisfying results would be, rather than generate a height between ground_y
and previousBlock_y + playerJumpHeight
, generate a random value between previousBlock_y - playerJumpHeight
and previousBlock_y + playerJumpHeight
.
Of course, since we want to take ground_y
and maxBlockHeight
into consideration also, we really want to find a random value between max(ground_y, previousBlock_y - playerJumpHeight)
and min(maxBlockHeight, previousBlock_y + playerJumpHeight)
. This will skew our distribution a bit (biased towards the center of the screen), but not enough to be noticeable.
The simplest way to do this would be
//delta_y is a random number between -/+ playerJumpHeight
min_y = max(ground_y, previousBlock_y - playerJumpHeight)
max_y = min(maxBlockHeight, previousBlock_y + playerJumpHeight)
range_y = max_y - min_y
block_y = random() % range_y + min_y
If you then want the block to have a random height as well, just generate a random number between ground_y
and block_y
to be the height.
[Edit] There is a way to have a probability of jumping down by any amount, while still giving the player equal probability of being anywhere on the screen at any given point.
Thanks to Didier Piau on the math forums for figuring this out. The full explanation is complex, so I'll leave it out; the curious can visit that page, from which I generalized this algorithm. The algorithm itself is actually pretty simple, though.
int getNextBlockHeight()
{
int playingFieldHeight = screen_y - ground_y;
int canonicalBlockMaxHeight = playingFieldHeight - playerHeight;
int nextBlockMaxHeight = min(currentBlockHeight + playerJumpHeight, canonicalBlockMaxHeight);
//Let's divide the screen vertically into chunks of size playerJumpHeight.
//This code makes it so that each chunk is approximately twice as likely as being chosen
//as the previous chunk
float canonicalHeightRatio = (float)canonicalBlockMaxHeight / playerJumpHeight;
float nextHeightRatio = (float)nextBlockMaxHeight / playerJumpHeight;
//The following looks complicated, but really it just ensures that the minimum is 0, the maximum is
//nextBlockMaxHeight, and everything in between is mapped logarithmically
float randomMin = pow(2, -canonicalHeightRatio);
float randomMax = pow(2, nextHeightRatio-canonicalHeightRatio);
float randomVal = randFloat(randomMin, randomMax);
float randomHeightRatio = log2(randVal)+canonicalHeightRatio;
return (int)(randomHeightRatio*playerJumpHeight) + ground_y;
}
//Return the log-base-2 of a number
const float log_of_2 = log(2);
float log2(float value)
{
return log(value) / log_of_2;
}
//Generates a random floating-point number between min and max
float randFloat(float min, float max)
{
float randomNormalized = (float)rand()/RAND_MAX; //Between 0.0 and 1.0
return randomNormalized*(max-min) + min;
}
min
andmax
, which is really trivial, as long as you figure out how to get a random value on your system (which is not the question). I think beginners questions are ok, but there's got to be a threshold. Also all the answers given don't provide a solution in plain Objective-C, so no real help there (assuming the OP is really totally new to Objective-C) \$\endgroup\$ – bummzack Jun 24 '11 at 10:33