Bevegelse i en sirkel
Hei og hå
Det er to involverte processing-filer:
_sirkelBalls.pde
float bigR; // surrounding circle float ballCount=5; // at start float maxSpeed=3; // pixels pr frame ArrayList<Ball> balls; void setup(){ size(600,600); bigR=width/2-50; ellipseMode(RADIUS); balls=new ArrayList(); int ix=0; while(ix < ballCount){ float xpos=random(0,width); float ypos=random(0,height); // keep within big circle if(dist(xpos,ypos,width/2,height/2) < bigR-Ball.R-3){ Ball B=new Ball(new PVector(xpos,ypos), new PVector(random(-maxSpeed,maxSpeed),random(-maxSpeed,maxSpeed))); // dont start with overlapping boolean useIt=true; for(Ball b:balls){ if(B.touch(b)) useIt=false; } if(useIt) { balls.add(B); ix++; } } } } // as called from hosting webpage void addBall(){ if(balls.size() >10) return; float xpos=width/2; float ypos=height/2; Ball B=new Ball(new PVector(xpos,ypos), new PVector(random(-maxSpeed,maxSpeed),random(-maxSpeed,maxSpeed))); balls.add(B); } // as called from hosting webpage void removeBall(){ if(balls.size()>1) balls.remove(0); } void draw(){ background(255); // big circle fill(200,200,120); ellipse(width/2,height/2,bigR,bigR); textSize(60); textAlign(CENTER,CENTER); fill(100); text(balls.size(),width/2,height/2); // balls int ix1=0; while(ix1 < balls.size()){ Ball b1=balls.get(ix1); b1.move(); // take out balls outside big circle if(dist(b1.pos.x,b1.pos.y,width/2,height/2) > bigR+b1.R){ balls.remove(ix1); makeSound("eat"); continue; } for(int ix2=0;ix2 <balls.size();ix2++){ Ball b2=balls.get(ix2); if(b1!=b2){ if(b1.touch(b2)){ //b.invertSpeed(); b1.swapSpeed(b2); //b.move(); } if(b2.hangOn(b1)){ //b.invertSpeed(); balls.remove(ix2); makeSound("eat"); //b2.replace(); } } } b1.draw(); ix1++; } } void makeSound(String s){ // calling hosting webpage playClick(s); } // since PVector.rotate() is not available in processingjs static PVector rotateVector(PVector p,float v){ //x2= x1·cos(v)-y1·sin(v) //y2= x1·sin(v)+y1·cos(v) float x2=p.x*cos(v)-p.y*sin(v); float y2=p.x*sin(v)+p.y*cos(v); return new PVector(x2,y2); }
og
_Ball.pde
class Ball{ static final float R=20; // radius for all balls PVector pos; // position PVector speed; // speed Ball(PVector pos,PVector speed){ this.pos=pos; this.speed=speed; } void move(){ pos.add(speed); // take out balls outside big circle // should not happen if(dist(pos.x,pos.y,width/2,height/2) > bigR+R){ speed=pos.get(); return; } // getting close to big circle if(dist(pos.x,pos.y,width/2,height/2) > bigR-R-5){ // make new speed direction // vector from centre to hit point PVector P=new PVector(pos.x-width/2,pos.y-height/2); // angle between speed av P PVector tmp=speed.get(); tmp.mult(-1); float V= PVector.angleBetween(P,tmp); //tmp.rotate(-2*V); tmp=rotateVector(tmp,-2*V); speed=tmp.get(); PVector nextP=new PVector(pos.x+speed.x,pos.y+speed.y); // going wron way ? if(dist(nextP.x,nextP.y,width/2,height/2) > bigR-R-5){ speed=rotateVector(speed,4*V+PI/100.0); } else { speed=rotateVector(speed,-PI/100.0); } //makeSound(); } } void invertSpeed(){ speed.mult(-1); } void replace(){ pos.mult(0.8); } void swapSpeed(Ball otherBall){ PVector tmp= speed.get(); speed=otherBall.speed.get(); otherBall.speed.set(tmp); makeSound("hit"); } boolean touch(Ball otherBall){ return (dist(pos.x,pos.y,otherBall.pos.x,otherBall.pos.y) < 2*R-maxSpeed-1); } boolean hangOn(Ball otherBall){ return dist(pos.x,pos.y,otherBall.pos.x,otherBall.pos.y) < 2*R-10; } void draw(){ float c=map(speed.mag(),0,6,100,255); fill(int(c),0,0); ellipse(pos.x,pos.y,R,R); //draw speed: line(pos.x,pos.y,pos.x+20*speed.x,pos.y+20*speed.y); } }
Løsningen involverer utstrakt bruk av PVector. En nyttig metode i PVector som ikke er implementert i Prosessingjs er PVector.rotate(). Alternativet er håndskrevet slik:
// since PVector.rotate() is not available in processingjs
static PVector rotateVector(PVector p,float v){
float x2=p.x*cos(v)-p.y*sin(v);
float y2=p.x*sin(v)+p.y*cos(v);
return new PVector(x2,y2);
}
Javascriptkoden er slik, med to funksjoner som kaller skissen, og en som blir kalt fra skissen:
_index.js
var soundIsOn=true; function playClick(sound){ if(soundIsOn){ var theSound=document.getElementById(sound); theSound.pause(); theSound.play(); } } function addBall(){ var pjs=Processing.getInstanceById("draw"); pjs.addBall()() } function removeBall(){ var pjs=Processing.getInstanceById("draw"); pjs.removeBall() }