class BigBlock
{
constructor(xCoord,yCoord,size,strokeColor,fillColor)
{
this.xCoord = xCoord;
this.yCoord = yCoord;
this.size = size;
this.strokeColor = strokeColor;
this.fillColor = 'maroon';
this.xCenter = this.xCoord + this.size/2;
this.yCenter = this.yCoord + this.size/2;
}
draw()
{
stroke(this.strokeColor);
strokeWeight(1);
fill(this.fillColor);
rect(this.xCoord,this.yCoord,this.size,this.size);
}
}
class SmallBlock
{
constructor(xCoord,yCoord,size,bigBlocks,fillColor)
{
this.id = ~~((Math.random() * 100000000) + 1);;
this.xCoord = xCoord;
this.yCoord = yCoord;
this.size = size;
this.fillColor = fillColor;
this.unitDistance = 4;
this.bigBlocks = bigBlocks;
this.smallBlocks = [];
this.speed = this.setInitialSpeed();
this.hasCollidedWithABigBlock = false;
this.hasCollidedWithAWall = false;
}
setSmallBlocks(smallBlocks)
{
this.smallBlocks = smallBlocks;
}
setInitialSpeed()
{
let x = 0;
let y = 0;
if(Math.random() > 0.5)
{
x = Math.random() > 0.5? -this.unitDistance: this.unitDistance;
}
else
{
y = Math.random() > 0.5? -this.unitDistance: this.unitDistance;
}
return {x:x,y:y};
}
hasTouchedABlock(otherBlock)
{
let topEdgeOfThisBlock = this.yCoord + this.size;
let rightEdgeOfThisBlock = this.xCoord + this.size;
let leftEdgeOfThisBlock = this.xCoord;
let bottomEdgeOfThisBlock = this.yCoord;
let topEdgeOfOtherBlock = otherBlock.yCoord + otherBlock.size;
let rightEdgeOfOtherBlock = otherBlock.xCoord + otherBlock.size;
let leftEdgeOfOtherBlock = otherBlock.xCoord;
let bottomEdgeOfOtherBlock = otherBlock.yCoord;
if
(
leftEdgeOfThisBlock < rightEdgeOfOtherBlock &&
rightEdgeOfThisBlock > leftEdgeOfOtherBlock &&
bottomEdgeOfThisBlock < topEdgeOfOtherBlock &&
topEdgeOfThisBlock > bottomEdgeOfOtherBlock
)
{
return true;
}
return false;
}
setDirectionAfterVerticalHit()
{
if(Math.random() > 0.5)
{
this.speed.x = 0;
this.speed.y = -this.speed.y;
}
else
{
this.speed.x = Math.random() > 0.5? this.unitDistance: -this.unitDistance;
this.speed.y = 0;
}
}
setDirectionAfterHorizontalHit()
{
if(Math.random() > 0.5)
{
this.speed.x = -this.speed.x;
this.speed.y = 0;
}
else
{
this.speed.x = 0;
this.speed.y = Math.random() > 0.5? this.unitDistance: -this.unitDistance;
}
}
blockHitsLeftWall(horizontalOffset)
{
if(this.xCoord < horizontalOffset)
{
return true;
}
return false;
}
blockHitsRightWall(width)
{
if(this.xCoord + this.size > width)
{
return true;
}
return false;
}
blockHitsTopWall(verticalOffset)
{
if(this.yCoord < verticalOffset)
{
return true;
}
return false;
}
blockHitsBottomWall(height)
{
if(this.yCoord + this.size > height)
{
return true;
}
return false;
}
checkCollisionWithWall(width,horizontalOffset,verticalOffset,height)
{
if(this.blockHitsLeftWall(horizontalOffset))
{
this.xCoord = horizontalOffset;
this.setDirectionAfterHorizontalHit();
this.hasCollidedWithAWall = true;
}
else if(this.blockHitsRightWall(width - horizontalOffset))
{
this.xCoord = width - horizontalOffset - this.size-1;
this.setDirectionAfterHorizontalHit();
this.hasCollidedWithAWall = true;
}
else if(this.blockHitsTopWall(verticalOffset))
{
this.yCoord = verticalOffset+1;
this.setDirectionAfterVerticalHit();
this.hasCollidedWithAWall = true;
}
else if(this.blockHitsBottomWall(height - verticalOffset))
{
this.yCoord = height - verticalOffset - this.size-1;
this.setDirectionAfterVerticalHit();
this.hasCollidedWithAWall = true;
}
}
checkCollisionWithBigBlocks()
{
for(let i = 0; i < this.bigBlocks.length; i++)
{
let block = this.bigBlocks[i];
if(this.hasTouchedABlock(block))
{
if(this.speed.x > 0)
{
if(block.yCoord + block.size <= this.yCoord)
{
continue;
}
this.xCoord = block.xCoord - this.size - 1;
this.setDirectionAfterHorizontalHit();
this.hasCollidedWithABigBlock=true;
break;
}
else if(this.speed.x < 0)
{
if(block.yCoord + block.size <= this.yCoord)
{
continue;
}
this.xCoord = block.xCoord + block.size + 1;
this.setDirectionAfterHorizontalHit();
this.hasCollidedWithABigBlock=true;
break;
}
else if(this.speed.y > 0)
{
if(block.xCoord + block.size <= this.xCoord)
{
continue;
}
this.yCoord = block.yCoord - this.size - 1;
this.setDirectionAfterVerticalHit();
this.hasCollidedWithABigBlock=true;
break;
}
else if(this.speed.y < 0)
{
if(block.xCoord + block.size <= this.xCoord)
{
continue;
}
this.yCoord = block.yCoord + block.size + 1;
this.setDirectionAfterVerticalHit();
this.hasCollidedWithABigBlock=true;
break;
}
}
}
}
checkCollisionWithSmallBlocks()
{
for(let i = 0; i < this.smallBlocks.length; i++)
{
let block = this.smallBlocks[i];
if(block.id !== this.id && this.hasTouchedABlock(block))
{
if(this.speed.x > 0)
{
if(block.yCoord + block.size <= this.yCoord)
{
continue;
}
this.xCoord = block.xCoord - this.size - 1;
this.setDirectionAfterHorizontalHit();
break;
}
else if(this.speed.x < 0)
{
if(block.yCoord + block.size <= this.yCoord)
{
continue;
}
this.xCoord = block.xCoord + block.size + 1;
this.setDirectionAfterHorizontalHit();
break;
}
else if(this.speed.y > 0)
{
if(block.xCoord + block.size <= this.xCoord)
{
continue;
}
this.yCoord = block.yCoord - this.size - 1;
this.setDirectionAfterVerticalHit();
break;
}
else if(this.speed.y < 0)
{
if(block.xCoord + block.size <= this.xCoord)
{
continue;
}
this.yCoord = block.yCoord + block.size + 1;
this.setDirectionAfterVerticalHit();
break;
}
}
}
}
update(width,horizontalOffset,height,verticalOffset)
{
this.hasCollidedWithABigBlock=false;
this.hasCollidedWithAWall = false;
this.xCoord += this.speed.x;
this.yCoord += this.speed.y;
this.checkCollisionWithBigBlocks();
if(!this.hasCollidedWithABigBlock)
{
this.checkCollisionWithWall(width,horizontalOffset,verticalOffset,height);
if(!this.hasCollidedWithAWall)
{
this.checkCollisionWithSmallBlocks();
}
}
}
draw()
{
fill(this.fillColor);
rect(this.xCoord,this.yCoord,this.size,this.size);
}
}
let bigBlocks = [];
let smallBlocks = [];
let blockLength = 50;
let horizontalOffset = 0;
let verticalOffset = 0;
let backgroundColor = 'rgba(0,0,0,0.05)';
function getBlockVertices(blockLength,windowSize)
{
let
bigBlockVertices = [],
smallBlockVertices = [];
let numHorizontal = ~~(windowSize.width/blockLength);
let horizontalRemainder = windowSize.width - blockLength * numHorizontal;
horizontalOffset = horizontalRemainder/2;
let numVertical = ~~(windowSize.height/blockLength);
let verticalRemainder = windowSize.height - blockLength * numVertical;
verticalOffset = verticalRemainder/2;
for(let y = verticalOffset; y < windowSize.height; y+=blockLength)
{
if(y+ blockLength > windowSize.height)
{
continue;
}
for(let x = horizontalOffset; x < windowSize.width; x+=blockLength)
{
if(x+blockLength > windowSize.width)
{
continue;
}
if( Math.random() > 0.5)
{
bigBlockVertices.push({x:x,y:y,size:blockLength});
}
else
{
if(Math.random() > 0.5)
{
smallBlockVertices.push({x:x,y:y});
}
}
}
}
return {bigBlocks:bigBlockVertices,smallBlocks:smallBlockVertices};
}
function getBrowserWindowSize()
{
let win = window,
doc = document,
offset = 20,
docElem = doc.documentElement,
body = doc.getElementsByTagName('body')[0],
browserWindowWidth = win.innerWidth || docElem.clientWidth || body.clientWidth,
browserWindowHeight = win.innerHeight|| docElem.clientHeight|| body.clientHeight;
return {width:browserWindowWidth-offset,height:browserWindowHeight-offset};
}
function setNewGrid()
{
let browserWindowSize = getBrowserWindowSize();
let vertices = getBlockVertices(blockLength,browserWindowSize);
let bigBlockVertices = vertices.bigBlocks;
let smallBlockVertices = vertices.smallBlocks;
bigBlocks = [];
bigBlockVertices.forEach(function(vertex)
{
bigBlocks.push(new BigBlock(vertex.x,vertex.y,blockLength,255,backgroundColor));
});
smallBlocks = [];
smallBlockVertices.forEach(function(vertex)
{
let divisor = Math.random() > 0.5? 2.1:4;
smallBlocks.push(new SmallBlock(vertex.x,vertex.y,blockLength/divisor,bigBlocks,backgroundColor));
});
smallBlocks.forEach(function(smallBlock)
{
smallBlock.setSmallBlocks(smallBlocks);
});
}
function setup()
{
let browserWindowSize = getBrowserWindowSize();
createCanvas(browserWindowSize.width,browserWindowSize.height);
let vertices = getBlockVertices(blockLength,browserWindowSize);
let bigBlockVertices = vertices.bigBlocks;
let smallBlockVertices = vertices.smallBlocks;
bigBlockVertices.forEach(function(vertex)
{
bigBlocks.push(new BigBlock(vertex.x,vertex.y,blockLength,255,backgroundColor));
});
smallBlockVertices.forEach(function(vertex)
{
let divisor = Math.random() > 0.5? 2.1:4;
smallBlocks.push(new SmallBlock(vertex.x,vertex.y,blockLength/divisor,bigBlocks,backgroundColor));
});
smallBlocks.forEach(function(smallBlock)
{
smallBlock.setSmallBlocks(smallBlocks);
});
background(backgroundColor);
document.addEventListener('click',(event)=>
{
setNewGrid();
});
window.addEventListener('resize',function()
{
let browserWindowSize = getBrowserWindowSize();
resizeCanvas(browserWindowSize.width,browserWindowSize.height);
setNewGrid();
background(backgroundColor);
});
}
function draw()
{
background(backgroundColor);
[...bigBlocks,...smallBlocks].forEach(function(block)
{
block.draw();
});
smallBlocks.forEach(function(block)
{
block.update(width,horizontalOffset,height,verticalOffset);
});
}
console