Practical Coding in Java

Learn to write and validate your own code

Darren Kessner, PhD

(revised January 9, 2026)

Previous: TimeComplexity

Phyllotaxis

//
// Ball.java
//


import processing.core.*;


public class Ball
{
    public Ball(PApplet p, PVector velocity, int color)
    {
        this.p = p;
        this.position = new PVector();  // start at (0,0)
        this.velocity = velocity.copy();
        this.color = color;
    }

    public void display(PGraphics pg)
    {
        pg.fill(color);
        pg.noStroke();
        pg.ellipse(position.x, position.y, radius*2, radius*2);

        position.add(velocity);
        velocity.mult(.9985f);
    }

    public boolean isDead()
    {
        return position.mag() > 3000;
    }

    private PApplet p;
    private PVector position;
    private PVector velocity;
    private int color;

    private static final int radius = 40;
}
//
// Phyllotaxis.java
//


import processing.core.*;
import java.util.*;


public class Phyllotaxis extends PApplet
{
    public void settings()
    {
        size(600, 900);
        pixelDensity(1);
    }

    public void setup()
    {
        pg = createGraphics(1800, 2700);
        colorMode(HSB, 100);
        noCursor();
    }

    private void drawStuffOffscreen()
    {
        pg.beginDraw();
        pg.background(0);
        pg.translate(pg.width/2, pg.height/2);

        for (Ball b : balls)
            b.display(pg);

        pg.endDraw();
    }

    public void draw()
    {
        // draw everything to the offscreen buffer (pg), 
        // then display the buffer scaled to the screen size

        drawStuffOffscreen();
        image(pg, 0, 0, width, height);

        // add a new ball with the current direction and color

        currentAngle += goldenAngle;
        currentHue += .25;

        PVector currentVelocity = PVector.fromAngle(currentAngle);
        currentVelocity.setMag(5);

        int currentColor = color(currentHue%100, 100, 100, 150);

        balls.add(new Ball(this, currentVelocity, currentColor));

        // remove dead balls

        balls.removeIf(ball -> ball.isDead());
    }

    public void keyPressed()
    {
        if (key == 'n')
            noLoop();
        else if (key == 'l')
            loop();
        else if (key == 's')
        {
            println("Saving frame.");
            pg.save("phyllotaxis.png");
        }
    }

    PGraphics pg;
    private ArrayList<Ball> balls = new ArrayList<Ball>();
    private float currentAngle = 0;
    private float currentHue = 0;

    private static final float phi = (float)(1 + Math.sqrt(5))/2; // Golden Ratio
    private static final float goldenAngleProportion = 1/phi/phi; // fraction of circle
    private static final float goldenAngle = 2*PI*goldenAngleProportion; // radians

    public static void main(String[] args)
    {
        println("goldenAngle: " + goldenAngle*180/PI + " degrees");
        PApplet.main("Phyllotaxis");
    }
}

Next: