• Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
    Dedicated community for Japanese speakers
  • 한국 커뮤니티
    Dedicated community for Korean speakers
Exit
1

Randomizing layout of blocks

Community Beginner ,
Dec 01, 2023 Dec 01, 2023

Copy link to clipboard

Copied

Hi all,

 

I'm sure there must be a way to do this but can't find a way/work it out.  I'd like a simple way of randomly mixing up the positions of the blocks but keeping within the square - like a jigsaw puzzle (shown below). I'm currently using keyframe positions and copy and pasting into each layer to mix them up but I'm hoping theres a way of using these keyframe positions as seeds and then randomly assigning to each layer?

 

Screenshot 2023-12-01 at 09.50.43.png

 

If this isnt going to work is there another work around to keep the structure but jumble up the sqaures instead of copy and pasting the positions in manually?

 

Thank you in advance.

TOPICS
Expressions , How to

Views

295

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Dec 01, 2023 Dec 01, 2023

Copy link to clipboard

Copied

You need to sort the values in an array and randomize that or have an extra loop that checks whether a position already has a card assigned. Check this old example by Dan Ebberts:

 

https://www.motionscript.com/expressions-lab-ae65/random-grid-movement.html

 

You can easily gut it and remove the motion part to just produce a static grid. The basics are all there.

 

Mylenium

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Dec 01, 2023 Dec 01, 2023

Copy link to clipboard

Copied

Oh, that's a really elegant bit of code from @Dan Ebberts .  I was curious so tried it out, but it initially threw an error.  I'm guessing the original is using ExtendScript and I was trying in Javascript.  

this_comp

needs to be replaced with

thisComp

helped.png

Here's the whole thing:

columns = 10; //number of columns in grid
tHold= .2; //hold time (must be less than tmin)
tMin = .5; //minimum cycle time (can't be zero)
tMax = 1; //maximum cycle time

gap = thisComp.width/columns;
origin = [gap,gap];
xGrid = columns - 1;
yGrid = Math.floor(thisComp.height/gap) - 1;

start = 0;
end = 0;
j = 1;

while (time >= end){
  j += 1;
  seedRandom(j,true);
  start = end;
  end += random(tMin,tMax);
}
targetX = Math.floor(random(0,xGrid)); 
targetY = Math.floor(random(0,yGrid)); 
seedRandom(j-1,true);
x = random(); //this is a throw-away value
oldX = Math.floor(random(0,xGrid)); 
oldY = Math.floor(random(0,yGrid)); 

if(targetX == oldX && targetY == oldY){
  origin + [oldX,oldY]*gap;
}else if (time - start < tHold){
  origin + [oldX,oldY]*gap;
}else{
  deltaX = Math.abs(targetX - oldX);
  deltaY = Math.abs(targetY - oldY);
  xTime = (end - start - tHold)*(deltaX/(deltaX + deltaY));
  yTime = (end - start - tHold)*(deltaY/(deltaX + deltaY));
  if (time < start + tHold + xTime){
    startPos = origin + [oldX,oldY]*gap;
    targetPos = origin + [targetX,oldY]*gap;
    easeOut((time - start - tHold)/xTime, startPos, targetPos);
  }else{
    startPos = origin + [targetX,oldY]*gap;
    targetPos = origin + [targetX,targetY]*gap
    easeIn((time - start - tHold - xTime)/yTime, startPos, targetPos);
  }
}

 

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Beginner ,
Dec 01, 2023 Dec 01, 2023

Copy link to clipboard

Copied

Thank you too @ShiveringCactus I will bare all the above in mind!

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Beginner ,
Dec 01, 2023 Dec 01, 2023

Copy link to clipboard

Copied

You are a legend - thank you for your help, I will give that a shot!

 

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Dec 01, 2023 Dec 01, 2023

Copy link to clipboard

Copied

LATEST

The trick with something like this is that you need to calculate the random order for all blocks in a single expression and then "publish" the result so that each block layer can use that result to determine its own position. I'd do it with a text layer named "order" at the bottom of the layer stack (below all the block layers) with a source text expression like this:

n = 16;
seed = 17;
a = [];
for (i = 0; i < n; i++){
  a.push(i+1);
}
seedRandom(seed,true);
for (i = 0; i < n; i++){
  idx = Math.floor(random(n));
  temp = a[i];
  a[i] = a[idx];
  a[idx] = temp;
}
a.toString()

To change the random order, just change the seed variable (or tie it to a slider, maybe). Then on each of the blocks, you'd have a position expression, something like this:


order = thisComp.layer("order").text.sourceText;
nCols = 4;
a = order.split(",");
for ( i = 0; i < a.length; i++){
  if (parseInt(a[i]) == index) break;
}
col = i%nCols;
row = Math.floor(i/nCols);
origin = [width,height]/2;
xOffset = col*width;
yOffset = row*height;
origin + [xOffset,yOffset]

I set this up with 16 solid layers and it would be somewhat different if you're using shape layers, but this should give you the idea.

 

 

 

 

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines