asobi

71 words · 9 groups

Reference

Every word asobi knows. Each example runs; motions move.

Shapes

§01 · 22 words

circle

Shapes
circle(radius: 10)

A filled circle.

Every shape sits with its centre at the middle of the picture, and every number can be left out.

The first number can be written without its name: circle(12) is the same as circle(radius: 12).

Lengths have no unit. Only the proportions matter, because the picture is fitted to the screen.

show circle
Open in playground
No numbers: it just works.
show circle(radius: 30)
Open in playground
A bigger one, with the number named.

See also ellipse ring colored

ellipse

Shapes
ellipse(width: 30, height: 20)

A filled ellipse, wider than it is tall.

width and height are the full size, not the radius. The first two numbers can be written without names: ellipse(40, 10).

show ellipse
Open in playground
show ellipse(width: 12, height: 40)
Open in playground

See also circle rect

triangle

Shapes
triangle(size: 20)

A filled triangle with equal sides, pointing up.

size is the length of one side. The triangle is centred on its bounding box, so it lines up with other shapes.

show triangle
Open in playground
show triangle(size: 50).colored(:orange)
Open in playground

See also polygon star

polygon

Shapes
polygon(sides: 6, radius: 10)

A filled shape with equal sides. One corner points up.

sides must be 3 or more. radius is the distance from the centre to a corner. The first two numbers can be written without names: polygon(8, 20).

show polygon
Open in playground
A hexagon, by default.
show polygon(sides: 8, radius: 30).colored(:teal)
Open in playground

See also triangle star circle

star

Shapes
star(points: 5, radius: 10, inner: radius * 0.45)

A filled star.

points is how many tips it has. radius reaches to the tips. inner is how far in the notches go: a small inner makes a sharp star, a big one makes a fat star.

The first two numbers can be written without names: star(8, 30).

show star
Open in playground
show star(points: 8, radius: 30, inner: 24).colored(:gold)
Open in playground

See also polygon heart

text

Shapes
text(string = "asobi", size: 16, font: nil)

Letters as a picture.

A text is a picture like any other: you can colour it, repeat it, turn it and arrange it. Strings and symbols become the same picture with to_art, so "hello".to_art is text("hello").

size is the height of the letters. font is the name of a font, such as "serif". Leave it out to use the page's usual font.

show text
Open in playground
No arguments: the word "asobi".
show text("hello", size: 40, font: "serif").colored(:navy)
Open in playground

See also to_art

path

Shapes
path(*points, closed: false, smooth: false)

Joins points, in order, with a line.

Each point is [x, y]. x grows to the right and y grows downwards, like on a screen, so [40, -30] is to the right and up.

An open path is a black line. With closed: true the last point joins the first and the shape is filled. With smooth: true the corners become a smooth curve.

The path is centred on its own bounding box, so it lines up with other shapes. With no points, you get a small example line.

show path
Open in playground
show path([0, 0], [40, -60], [80, 0], [120, -60], smooth: true).outlined(:crimson, width: 3)
Open in playground
show path([0, 0], [40, -60], [80, 0], closed: true).colored(:orange)
Open in playground

See also line arc wave

arc

Shapes
arc(radius: 20, from: 0, to: 180)

A piece of a circle, drawn as a line.

Angles are degrees, clockwise. 0 is straight up, so from: 0, to: 180 is the right half.

The arc is centred on the middle of its circle, so arcs of the same circle line up.

show arc(radius: 30, from: 90, to: 360).outlined(:navy, width: 5)
Open in playground

See also wave path ring

wave

Shapes
wave(length: 100, height: 10, waves: 3)

A smooth wavy line.

waves is how many full ups and downs fit in length. height is measured from the top of a crest to the bottom of a trough.

show wave
Open in playground
show wave(length: 120, height: 20, waves: 5).outlined(:teal, width: 3)
Open in playground

See also line path arc

ring

Shapes
ring(radius: 20, thickness: 4)

A doughnut. The hole is really a hole.

thickness is the width of the band, measured inwards from radius. What is behind the ring shows through the hole.

show ring
Open in playground
show ring(radius: 40, thickness: 12).colored(:crimson)
Open in playground

See also circle arc

petal

Shapes
petal(length: 20, width: 10)

A leaf shape that starts at the centre and grows straight up.

