DZone Snippets is a public source code repository. Easily build up your personal collection of code snippets, categorize them with tags / keywords, and share them with the world

Snippets has posted 5883 posts at DZone. View Full User Profile

Spirograph Demo

  • submit to reddit
    Title:  "Simple Spirograph"
    Author: "Gregg Irwin"

    Comment: {
        Set max number of lines
        Generate random start point and velocity
        at each iteration
            for each set
                calculate next set of end-points from previous end-points
                append line command to draw effect, wrap if at max-lines

            Allow for multiple line "sets".
            Figure out why it's so slow for large canvases.
            Use color-shifting lines, rather than restarting with a new color.

num-lines: 30   ; change this for longer, or shorter, line sets.
end-points: make block! 128
pt-1: pt-2: 0x0
delta-1: delta-2: 0x0
direction-1: direction-2: 'SE
color: 0.0.0

directions: [
    SE   1x1
    NW  -1x-1
    NE   1x-1
    SW  -1x1

initialize: func [
    "Initialize starting coordinates, directions, and colors."
    i [integer!]
    random/seed now
    ; Starting locations for line end points
    pt-1: random face/size
    pt-2: random face/size
    change/only at end-points i [pt-1 pt-2]
    ; Direction of travel
    direction-1: pick [SE NW NE SW] random 4
    direction-2: pick [SE NW NE SW] random 4
    ; Angle of travel. Bigger numbers move things faster.
    ;delta-1: 2 + (random 3x3)
    ;delta-2: 2 + (random 3x3)
    delta-1: random 3x3
    delta-2: random 3x3
    ; Colors. The + 32 keeps it from being too dark.
    color: (random 200.200.200) + 32

move-points: func [face] [
    ; direction-1 = Direction of Travel for Point 1
    ; direction-2 = Direction of Travel for Point 2

    ;TBD Should be able to map these so the code isn't duped for each point.
    pt-1: pt-1 + (delta-1 * (select directions direction-1))
    switch direction-1 [
        NE [if pt-1/x > face/size/x [direction-1: 'NW]
            if pt-1/y < 1 [direction-1: 'SE]]
        SE [if pt-1/x > face/size/x [direction-1: 'SW]
            if pt-1/y > face/size/y [direction-1: 'NE]]
        SW [if pt-1/x < 1 [direction-1: 'SE]
            if pt-1/y > face/size/y [direction-1: 'NW]]
        NW [if pt-1/x < 1 [direction-1: 'NE]
            if pt-1/y < 1 [direction-1: 'SW]]

    pt-2: pt-2 + (delta-2 * (select directions direction-2))
    switch direction-2 [
        NE [if pt-2/x > face/size/x [direction-2: 'NW]
            if pt-2/y < 1 [direction-2: 'SE]]
        SE [if pt-2/x > face/size/x [direction-2: 'SW]
            if pt-2/y > face/size/y [direction-2: 'NE]]
        SW [if pt-2/x < 1 [direction-2: 'SE]
            if pt-2/y > face/size/y [direction-2: 'NW]]
        NW [if pt-2/x < 1 [direction-2: 'NE]
            if pt-2/y < 1 [direction-2: 'SW]]


do-spiro: func [
    max-interval [time!]
    /local i t interval
    i: j: 0
    t: now/time/precise
    interval: 0:0:3 + random max-interval
    initialize face i
    forever [
        if now/time/precise > (t + interval) [
            clear draw-cmds
            interval: 0:0:3 + random max-interval
            t: now/time/precise
            initialize face i
            wait .05

        append draw-cmds compose [pen (color) line (pt-1) (pt-2)]
        ; Erase oldest line
        if (length? draw-cmds) > (num-lines * 5) [
            remove/part head draw-cmds 5

        ;print mold draw-cmds
        move-points face
        i: either i < 127 [i + 1][0]
        j: either j < 127 [j + 1][0]

        show face
        ; wait 0 isn't as system friendly as wait .001, but it's faster.
        wait 0 ;.001

lay: layout [
    origin 0x0
    backdrop black
    ; Using a larger canvas really slows things down
    ;canvas: image black 640x480
    canvas: image black 320x240
    button "go" [do-spiro canvas 0:0:10]
    button "quit" [quit]
canvas/effect: reduce ['draw draw-cmds: make block! (num-lines * 5)]

view lay
;view/offset lay 0x0