package creeper_Behavior_P3; import processing.core.*; import java.util.ArrayList; import java.util.List; import toxi.color.*; import java.util.Random; import creeper_Behavior_P3.ImprovedPerlinNoise; public class Creeper{ public PVector loc; public PVector speed; private PVector acc = new PVector(); public ArrayList<PVector> creeperTrails; public List<Creeper> creeperCollection; public List<List<PVector>> trailData; public List<ArrayList> trailColors; private float width; private float height; public float searchRad; public float av; public float sv; public float cv; public float connThresh; public float connect; public float max; public boolean swarm; public boolean perlin; public boolean hybrid; public boolean bounds; private boolean needsRefresh; public boolean applyMap; public boolean applyColor; public PImage img; private List<PVector> otherPtsList; private List<PVector> otherMoveValues; private List<Float> allDist; private PVector cummVec, alignVector, separateVector, cohesionVector; private TColor colorA = TColor.newRGB(255.0f / 255.0f, 0.0f / 255.0f, 0.0f / 255.0f); private TColor colorB = TColor.newRGB(1.0f / 255.0f, 53.0f / 255.0f, 103.0f / 255.0f); private TColor colorC = TColor.newRGB(187.0f / 255.0f, 216.0f / 255.0f, 40.0f / 255.0f); private ColorGradient gradA = new ColorGradient(); private ToneMap toneMapA; public boolean simulate; public float strokeWidth, transparency; public int trailResolution; private float newMap; public boolean mapAV,mapSV,mapCV,mapPS,mapPSC, mapPM; // -----Noise Fields------- public float multiplier, scale, strength, velocity, blend; private Random r; // CONSTRUCTOR - INITIALIZE THE CLASS // ------------------------------------------------------------------------------------- public Creeper(PVector origin, PVector speed, float width, float height) { this.loc = origin; this.creeperTrails = new ArrayList<PVector>(); this.speed = speed; this.width = width; this.height = height; this.creeperCollection = new ArrayList<Creeper>(); gradA.addColorAt(0.0f, colorA); gradA.addColorAt(255.0f, colorC); toneMapA = new ToneMap(0.0f, 1.0f, gradA); } // ALL FUNCTIONS // --------------------------------------------------------------------------------------------------------- public void action() { this.r = new Random(); if (this.simulate) { if (this.swarm || (this.hybrid && this.blend == 1.0)) { flocking(); bounce(); this.loc.add(speed); this.creeperTrails.add(new PVector(loc.x, loc.y, 0)); acc = new PVector(); } if (this.perlin || (this.hybrid && this.blend == 0.0)) { perlinNoise(); if (this.bounds) { checkLoc(); } speed = new PVector(); speed.add(acc); this.loc.add(speed); this.creeperTrails.add(new PVector(loc.x, loc.y, 0)); acc = new PVector(); } if (this.hybrid && (this.blend != 0.0 && this.blend != 1.0)) { speed.add(acc); speed.limit(this.max); this.loc.add(speed); this.creeperTrails.add(new PVector(loc.x, loc.y, 0)); acc = new PVector(); perlinNoise(); flocking(); bounce(); } if (!this.swarm && !this.perlin && !this.hybrid) { this.acc = new PVector(1.0f, 0, 0); } trails(); } } private void checkLoc_B() { Float w = width; Double dW = (double) w; Float h = height; Double dH = (double) h; this.needsRefresh = false; if (loc.x > width || this.loc.x < 0 || this.loc.y > height || this.loc.y < 0) { this.needsRefresh = true; } } private void checkLoc() { Float w = width; Double dW = (double) w; Float h = height; Double dH = (double) h; this.needsRefresh = false; if (loc.x > width || this.loc.x < 0 || this.loc.y > height || this.loc.y < 0) { this.needsRefresh = true; float x = GetRandomNumbers(0.0f, dW, this.r); float y = GetRandomNumbers(0.0f, dH, this.r); this.loc = new PVector(x, y, 0); this.creeperTrails = new ArrayList<PVector>(); } } // BOUNCE METHOD // ------------------------------------------------------------------------------------------------------------ private void bounce() { if (loc.x > width) { speed.x = speed.x * -1; } if (loc.x < 0) { speed.x = speed.x * -1; } if (loc.y > height) { speed.y = speed.y * -1; } if (loc.y < 0) { speed.y = speed.y * -1; } } private float GetRandomNumbers(double minimum, double maximum, Random r) { double rX = this.r.nextDouble() * (maximum - minimum) + minimum; float fX = (float) rX; return fX; } private PVector GetRandomNumber(double minimum, double maximum, Random r) { PVector rando = new PVector(); double rX = this.r.nextDouble() * (maximum - minimum) + minimum; double rY = this.r.nextDouble() * (maximum - minimum) + minimum; float fX = (float) rX; float fY = (float) rY; rando.x = fX; rando.y = fY; rando.z = 0.00f; return rando; } private void perlinNoise() { if (!this.applyMap) { PVector multSpeed = GetRandomNumber(-this.multiplier, this.multiplier, this.r); double noiseVal = ImprovedPerlinNoise.noise(this.loc.x / (Float) this.scale, this.loc.y / (Float) this.scale, 0.0) * this.strength; double angle = noiseVal; double ddX = Math.cos(angle); float dX = (float) ddX; double ddY = Math.sin(angle); float dY = (float) ddY; PVector dir = new PVector(dX, dY, 0); dir.mult(this.velocity); dir.add(multSpeed); this.acc.add(dir); }else{ if (this.loc.x <= img.width && this.loc.x >= 0 && this.loc.y >= 0 && this.loc.y <= img.height) { getColorValue(); }else{ this.newMap = 0; } PVector multSpeed; if(this.mapPM){ multSpeed = GetRandomNumber(-this.multiplier*this.newMap, this.multiplier*this.newMap, this.r); }else{ multSpeed = GetRandomNumber(-this.multiplier, this.multiplier, this.r); } if(this.mapPSC){ if(this.newMap == 0.0f){ this.newMap = 0.1f; } this.scale *= this.newMap; } if(this.mapPS){ this.strength *= this.newMap; } if(this.mapPS && this.mapPSC){ this.scale *= this.newMap; this.strength *= this.newMap; } double noiseVal = ImprovedPerlinNoise.noise(this.loc.x / (Float) this.scale, this.loc.y / (Float) this.scale, 0.0f)* (this.strength); double angle = noiseVal; double ddX = Math.cos(angle); float dX = (float) ddX; double ddY = Math.sin(angle); float dY = (float) ddY; PVector dir = new PVector(dX, dY, 0); dir.mult(this.velocity); dir.add(multSpeed); this.acc.add(dir); } } private void getColorValue(){ double f = Math.floor(this.loc.y)*img.width + Math.floor(this.loc.x); Integer i = (int)f; Integer col = img.pixels[i]; float red = col >> 16 & 0xFF; // Very fast to calculate float green = col >> 8 & 0xFF; // Very fast to calculate float blue = col & 0xFF; // Very fast to calculate int greyscale = (int) Math.round(red*0.222+ green*0.707+blue*0.071); newMap = map(greyscale, 0, 255, 0, 1); } // FLOCK METHOD // --------------------------------------------------------------------------------------------------------------- private void flocking() { if(this.applyMap){ if (this.loc.x <= img.width && this.loc.x >= 0 && this.loc.y >= 0 && this.loc.y <= img.height) { getColorValue(); if(this.mapAV){ this.av *= this.newMap; } if(this.mapSV){ this.sv *= this.newMap; } if(this.mapCV){ this.cv *= this.newMap; } }else{ this.newMap = 0; } } this.otherPtsList = new ArrayList<PVector>(); this.otherMoveValues = new ArrayList<PVector>(); this.allDist = new ArrayList<Float>(); for (int i = 0; i < this.creeperCollection.size(); i++) { Creeper other = (Creeper) creeperCollection.get(i); float distance = this.loc.dist(other.loc); if (distance > 0 && distance < this.searchRad) { this.otherPtsList.add(this.creeperCollection.get(i).loc); this.allDist.add(distance); this.otherMoveValues.add(this.creeperCollection.get(i).speed); } } if (this.otherPtsList.size() > 0) { this.cummVec = new PVector(); // ----------Align----------------- align(); if (this.alignVector.mag() > 0) { this.alignVector.normalize(); } this.alignVector.mult(this.av); // ----------Separate----------------- separate(); if (this.separateVector.mag() > 0) { this.separateVector.normalize(); } this.separateVector.mult(this.sv); // ----------Cohesion----------------- cohesion(); if (this.cohesionVector.mag() > 0) { this.cohesionVector.normalize(); } this.cohesionVector.mult(this.cv); // ----------------------------------- this.cummVec.add(this.alignVector); this.cummVec.add(this.separateVector); this.cummVec.add(this.cohesionVector); if (this.hybrid) { if (this.blend != 0.0 && this.blend != 1.0) { acc.add(this.cummVec); float newVal = 1.0f - this.blend; this.acc.mult(newVal); } else if (this.blend == 1.0) { this.acc = new PVector(); this.speed.add(this.cummVec); this.speed.normalize(); this.speed.mult(this.velocity); } } else { this.speed.add(this.cummVec); this.speed.normalize(); this.speed.mult(this.velocity); } } } // COHESION // --------------------------------------------------------------------------------------------------------------------- // -----------Method Computes the cohesion----------------------------- private void cohesion() { this.cohesionVector = new PVector(); for (int i = 0; i < this.otherPtsList.size(); i++) { this.cohesionVector.add(this.otherPtsList.get(i)); } PVector scaleVec = PVector.mult(this.cohesionVector, (1.00f / this.otherPtsList.size())); float dist = this.loc.dist(scaleVec); this.cohesionVector = PVector.mult(PVector.sub(scaleVec, this.loc), this.searchRad / dist); } // -----------Method Computes the separation---------------------------- private void separate() { this.separateVector = new PVector(); for (int i = 0; i < this.otherPtsList.size(); i++) { this.separateVector.add(PVector.mult(PVector.sub(this.loc, this.otherPtsList.get(i)), this.searchRad / this.allDist.get(i))); } } // -----------Method Computes the alignment---------------------------- private void align() { this.alignVector = new PVector(); for (int i = 0; i < this.otherPtsList.size(); i++) { this.alignVector.add(PVector.mult(this.otherMoveValues.get(i), this.searchRad / this.allDist.get(i))); } } // TRAIL FUNCTION // --------------------------------------------------------------------------------------------------------------------------------- private void trails() { this.trailData = new ArrayList<List<PVector>>(); this.trailColors = new ArrayList<ArrayList>(); int counter = 0; List<PVector> pvecList = new ArrayList<PVector>(); for (int k = 0; k < creeperTrails.size(); k++) { if (counter % this.trailResolution == 0) { pvecList.add(creeperTrails.get(k)); } counter++; } if (pvecList.size() > 0) { for (int j = 0; j < pvecList.size(); j++) { if (j != 0) { List<PVector> vecList = new ArrayList<PVector>(); ArrayList colList = new ArrayList(); PVector pos = pvecList.get(j); PVector prevpos = pvecList.get(j - 1); vecList.add(pos); vecList.add(prevpos); trailData.add(j - 1, vecList); if(this.applyColor){ int a = toneMapA.getARGBToneFor(j / (1.0f * pvecList.size())); float value = map(j / (1.0f * pvecList.size()), 0, 1.0f, 0, this.strokeWidth); float value2 = map(j / (1.0f * pvecList.size()), 0, 1.0f, 10, this.transparency); colList.add(value); colList.add(a); colList.add(value2); trailColors.add(j - 1, colList); } } } } } static public final float map(float value, float istart, float istop, float ostart, float ostop) { return ostart + (ostop - ostart) * ((value - istart) / (istop - istart)); } }