Files
havox/tutorials/midpoint_displacement/index.html
2026-03-16 18:03:17 +00:00

105 lines
4.3 KiB
HTML

<html>
<title>Midpoint Displacement</title>
<link href="https://fonts.googleapis.com/css?family=Roboto" rel="stylesheet">
<link href="https://fonts.googleapis.com/css?family=Inconsolata" rel="stylesheet">
<link rel"shortcut icon" type"image/ico" href"/Media/iconImage.ico">
<link rel="stylesheet" type="text/css" href="style.css">
<button id="backButton" onclick="window.location.href='/#tutorials'">Back</button>
<head>
<h1>Midpoint Displacement</h1>
<p>Midpoint displacement is a common way to generate terrains in video
games. Instead of manually creating a stage you can make an
algorithm create one based off randomness. This is faster to
calculate than a perlin noise stage which is why it can be found
frequently in older video game titles.</p><br>
<p>Psudo code:</p>
<div class="psudoCode">
<ul>
<li>Create two points.</li>
<li>Find the center x coordinate.</li>
<li>Create a new point in between the two first points with some
offset in the y coorindate.</li>
<li>Repeat. (can be recursive)</li>
</div>
<br>
</head>
<body>
<p>This canvas starts off with two points in an array called
<a>points[]</a>, one at <a>height/2</a> and one at
<a>math.random(-vertical_displacement, vertical_displacement)</a>.
The center point is found and a new point is made and added to the
array. This new point is offset on the y-axis by an amount however
we can't use the same <a>vertical_displacement</a> as we did before
as we'd end up with a very jagged terrain.
</p>
<img class="examples" src="Jagged_Terrain.jpg">
<p>Instead we have to iterate our variable -
<a>vertical_displacement</a> - based on the iteration number of the
sketch, in order to generate a smooth stage/terrain.
</p>
<div class="psudoCode">
<a>vertical_displacement = points[0].y + points[1].y / 2;</a><br>
<a>vertical_displacement *= 2 ** (-roughness);</a>
</div>
<p>The top formula is the inital value. The second is applied very
iteration of the sketch.</p>
<p>Right now we can add one point to the list, time to add several! This
means for loops. But before we can loop through our array how do we
know which point should connect to which? We need to sort the array
based on x value, so that the points read off from left to right.
</p>
<p>I just used a bubble sort for simplicity however it's worth pointing
out that the number of points grows exponetially - <a>O(2^n)</a>
where n = iterations - so after just 10 iterations <a>points.length
= 1024</a>. A merge sort could be used to speed up computation
times.</p>
<p>Now we can use a for loop to go through our array and compare the ith
item to the (i+1)th item, and then update <a>iterations</a> and
<a>vertical_displacement</a>.
</p>
<div class="psudoCode">
<a>var pLength = points.length;</a><br><br>
<a>&nbsp;for (var i = 0; i < pLength - 1; i++){</a><br>
<a>&nbsp;&nbsp;&nbsp;var midX = (points[i].x + points[i +
1].x) / 2;</a><br>
<a>&nbsp;&nbsp;&nbsp;var midY = (points[i].y + points[i +
1].y) / 2;</a><br>
<a>&nbsp;&nbsp;&nbsp;midY += random(-vertical_displacement,
vertical_displacement);</a><br>
<a>&nbsp;&nbsp;&nbsp;points[pLength + i] = new point(midX,
midY);</a><br>
<a>&nbsp;}</a><br><br>
<a>iterations += 1;</a><br>
<a>vertical_displacement *= 2 ** (-roughness);</a><br>
<a>bubbleSort();</a><br>
</div>
<h2>NOTE: Do not use points.length to define your for loop as we are
increasing the length of the array within the loop</h2>
<!--<span id="c1"></span>-->
</body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.2.0/p5.min.js"
integrity="sha512-b/htz6gIyFi3dwSoZ0Uv3cuv3Ony7EeKkacgrcVg8CMzu90n777qveu0PBcbZUA7TzyENGtU+qZRuFAkfqgyoQ=="
crossorigin="anonymous"></script>
<script src="sketch.js"></script>
<script src="dot.js"></script>
</html>