Unlike the other shapes, a petal is not centred: its base is at the centre of the picture. That is on purpose. Rotate copies of it around the centre and you get a flower:

petal.repeat(8).in_fan

show petal
Open in playground
show petal(length: 40, width: 16).repeat(8).in_fan.colored(:crimson, :navy)
Open in playground
A flower.

See also in_fan repeat

moon

Shapes
moon(size: 20)

A crescent moon, opening to the right.

size is the height of the moon. Use mirror to open it to the left.

show moon.colored(:gold)
Open in playground
show moon(size: 60).mirror.colored(:ivory), on: :midnightblue
Open in playground

See also star mirror

drop

Shapes
drop(size: 20)

A water drop, with its point up.

size is the height of the drop.

show drop.colored(:deepskyblue)
Open in playground
show drop(size: 50).colored(:steelblue).flip
Open in playground

See also heart circle

cloud

Shapes
cloud(size: 30)

A soft cloud with a flat bottom.

size is the width of the cloud.

show cloud.colored(:lightsteelblue)
Open in playground
show cloud(size: 80).colored(:white), on: :skyblue
Open in playground

See also drop circle

nothing

Shapes
nothing

The empty picture.

It has no size and takes up no room. It is handy inside change_each, to leave some pictures out. nil and 0 also become nothing with to_art.

dots = circle(8).repeat(9).in_row(gap: 4)
show dots.change_each { |dot, t, i| i.even? ? dot : nothing }
Open in playground

See also space change_each

hsl

Shapes
hsl(hue = 0, saturation = 70, lightness = 50)

A colour made from hue, saturation and lightness.

hue is an angle from 0 to 360 (0 is red, 120 is green, 240 is blue). saturation and lightness go from 0 to 100.

Use it anywhere a colour is expected. It is the easiest way to make a rainbow.

show circle(30).colored(hsl(200))
Open in playground
dots = circle(8).repeat(12).change_each { |dot, t| dot.colored(hsl(t * 360, 80, 55)) }
show dots.in_ring
Open in playground
t goes from 0 up to 1, so the hue goes once round.

See also gray colored change_each

gray

Shapes
gray(lightness = 50)

A gray: 0 is black and 100 is white.

Use it anywhere a colour is expected.

show circle(30).colored(gray(30))
Open in playground
squares = square(24).repeat(5).change_each { |s, t| s.colored(gray(t * 100)) }
show squares.in_row.stroke(:black)
Open in playground
Five grays from black towards white.

See also hsl colored

Combine

§02 · 7 words

on

Combine
a.on(b)

Put a on top of b.

The result is again one picture. a is in front.

b can be anything that can become a picture, such as a number. If either one is a motion, the result is a motion.

show circle(8).colored(:gold).on(circle(20).colored(:navy))
Open in playground
show star(radius: 20).colored(:gold).on(30)
Open in playground
30 is a picture too: a circle of radius 30.

See also under +

under

Combine
a.under(b)

Put b on top of a.

The opposite of on: what you write later is in front. a + b means the same.

show circle(20).colored(:navy).under(circle(8).colored(:gold))
Open in playground

See also on +

+

Combine
a + b

Put pictures on top of each other. What you write later is in front.

The same as a.under(b). It is one of the only two symbols in asobi (the other is *).

sun = circle(30).colored(:gold)
show sun + circle(14).colored(:orange) + circle(5).colored(:crimson)
Open in playground

See also on under *

repeat

Combine
repeat(count = 2)

Make copies of a picture.

The copies are all in the same place, so you cannot see the difference yet. Arrange them with in_row, in_ring, in_fan and the other arranging words.

The result is a group of pictures (a Many): one picture that is also a list. a * 12 is the same as a.repeat(12).

show circle.repeat(5).in_row
Open in playground
Five circles in a row.
show star.repeat(times: 7).in_ring(radius: 40)
Open in playground

See also * in_row in_ring

*

Combine
a * count

Make copies of a picture, like repeat.

circle * 12 is circle.repeat(12). It is one of the only two symbols in asobi (the other is +).

hearts = heart * 6
show hearts.in_row(gap: 4).colored(:crimson)
Open in playground

See also repeat +

beside

Combine
a.beside(b, gap: 0)

Put b to the right of a.

The result is one picture, centred as a whole. gap is the space between them.

