So im trying to create a procedural road generator (I cant find code online I can look at to be inspired by), and I've managed to get vectors to generate the start of the road (at the red dot, as origin)and the start of its lengthening using new segments created where the end of the starting segments end using recursion. but for some reason I cant comprehend why each new segment is longer and longer despite min max variables
I still need to implement collision detection, rules to deal with that and branching.
here is an example of what it looks like

ive tried a depth parameter to control recursion and reduces the length of segments as the depth increases. but its still happening.
// This function tries to extend a road segment based on certain conditions
function extendRoadSegment(segment, svgElement, depth = 0) {
var minLength = 2; // Minimum length for a new road segment
var depthLengthReduction = 0.5; // Reduction factor per depth level
var maxLength = 5 - (depth * depthLengthReduction); // Reduce max length as depth increases
maxLength = Math.max(minLength, maxLength); // Ensure maxLength does not go below minLength
var maxAngleVariance = Math.PI / 8; // Max variance in angle for new road direction
var maxDepth = 5; // Maximum recursion depth
// Stop the recursion if the maximum depth is exceeded
if (depth > maxDepth) {
return;
}
// Determine whether to stop extending the current segment
var shouldStop = Math.random() < (0.01 + depth * 0.01); // Increasing chance to stop with depth
if (shouldStop) {
return; // Stop extending this segment
}
// Determine whether to branch the current segment
var shouldBranch = Math.random() < (0.3 - depth * 0.05); // Decreasing chance to branch with depth
// Rotate the direction of the new segment within the allowed variance
var newDirection = segment.direction.clone();
newDirection.rotate(getRandomArbitrary(-maxAngleVariance, maxAngleVariance));
// Determine the length of the new segment, ensuring it's not less than the minimum
var newLength = getRandomInt(minLength, maxLength);
console.log(`Depth: ${depth}, New Segment Length: ${newLength}`);
// Create the new segment and draw it on the SVG
var newSegment = new RoadSegment(segment.end, newDirection, newLength);
var drawableSegment = newSegment.toDrawable();
svgElement.appendChild(drawableSegment);
console.log(`New Segment Start: (${newSegment.start.x}, ${newSegment.start.y})`);
console.log(`New Segment End: (${newSegment.end.x}, ${newSegment.end.y})`);
// Recursively extend from the new segment
if (shouldBranch) {
extendRoadSegment(newSegment, svgElement, depth + 1);
}
console.log(`Should Stop: ${shouldStop}, Should Branch: ${shouldBranch}`);
}
I suspect the issue could be here? are the newLength generated seems consistent:
class Vector2 {
constructor(x, y) {
this.x = x;
this.y = y;
}
clone() {
return new Vector2(this.x, this.y);
}
add(vector) {
this.x += vector.x;
this.y += vector.y;
}
rotate(angle) {
const cos = Math.cos(angle);
const sin = Math.sin(angle);
const x = this.x * cos - this.y * sin;
const y = this.x * sin + this.y * cos;
this.x = x;
this.y = y;
}
multiplyScalar(scalar) {
this.x *= scalar;
this.y *= scalar;
return this;
}
// Additional vector operations as needed...
}
[1]: https://i.stack.imgur.com/t0v8y.png