Skip to content

Instantly share code, notes, and snippets.

@christinapetris
Forked from dribnet/.block
Last active June 9, 2017 00:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save christinapetris/420e2a9ebaad9350687dfc1d1bffedd5 to your computer and use it in GitHub Desktop.
Save christinapetris/420e2a9ebaad9350687dfc1d1bffedd5 to your computer and use it in GitHub Desktop.
17.1.MDDN242 PS4
license: mit
// note: this file is poorly named - it can generally be ignored.
// helper functions below for supporting blocks/purview
function saveBlocksImages(doZoom) {
if(doZoom == null) {
doZoom = false;
}
// generate 960x500 preview.jpg of entire canvas
// TODO: should this be recycled?
var offscreenCanvas = document.createElement('canvas');
offscreenCanvas.width = 960;
offscreenCanvas.height = 500;
var context = offscreenCanvas.getContext('2d');
// background is flat white
context.fillStyle="#FFFFFF";
context.fillRect(0, 0, 960, 500);
context.drawImage(this.canvas, 0, 0, 960, 500);
// save to browser
var downloadMime = 'image/octet-stream';
var imageData = offscreenCanvas.toDataURL('image/jpeg');
imageData = imageData.replace('image/jpeg', downloadMime);
p5.prototype.downloadFile(imageData, 'preview.jpg', 'jpg');
// generate 230x120 thumbnail.png centered on mouse
offscreenCanvas.width = 230;
offscreenCanvas.height = 120;
// background is flat white
context = offscreenCanvas.getContext('2d');
context.fillStyle="#FFFFFF";
context.fillRect(0, 0, 230, 120);
if(doZoom) {
// pixelDensity does the right thing on retina displays
var pd = this._pixelDensity;
var sx = pd * mouseX - pd * 230/2;
var sy = pd * mouseY - pd * 120/2;
var sw = pd * 230;
var sh = pd * 120;
// bounds checking - just displace if necessary
if (sx < 0) {
sx = 0;
}
if (sx > this.canvas.width - sw) {
sx = this.canvas.width - sw;
}
if (sy < 0) {
sy = 0;
}
if (sy > this.canvas.height - sh) {
sy = this.canvas.height - sh;
}
// save to browser
context.drawImage(this.canvas, sx, sy, sw, sh, 0, 0, 230, 120);
}
else {
// now scaledown
var full_width = this.canvas.width;
var full_height = this.canvas.height;
context.drawImage(this.canvas, 0, 0, full_width, full_height, 0, 0, 230, 120);
}
imageData = offscreenCanvas.toDataURL('image/png');
imageData = imageData.replace('image/png', downloadMime);
p5.prototype.downloadFile(imageData, 'thumbnail.png', 'png');
}

PS4 MDDN 242 2017

Chicken Cycle

For my idea I wanted to show the cycle of chicken who's lives are soley to become either fried chicken or drumsticks. I showed this through both dynamic and static elements. The simulation starts off with all dynamic elements, some which are invisable but are essential in governing the simulation. The rest are chickens formed in an egg shape.

The user can move their pointer around to create chickens.