show circle.beside(square)
Open in playground
show circle.colored(:crimson).beside(square.colored(:navy), gap: 8).beside(star)
Open in playground

See also above in_row space

above

Combine
a.above(b, gap: 0)

Put b under a, so that a is on top.

The result is one picture, centred as a whole. gap is the space between them.

show circle.above(square)
Open in playground
show text("asobi", size: 24).above(wave(60, 6, 3), gap: 6)
Open in playground

See also beside in_column

Change

§03 · 7 words

move

Change
move(right: 0, left: 0, up: 0, down: 0)

Move a picture.

Say where to, not how to count: right, left, up, down. You never think about which way y goes.

A picture alone on the screen is always fitted to the middle, so moving it by itself shows nothing. Moving matters when there is something else to compare with, or when you will turn it around the centre (see rotate).

show square(40).colored(:gold) + circle(8).colored(:navy).move(right: 20, up: 20)
Open in playground
show circle(6).repeat(3).change_each { |dot, t, i| dot.move(right: i * 20, down: i * 10) }
Open in playground

See also rotate scale

rotate

Change
rotate(degrees = 45)

Turn a picture clockwise.

Angles are degrees. rotate(90) is a quarter turn. To write a turn, use 0.25.turn, which is 90.0.

Turning happens around the centre of the picture, the point where a fresh shape sits. So if you move a shape off the centre first and then rotate it, it swings around the centre. That is how petal and in_fan make a flower.

show rect(50, 10).rotate(30)
Open in playground
stick = rect(50, 8).repeat(6).change_each { |r, t| r.rotate(t * 180) }
show stick.colored(:teal).opacity(0.6)
Open in playground

See also move in_fan turn

scale

Change
scale(factor = 2, width: factor, height: factor)

Make a picture bigger or smaller.

scale(2) makes it twice as big, scale(0.5) half as big. To stretch one way only, name the direction: scale(width: 2, height: 1). A negative number flips the picture over.

grow and shrink say the same thing in words.

show circle.scale
Open in playground
No number: twice as big.
show circle(20).scale(width: 2, height: 0.5).colored(:orange)
Open in playground

See also grow shrink mirror

mirror

Change
mirror

Swap left and right.

Mirroring happens around the centre of the picture.

leaf = petal.rotate(30)
show leaf.beside(leaf.mirror)
Open in playground

See also flip scale

flip

Change
flip

Swap top and bottom.

Flipping happens around the centre of the picture.

show petal.beside(petal.flip)
Open in playground

See also mirror scale

Colour

§04 · 4 words

colored

Colour
colored(*colors, from: nil, to: nil, angle: 0, around: false)

Paint a picture, with one colour, several, or a gradient.

A colour is a CSS colour name as a symbol (:crimson, :navy, :skyblue), a string such as "#ff0066", or the result of hsl or gray. With no colour at all you get :crimson.

Give a group of pictures several colours and they are used in turn, round and round: petal.repeat(8).in_fan.colored(:crimson, :navy). A single picture takes the first colour.

Pictures are black by default, on a white page. If you paint the same picture twice, the later colour wins. A colour given to a whole group does not overwrite colours given to pictures inside it.

For a gradient, name where it starts and where it ends: colored(from: :gold, to: :crimson). It runs from the top to the bottom. angle: turns the direction, in degrees clockwise: angle: 90 runs from the right to the left. around: true runs from the centre outwards. If you leave out from, it starts at crimson; if you leave out to, it ends at navy.

On a group, the gradient flows once across the whole group, not once per picture. The colours inside the group give way to it. The gradient belongs to the picture: move it, turn it or resize it, and the gradient goes along.

show heart.colored
Open in playground
No colour: crimson.
show square(20).repeat(6).in_row(gap: 4).colored(:gold, :teal, :crimson)
Open in playground
show circle(40).colored(from: :gold, to: :crimson)
Open in playground
A gradient, top to bottom: a sunset.
show circle(40).colored(from: :white, to: :navy, around: true)
Open in playground
around: true goes from the centre outwards.
dots = circle(8).repeat(12).in_row(gap: 4)
show dots.colored(from: :gold, to: :crimson, angle: 90)
Open in playground
Across a whole group, once. angle: 90 runs from right to left.

See also outlined stroke opacity hsl shadowed glowing

opacity

Colour
opacity(value = 0.5)

