So far the world has been one object on a floor. On this last page it becomes a place: a lawn under a real sky, where the sun crosses the sky as the day passes, six lanterns along a walk that light up together at dusk, and a doorframe standing alone on the lawn that takes you, when you walk through it, down into a cellar, a second place with no sky at all. The new ideas are a design and its copies, the sky and the time of day, and scenes joined by a portal.

The whole world

The lantern's shape and materials are as on page 4. What has changed is where everything lives.

part hello                                              // the world
  field dayLength: duration = sim(24 min)               // new: a whole day passes in 24 minutes
  field latitude: angle = 45 deg                        // new: where on Earth the sky is worked out for
  field date: count = 288, within: 1 ..= 365            // new: the day of the year, 15 October
  part materials
    ...                                                 // steel, amber and stone, as on page 4
    part grass: plain(srgb(70, 105, 55))                // new

  part garden: scene                                    // new: the place you arrive in
    field lampLevel: fraction = 0, within: 0 ..= 1, mutable: true   // how lit every lantern is

    part sky: skyDome(atmosphere: preetham(turbidity: 2.5), sun: sunFace),
              at: around(camera, rotation: world)
    part sun: sunLight(direction: sunDirection(latitude: latitude, day: date, hour: hour(now(world))),
                       color: sky.sunColor, lux: sky.sunLux, castsShadow: true)
    part sunFace: sunDisc(direction: sun.direction)

    part lawn: box(x: -10 ..= 10, y: -0.1 ..= 0, z: -15 ..= 5), material: materials.grass, at: (0, 0, 0)
      solid(self, derived)

    part gardenLantern                                  // new: a design, not itself in the world
      fn frame() shape { ... }                          // as on page 3
      part body : frame(), material: materials.steel
      part glass: box(x: -0.11 ..= 0.11, y: 0.94 ..= 1.2, z: -0.11 ..= 0.11), material: materials.amber
      part lamp : pointLight(color: color(1, 0.6, 0.25), source: 2 cm, reach: 4 m, castsShadow: true),
                  at: (0, 1.07, 0)
      derive(lamp.intensity, lampLevel * 60 candela)

    part walk, at: (0, 0, 0)                            // new: six copies, three on each side
      each k in 0 ..< 3 {
        part left[k] : gardenLantern, at: (-1.2, 0, -2 * k)
        part right[k]: gardenLantern, at: (1.2, 0, -2 * k)
      }
    derive(materials.amber.glow, lampLevel * 40 nits)

    on(created, {                                       // new: a world opened after dark is lit at once
      let h = hour(now(world));
      set(lampLevel, if h >= sky.duskHour || h < sky.dawnHour { 1 } else { 0 });
    })
    on(dusk, start(transition(lampLevel, to: 1, over: world(15 min), ease: linear,
                              from: current, begin: dusk.due)))
    on(dawn, start(transition(lampLevel, to: 0, over: world(15 min), ease: linear,
                              from: current, begin: dawn.due)))

    part door: join([box(x: -0.55 ..= -0.45, y: 0 ..= 2.1, z: -0.05 ..= 0.05),    // new: a doorframe
                     box(x: 0.45 ..= 0.55, y: 0 ..= 2.1, z: -0.05 ..= 0.05),      // standing alone
                     box(x: -0.55 ..= 0.55, y: 2 ..= 2.1, z: -0.05 ..= 0.05)]),   // on the lawn
               material: materials.steel, at: (3, 0, -2)
      part way: portal(to: cellar.arrivals.foot, passage: true, window: false,    // new: walk through it
                       mouth: box(x: -0.45 ..= 0.45, y: 0 ..= 2, z: -0.05 ..= 0.05))
    part arrivals
      part start, at: (0, 0, 3), facing: (0, 0, -1)     // at the foot of the walk, looking up it

  part cellar: scene                                    // new: a second place, with no sky
    part floor: box(x: -3 ..= 3, y: -0.1 ..= 0, z: -3 ..= 3), material: materials.stone, at: (0, 0, 0)
      solid(self, derived)
    part bulb: pointLight(color: color(1, 0.8, 0.6), reach: 6 m, castsShadow: true), at: (0, 2.2, 0)
    derive(bulb.intensity, 40 candela)
    part arrivals
      part foot, at: (0, 0, 2), facing: (0, 0, -1)

