Slope of Perlin Noise

Hello,
I am generating 1D noise using the noise() function, and I need to draw a line perpendicular to the perlin noise in the x position of the mouse.
I tried calculating the slope of 2 points near each other, but the result is very inacurate.
I don’t really mind to use another noise generation method, but I already have the perlin noise example in my code.

Thank you for any help,
Arad.

By this, do you mean that the two perlin noise values calculated aren’t very close to one another? Did you try dividing the co-ordinates by some factor (probably around 30), to get a more smooth line?

Here is a example using perlin noise on the p5 website.

Also (especially if this isn’t your problem), it would be really helpful if you could post some code to show us what you are doing at the moment, and so that the problem can be better understood.

1 Like

I am using a value for the resolution of the x axis, but when I increase it, something goes wrong…
I’ll add the code so you can see it. I also made changes to the slope calculation. just averaging the slopes of the current position with lots of other points, but its working only on 4 points to each direction for some reason.
I already added a player and an enemy class (I won’t include the enemy class because it is npt related to the problem and I am not actually using it now).
The blue rectangle is the bounding box of the player, red line is the position, and green line is the angle.
nothing is really working now, I am just trying to get the angle works.

int window_width = 900, window_height = 700;
int terrainResolutionX = 2;

int slope_offset = 4;

float xoff = 0.0;
float[] terrain = new float[window_width / terrainResolutionX + 1];

float playerRotation = 0;
float playerFloorLineB = 0;

int playerX = 0, playerY = 0;
int playerWidth = 40, playerHeight = 50;

int playerAcceleration = 2;
float playerVel = 0;
int playerMaxVel = 20;

boolean key_a = false, key_d = false;

int enemyCount = 0;
ArrayList<Enemy> enemies = new ArrayList<Enemy>();

char[] enemyTypes = {'a', 'b', 'c', 'd', 'e', 'f', 'g'};

int score = 0;

void setup(){
  size(900, 700);
  
  playerX = window_width / 2;
  
  generateTerrain();
  
  for(int i = 0; i < 0; i++){
    newEnemy();
    print(enemies.get(i).enemyType);
  }
}

void draw() {
  background(255);
  
  updateKeysStates();
  
  playerX += playerVel;
  
  if(playerX > window_width - 1){
    playerX = window_width - 1;
  }else if(playerX < 0){
    playerX = 0;
  }
  
  if(playerVel < 0.25 && playerVel > -0.25){
    playerVel = 0;
  }
  
  float[] tempSlopes = new float[slope_offset * 2];
  float[] yValues = new float[slope_offset * 2];
  float playerSlope = 0;
  
  for(int i = 0; i < slope_offset * 2; i++){
    int operator = 0;
    if(i < slope_offset){
      operator = -1;
    }
    
    if(playerX + (i - 3 + operator) < slope_offset || playerX + (i - 3 + operator) > window_width - slope_offset){
      yValues[i] = terrain[playerX / terrainResolutionX];
    }else{
      yValues[i] = terrain[(playerX / terrainResolutionX) + (i - 3 + operator)];
    }
  }
  
  for(int i = 0; i < slope_offset * 2; i++){
    int operator = 0;
    if(i < slope_offset){
      operator = -1;
    }
    
    tempSlopes[i] = (terrain[playerX / terrainResolutionX] - yValues[i]) / (i - 3 + operator);
    playerSlope += tempSlopes[i];
  }
  
  playerSlope /= (slope_offset * 2);
  
  playerVel -= playerSlope * 0.3;
  
  if(playerVel > playerMaxVel){
    playerVel = playerMaxVel;
  }
  if(playerVel < -playerMaxVel){
    playerVel = -playerMaxVel;
  }
  
  playerVel -= 0.2 * playerVel;
  
  stroke(0);
  for(int i = 0; i < (window_width / terrainResolutionX) - 1; i++){
    line(i * terrainResolutionX, terrain[i], (i * terrainResolutionX) + 1, terrain[i + 1]);
  }
  
  stroke(255, 0, 0);
  line(playerX, terrain[(int)(playerX / terrainResolutionX)], playerX, terrain[(int)(playerX / terrainResolutionX)] - playerHeight);
  
  stroke(0, 255, 0);
  float angle1;
  angle1 = degrees(atan(playerSlope));
  float angle2 = 90 - angle1 + 90;
  float ratioA = playerHeight / sin(HALF_PI);
  float side1H = ratioA * sin(radians(angle2));
  float side2W = sqrt(pow(playerHeight / 2, 2) - pow(side1H, 2));
  line(playerX, terrain[playerX / terrainResolutionX], playerX - side1H, terrain[playerX / terrainResolutionX] - side2W);
    
  for(Enemy e : enemies){
    e.update();
    e.show();
  }
  
  float temp = 0;
  for(int i = enemies.size() - 1; i >= 0; i--){
    if(enemies.get(i).xPos >= window_width - 1 || enemies.get(i).xPos <= 1){
      temp++;
      enemies.remove(i);
    }else if(enemies.get(i).yPos + enemies.get(i).size / 2 >= terrain[floor(enemies.get(i).xPos / terrainResolutionX)]){
      temp++;
      enemies.remove(i);
    }
  }
  
  for(int i = 0; i < temp; i++){
    newEnemy();
  }
  
  fill(0);
  textSize(40);
  textAlign(LEFT, TOP);
  text(score, 10, 10);
  
  pushMatrix();
  
  noFill();
  stroke(0, 0, 255);
  translate(playerX, terrain[playerX / terrainResolutionX] - 0.5 * playerHeight);
  //rotate(radians(angle1));
  rect(-playerWidth / 2, -playerHeight / 2, playerWidth, playerHeight);
  
  popMatrix();
}