Make a picture see-through.

0 is invisible and 1 is solid. Overlapping see-through pictures mix their colours.

show circle(20).colored(:navy) + circle(20).colored(:crimson).opacity.move(right: 16)
Open in playground
show circle(20).colored(:navy) + circle(20).colored(:crimson).opacity(0.2).move(right: 16)
Open in playground

See also colored fade blended

Effects

§05 · 5 words

glowing

Effects
glowing(size: 4, color: nil)

Make the edges glow.

The glow is the picture's own colour, blurred and spread outwards. Give color: to glow in another colour. size is in the same units as the picture. You can write it without its name: glowing(8).

A glow needs a dark page to show: use on: :black or a dark blue. On white paper there is nothing to glow against.

The glow spills outside the picture, and the picture is fitted to the screen with the spill included. All the effect words work on motions too.

petals = petal(40, 16).repeat(8).in_fan.colored(:hotpink, :gold)
show petals.glowing, on: :black
Open in playground
show star(radius: 30).colored(:white).glowing(size: 12, color: :orange), on: :black
Open in playground
A white star with an orange glow.

See also blurred blended shadowed trail

blurred

Effects
blurred(amount: 2)

Blur a picture.

amount is in the same units as the picture. You can write it without its name: blurred(6).

The blur spills outside the picture, and the picture is fitted to the screen with the spill included. A big blur on a few shapes makes soft light, like an aurora.

show circle(30).colored(:crimson).blurred, on: :black
Open in playground
show star(radius: 30).colored(:gold).blurred(amount: 5), on: :navy
Open in playground

See also glowing blended

blended

Effects
blended(mode = :screen)

Choose how a picture mixes with what is under it.

Without a name, you get :screen: where pictures overlap, the colours get lighter, like lights shining on a wall. The other modes are :multiply (darker, like inks), :overlay, :lighten, :darken, :difference and :normal (no mixing).

blended changes how a picture mixes with what is under it. So it shows only when something is underneath, and the page colour counts: :screen on a white page does nothing, because white is already as light as it gets. Use :screen on a dark page and :multiply on a light one.

A wrong mode name gets an error that lists the right ones.

red = circle(30).colored(:crimson).move(left: 14)
blue = circle(30).colored(:dodgerblue).move(right: 14)
show red.blended + blue.blended, on: :black
Open in playground
Screen: where the circles overlap, the light adds up.
yellow = circle(30).colored(:gold).move(left: 14)
cyan = circle(30).colored(:deepskyblue).move(right: 14)
show yellow + cyan.blended(:multiply)
Open in playground
Multiply on white paper: where they overlap, the inks mix to green.

See also glowing blurred trail opacity

shadowed

Effects
shadowed(down: 2, right: 0, blur: 3, color: :black, opacity: 0.4)

Drop a soft shadow under a picture.

down and right say where the shadow falls, blur how soft it is, and opacity how dark. The first number can be written without its name: shadowed(6) is shadowed(down: 6). Sizes are in the same units as the picture.

A shadow needs a light page to show. It makes pictures look like cut-out paper lying on top of each other.

show star(radius: 30).colored(:tomato).shadowed, on: :linen
Open in playground
show star(radius: 30).colored(:tomato).shadowed(down: 8, right: 6, blur: 6, opacity: 0.5), on: :linen
Open in playground

See also colored glowing clipped_by

clipped_by

Effects
clipped_by(shape = nil)

Show a picture only through the window of a shape.

The shape is used where it is, so you can move it to choose which part shows. A number works as a round window: clipped_by(8) is clipped_by(circle(8)). With nothing, you get a round window, a bit smaller than the picture.

The shape can be anything that becomes a picture, even your own class. Combine it with a pattern, a gradient or a motion and the picture shows through the shape.

stripes = rect(10, 80).repeat(10).in_row.colored(:crimson, :gold)
show stripes.clipped_by
Open in playground
No shape: a round window.
stripes = rect(10, 80).repeat(10).in_row.colored(:crimson, :gold)
show stripes.clipped_by(heart(60))
Open in playground
show wave(120, 20, 4).outlined(:white, width: 8).clipped_by(circle(40)), on: :navy
Open in playground

See also colored shadowed circle

Arrange

§06 · 8 words

in_row

Arrange
in_row(gap: 0)

