Each fish looks only at its neighbours and follows three rules: keep your distance, swim the way they swim, stay with them. Move the mouse and it becomes a predator the shoal parts around; click to drop food.
Craig Reynolds' boids (1986), in the example's own code, with a grid of buckets so each fish only checks the fish around it. The engine's part is 450 sprites turned and tinted every frame: each fish is coloured by its heading, so streams read as bands of colour.
Try changing SEPARATION, ALIGNMENT and COHESION: more cohesion and it balls up, more alignment and it streams, more separation and it spreads into a haze.