Skip to content

Random planets

Scroll and drag to zoom/pan. (No mobile support.)

This was inspired by the JS13K 2018 submission "Exo" by Jack Oatley and Anton K. I wanted to make a strategy game focused around building structures in orbits of limited space that can also be taken up by moons / planets.

This particular sketch was an experiment in making a simple logical structure which assigns whole numbers to planet masses and orbit "sizes", but at the same time disallows overlapping orbits.

I ended up with a system structured around the fibonacci numbers: a size-n planet has mass equal to F_n, the n-th fibonacci number, takes up F_{n+1} spaces on an orbit, and has n/2-2 orbits with available space ranging from F_{n/2+1} to F_{n-1}.

The big numbers displayed are "gravity potentials", to be used for computing the energy needed to travel from surface/orbit to surface/orbit.

An system of planets spinning along circular orbits

function setup() {
  createCanvas(windowWidth, windowHeight);
  pan = createVector(0, 0)
  time = (random() + random() + 1) * 100000000
}

let zoom = 0
let pan
let time = 1441432

function draw() {
  background(220)
  randomSeed(100)
  textAlign(CENTER, CENTER)
  if (mouseIsPressed) {
    pan.x += mouseX - pmouseX
    pan.y += mouseY - pmouseY
  }
  translate(pan)
  scale(2 ** (zoom/12))
  strokeWeight(2 ** (-zoom/12))
  drawFull(width/2, height/2, 16, 0)
  time += deltaTime / 1000 * (keyIsDown(32)?125:25) * (2 ** (-zoom/12))
  resetMatrix()
  strokeWeight(1)
  fill(0)
  noStroke()
  {
    textAlign(RIGHT, BOTTOM)
    textSize(10)
    let d = time / 60
    let m = d / 30; d %= 30
    let y = m / 12; m %= 12
    let c = y / 1000; y %= 1000
    text(`epoch ${floor(c)}, ${('00' + floor(y)).slice(-3)}-${('0' + floor(m+1)).slice(-2)}-${('0' + floor(d+1)).slice(-2)}`, width, height)
  }
}
function mouseWheel(event) {
  let oldzoom = zoom
  if (event.delta > 0) {
    zoom--
  } else {
    zoom++
  }
  pan.x = (pan.x - mouseX) * (2 ** ((zoom-oldzoom)/12)) + mouseX
  pan.y = (pan.y - mouseY) * (2 ** ((zoom-oldzoom)/12)) + mouseY
}

let fibs = [1, 1]
{
  while (fibs.length < 30) {
    fibs[fibs.length] = fibs[fibs.length-1] + fibs[fibs.length-2]
  }
}

function drawFull(x, y, size, evt) {
  let mass = fibs[size]
  fill(255)
  stroke(0)
  circle(x, y, (mass ** (1/2)) * 4)
  for (let i = floor(size/2)+1; i <= size - 2; i++) {
    drawOrbit(x, y, i, i-2, evt + (mass / fibs[i]) ** 0.5)
  }
  fill(0)
  noStroke()
  textSize(sqrt(fibs[size] + 10) * 4 * 1.2 ** (-zoom/12))
  let ev = mass ** (1/2-1/6)
  text(round((evt + ev) * 4), x, y)
}
function drawOrbit(x, y, distance, size, evt) {
  let r = fibs[distance] * 5
  let period = (fibs[distance] / fibs[12]) ** 1.5 * 14400
  let t = ((time / period)%1 + random())*PI*2 * (random()<0.01?-1:1)
  let sections = fibs[distance+1]
  noFill()
  stroke(0)
  
  let dashes = sections / 1
  for (let i = 0; i < dashes; i ++) {
    arc(x, y, r * 2, r * 2, (i-0.25)/dashes*2*PI+t, (i+0.25)/dashes*2*PI+t, OPEN)
  }
  
  let z = 0
  let a = 0
  while (a < sections) {
    let sub = floor(random(size)) + 1
    let inc = fibs[sub+1]
    while (sub > 1 && a + inc >= sections) {
      sub --
      inc = fibs[sub+1]
    }
    if (random() > 0.1) {
      drawFull(x + r * cos((a + inc/2)/sections*PI*2+t), y + r * sin((a + inc/2)/sections*PI*2+t), sub, evt)
    }
    a += inc
  }
  
  fill(0)
  noStroke()
  textSize(sqrt(evt) * 4 * 1.2 ** (-zoom/12))
  text(round(evt*4), x + r, y)
}

(Originally seen at https://editor.p5js.org/bojidar-bg/sketches/qk-1cumfp)

Experiments tagged p5 (11/85)

|← Experiments tagged wip (1/5)

Experiments on this site (11/85)