Put a group in a row, left to right.

gap is the space between neighbours. The whole row is centred.

Arranging words work on a group of pictures, which you get from repeat or from an array's to_art. They also work on one picture alone.

show circle.repeat(5).in_row
Open in playground
show star.repeat(5).in_row(gap: 6).colored(:gold)
Open in playground

See also in_column in_grid beside

in_column

Arrange
in_column(gap: 0)

Put a group in a column, top to bottom.

gap is the space between neighbours. The whole column is centred.

show circle.repeat(4).in_column
Open in playground
show rect(40, 8).repeat(4).in_column(gap: 6).colored(:teal)
Open in playground

See also in_row in_grid above

in_grid

Arrange
in_grid(columns: nil, gap: 0)

Put a group in a table, filled row by row.

Without columns, the table is about as wide as it is tall. gap is the space between cells.

Every cell is as big as the biggest picture. You can write the number of columns without its name: in_grid(4).

show square.repeat(9).in_grid
Open in playground
show circle(8).repeat(20).in_grid(columns: 5, gap: 4).colored(:crimson, :navy)
Open in playground

See also in_row in_column change_each

in_ring

Arrange
in_ring(radius: nil, facing_out: false)

Put a group evenly round a circle, clockwise from the top.

Without radius, the circle is just big enough that neighbours do not touch. With facing_out: true, each picture turns so that its top points away from the centre.

You can write the radius without its name: in_ring(60). Even one picture can go on a ring: it sits at the top.

show circle(5).repeat(12).in_ring
Open in playground
show triangle(14).repeat(10).in_ring(radius: 40, facing_out: true).colored(:orange)
Open in playground

See also in_fan in_spiral orbit

in_fan

Arrange
in_fan(over: 360)

Turn each picture a little more than the one before, around the centre.

Made for petals: a picture that sits off the centre, copied and fanned out, is a flower.

over is how many degrees the fan covers. With a full 360 the pictures go all the way round. With less, they spread evenly and the fan is centred on straight up.

show petal.repeat(8).in_fan
Open in playground
show petal(50, 8).repeat(7).in_fan(over: 120).colored(:teal)
Open in playground
A fan of 120 degrees.

See also petal in_ring rotate

in_spiral

Arrange
in_spiral(spacing: nil)

Put a group in a sunflower-seed spiral, from the centre outwards.

Each picture is turned by the golden angle from the one before, and moves a little further out. Without spacing, it is the size of the biggest picture.

You can write it without its name: in_spiral(8).

show circle(3).repeat(100).in_spiral
Open in playground
show circle(2).repeat(200).in_spiral(spacing: 5).colored(:gold, :orange)
Open in playground

See also in_ring in_grid

scattered

Arrange
scattered(over: nil, seed: nil)

Put a group in random places.

Without over, the area is chosen from how many pictures there are and how big they are. over: 200 is a 200 by 200 square. over: [300, 100] is 300 wide and 100 tall. The area is centred.

Each run looks different. But while the live view is running, it stays put: saving the file again does not shuffle the pictures. Write seed: 7 (any whole number) to get the same picture every time, on every machine.

show circle(3).repeat(30).scattered
Open in playground
show star(radius: 4).repeat(40).scattered(over: [200, 100], seed: 7).colored(:gold), on: :midnightblue
Open in playground

See also in_grid in_spiral

change_each

Arrange
change_each { |one, t, i| ... }

Change the pictures of a group one at a time.

The block gets each picture (one), how far along it is (t: 0.0 for the first, creeping up towards 1.0 for the last) and its number (i, from 0). It answers the changed picture.

The pictures stay where they are, so change_each can come before or after the arranging words. One thing to know: moving, turning and scaling happen around the centre of the whole picture. If you want each picture to turn or grow around itself, do it before arranging, as in the example.

dots = circle(6).repeat(10).change_each { |dot, t| dot.grow(to: 1 + t * 2) }
show dots.in_row(gap: 4)
Open in playground
tiles = square(18).repeat(25).change_each { |s, t, i| s.rotate(t * 90).colored(i.even? ? :tomato : :navy) }
show tiles.in_grid(5, gap: 4)
Open in playground

See also in_grid nothing hsl

Objects as pictures

§07 · 1 words

to_art

Objects as pictures
to_art(as: nil)