The dynamic agents are chickens, baby chicks and invisible agents (which we'll call "nothing"). Everything else is static.

The rules for chicken are: -To ensure there are not too many chicken, when a chicken collides with eith a baby chick or chicken then it becomes a drumstick.

-For reproduction when chicken collides with nothing then nothing becomes an egg.

The rules which make the egg eventually turn into a chicken is this: -An egg turns into a hatching chick if it is in contact with a chicken -A hatching chick becomes a baby chick if it is in contact with a chicken -A baby chick becomes a chicken if it is in contact with a chicken or a baby chick

While the rules which will kill of an egg, hatching chick or baby chick are: (the reason they die is usually because a chicken is not near them to keep them alive) -if an egg collides with nothing it becomes a fried egg -if a hatching chick collides with nothing, it becomes nothing -if a baby chick collides with nothing, it also becomes nothing.

Furthermore, the drumbstick and fried eggs dissappear back into nothing if they collide with any of the moving agents.

function Agent1() {
// any variables you add here are for your own internal state
this.life_stage = "egg";
this.next_life_stage = "egg";
// setup is run when the agent is reset
// value is a number between 0 and 100
this.setup = function(value) {
// this.life_stage = "egg";
// this.next_life_stage = "egg";
if(value > 80) {
this.life_stage = "egg";
}
else if(value > 60) {
this.life_stage = "chicken";
}
else {
this.life_stage = "nothing";
}
this.next_life_stage = this.life_stage;
this.agent_type = agent_type;
}
// this happens generally on mouse over
this.activate = function() {
this.life_stage = "chicken";
}
// decide on your next move based on neighbors (but don't do it yet)
this.step = function(neighbors) {
var num_neighbors_chicken = 0;
for(var i=0; i<neighbors.length; i++) {
if(neighbors[i].agent.life_stage == "chicken" || neighbors[i].agent.life_stage == "hatchingchick" || neighbors[i].agent.life_stage == "babychick") {
num_neighbors_chicken = num_neighbors_chicken + 1;
}
}
var num_neighbors_egg = 0;
for(var i=0; i<neighbors.length; i++) {
if(neighbors[i].agent.life_stage == "egg") {
num_neighbors_egg = num_neighbors_egg + 1;
}
}
// this.next_life_stage = this.life_stage;
// //lonliness
if ((this.life_stage == "chicken" || this.life_stage == "hatchingchick" || this.life_stage == "babychick") && num_neighbors_chicken < 1) {
this.next_life_stage = "drumstick";
}
else if (this.life_stage == "egg" && num_neighbors_chicken < 1) {
this.next_life_stage = "friedegg";
}
// // overpopulation of chicken or eggs
else if ((this.life_stage == "chicken" || this.life_stage == "hatchingchick" || this.life_stage == "babychick") && (num_neighbors_chicken > 2 || num_neighbors_egg > 2 )) {
this.next_life_stage = "drumstick";
}
else if (this.life_stage == "egg" && num_neighbors_egg > 2) {
this.next_life_stage = "friedegg";
}
// // reproduction
else if (this.life_stage == "nothing" && num_neighbors_chicken == 2) {
this.next_life_stage = "egg";
}
// // egg into chicken //growth
else if (this.life_stage == "egg" && num_neighbors_chicken == 2) {
this.next_life_stage = "hatchingchick";
}
else if (this.life_stage == "hatchingchick" && num_neighbors_chicken == 2) {
this.next_life_stage = "babychick";
}
else if (this.life_stage == "babychick" && num_neighbors_chicken == 2) {
this.next_life_stage = "chicken";
}
// // drumstick disappears
else if (this.life_stage == "drumstick") {
this.next_life_stage = "nothing";
}
// // fried egg disappears
else if (this.life_stage == "friedegg") {
this.next_life_stage = "nothing";
}
// // statis
else {
this.next_life_stage = this.life_stage;
}
}
// execute the next move you decided on
this.update_state = function() {
this.life_stage = this.next_life_stage;
}
this.draw = function(size) {
stroke(0);
if(this.life_stage == "nothing") {
fill(39, 127, 58);
//image(grass, 0, 0, size, size);
}
else if(this.life_stage == "egg") {
image(egg, 0, 0, size, size);
}
else if(this.life_stage == "hatchingchick") {
image(hatchingchick, 0, 0, size, size);
}
else if(this.life_stage == "babychick") {
image(babychick, 0, 0, size, size);
}
else if(this.life_stage == "chicken") {
image(chicken, 0, 0, size, size);
}
else if(this.life_stage == "friedegg") {
image(friedegg, 0, 0, size, size);
}
else if(this.life_stage == "friedegg") {
image(friedegg, 0, 0, size, size);
}
else if(this.life_stage == "heaven") {
image(heaven, 0, 0, size, size);
}
else if(this.life_stage == "drumstick"){
image(drumstick, 0, 0, size, size);
}
}
}
//code from my old agent 3
function Agent2() {
// any variables you add here are for your own internal state
// setup is run when the agent is reset
// value is a number between 0 and 100
this.setup = function(value, agent_type) {
this.agent_type = agent_type;
}
// this happens generally on mouse over
this.activate = function() {
if(this.agent_type == 1) {
this.life_stage = "egg";
}
else{
this.life_stage = "chicken";
}
}
// decide on your next move based on neighbors (but don't do it yet)
this.step = function(neighbors, radius) {
this.close = false;
if(this.agent_type >= 2) {
v = p5.Vector.random2D().mult(radius/10);
return v;
}
//rules
var num_neighbors_chicken = 0;
for(var i=0; i<neighbors.length; i++) {
if(neighbors[i].agent.life_stage == "chicken" || neighbors[i].agent.life_stage == "babychick") {
num_neighbors_chicken = num_neighbors_chicken + 1;
}
}
var num_neighbors_egg = 0;
for(var i=0; i<neighbors.length; i++) {
if(neighbors[i].agent.life_stage == "egg") {
num_neighbors_egg = num_neighbors_egg + 1;
}
}
//chicken for food
// //lonliness
if ((this.life_stage == "chicken" || this.life_stage == "hatchingchick" || this.life_stage == "babychick") && num_neighbors_chicken < 1) {
this.life_stage = "drumstick";
}
else if (this.life_stage == "egg" && num_neighbors_chicken < 1) {
this.life_stage = "friedegg";
}
// // overpopulation of chicken or eggs
else if ((this.life_stage == "chicken" || this.life_stage == "hatchingchick" || this.life_stage == "babychick") && (num_neighbors_chicken > 1 || num_neighbors_egg > 1 )) {
this.life_stage = "drumstick";
}
else if (this.life_stage == "egg" && num_neighbors_egg > 1) {
this.life_stage = "friedegg";
}
// // reproduction
else if (this.life_stage == "nothing" && num_neighbors_chicken == 1) {
this.life_stage = "egg";
}
// // egg into chicken //growth
else if (this.life_stage == "egg" && num_neighbors_chicken == 1) {
this.life_stage = "chicken";
}
// else if (this.life_stage == "hatchingchick" && num_neighbors_chicken == 2) {
// this.next_life_stage = "babychick";
// }
// else if (this.life_stage == "babychick" && num_neighbors_chicken == 2) {
// this.next_life_stage = "chicken";
// }
// // drumstick disappears
else if (this.life_stage == "drumstick") {
this.life_stage = "nothing";
}
// // fried egg disappears
else if (this.life_stage == "friedegg") {
this.life_stage = "nothing";
}
// // statis
else {
this.life_stage = this.life_stage;
}
}
this.draw = function(radius) {
stroke(0);
if(this.agent_type == 0) {
//fill(255);
image(egg, -radius, -radius, radius*2, radius*2);
}
else if(this.agent_type == 1) {
//fill(0);
}
else if(this.agent_type == 2) {
// fill(255, 0, 0);
// tint(0, 153, 204);
image(chicken, -radius*2.5, -radius*2.5, radius*5, radius*5);
}
else if(this.agent_type == 3) {
// fill(0, 255, 0);
image(babychick, -radius*2, -radius*2, radius*4, radius*4);
}
else if(this.agent_type == 4) {
// fill(0, 0, 255);
image(friedegg, -radius, -radius, radius*2, radius*2);
}
//ellipse(0, 0, radius*2, radius*2);
if(this.life_stage == "nothing") {
fill(39, 127, 58);
//image(grass, 0, 0, size, size);
}
else if(this.life_stage == "egg") {
image(egg, -radius, -radius, radius*2, radius*2);
}
// else if(this.life_stage == "hatchingchick") {
// image(hatchingchick, 0, 0, size, size);
// }
else if(this.life_stage == "babychick") {
image(babychick, 0, 0, radius, radius);
}
else if(this.life_stage == "chicken") {
image(chicken, 0, 0, radius, radius);
}
else if(this.life_stage == "friedegg") {
image(friedegg, -radius, -radius, radius*2, radius*2);
}
else if(this.life_stage == "heaven") {
image(heaven, 0, 0, radius, radius);
}
else if(this.life_stage == "drumstick"){
image(drumstick, 0, 0, radius, radius);
}
}
}
function Agent3Preload() {
drumstick = loadImage('drumstick.png');
egg = loadImage('egg.png');
chicken = loadImage('chickenhead.png');
friedegg = loadImage('friedegg.png');
hatchingchick = loadImage('hatchingchick.png');
babychick = loadImage('babychick.png');
heaven = loadImage('heaven.png');
grass = loadImage('grass.png');
}
/////////AGENT TYPE REFERENCE:
//agent type 0=friedeggs
//agent type 1=eggs
//agent type 2=chicken
//agent type 3=baby chicks
//agent type 4=nothing
//agent type 5= drumsticks
function Agent3() {
// any variables you add here are for your own internal state
// setup is run when the agent is reset
// value is a number between 0 and 100
this.setup = function(value, agent_type) {
this.agent_type = agent_type;
}
// this happens generally on mouse over
this.activate = function() {
this.agent_type = 2;
}
// decide on your next move based on neighbors (but don't do it yet)
this.step = function(neighbors, radius) {
this.close = false;
//if this is a moving thing or nothing
if(this.agent_type >= 2 && this.agent_type <=4) {
v = p5.Vector.random2D().mult(radius/8);
for(var i=0; i<neighbors.length; i++) {
var npos = neighbors[i].pos;
var d = npos.mag();
var agent = neighbors[i].agent;
if ((d > 0) && (d < radius + neighbors[i].radius)) {
this.close = true;
//reproduction if chicken collides with "nothing", "nothing" becomes an egg
if(this.agent_type == 4 && agent.agent_type == 2){
this.agent_type = 1;
}
//overpopulation
//chicken into drumstick. when collide with chicken/babychick
else if((this.agent_type == 2 ) && (agent.agent_type ==2 || agent.agent_type ==3)){
this.agent_type = 5;
}
//lomilness of baby chick
else if(this.agent_type == 3 && agent.agent_type == 4){
this.agent_type = 4;
}
// Calculate vector pointing away from neighbor
var move_away = npos.mult(-1);
move_away.normalize();
move_away.div(d*0.1); // Weight by distance
v.add(move_away);
}
}
return v;
}
//stationary things
else{
for(var i=0; i<neighbors.length; i++) {
var npos = neighbors[i].pos;
var d = npos.mag();
var agent = neighbors[i].agent;
if ((d > 0) && (d < radius + neighbors[i].radius)) {
this.close = true;
//to make sure there arent too many eggs
//egg into fried egg if egg collide with nothing
if(this.agent_type == 1 && agent.agent_type == 4){
this.agent_type = 0;
}
//growth of chicken
//egg turns into chick when egg collide with chicken
else if(this.agent_type == 1 && agent.agent_type == 2){
this.agent_type = 6;
}
//hatchingchick into baby chick
else if(this.agent_type == 6 && agent.agent_type == 2){
this.agent_type = 3;
}
//hatchingchick die
else if(this.agent_type == 6 && agent.agent_type == 4){
this.agent_type = 4;
}
//hatchingchick into baby chick
else if(this.agent_type == 6 && agent.agent_type == 2){
this.agent_type = 3;
}
//baby chick into a chicken
else if(this.agent_type == 3 && ( agent.agent_type == 2 || agent.agent_type == 3)){
this.agent_type = 2;
}
//fried egg disappears
else if (this.agent_type == 0 && agent.agent_type >=1) {
this.agent_type = 4;
}
// // // // drumstick disappears
else if (this.agent_type == 5 && agent.agent_type <=4) {
this.agent_type = 4;
}
}
}
}
}
this.draw = function(radius) {
stroke(0);
if(this.agent_type == 0) {
image(friedegg, -radius*2, -radius*2, radius*4, radius*4);
}
else if(this.agent_type == 1) {
image(egg, -radius*2, -radius*2, radius*4, radius*4);
}
else if(this.agent_type == 2) {
image(chicken, -radius*2, -radius*2, radius*4, radius*4);
}
else if(this.agent_type == 3) {
image(babychick, -radius*2, -radius*2, radius*4, radius*4);
}
else if(this.agent_type == 4) {
// image(grass, -radius*2, -radius*2, radius*4, radius*4);
}
else if(this.agent_type == 5) {
image(drumstick, -radius*2, -radius*2, radius*4, radius*4);
}
else if(this.agent_type == 6) {
image(hatchingchick, -radius*2, -radius*2, radius*4, radius*4);
}
}
}
<head>
<script src="http://cdnjs.cloudflare.com/ajax/libs/p5.js/0.5.7/p5.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/p5.js/0.5.7/addons/p5.dom.js"></script>
<script language="javascript" type="text/javascript" src=".purview_helper.js"></script>
<script language="javascript" type="text/javascript" src="agent3.js"></script>
<script language="javascript" type="text/javascript" src="sketch.js"></script>
<style>
body { padding: 0; margin: 0; }
.inner { position: absolute; }
#controls {
font: 300 12px "Helvetica Neue";
padding: 5;
margin: 5;
background: #f0f0f0;
opacity: 0.0;
-webkit-transition: opacity 0.2s ease;
-moz-transition: opacity 0.2s ease;
-o-transition: opacity 0.2s ease;
-ms-transition: opacity 0.2s ease;
}
#controls:hover { opacity: 0.9; }
</style>
</head>
<body style="background-color:white">
<div class="outer">
<div class="inner">
<div id="canvasContainer"></div>
</div>
<div class="inner" id="controls" height="500px">
<table>
<tr>
<td>World</td>
<td id="selector1Container"></td>
</tr>
<tr>
<td>Size</td>
<td id="selector2Container"></td>
</tr>
<tr>
<td>Speed</td>
<td id="selector3Container"></td>
</tr>
<tr>
<td></td>
<td id="playButtonContainer"></td>
</tr>
<tr>
<td></td>
<td id="clearButtonContainer"></td>
</tr>
<tr>
<td></td>
<td id="checkContainer"></td>
</tr>
</div>
</div>
</table>
</body>
<head>
<script src="http://cdnjs.cloudflare.com/ajax/libs/p5.js/0.5.7/p5.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/p5.js/0.5.7/addons/p5.dom.js"></script>
<script language="javascript" type="text/javascript" src=".purview_helper.js"></script>
<script language="javascript" type="text/javascript" src="clock.js"></script>
<script language="javascript" type="text/javascript" src="sketch.js"></script>
</head>
<body style="background-color:white">
<div class="outer">
<div class="inner">
<div id="canvasContainer"></div>
</div>
</div>
</table>
</body>
var canvasWidth = 960;
var canvasHeight = 500;
var is_playing = false;
var show_oddball = false;
var modeSelector;
var sizeSelector;
var speedSelector;
var max_vals = [360, 100, 100];
var allAgents = [];
var numActiveAgents = 0;
var clearButton, randomButton, playButton, stepButton, stopButton;
var backgroundImage = null;
var agentLookupWidth = 1;
var agentLookupHeight = 1;
var agentLookupTable = [0];
var haveSeenMovement = false;
function preload() {
backgroundImage = loadImage("z_background.jpg");
// this is called for static assets your agents need
Agent3Preload();
}
function setup() {
// create the drawing canvas, save the canvas element
var main_canvas = createCanvas(canvasWidth, canvasHeight);
main_canvas.parent('canvasContainer');
modeSelector = createSelect();
modeSelector.option('grid');
modeSelector.option('hexgrid');
// modeSelector.option('vornoi');
// modeSelector.option('freestyle');
modeSelector.changed(gridTypeChanged);
modeSelector.value('hexgrid');
modeSelector.parent('selector1Container');
sizeSelector = createSelect();
sizeSelector.option('16');
sizeSelector.option('32');
sizeSelector.option('64');
sizeSelector.option('128');
sizeSelector.option('256');
sizeSelector.parent('selector2Container');
sizeSelector.value('32');
sizeSelector.changed(sizeChangedEvent);
speedSelector = createSelect();
speedSelector.option('1');
speedSelector.option('2');
speedSelector.option('5');
speedSelector.option('10');
speedSelector.option('24');
speedSelector.option('60');
speedSelector.parent('selector3Container');
speedSelector.value('10');
speedSelector.changed(speedChangedEvent);
stepButton = createButton('step');
stepButton.mousePressed(stepButtonPressedEvent);
stepButton.parent('playButtonContainer');
playButton = createButton('play');
playButton.mousePressed(playButtonPressedEvent);
playButton.parent('playButtonContainer');
// stopButton = createButton('stop');
// stopButton.mousePressed(stopButtonPressedEvent);
// stopButton.parent('playButtonContainer');
clearButton = createButton('reset');
clearButton.mousePressed(clearButtonPressedEvent);
clearButton.parent('clearButtonContainer');
randomButton = createButton('random');
randomButton.mousePressed(randomButtonPressedEvent);
randomButton.parent('clearButtonContainer');
// guideCheckbox = createCheckbox('', false);
// guideCheckbox.parent('checkContainer');
// guideCheckbox.changed(guideChangedEvent);
// setup lookup table from pixels
backgroundImage.loadPixels();
var p = backgroundImage.pixels;
agentLookupHeight = backgroundImage.height;
agentLookupWidth = backgroundImage.width;
agentLookupTable = new Array(agentLookupHeight);
for(var j=0; j<agentLookupHeight; j++) {
agentLookupTable[j] = new Array(agentLookupWidth);
for(var i=0; i<agentLookupWidth; i++) {
var ix = 4 * (j * agentLookupWidth + i);
if(p[ix] > 128 && p[ix+1] > 128 && p[ix+2] > 128) {
// white
agentLookupTable[j][i] = 0;
}
else if(p[ix] < 128 && p[ix+1] < 128 && p[ix+2] < 128) {
// black
agentLookupTable[j][i] = 1;
}
else if(p[ix] > p[ix+1] && p[ix] > p[ix+2] ) {
// red-ish
agentLookupTable[j][i] = 2;
}
else if(p[ix+1] > p[ix] && p[ix+1] > p[ix+2] ) {
// green-ish
agentLookupTable[j][i] = 3;
}
else {
agentLookupTable[j][i] = 4;
}
}
}
noLoop();
refreshGridData();
modeChangedEvent();
speedChangedEvent();
playButtonPressedEvent();
}
/*
function mouseClicked() {
if (mouseX > width/4) {
refreshGridData();
}
redraw();
}
*/
var numGridRows;
var numGridCols;
var gridValues; // row, col order
var gridOffsetX, gridOffsetY;
var gridSpacingX, gridSpacingY;
// Generate data for putting glyphs in a grid
function clamp(num, min, max) {
return Math.min(Math.max(num, min), max);
}
function getNewAgent() {
a = new Agent3();
return a;
}
function lookupAgentType(x, y, size) {
s2 = size/2;
x += s2;
y += s2;
if(x < 0 || y < 0 || x >= canvasWidth || y >= canvasHeight) {
print("ERROR");
return 0;
}
var ix = int(map(x, 0, canvasWidth, 0, agentLookupWidth));
var iy = int(map(y, 0, canvasHeight, 0, agentLookupHeight));
return agentLookupTable[iy][ix];
}
function refreshGridData() {
var mode = modeSelector.value();
var glyphSize = parseInt(sizeSelector.value(), 10);
if (mode == "hexgrid") {
if(glyphSize == 16) {
numGridCols = 58;
numGridRows = 33;
gridOffsetX = 20;
gridSpacingX = 16;
gridOffsetY = 1;
gridSpacingY = 15;
}
if(glyphSize == 32) {
numGridCols = 30;
numGridRows = 17;
gridOffsetX = 10;
gridSpacingX = 31;
gridOffsetY = 2;
gridSpacingY = 29;
}
else if(glyphSize == 64) {
numGridCols = 13;
numGridRows = 7;
gridOffsetX = 35;
gridSpacingX = 66;
gridOffsetY = 35;
gridSpacingY = 59;
}
else if(glyphSize == 128) {
numGridCols = 7;
numGridRows = 4;
gridOffsetX = 10;
gridSpacingX = 132;
gridOffsetY = 0;
gridSpacingY = 118;
}
else if(glyphSize == 256) {
numGridCols = 3;
numGridRows = 2;
gridOffsetX = 96;
gridSpacingX = 262;
gridOffsetY = 0;
gridSpacingY = 234;
}
}
else if(glyphSize == 128) {
numGridCols = 7;
numGridRows = 3;
gridOffsetX = 10;
gridSpacingX = 136;
gridOffsetY = 20;
gridSpacingY = 166;
}
else if(glyphSize == 256) {
numGridCols = 3;
numGridRows = 1;
gridOffsetX = 20;
gridSpacingX = 320;
gridOffsetY = 100;
gridSpacingY = 500;
}
else if(glyphSize == 64) {
numGridCols = 14;
numGridRows = 7;
gridOffsetX = 3;
gridSpacingX = 68;
gridOffsetY = 6;
gridSpacingY = 71;
}
else if(glyphSize == 32) {
numGridCols = 24;
numGridRows = 13;
gridOffsetX = 4;
gridSpacingX = 40;
gridOffsetY = 4;
gridSpacingY = 38;
}
else if(glyphSize == 16) {
numGridCols = 48;
numGridRows = 25;
gridOffsetX = 1;
gridSpacingX = 20;
gridOffsetY = 1;
gridSpacingY = 20;
}
// this updates the grid to account for center spacing
gridOffsetX += glyphSize/2;
gridOffsetY += glyphSize/2;
// determine active agents and reset
numActiveAgents = 0;
var hexOffset = (mode == "hexgrid");
gridValues = new Array(numGridRows);
for (var i=0; i<numGridRows; i++) {
var tweakedNumGridCols = numGridCols;
if (hexOffset && i%2 == 1) {
tweakedNumGridCols = numGridCols - 1;
}
gridValues[i] = new Array(tweakedNumGridCols);
for (var j=0; j<tweakedNumGridCols; j++) {
if(numActiveAgents >= allAgents.length) {
allAgents.push(getNewAgent());
}
gridValues[i][j] = allAgents[numActiveAgents];
numActiveAgents = numActiveAgents + 1;
}
}
// assign positions
for (var i=0; i<numGridRows; i++) {
var tweakedNumGridCols = numGridCols;
var offsetX = 0;
if (hexOffset && i%2 == 1) {
offsetX = gridSpacingX / 2;
tweakedNumGridCols = numGridCols - 1;
}
for (var j=0; j<tweakedNumGridCols; j++) {
gridValues[i][j]._x = gridOffsetX + j * gridSpacingX + offsetX;
gridValues[i][j]._y = gridOffsetY + i * gridSpacingY;
gridValues[i][j]._type = lookupAgentType(gridValues[i][j]._x, gridValues[i][j]._y, glyphSize);
if(gridValues[i][j]._type > 1) {
gridValues[i][j]._static = false;
gridValues[i][j]._size = glyphSize/4;
}
else {
gridValues[i][j]._static = true;
gridValues[i][j]._size = glyphSize/2;
}
}
}
// setup
for (var i=0; i<numActiveAgents; i++) {
var agent = allAgents[i];
agent.setup(0, agent._type);
}
// compute neighbors
computeNeighbors(glyphSize);
}
function computeNeighbors(glyphSize) {
var mode = modeSelector.value();
var hexOffset = (mode == "hexgrid");
for (var i=0; i<numActiveAgents; i++) {
allAgents[i]._neighbors = []
}
var dist_thresh = 2.0;
if(hexOffset) {
dist_thresh = 1.4;
}
for (var i=0; i<numActiveAgents; i++) {
var agent = allAgents[i];
// agent.setup(0, agent._type);
for (var j=i+1; j<numActiveAgents; j++) {
var other = allAgents[j]
var d = dist(agent._x, agent._y, other._x, other._y) / glyphSize
if (d < dist_thresh) {
var o1 = {
'distance': d,
'agent': other,
'radius': other._size,
'x': other._x - agent._x,
'y': other._y - agent._y,
'pos': createVector(other._x - agent._x, other._y - agent._y)
}
agent._neighbors.push(o1)
var o2 = {
'distance': d,
'agent': agent,
'radius': agent._size,
'x': agent._x - other._x,
'y': agent._y - other._y,
'pos': createVector(agent._x - other._x, agent._y - other._y)
}
other._neighbors.push(o2)
}
}
}
}
function speedChangedEvent() {
var speed = parseInt(speedSelector.value(), 10);
frameRate(speed)
}
function sizeChangedEvent() {
var mode = modeSelector.value();
refreshGridData();
redraw();
}
function guideChangedEvent() {
show_oddball = guideCheckbox.checked();
redraw();
}
function modeChangedEvent() {
var mode = modeSelector.value();
if (is_playing) {
playButton.elt.textContent = "pause";
stepButton.attribute('disabled','');
// stopButton.removeAttribute('disabled');
}
else {
playButton.elt.textContent = "play";
stepButton.removeAttribute('disabled');
// stopButton.attribute('disabled','');
}
if (mode === "drive") {
// disable the button
// button.attribute('disabled','');
// enable the size selector
sizeSelector.removeAttribute('disabled');
}
else {
// enable the button
// button.removeAttribute('disabled');
// enable the size selector
// sizeSelector.removeAttribute('disabled');
// refresh data
// refreshGridData();
}
if (mode === "hexgrid") {
// refresh data
// refreshGridData();
}
redraw();
}
function gridTypeChanged() {
modeChangedEvent();
refreshGridData();
redraw();
}
function clearButtonPressedEvent() {
refreshGridData();
for(var i=0; i<numActiveAgents; i++) {
var agent = allAgents[i];
agent.setup(0, agent._type);
}
redraw();
}
function randomButtonPressedEvent() {
// refreshGridData();
for(var i=0; i<numActiveAgents; i++) {
var agent = allAgents[i];
agent.setup(random(100), agent._type);
}
redraw();
}
function playButtonPressedEvent() {
if(is_playing) {
is_playing = false
noLoop();
}
else {
is_playing = true;
loop();
}
modeChangedEvent()
// refreshGridData();
redraw();
}
function stepButtonPressedEvent() {
is_playing = true;
// refreshGridData();
redraw();
is_playing = false;
}
function stopButtonPressedEvent() {
// refreshGridData();
redraw();
}
var colorBack = "rgb(232, 232, 232)";
var colorBack = "rgb(39, 127, 58)";
function highlightGlyph(glyphSize) {
halfSize = glyphSize / 2.0;
stroke(0, 0, 255, 128);
noFill();
strokeWeight(4);
ellipse(halfSize, halfSize, glyphSize+4);
fill(0);
strokeWeight(1);
}
function drawGrid() {
var glyphSize = parseInt(sizeSelector.value(), 10);
background(colorBack);
for (var i=0; i<numActiveAgents; i++) {
resetMatrix();
agent = allAgents[i];
translate(agent._x, agent._y);
agent.draw(agent._size);
resetMatrix();
if (show_oddball) {
translate(agent._x, agent._y);
highlightGlyph(glyphSize)
}
}
}
function clamp(num, min, max) {
return num <= min ? min : num >= max ? max : num;
}
function stepGrid() {
var glyphSize = parseInt(sizeSelector.value(), 10);
var radius = glyphSize / 2;
var min_x = int(0);
var min_y = int(0);
var max_x = int(canvasWidth - radius) - 1;
var max_y = int(canvasHeight - radius) - 1;
var updatedAgents = new Array(numActiveAgents);
for (var i=0; i<numActiveAgents; i++) {
// make a shallow copy of the agent
agent = allAgents[i];
var clone = Object.assign({}, agent);
agent._new_me = clone;
var movement = clone.step(clone._neighbors, clone._size);
if(typeof movement !== 'undefined') {
haveSeenMovement = true;
var new_x = clone._x + movement.x;
var new_y = clone._y + movement.y;
clone._x = clamp(new_x, min_x, max_x);
clone._y = clamp(new_y, min_y, max_y);
}
updatedAgents[i] = clone;
}
for (var i=0; i<numActiveAgents; i++) {
allAgents[i] = updatedAgents[i];
}
if(haveSeenMovement) {
// copy new version of neighbors
computeNeighbors(glyphSize);
}
else {
for (var i=0; i<numActiveAgents; i++) {
agent = allAgents[i];
var old_neighbors = agent._neighbors;
for(var j=0; j<old_neighbors.length; j++) {
if ('_new_me' in old_neighbors[j].agent) {
agent._neighbors[j].agent = agent._neighbors[j].agent._new_me;
}
}
}
// weakly check optimization assertion (not a memory leak)
for (var i=0; i<numActiveAgents; i++) {
if ('_new_me' in allAgents[i]) {
print("you flubbed the _new_me setup");
}
}
}
}
function activateGrid(x, y) {
var glyphSize = parseInt(sizeSelector.value(), 10);
for (var i=0; i<numActiveAgents; i++) {
agent = allAgents[i];
if( (agent._x <= x) && (agent._x + glyphSize > x) &&
(agent._y <= y) && (agent._y + glyphSize > y) ) {
agent.activate();
}
}
}
function mouseClicked () {
activateGrid(mouseX, mouseY);
drawGrid();
}
function draw () {
var mode = modeSelector.value();
// first do all steps
if (is_playing) {
stepGrid();
}
// then do activate
activateGrid(mouseX, mouseY);
// the do all draws
drawGrid();
resetMatrix();
}
function keyTyped() {
if (key == '!') {
saveBlocksImages();
}
else if (key == '@') {
saveBlocksImages(true);
}
else if (key == ' ') {
playButtonPressedEvent();
}
else if (key == 's') {
var old_value = guideCheckbox.checked();
guideCheckbox.checked(!old_value);
guideChangedEvent();
}
else if (key == '1') {
sizeSelector.value('16');
sizeChangedEvent()
}
else if (key == '2') {
sizeSelector.value('32');
sizeChangedEvent()
}
else if (key == '3') {
sizeSelector.value('64');
sizeChangedEvent()
}
else if (key == '4') {
sizeSelector.value('128');
sizeChangedEvent()
}
else if (key == '5') {
sizeSelector.value('256');
sizeChangedEvent()
}
else if (key == 'd') {
modeSelector.value('drive');
modeChangedEvent()
}
else if (key == 'g') {
modeSelector.value('grid');
gridTypeChanged()
}
else if (key == 'r') {
modeSelector.value('random');
modeChangedEvent()
}
else if (key == 'h') {
modeSelector.value('hexgrid');
gridTypeChanged()
}
}
function keyPressed() {
}
Display the source blob
Display the rendered blob
Raw
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment