shuffling arrays/colorblocks - resort them - SOLVED

edited October 2017 in Questions about Code

Hey there,

I've been playing with processing for some time and stepped on a nice little colour sorting effect which I would like to recreate. Blocks of colours (HSB mode), number depending on resolution (set as variable), are supposed to be put on the screen, then get shuffled (problem here!) and start to move back to their correct position. I got the movement more or less right but I can't figure out how to shuffle the ArrayList containing the blocks. I already tried a different approach with an IntList but I assume I'm just putting the blocks at their regular/sorted position without even using the IntList correctly.... :-D

I guess you get the idea what I'm trying to do and would like to ask for your help to get it right. Thanks! (there's still some "test code" inside to see if the shuffling works....) Also available under https://www.openprocessing.org/sketch/463639

I need the colors to be evenly spread over width (from 0 (red) to max HSB color - red again, rainbow pattern). Using random for color selection I get multiple results for some colors which result in gaps in every line of blocks.

import java.util.Collections;

float resolution = 40;
ArrayList<Block> Tiles;
boolean run = false;
int numTiles = 0;
IntList index;

void setup() {
  size(400, 400);
  colorMode(HSB, width, 255, 255);
  Tiles = new ArrayList<Block>();
  index = new IntList();

  for (float x=0; x < width; x += resolution) {
    for (float y=0; y < height; y += resolution) {
      Tiles.add(new Block(x, y, resolution, int(x)));
      numTiles += 1;
    }
  }

  println("index = " + index.size());         //should be 0 at start
  println("numTiles = " + numTiles);       //100 blocks/tiles on these settings -> for loop above works fine
  delay(2000);

  for (int i = Tiles.size()-1; i >= 0; i--) {
    index.append(i);                                 //IntList with 100, 99, 98, 97, ...
  }

  println(index);
  println("Shuffling......");
  delay(1000);
  index.shuffle();                                      //IntList now 45, 89, 2, 8, 75, ....
  println(index);
  println("Shuffled.......");
}

void draw() {
  //if (run) {
  //background(100);

  for (int i = numTiles-1; i >= 0; i--) {
    Block b = Tiles.get(index.get(i));
    b.display();
    b.checkPos();

    if (b.inPos()) {
      //Tiles.remove(i); //when enabled I get y "out of bounds error" -> aim was to stop calc for the block in position
    }
  }
}

void mousePressed() {
  run = !run;
}

class Block {

  float xPos;
  float yPos;
  float col;
  float res;

  Block(float x, float y, float bSize, int farbe) {
    xPos = x;
    yPos = y;
    res = bSize;
    col = farbe;
  }

  //check pos vs. color
  void checkPos() {
    if (xPos >= col) {
      xPos = xPos - 1;
    } else if (xPos <= col) {
      xPos = xPos + 1;
    }
  }

  boolean inPos() {
    if (xPos == col) {
      return true;
    } else {
      return false;
    }
  }

  void display() {
    fill(col, 255, 255, 200);
    rect(xPos, yPos, res, res);
  }
}  
Tagged:

Answers

  • edited October 2017

    Re:

    Blocks of colours (HSB mode), number depending on resolution (set as variable), are supposed to be put on the screen, then get shuffled (problem here!) and start to move back to their correct position. I got the movement more or less right

    Please say more about "and start to move back to their correct position" -- what exactly do you mean by this? That they will swap with whatever is in their correct spot, one at a time? That they will "walk" across the board, swapping with a neighbor to get closer to their home position?

    You said "I got the movement more or less right" -- how is that? The sketch above has no movement or interaction -- it is just a rainbow.

    Edit: ah, I just saw the open processing link. That makes it clearer.

  • edited October 2017

    Your first error is checking for equality on two floats. cast them to int instead.

      boolean inPos() {
        if ((int)xPos == (int)col) {
          return true;
        } else {
          return false;
        }
      }
    

    Or you could provide a fudge factor for float comparison, or you could make x, y, xPos, yPos, and col all ints.

    Now your squares all disappear once they return 'home' -- which I believe was what you wanted...?

  • edited October 2017 Answer ✓

    Hi Jeremy, thanks for your reply and sorry for not being precise! Imagine the whole "rainbow" image made out of quadratic tiles (based on HSB mode). I'd like to shuffle these tiles around horizontally and like them to move left or right depending on their color matching the rainbow. Movement is done in the Block class (think of it as a particle). They shoudn't disappear though.....

    I put the shuffle code inside setup now and it works for shuffling the rndCol List and assign it to the Tiles. Still having some problems with the loops and setting x/y taking resolution into account. Will figure it out!

    Edit Changed floats to int as suggested. And swapped the shuffle in front of the loop Edit 2 It's working now! :-) Thanks for your help!!

    import java.util.Collections;
    
    int resolution = 5;
    ArrayList<Block> Tiles;
    boolean run = false;
    int numTiles = 0;
    int columns = 0;
    int currColumn = 0;
    int rows = 0;
    IntList rndCol;
    
    void setup() {
      size(800, 800);
      Tiles = new ArrayList<Block>();
      rndCol = new IntList();
      columns = width/resolution;
      rows = height/resolution;
      colorMode(HSB, columns, 255, 255);
      numTiles = rows * columns;
    
      for (int y = 0; y < height; y+=resolution) {
    
        for (int i = 0; i < columns; i++) {
          rndCol.append(i);
        }
    
        rndCol.shuffle();
        for (int x = 0; x < width; x+=resolution) {
          Tiles.add(new Block(x, y, resolution, rndCol.get(currColumn)));
          currColumn += 1;
        }
        rndCol.clear();
        currColumn = 0;
      }
    textSize(26);
    text("click to start...", 40, 40);
    }
    
    void draw() {
      if (run) {
    
      for (int i = numTiles-1; i > 0; i--) {
        Block b = Tiles.get(i); 
        b.display();
        b.checkPos();
      }
      }
    }
    
    void mousePressed() {
      run = !run;
    }
    
    class Block {
    
      int xPos;
      int yPos;
      int col;
      int res;
    
      Block(int x, int y, int bSize, color bCol) {
        xPos = x;
        yPos = y;
        res = bSize;
        col = bCol;
      }
    
      void checkPos() {
        if (map(xPos,0,width,0,columns) <= col) {
          xPos += 1;
        } else {
          xPos -= 1;
        }
      }
    
      boolean inPos() {
        if (xPos == col) {
          return true;
        } else {
          return false;
        }
      }
    
      void display() {
        //stroke(0);
        noStroke();
        fill(col, 255, 255,50);
        rect(xPos, yPos, res, res);
      }
    }  
    
  • Glad it worked out, @drdoctor -- rather than retitling the thread to solved, you can simply mark one of the answers as accepted.

Sign In or Register to comment.