Ask any object to become a picture.

This is the heart of asobi: treat objects as pictures, and pictures as objects.

What each thing becomes:

A number is a circle of that radius. A negative number is the same circle, as a line only. 0 is nothing.

With as: you hand over the shape, and the number says how big it should be (half of its larger side). 8.to_art(as: star) is a star of radius 8.

An array or a range turns each item into a picture and puts them in a row, with a small gap. as: goes to every item. An array of arrays is a table: each inner array is a row. A string or a symbol is its letters, like text. A hash makes one row per pair: the key's picture beside the value's picture. nil is nothing.

An array that holds something in motion becomes a motion.

You do not need to call to_art yourself to show things: show and the words on, under, beside and above ask for it for you.

Your own class only has to write a to_art method (see the last example). Add include Asobi::Art to the class when you want to call picture words directly on its objects, such as planet.rotate(20). This is like Enumerable, which asks only for each.

show 20.to_art
Open in playground
A number: a circle.
show [3, 6, 9, -12, 0, 12].to_art
Open in playground
An array: a row. A negative number is only a line. Zero is empty.
show [1, 2, 3, 5, 8].to_art(as: star).colored(:gold, :orange), on: :black
Open in playground
as: gives the shape; the numbers give the sizes.
hearts = (1..5).to_art(as: heart)
show hearts.colored(:crimson)
Open in playground
A range works like an array.
show [[1, 2, 3], [4, 5, 6], [7, 8, 9]].to_art(as: square).colored(:teal, :navy)
Open in playground
An array of arrays: a table.
show "asobi".chars.to_art.colored(:crimson, :navy)
Open in playground
A string: its letters. Here, split into one picture per letter.
show({ 3 => 12, 5 => 6 }.to_art.colored(:teal))
Open in playground
A hash: one row for each key and value.
class Planet
  def initialize(size, color)
    @size = size
    @color = color
  end

  def to_art
    circle(@size).colored(@color)
  end
end

show [Planet.new(6, :tomato), Planet.new(10, :gold), Planet.new(4, :skyblue)].to_art
Open in playground
Your own class: write to_art, and arrays and show can use it.
class Planet
  include Asobi::Art

  def initialize(size, color)
    @size = size
    @color = color
  end

  def to_art
    circle(@size).colored(@color)
  end
end

show Planet.new(10, :gold).spin(every: 4).move(right: 20).on(40)
Open in playground
With include Asobi::Art, picture words work on the object itself.

See also text repeat orbit

Motion

§08 · 12 words

spin

Motion
spin(every: 4, clockwise: true)

Turn round and round.

every is the seconds for one full turn. With clockwise: false it turns the other way.

A motion is a function from time to a picture. It has no frame counter and no memory, so the same moment is always the same picture. Motion words can follow each other: flower.spin(every: 8).pulse(every: 1). All the picture words work on a motion too: flower.spin.colored(:crimson).

The loop length of a combination is the least common multiple of the parts (or the longest part, if that would be more than a minute).

show star.spin
Open in playground
show star(radius: 30).spin(every: 2, clockwise: false).colored(:gold)
Open in playground
flower = petal(40, 16).repeat(8).in_fan.colored(:crimson, :navy)
show flower.spin(every: 8).pulse(every: 1)
Open in playground
Two motion words, one after the other.

See also pulse sway orbit one_by_one trail

pulse

Motion
pulse(every: 1, to: 1.2)

Swell up and come back.

to is how big it gets, as a multiple (to: 2 is twice as big). every is the seconds for one pulse. You can write every without its name: pulse(2).

show heart.colored(:crimson).pulse
Open in playground
show heart(40).colored(:crimson).pulse(every: 0.8, to: 1.5)
Open in playground

See also spin fade one_by_one

sway

Motion
sway(every: 2, by: 10)

Rock to one side and the other.

by is how many degrees it rocks each way. every is the seconds for one swing there and back.

It rocks around the centre of the picture. To make something hang from a point, put that point at the centre: petal.flip.sway swings like a bell.

show petal(40, 16).flip.colored(:teal).sway
Open in playground
show petal(40, 16).repeat(3).in_fan(over: 90).colored(:crimson).sway(every: 3, by: 20)
Open in playground

See also spin bounce

orbit

Motion
orbit(radius: nil, every: 4)

Go round a circle.