One lantern, six times: a design and its copies

part gardenLantern has no at:, so it is not itself in the world. (Every part on these pages that is in the world says where with at:, or, like the sun, is placed by a direction; parts inside a placed part stand at its middle unless they say otherwise.) It is a design: a part that other parts copy. part left[k]: gardenLantern, at: ... makes a copy of it, placed. A copy has everything the design holds (the body, the glass, the lamp and its rule), and if you change the design, every copy follows.

The copies are made by a loop. each k in 0 ..< 3 runs its lines with k as 0, 1 and 2, and each time places a lantern on each side of the walk, 2 m further away. A part made in a loop is one of a numbered family: left[0], left[1] and left[2], so the far left lantern's glass is walk.left[2].glass.

The six copies share one mesh, hydrated once and drawn six times, so copies are cheap.

The nearness of pages 2 to 4 is gone: these lanterns follow the time of day instead, and every visitor sees them lit together.

A sky, and the time of day

Until now there was nothing behind the world. The sky part draws one: a dome of sky colored by the browser's model of the day sky, preetham (named for the clear-sky formula it starts from, carried on through twilight into night), with turbidity for how hazy the air is. It is placed around(camera, ...), so it stays round you however far you walk, and you can never reach it.

The world now has a clock of its own, and the root holds where and when the sky is: latitude and date, which the sky reads by those names. now(world) is the present moment on the world's clock, hour(...) gives its hour of the day, and dayLength says a whole day passes in 24 minutes of running time. The sun's direction is worked out from the hour, the day of the year and the latitude, so the sun rises, crosses the sky and sets, and the sky's colors follow it. The sun's color and brightness come from the sky, sky.sunColor and sky.sunLux, so it is orange and faint near the horizon and white at noon. sunFace is the sun's disc as you see it, a separate part from its light.

The sky also answers when dusk and dawn are: sky.duskHour and sky.dawnHour.

All the lamps at dusk

One field, lampLevel, now says how lit every lantern is, and each lantern's lamp, and the shared amber glow, follow it. Three rules move it:

lampLevel has no lives: client, so it is one value for the whole world, the same for everyone in it.

Scenes, and a portal between them

The world now holds two scenes, garden and cellar. A scene is a separate place with its own space: the cellar's floor at (0, 0, 0) is not under the garden's, or anywhere near it. Each scene has its own light; the cellar has no sky and no sun, only one bulb. What belongs to the whole world, like dayLength and the materials, sits on the world itself, above both scenes.

The only way between scenes is a portal. The door is a steel doorframe standing on the lawn, joined from three boxes, and way, inside it, is the portal: its mouth is the opening of the frame, and walking through it takes you to cellar.arrivals.foot. Because the portal names an arrival, you land where the arrival says and face the way it says (Portals: which way you face). window: false means you cannot see the cellar through the frame: you see the lawn behind it, until you step through.

Opening the world

Opening a world with scenes works as on page 1, one scene at a time. The browser builds the garden, the scene you arrive in, and starts it. It does not build the cellar until it might be needed: as you walk toward the door, it fetches and builds the cellar, so stepping through is immediate. You arrive at the garden's start, at the foot of the walk, looking up it.

Try changing it

What you have now

Everything a small world needs. A design is made once and copied, by hand or in a loop. A sky and a sun follow the world's clock, and rules act at dusk and dawn. Scenes are separate places, joined by portals that land you at an arrival. Together with the first four pages (parts and recipes, materials, animators and rules, shaping from paths, and lights), that is the whole of the language in outline. The reference has the detail of each, for wherever you want to go next.

Still open

← Guide 4: Light it | Contents