Programmation réactive en Java :
sinus || cosinus = cercle


class Ball
{
final static boolean SINE = true, COSINE = false;
double x, y, angleX = 0, angleY = 0;
int radius = 8, steps = 100, scale = 5;
Color color;

public Ball(int x,int y,Color color){
this.x = x; this.y = y; this.color = color;
}
public Ball(int x,int y){ this(x,y,ColorBall.nextColor()); }

public void paint(Graphics g,Color color){
g.setColor(color);
g.fillOval((int)x-radius,(int)y-radius,radius*2,radius*2);
}

public void
sine(){
angleY += (2*Math.PI/steps);
y += scale*Math.sin(angleY);
}
public void
cosine(){
angleX += (2*Math.PI/steps);
x += scale*Math.sin(angleX+Math.PI/2);
}
}

L'action de mouvement en sinus ou en cosinus :

class Move implements Action
{
boolean move;
public Move(boolean m){ move = m; }
public void
execute(Environment env){
Ball ball = (Ball)
env.linkedObject();
if (move == Ball.SINE) ball.sine(); else ball.cosine();
}
}

L'applet réactive :

class ReactiveApplet
extends DoubleBufferedApplet
implements Runnable
{
Machine machine =
Jr.SyncMachine();
public ReactiveApplet(){ new Thread(this).start(); }
public void run(){
while(true){
try{ Thread.sleep(1); }catch(Exception e){}
machine.react();
paint(getGraphics());
}
}
}

L'applet :

public class SinCos6 extends ReactiveApplet
{
Ball ball1 = new Ball(startx,starty);
Ball ball2 = new Ball(startx,starty);
Ball ball3 = new Ball(startx,starty);

public void paint(Graphics g) {
super.paint(g);
ball1.paint(g,Color.red);
ball2.paint(g,Color.green);
ball3.paint(g,Color.blue);
}

Program sine(Ball ball){
return
Jr.Link(ball,
Jr.Loop(Jr.Seq(Jr.Atom(new Move(Ball.SINE)),Jr.Stop())));

}
Program cosine(Ball ball){
return Jr.Link(ball,
Jr.Loop(Jr.Seq(Jr.Atom(new Move(Ball.COSINE)),Jr.Stop())));
}
Program circle(Ball ball){
return
Jr.Par(sine(ball),cosine(ball));
}

public void init(){
machine.add(circle(ball1));
for (int i = 0; i < 2; i++) machine.add(sine(ball1));

machine.add(circle(ball2));
for (int i = 0; i < 2; i++) machine.add(cosine(ball2));

machine.add(circle(ball3));

}
}

résultat


Ajouts dynamiques

Transformation d'un clic souris en événement :

public class GenerateAdapter extends MouseAdapter
{
Machine machine;
Vector events;
public GenerateAdapter(Machine machine,Vector events){
this.machine = machine; this.events = events;
}

public void mouseClicked(MouseEvent evt){
Enumeration enum = events.elements();
while(enum.hasMoreElements()){
String event = (String)enum.nextElement();
machine.generate(Jr.StringIdentifier(event));
}
}
}

L'applet :

public class DynSinCos extends ReactiveApplet
{
int rand(int n){ return (int)(Math.random()*1000)%n; }
Vector items = new Vector();

public void paint(Graphics g){
synchronized(items){
Enumeration enum = items.elements();
while(enum.hasMoreElements()) ((Ball)enum.nextElement()).paint(g);
}
}



void createBall(){
Ball ball =
new Ball(rand(size().width),rand(size().height));
ball.radius = 5;
items.addElement(ball);

Program sin =
Jr.Seq(Jr.Await("sin"),
Jr.Loop(Jr.Seq(Jr.Atom(new Move(Ball.SINE)),Jr.Stop())));
Program cos =
Jr.Seq(Jr.Await("cos"),
Jr.Loop(Jr.Seq(Jr.Atom(new Move(Ball.COSINE)),Jr.Stop())));

machine.add(Jr.Link(ball,Jr.Par(sin,cos)));
}

public void init(){
Button sin = new Button("sin");
Button cos = new Button("cos");
Button sincos = new Button("sin+cos");
Button start = new Button("new circle");

Vector params = new Vector();
params.addElement("sin");
sin.addMouseListener(new GenerateAdapter(machine,params));

params = new Vector();
params.addElement("sin");
params.addElement("cos");
sincos.addMouseListener(new GenerateAdapter(machine,params));

params = new Vector();
params.addElement("cos");
cos.addMouseListener(new GenerateAdapter(machine,params));

start.addMouseListener(new CreateBall(this));

Panel p = new Panel();
p.setBackground(Color.lightGray);
setLayout(new BorderLayout());
p.setLayout(new GridLayout(1,5,5,20));
add("South",p);

p.add(sin);
p.add(cos);
p.add(sincos);
p.add(start);

//for(int i=0; i<1000; i++) createBall();
}

}

résultat