The picture itself does not turn. It travels round a circle of radius, clockwise, starting from the top. Without radius, the circle is as big as the picture's larger side.

You can write the radius without its name: orbit(40).

show circle(5).colored(:crimson).orbit
Open in playground
show circle(10).colored(:gold) + circle(4).colored(:skyblue).orbit(radius: 30, every: 3), on: :black
Open in playground

See also spin in_ring drift trail

fade

Motion
fade(every: 2, to: 0.2)

Fade out and come back.

to is how faint it gets: 0 is invisible and 1 does nothing.

show circle(20).colored(:navy).fade
Open in playground
show star(radius: 20).repeat(6).in_ring.colored(:gold).fade(every: 3, to: 0).one_by_one, on: :black
Open in playground

See also opacity pulse one_by_one

bounce

Motion
bounce(height: 20, every: 1)

Jump up and fall back, like a ball.

height is how high it jumps. It is slow at the top and fast near the ground. You can write the height without its name: bounce(40).

show circle(8).colored(:tomato).bounce
Open in playground
show circle(6).repeat(10).in_row(gap: 4).colored(:teal).bounce(height: 30, every: 2).one_by_one
Open in playground

See also drift one_by_one

drift

Motion
drift(right: nil, left: nil, up: nil, down: nil, every: 4)

Go somewhere and come back, smoothly.

Name the way, like move: drift(right: 40). With nothing named, it drifts to the right by the width of the picture.

show circle.colored(:orange).drift
Open in playground
show square(20).colored(:navy).drift(right: 30, up: 20, every: 3)
Open in playground

See also orbit bounce move

shift_color

Motion
shift_color(from: nil, to: :crimson, every: 4)

Slowly change colour and come back.

Give it two colours, shift_color(:navy, :gold), to go from the first to the second and back. Give it one colour, shift_color(:gold), to go from black to that colour. With nothing, it goes from black to crimson.

You can also name them: shift_color(from: :navy, to: :gold, every: 6).

show circle(20).shift_color
Open in playground
show heart(40).shift_color(:navy, :hotpink, every: 3)
Open in playground

See also colored hsl one_by_one

one_by_one

Motion
one_by_one(gap: nil)

Make a group move one at a time, instead of all together.

Write it right after a motion word (spin, pulse, bounce and so on) on a group of pictures. Each picture does the motion a little after the one before. By default, the loop is shared out evenly, and that makes a wave.

gap is the seconds between one picture and the next. Each picture does the motion around its own centre, so a ring of dots that pulses one by one stays a ring.

one_by_one belongs right after the motion word it staggers. If you stagger two motions, write it after each of them, as in the hearts example below: one for the colour, one for the bounce.

show circle(6).repeat(12).in_ring(40).colored(:crimson).pulse(every: 1.5, to: 1.8).one_by_one
Open in playground
show circle(5).repeat(16).in_row(gap: 5).colored(:teal).bounce(height: 20, every: 2).one_by_one(gap: 0.1)
Open in playground
hearts = heart(20).repeat(5).in_row(gap: 6)
show hearts.shift_color(:crimson, :orchid).one_by_one.bounce(height: 24).one_by_one
Open in playground
Two motions, so two one_by_one: one right after shift_color, one right after bounce.

See also pulse bounce fade spin

trail

Motion
trail(count: 5, gap: nil)

Leave fading copies of earlier moments behind a moving picture.

The copies come from gap seconds earlier, then twice that, and so on, each fainter than the last, drawn underneath. Without gap it is a short moment, which looks good. count is how many copies. You can write it without its name: trail(10).

On a still picture it does nothing: there is no earlier moment. Each copy is a whole picture, so a big picture with a long trail makes a heavy animation.

show circle(5).colored(:gold).orbit(30).trail, on: :black
Open in playground
show circle(5).colored(:hotpink).orbit(radius: 30, every: 3).trail(count: 12).glowing, on: :black
Open in playground
A long trail, with a glow.

See also glowing blended orbit spin

animate

Motion
animate(seconds = 4) { |picture, t| ... }

Make your own motion.

The block gets the picture and t, which runs from 0.0 up to (not including) 1.0 and then starts again, once every seconds seconds. It answers the picture for that moment.

Use the other words inside the block. Anything they can do, your motion can do.

