diff --git a/ABMobility/ABMobility.pde b/ABMobility/ABMobility.pde index 645e727..6aee862 100644 --- a/ABMobility/ABMobility.pde +++ b/ABMobility/ABMobility.pde @@ -28,7 +28,7 @@ boolean showZombie = false; boolean dynamicSlider = true; boolean showCollisionPotential = false; boolean inAnimationMode = false; -boolean enableAnimationMode = false; +boolean enableAnimationMode = true; UDPReceiver udpR; void settings(){ @@ -46,6 +46,7 @@ void setup(){ void draw(){ drawScene(); + //println(frameRate); } /* Draw ------------------------------------------------------ */ diff --git a/ABMobility/Agent.pde b/ABMobility/Agent.pde index e831077..aef427d 100644 --- a/ABMobility/Agent.pde +++ b/ABMobility/Agent.pde @@ -48,6 +48,7 @@ public class Agent { private PVector dir; private float speed; private boolean isZombie; + private color myColor; Agent(HashMap _networks, HashMap _glyphsMap, int _worldId, @@ -180,10 +181,18 @@ public class Agent { public void draw(PGraphics p, boolean glyphs) { + if(worldId==1){ + myColor = universe.colorMapBad.get(mobilityType); + }else{ + myColor=universe.colorMapGood.get(mobilityType); + } + p.fill(myColor); if(inAnimationMode && enableAnimationMode){ - if(residentialBlockId == universe.grid.currentBlockAnimated || officeBlockId == universe.grid.currentBlockAnimated ||officeBlockId == universe.grid.currentBlockAnimated){ - p.fill(#FF0000); + if(residentialBlockId == universe.grid.currentBlockAnimated || officeBlockId == universe.grid.currentBlockAnimated || amenityBlockId == universe.grid.currentBlockAnimated){ + //p.fill(#FF0000); + int curRadius; p.ellipse(pos.x, pos.y, 10*SCALE, 10*SCALE); + //drawPath(p,myColor); } } else{ @@ -202,11 +211,6 @@ public class Agent { } } else { p.noStroke(); - if(worldId==1){ - p.fill(universe.colorMapBad.get(mobilityType)); - }else{ - p.fill(universe.colorMapGood.get(mobilityType)); - } p.ellipse(pos.x, pos.y, 10*SCALE, 10*SCALE); } @@ -230,6 +234,24 @@ public class Agent { } } } + + // DRAW AGENT PATH TO DESTINATION ---> + public void drawPath(PGraphics p, color c) { + if (path != null) { + for (int i=1; i + p.stroke(c); + p.strokeWeight(1); + p.noFill(); + p.line( iNodePos.x, iNodePos.y, iPrevNodePos.x, iPrevNodePos.y ); + //p.strokeWeight(3); // Route from pos to next node is always thicker ---> + // p.line( pos.x, pos.y, toNodePos.x, toNodePos.y ); + } + } + } private String chooseMobilityType() { /* Agent makes a choice about which mobility diff --git a/ABMobility/Grid.pde b/ABMobility/Grid.pde index a547544..2696d8f 100644 --- a/ABMobility/Grid.pde +++ b/ABMobility/Grid.pde @@ -67,16 +67,17 @@ public class Grid { public void draw(PGraphics p) { // Draw building block locations drawBuildingBlocks(p); + // Draw grid animations (if they occured) + for (GridInteractionAnimation ga: gridAnimation){ + ga.draw(p); + } // Draw buildings for (Building b: buildings) { if (b.loc != zombieLandLocation) { b.draw(p); } } - // Draw grid animations (if they occured) - for (GridInteractionAnimation ga: gridAnimation){ - ga.draw(p); - } + } public void drawBuildingBlocks(PGraphics p) { @@ -114,6 +115,7 @@ public class Grid { gridAnimation.get(i).put(); currentBlockAnimated = buildingId; } + building.loc = gridMap.get(i); // Record that the building is on the grid buildingIdsFromData[buildingId] = 1; diff --git a/ABMobility/GridInteractionAnimation.pde b/ABMobility/GridInteractionAnimation.pde index 8e668e7..e82df95 100644 --- a/ABMobility/GridInteractionAnimation.pde +++ b/ABMobility/GridInteractionAnimation.pde @@ -4,13 +4,14 @@ public class GridInteractionAnimation { int OFFSET = 2; int LINE_LENGTH = 5; - int DURATION = 2000; // milliseconds + int DURATION = 3000; // milliseconds int LINE_NUM = 4; PVector center; float start; // start millis of animation boolean isActive; boolean isPut; + ParticleSystem ps; public GridInteractionAnimation(PVector _loc){ center = new PVector( @@ -21,6 +22,59 @@ public class GridInteractionAnimation { start = 0.0; isActive = true; isPut = false; + ps = new ParticleSystem(center,#FFFFFF); + } + + void runParticleSystem(PGraphics p){ + for(int i=0;i<=20;i++){ + ps.addParticle(); + } + + ps.run(p); + } + + void dynamicRadius(PGraphics p,float t, color c){ + p.fill(c); + p.ellipse(center.x, center.y, BUILDING_SIZE+t*100, BUILDING_SIZE+t*100); + p.fill(c,70); + p.ellipse(center.x, center.y, BUILDING_SIZE+BUILDING_SIZE*0.25+t*100, BUILDING_SIZE+BUILDING_SIZE*0.25+t*100); + p.fill(c,100); + p.ellipse(center.x, center.y, BUILDING_SIZE+BUILDING_SIZE*0.5+t*100, BUILDING_SIZE+BUILDING_SIZE*0.5+t*100); + } + + void dynamicSquare(PGraphics p,float t,color c){ + p.fill(c); + p.rect(center.x, center.y, BUILDING_SIZE+t*100, BUILDING_SIZE+t*100); + p.fill(c,70); + p.rect(center.x, center.y, BUILDING_SIZE+BUILDING_SIZE*0.25+t*100, BUILDING_SIZE+BUILDING_SIZE*0.25+t*100); + p.fill(c,100); + p.rect(center.x, center.y, BUILDING_SIZE+BUILDING_SIZE*0.5+t*100, BUILDING_SIZE+BUILDING_SIZE*0.5+t*100); + p.rect(center.x, center.y, BUILDING_SIZE+t*100, BUILDING_SIZE+t*100); + } + + void minimalLine(PGraphics p, float t){ + p.pushMatrix(); + p.stroke(#FFFFFF); + p.translate(center.x, center.y); + + float unitX = BUILDING_SIZE / LINE_NUM; + for(int r = 0; r < 4; r++){ + p.pushMatrix(); + p.rotate(PI * 0.5 * r); + p.translate(-BUILDING_SIZE * 0.5, 0); // new line + + p.pushMatrix(); + for(int i = 0; i < LINE_NUM; i++){ + drawLine(p, t, isPut); + p.translate(unitX, 0); + } + drawLine(p, t, isPut); + p.popMatrix(); + + p.popMatrix(); // origin is back to center + } + + p.popMatrix(); } void drawLine(PGraphics p, float elapsed, boolean flip){ @@ -57,36 +111,22 @@ public class GridInteractionAnimation { void draw(PGraphics p){ if(!isActive) return; - inAnimationMode = true; float t = (millis() - start) / DURATION; - + if(isPut == false){ + inAnimationMode = true; + dynamicSquare(p,pow(t,t),#FFFFFF); + runParticleSystem(p); + //dynamicRadius(p,pow(t,t),#FFFFFF); + + minimalLine(p,t); + } + if(t < 0 || t > 1){ isActive = false; inAnimationMode = false; } - p.pushMatrix(); - p.stroke(#FFFFFF); - p.translate(center.x, center.y); - float unitX = BUILDING_SIZE / LINE_NUM; - for(int r = 0; r < 4; r++){ - p.pushMatrix(); - p.rotate(PI * 0.5 * r); - p.translate(-BUILDING_SIZE * 0.5, 0); // new line - - p.pushMatrix(); - for(int i = 0; i < LINE_NUM; i++){ - drawLine(p, t, isPut); - p.translate(unitX, 0); - } - drawLine(p, t, isPut); - p.popMatrix(); - - p.popMatrix(); // origin is back to center - } - - p.popMatrix(); } } @@ -103,3 +143,87 @@ float cubicEase(float t) { float y = curvePoint(800, 100, 0, 5, t); return map(y, 100.0, 0.0, 0, 1.0); } + +class Particle { + PVector location; + PVector velocity; + PVector acceleration; + float lifespan; + color c; + + Particle(PVector l, color _c) { + acceleration = new PVector(random(-0.1, 0.1),random(-0.1,0.1)); + velocity = new PVector(random(-5,5),random(-5,5)); + location = l.get(); + lifespan = 255.0; + c= _c; + } + + void run(PGraphics p) { + update(); + display(p); + } + + // Method to update location + void update() { + velocity.add(acceleration); + location.add(velocity); + acceleration.mult(0); + lifespan -= 5; + } + + // Method to display + void display(PGraphics p) { + p.stroke(c,lifespan); + p.fill(c,lifespan); + p.ellipse(location.x,location.y,10*SCALE,10*SCALE); + } + + void applyForce(PVector force){ + acceleration.add(force); + } + + // Is the particle still useful? + boolean isDead() { + if (lifespan < 0.0) { + return true; + } else { + return false; + } + } +} + +// A class to describe a group of Particles +// An ArrayList is used to manage the list of Particles + +class ParticleSystem { + ArrayList particles; + PVector origin; + color c; + + ParticleSystem(PVector _location, color _c) { + origin = _location; + particles = new ArrayList(); + c = _c; + } + + void addParticle() { + particles.add(new Particle(origin,c)); + } + + void applyForce(PVector force){ + for(Particle p : particles){ + p.applyForce(force); + } + } + + void run(PGraphics _p) { + for (int i = particles.size()-1; i >= 0; i--) { + Particle p = particles.get(i); + p.run(_p); + if (p.isDead()) { + particles.remove(i); + } + } + } +}