void generateTerrain(){
  for(int i = 0; i < window_width / terrainResolutionX; i++){
    xoff = xoff + .01;
    float n = noise(xoff) * 150;
    terrain[i] = window_height - n;
  }
}

void updateKeysStates(){
  if(key_a){
    playerVel -= playerAcceleration;
  }
  if(key_d){
    playerVel += playerAcceleration;
  }
}

void newEnemy(){
  enemies.add(new Enemy(random(60, 840), enemyTypes[(int)random(0, enemyTypes.length)], random(6, 9), random(-15, 15), random(25, 35)));
}

void keyPressed(){
  if(key == 'a'){
    key_a = true;
  }
  if(key == 'd'){
    key_d = true;
  }
}
void keyReleased(){
  if(key == 'a'){
    key_a = false;
  }
  if(key == 'd'){
    key_d = false;
  }
}

I you have any questions about the code, just ask me :slight_smile:
I need this really fast so I hope you have an answer.

1 Like

Is there another tab with the Enemy class?

yes,

class Enemy{
  float xPos = 0, yPos = 0;
  float vel = 0, theta = 0;
  char enemyType = '0';
  float size;
  
  Enemy(float x, char type, float speed, float angle, float radius){
    xPos = x;
    enemyType = type;
    vel = speed;
    theta = angle;
    size = radius;
    yPos = -size;
  }
  
  void update(){
    float ratio = vel / degrees(sin(HALF_PI));
    float delta_x = ratio * degrees(sin(radians(theta)));
    float delta_y = sqrt((vel * vel) - (delta_x * delta_x));
    
    xPos += delta_x;
    yPos += delta_y;
    
    //print(delta_x, " , ", delta_y);
  }
  
  void show(){
    noStroke();
    
    if(enemyType == 'a'){
      fill(244, 66, 83);
    }
    if(enemyType == 'b'){
      fill(238, 65, 244);
    }
    if(enemyType == 'c'){
      fill(112, 65, 244);
    }
    if(enemyType == 'd'){
      fill(65, 169, 244);
    }
    if(enemyType == 'e'){
      fill(65, 244, 193);
    }
    if(enemyType == 'f'){
      fill(65, 244, 73);
    }
    if(enemyType == 'g'){
      fill(232, 244, 65);
    }
    if(enemyType == 'h'){
      fill(244, 169, 65);
    }
    
    ellipse(xPos, yPos, size, size);
    //println("hello!!! , ", xPos, " , ", yPos);
  }
  
};

Ah, I think I understand what you mean now.
What you want to do is calculate the gradient of a tangent to a part of the terrain and then find the line perpendicular to it.
Here is some psuedo code for it:

x1 = player x - 1 pixel
x2 = player x
y1 = height at the pixel 1 pixel before the one the player is on.
y2 = height at the pixel the player is on

perpendicularLineGradient= (x1-x2)/(y1-y2) [I think]

lineLength = 20

scale = sqrt(lineLength^2/(perpendicularLineGradient^2+1))

line(x2, y2, x2 + scale, y2 + perpendicularLineGradient * scale)

I’m not sure I got this quite right; it’s quite a lot of math. If it isn’t correct then let me know.
Here is a BBC bitesize page on calculating equations of perpendicular lines.

When I say pixel, any unit will do as long as you keep it the same throughout.

Also, the last bit involving the variable I named “scale” is so that the length of the lines is constant, rather than just having a constant x or y length of the line.

I really hope this works and makes sense. :joy:

Feel free to ask me any questions.

1 Like

perpendicularLineGradient= (x1-x2)/(y1-y2) [I think]

its (y - y)/(x-x)

I already tried it, and it wast precise enough.
Because Im short of time I decided to stick with a sine wave, that is simpler.

No I think

is the gradient of the line but -(x-x)/(y-y) is gradient of the perpendicular line.