Wanting advise on how I could randomize my work more

#1

I am working on a project where I use a keylogger to collect button input, let Processing read it and let it do certain actions when it goes over the specific letter. I need to make the program somewhat random, and I am tryin to get that effect if it comes to the directions of the drawing.

Posted someting about it before here and even got a comment to implement some sort of Shuffle-process, but it is yet something I have to investigate (mainly due lack of knowledge and a time crunch)

Anyway. Currently my code has somewhat specific values. The speed is slightly random, and so is the position. The issue is: The line always moves to the lower-right corner, and restarting the program (resetting its position on a random place from 0 to width and 0 to height) always results in a somewhat same-ish pattern. I want to try to break free from it.

TekenLine drawing;
String[] buttonLog;
char[] letters;
int charIndex;
//boolean isA = false;

void setup() {
  size(600, 800);
  background(255);
  buttonLog = loadStrings("buttonLog.txt");
  letters = buttonLog[0].toCharArray();
  drawing = new TekenLine(int(random(0, width)), int(random(0, height)), int(random(1,3)),int(random(1,3)));
}

void draw() {
  switch(letters[charIndex]) {
  case 'a': 
    fill(#CC00CC);
    //isA = true;
    break;
  case 'w': 
    fill(#404040);
    //isA = false;
    break;
  case 's': 
    fill(#0000CC);
    //isA = false;
    break;
  case 'd': 
    fill(#00CCCC);
    //isA = false;
    break;
  }
  charIndex = (charIndex + 1) % letters.length;
  drawing.drawLine();
  drawing.moveLine();
  drawing.bounceLine();
}

Class :

class TekenLine {

  float x;
  float y;
  float lineWidth;
  float lineHeight;
  float xSnelheid;
  float ySnelheid;


  TekenLine(int tempX, int tempY, int tempXSnelheid, int tempYSnelheid) {
    
    //x = width / 2;
    //y = height / 2;
    
    x = tempX;
    y = tempY;
    xSnelheid = tempXSnelheid;
    ySnelheid = tempYSnelheid;
    lineWidth = 10;
    lineHeight = 10;
    //xSnelheid = 5;
    //ySnelheid = 5;
    
  }

  void drawLine() {
    noStroke();
    rect(x, y, lineWidth, lineHeight, 20);
  }

  void moveLine() {
    x += xSnelheid;
    y += ySnelheid;
  }

  void bounceLine() {
    //if(isA){
    // xSnelheid = -xSnelheid;
     
    //}
    
    if (x >= width || x <= 0) {
      xSnelheid = -xSnelheid;
      //lineWidth = (random(10, 20));
    }
    if (y >= height || y <= 0) {
      ySnelheid = -ySnelheid;
      ySnelheid = ySnelheid*random(0.8,1.2);
      //lineHeight = (random(10, 30));
    }
  }
}

Currently, as mentioned before, my code goes into the same direction, but each from a different height and width each restart, bouncing from the walls and changing colors assigned to “W. A. S. D” from the buttonlog.text log.

I have a certain ideas, but do not know how to start or implement it. The ideas are:

  • if letter = A (for instance), then slightly turn to the left/right
  • if letter = W, then move to random direction.

Probably not the best examples that I can think of, but it is something that I need to make the movement of my drawing-line a bit more randomized so that each new re-start can be a little bit more unique.

Any ideas are welcome!

1 Like
#2

Just use random (-4,4) in last line of setup ()

#3

I used to do that before, issue is, it still seems to stick to a “regular” pattern. I’m still trying to find out how it can randomize itself too when the program is running. as I said in my post, for example:

  • if letter = A (for instance), then slightly turn to the left/right
  • if letter = W, then move to random direction.
#4

Does it only log wasd letters or all of them?

#5

Can you please post as text a typical text produced by the keylogger?

In theory the switch () command has to change xsnelheid and ysnelneid in the class

Either by adding something or subtract something or by setting both to a new value with random (-4,4);

#6

To answer both your questions:

The KeyLogger is a form of code that runs in Powershell. I noticed it only logs A to Z, 1 to 0 and all the other characters except for CTRL, ALT, SHIFT, ESC etc. etc.

A line of text from the .txt file could be: aaawwwwwwaasssdaawwsddsssssddaaaaaa for instance. All on 1 line.

#7

but a text could also be NMBKUWZZOzoidzhfkvbmnbmsb, right?

#8

Regards, Chrisir :wink:

// The letter is converted to ascii (by int) and then used as an angle for a circle. 

// The angle is used to set the direction (xSnelheid and ySnelheid) in 
// the class TekenLine.
// The min and max value of all found asciis are used and the circle is calculated 
// in a way that min ascii is 0 degree and max ascii is 360 degree. 

// To change this circle more, offset is used that slowly rotates the circle. 
// We could also shuffle letters.
// Obviously the randomness is higher, when we have all kind of letters and not 
// only wasd. It's also higher the longer the given keylogger text is (since the
// text is used again and again). 

// https://discourse.processing.org/t/wanting-advise-on-how-i-could-randomize-my-work-more/9267/5

TekenLine drawing;

char[] letters;
int charIndex;
int minAngle=19999, maxAngle=-1000; 
float offset=0;

void setup() {
  size(600, 800);
  background(255);

  String[] buttonLog;
  buttonLog = new String[1];
  // buttonLog = loadStrings("buttonLog.txt");
  buttonLog[0] = "NMBKUWZZOzoaaawwwwwwaasssdaawwsddsssssddaaaaaaidzhfkv bm01234556789nbmsb";
  // buttonLog[0] = "aaawwwwwwaasssdaawwsddsssssddaaaaaa";

  letters = buttonLog[0].toCharArray();

  // identify min and max value
  for (char c1 : letters) {
    int intValue = int (c1); 
    if (intValue<minAngle) {
      minAngle=intValue;
    }
    if (intValue>maxAngle) {
      maxAngle=intValue;
    }
  }//for

  // make object from class
  drawing = new TekenLine(int(random(20, width-33)), int(random(20, height-33)), 
    int(random(-3, 3)), int(random(-3, 3)));
}//setup

void draw() {

  int intValue = int (letters[charIndex] ); 
  // println (angle);
  float angle = map(intValue, 
    minAngle-10, maxAngle+10, 
    0, 360); 

  float r = 11.2; // speed  
  float x =  r * cos(radians(angle+offset)) ;
  float y =  r * sin(radians(angle+offset));

  drawing.setSnelheid(x, y); 
  drawing.bounceLine();

  fill(angle, 0, 0); 

  switch(letters[charIndex]) {
  case 'a': 
    fill(#CC00CC);
    //isA = true;
    break;
  case 'w': 
    fill(#404040);
    //isA = false;
    break;
  case 's': 
    fill(#0000CC);
    //isA = false;
    break;
  case 'd': 
    fill(#00CCCC);
    //isA = false;
    break;
  }

  charIndex = (charIndex + 1) % letters.length;
  offset+=random(.4, 1.27);

  drawing.drawLine();
  drawing.moveLine();
  drawing.bounceLine();
}//draw

// ==============================================================

class TekenLine {

  // class mover 

  float x;
  float y;

  float lineWidth;
  float lineHeight;

  float xSnelheid;
  float ySnelheid;


  TekenLine(int tempX, int tempY, 
    int tempXSnelheid, int tempYSnelheid) {

    //x = width / 2;
    //y = height / 2;

    x = tempX;
    y = tempY;
    xSnelheid = tempXSnelheid;
    ySnelheid = tempYSnelheid;
    lineWidth = 10;
    lineHeight = 10;
    //xSnelheid = 5;
    //ySnelheid = 5;
  }

  void drawLine() {
    noStroke();
    rect(x, y, lineWidth, lineHeight, 20);
  }

  void moveLine() {
    x += xSnelheid;
    y += ySnelheid;
  }

  void bounceLine() {

    if (x >= width-5 ) {
      xSnelheid = -abs(xSnelheid);
      //lineWidth = (random(10, 20));
    } else if ( x <= 0) {
      xSnelheid = abs(xSnelheid);
    }

    if (y >= height) {
      ySnelheid = -abs(ySnelheid);
      ySnelheid = ySnelheid*random(0.8, 1.2);
      //lineHeight = (random(10, 30));
    } else if ( y < 5) {
      ySnelheid = abs(ySnelheid);
      ySnelheid = ySnelheid*random(0.8, 1.2);
    } // else if
  }// method

  void setSnelheid(float x_, float y_) {

    // set direction (but keep pos or neg)

    // monitor if the values are neg
    boolean xIsNeg=false; 
    boolean yIsNeg=false;

    // monitor if the values are neg
    if (xSnelheid<0)
      xIsNeg=true;
    if (ySnelheid<0)
      yIsNeg=true;

    // set value 
    xSnelheid=x_;
    ySnelheid=y_;

    // apply if negative
    if (xIsNeg) 
      xSnelheid*=-1;
    if (yIsNeg) 
      ySnelheid*=-1;
  }
  //
}
//
1 Like
#9

Holy moly that is a lot to process lol.

Thank you, do you mind explaining tho what moat of your code means? (Mainly because I am still very beginner)

#10

It’s all explained at the beginning of the code

The letters are interpreted as angles / degrees in a circle

The line goes where the angle points to

1 Like
#11

Hey there, so I gave your code a full-look, and I have a few questions left if you do not mind answering them!

  1. First of all, I have a hard time figuring out what you mean with the following code
int minAngle=19999, maxAngle=-1000; 

for (char c1 : letters) {
    int intValue = int (c1); 
    if (intValue<minAngle) {
      minAngle=intValue;
    }
    if (intValue>maxAngle) {
      maxAngle=intValue;
    }
  }

What exactly does the value forint minAngle=19999, maxAngle=-1000; represent, and what exactly does for (char c1 : letters) do?

  1. I noticed that you left the tempXSnelheid and tempYsnelheid in the
drawing = new TekenLine(int(random(20, width-33)), int(random(20, height-33)), 
    int(random(-3, 3)), int(random(-3, 3)));

line (the last 2 random INTs). I noticed you already determined the snelheid somewhere else, being at: void setSnelheid(float x_, float y_). Could I remove the INT(random) parts in my TekenLine and the xSnelheid and ySnelheid floats, because you are setting up the speedvalue there anway, or is it for something else?

  1. in regards to float angle = map(intValue, minAngle-10, maxAngle+10, 0, 360);
    Could you tell me exactly what is going on in this part?

  2. I see you are doing a check for a negative value under the void setSnelheid tab. Could you also explain me why this would be needed?

Sorry if you have to write up a lot, it is just that I cannot wrap my head around it myself.

1 Like
#12

We are searching the min and the maximum letter ascii value within letters. This is the ascii value - see Wikipedia. The for loop is a short version of saying: in each for loop iteration give c1 one char in letters, first the 0th, then the 1st … etc.

Both min and maximum variables get an initial value that makes sure the if clause condition is met once - being initially very small or very big respectively.

Ascii goes from 0…255 what would be equivalent to the full circle (0…360 degrees). But when we determine the range of actual letters and it is eg only 95 to 130, this range would be equivalent to the degrees 0…360. This means that each letter has a bigger impact on the next step than without finding min and max ascii value first and using it in the map() statement (that maps the ascii range to the degree range).

I think you can leave the snelheid out in the constructor of the class since we set them later throughout.

We translate the ascii value of the letters to an angle in degrees - see reference for map(). It transfers a value from one range to another.

In this line we want to get the angle from the current ascii value. Since we know that the range of the ascii is between min and max we transfer this value to an angle between 0 and 360 degrees.

When we modify the snelheid we change the angle of the movement.

But (this is probably important for a situation when we are close to the screen border) we keep the +/- sign so the general direction stays the same when we apply a new letter.

I am not sure why I did this, probably I experienced unwanted behavior of the line progress. For example it could occur when we just bounced on the right wall we are going left now. When now the letter commands to go right we would be trapped on the wall (bouncing on and off the wall). To avoid this we keep the general direction left by keeping the +/- sign.

Chrisir

2 Likes
#13

Thank you so much :ok_hand:

1 Like
#14

One more thing to ask.

A small thing I would like to try is, but is not necessary (IMO), is to make the space 3D and so you can use the mouseX/mouseY just to look/spin around the lines being drawn. Would that possible with this code or not? Otherwise I would just drop it.

#15

It’s possible.

At the moment, the lines are not stored but just drawn. To watch them in 3D you need to store them and draw them from the storage. That’s easy, use an ArrayList. See reference.
https://www.processing.org/reference/ArrayList.html

For the watching in 3D itself use peasyCam. Easy as well.
http://mrfeinberg.com/peasycam/

The harder part is that at the moment all lines are in one plane. So to look at it in 3D might be boring. To make this interesting we would need a drawing in 3D space instead of in a 2D plane only. This is a bit tricky because for 3D you have at least 2 angles, left/right (like now) and up/down (new). You could for example use all small letters for the 1st angle and all capital letters for the 2nd angle.

This would require a few changes in your code.

Chrisir

1 Like
#16

Quick 3D demo for points 1 and 2 (Storage of lines and PeasyCam)



// New version in 3D with PeasyCam.  
// Also changed bounceLine() in the class.


// The letter is converted to ascii (by int) and then used (with map()) as an angle for a circle. 

// The angle is used to set the direction (xSnelheid and ySnelheid) in 
// the class TekenLine.
// The min and max value of all found asciis are used and the circle is calculated 
// in a way that min ascii is 0 degree and max ascii is 360 degree (with map()). 

// To change this circle more, offset is used that slowly rotates the circle. 
// We could also shuffle letters.
// Obviously the randomness is higher, when we have all kind of letters and not 
// only wasd. It's also higher the longer the given keylogger text is (since the
// text is used again and again). 

// https://discourse.processing.org/t/wanting-advise-on-how-i-could-randomize-my-work-more/9267/5


import peasy.*;

PeasyCam cam;

// list of all entries 
ArrayList<TekenLine> drawingList = new ArrayList();

// current line 
TekenLine currentTekenLine; 

char[] letters;
int charIndex;
int minAngle=19999, maxAngle=-1000; 
float offset=0;

void setup() {
  size(600, 800, P3D);
  background(255);

  cam = new PeasyCam(this, 800);
  //  cam.setMinimumDistance(50);
  // cam.setMaximumDistance(500);

  String[] buttonLog;
  buttonLog = new String[1];
  // buttonLog = loadStrings("buttonLog.txt");
  buttonLog[0] = "NMBKUWZZOzoaaawwwwwwaasssdaawwsddsssssddaaaaaaidzhfkv bm01234556789nbmsb";
  // buttonLog[0] = "aaawwwwwwaasssdaawwsddsssssddaaaaaa";

  letters = buttonLog[0].toCharArray();

  // identify min and max value
  for (char c1 : letters) {
    int intValue = int (c1); 
    if (intValue<minAngle) {
      minAngle=intValue;
    }
    if (intValue>maxAngle) {
      maxAngle=intValue;
    }
  }//for

  // make object from class
  currentTekenLine = new TekenLine(int(random(20, width-33)), int(random(20, height-33)), 
    int(random(-3, 3)), int(random(-3, 3)), 
    0);
  //
}//setup

void draw() {

  background(255);

  int intValue = int (letters[charIndex] ); 
  // println (angle);
  float angle = map(intValue, 
    minAngle-10, maxAngle+10, 
    0, 360); 

  float r = 11.2; // speed  
  float x =  r * cos(radians(angle+offset)) ;
  float y =  r * sin(radians(angle+offset));

  currentTekenLine.setSnelheid(x, y); 
  currentTekenLine.bounceLine();

  fill(angle, 0, 0); 

  switch(letters[charIndex]) {
  case 'a': 
    currentTekenLine.col=#CC00CC; 
    break;
  case 'w': 
    currentTekenLine.col=#404040; 
    break;
  case 's': 
    currentTekenLine.col=#0000CC;
    break;
  case 'd': 
    currentTekenLine.col=#00CCCC; 
    break;
  }

  charIndex = (charIndex + 1) % letters.length;
  offset+=random(.4, 1.27);

  // add current to 
  currentTekenLine.moveLine();
  currentTekenLine.bounceLine();
  drawingList.add(currentTekenLine.copy());

  // draw from list
  for (TekenLine tl : drawingList) {
    tl.drawLine();
  }
}//draw

// ==============================================================

class TekenLine {

  // class mover 

  float x; 
  float y; 

  float lineWidth; 
  float lineHeight; 

  float xSnelheid; 
  float ySnelheid; 

  color col; 

  TekenLine(float tempX, float tempY, 
    float tempXSnelheid, float tempYSnelheid, 
    color tempCol ) {

    //x = width / 2;
    //y = height / 2;

    x = tempX; 
    y = tempY; 
    xSnelheid = tempXSnelheid; 
    ySnelheid = tempYSnelheid; 
    lineWidth = 10; 
    lineHeight = 10; 
    //xSnelheid = 5;
    //ySnelheid = 5;
    col = tempCol;
  }

  void drawLine() {
    noStroke(); 
    fill(col); 
    rect(x, y, lineWidth, lineHeight, 20);
  }

  void moveLine() {
    x += xSnelheid; 
    y += ySnelheid;
  }

  TekenLine copy() {
    return new TekenLine (x, y, 
      xSnelheid, ySnelheid, 
      col);
  }

  void bounceLine() {

    if (x >= width/2-5 ) {
      xSnelheid = -abs(xSnelheid); 
      //lineWidth = (random(10, 20));
    } else if ( x <= -width/2) {
      xSnelheid = abs(xSnelheid);
    }

    if (y >= height/2) {
      ySnelheid = -abs(ySnelheid); 
      ySnelheid = ySnelheid*random(0.8, 1.2); 
      //lineHeight = (random(10, 30));
    } else if ( y < -height/2) {
      ySnelheid = abs(ySnelheid); 
      ySnelheid = ySnelheid*random(0.8, 1.2);
    } // else if
  }// method

  void setSnelheid(float x_, float y_) {

    // set direction (but keep pos or neg)

    // monitor if the values are neg
    boolean xIsNeg=false; 
    boolean yIsNeg=false; 

    // monitor if the values are neg
    if (xSnelheid<0)
      xIsNeg=true; 
    if (ySnelheid<0)
      yIsNeg=true; 

    // set value 
    xSnelheid=x_; 
    ySnelheid=y_; 

    // apply if negative
    if (xIsNeg) 
      xSnelheid*=-1; 
    if (yIsNeg) 
      ySnelheid*=-1;
  }
  //
}//class
//
2 Likes
#17

Impressive! I like really like that.

How come tho that I cannot use the ‘Fill’ the same way as in the other examples (instead of making another color variable and such). And why would the “copy” variable be needed, or is that to save the drawing space on the location it’s gotta draw and so the camera can easily go around it?

#18

The total approach of the sketch has changed. Basically to make the camera work.

Before we were drawing on the canvas which we didn‘t erase. So each iteration of draw() the canvas was filled. So we could use the fill() command.

Now everything changed. We don’t draw directly on the canvas but into the Arraylist. Then we for loop over the ArrayList and draw the items from there. We clear the canvas at the beginning of draw(). Hence we can’t use fill anymore but use it in the class, using the stored color.

Also, we need the copy command to make a copy of the currentTekenLine because we change it in draw() throughout.

Point 3 of the above list still needs to be done…

Chrisir

1 Like
#19

a few stupid questions left (sorry about that) before I try to continue working on your point 3:

  1. I noticed that the ‘Bouncing’ doesn’t seem to work anymore, guess it has to do with the 3D space, correct?

  2. I noticed a few times that the drawing will happen outside of the canvas. So I have to zoom out to find the drawing. Been messing with so me of the Peasy settings but cannot seem to figure out what to do. Is there any way to fix this/to track where the drawing starts? :slight_smile:

#20

1.

In my version the bouncing works. It just looks different since it’s not exactly at the screen border anymore.

2.

To make the camera work: the camera looks at the point 0,0,0 so I made it so that the drawing is

  • from -width/2 to +width/2,

that’s where the bouncing is.
Initially the camera looks at 0,0,0 what is the center of the origin.
Hence when you don’t move the camera everything should be visible.
To restore the initial view after rotation, just double click the mouse.

1 Like