show star.animate(4) { |picture, t| picture.rotate(t * 360).grow(to: 1 + t) }
Open in playground
dots = circle(5).repeat(8).in_ring(30)
show dots.animate(3) { |ring, t| ring.change_each { |dot, u| dot.colored(hsl((t + u) * 360)) } }
Open in playground
Colours run round the ring.

See also spin at hsl

at

Motion
at(seconds = 0)

The picture a motion shows at one moment. Also: every, frames.

motion.at(1.5) is the still picture 1.5 seconds in. Time is in seconds, and it repeats: a motion with every of 4 shows the same picture at 0.5 and at 4.5.

motion.every is how many seconds one loop takes. motion.frames(fps: 30) is one loop as a lazy list of pictures, at 30 pictures a second.

You never need them to show a motion: just show it.

show circle(5).colored(:crimson).orbit(radius: 30, every: 4).at(1)
Open in playground
One moment: a quarter of the way round.
trail = circle(3).colored(:navy).orbit(radius: 30, every: 4).frames(fps: 6)
show trail.reduce(:+)
Open in playground
Every frame on top of each other draws the path.

See also animate spin

Show

§09 · 5 words

show

Show
show(picture, on: :white, paper: nil, grain: nil)

Show a picture (or a motion) on screen.

The picture is fitted to the screen, so you never have to think about the size of the window.

on: is the background colour. paper: [800, 800] shows a paper of that size (width and height) with the picture in the middle; anything that sticks out is cut off.

grain: lays a fine film grain over the whole picture, like paper or old film. grain: true is a gentle grain (0.12), and a number from 0 to 1 sets the strength: grain: 0.3. It belongs to the way the picture is shown, not to the picture, so it covers everything, background included.

If you call show several times, the last one is what appears.

Run a sketch with ruby flower.rb or asobi flower.rb and a browser opens. Save the file, and the picture changes. Press Ctrl-C to stop. A mistake in your code does not close anything: the last good picture stays, and the error is written below it, with a hint.

Move the mouse and small controls appear at the edge for a few seconds. Press c to lay the code over the picture, and r to start and stop recording a video (the browser saves the file).

show star(radius: 30).colored(:gold)
Open in playground
show star(radius: 30).colored(:gold), on: :midnightblue
Open in playground
A background colour.
show circle(40).colored(:crimson), paper: [300, 200]
Open in playground
A 300 by 200 paper. The circle is cut off at the edge.
show star(radius: 30).colored(:gold).glowing, on: :black, grain: true
Open in playground
A film grain over everything. Try grain: 0.3 for a rougher one.

See also save bounds

save

Show
save(path, on: :white, paper: nil, grain: nil)

Write a picture to a file.

A still picture goes to an SVG file: flower.save("flower.svg"). A motion goes to an HTML page that plays by itself in any browser: flower.spin.save("flower.html"). Both accept on:, paper: and grain: as show does: flower.save("flower.svg", grain: true).

To get one moment of a motion as SVG, ask for it with at: flower.spin.at(1).save("still.svg").

flower = petal(40, 16).repeat(8).in_fan.colored(:crimson, :navy)

# Remove the "#" to write the file:
# flower.save("flower.svg")

show flower
Open in playground
The line starting with # is a comment; Ruby skips it.

See also show at to_svg

to_svg

Show
to_svg(on: :white, paper: nil)

The picture as SVG text.

It answers a string. save("x.svg") writes the same text to a file. It works on still pictures. For a motion, take a moment with at first.

svg = circle(10).colored(:crimson).to_svg
show text("#{svg.length} characters of SVG", size: 8)
Open in playground

See also save at

bounds

Show
bounds, width, height

Measure a picture.

width and height are the size of the smallest box around the picture. bounds is that box, with x0, y0, x1 and y1. For a motion, they cover everything it shows over one loop.

shape = star(radius: 20)
show text("#{shape.width.round(1)} x #{shape.height.round(1)}", size: 12)
Open in playground

See also show save

turn

Show
turn

An angle written as a number of turns.

Angles in asobi are degrees, clockwise. 0.25.turn is 90.0, so rotate(0.25.turn) is a quarter turn. turns means the same: 2.turns is 720.0.

show rect(50, 10).colored(:navy).on(rect(50, 10).colored(:crimson).rotate(0.25.turn))
Open in playground

See also rotate spin