commit
3d4268fce0
19
README.md
19
README.md
@ -2,7 +2,13 @@
|
|||||||
|
|
||||||
_"All I wanted, was a quick way of resizing a few photos.."_
|
_"All I wanted, was a quick way of resizing a few photos.."_
|
||||||
|
|
||||||
Ronin is a [LISP](https://en.wikipedia.org/wiki/Lisp_(programming_language)) repl to create generative graphics currently under development. You can follow the daily progress on [Mastodon](https://merveilles.town/@neauoire/).
|
The application was created to automate basic graphical tasks using a dialect of [LISP](https://en.wikipedia.org/wiki/Lisp_(programming_language)), it all went south when we started adding animation tools. You can look at these [example files](https://github.com/hundredrabbits/Ronin/tree/master/examples) to better understand how this all works.
|
||||||
|
|
||||||
|
```lisp
|
||||||
|
; draw a red square
|
||||||
|
(stroke
|
||||||
|
(rect 30 30 100 100) 2 "red")
|
||||||
|
```
|
||||||
|
|
||||||
## Install & Run
|
## Install & Run
|
||||||
|
|
||||||
@ -31,6 +37,7 @@ npm start
|
|||||||
- `(stroke ~shape)` Strokes a shape.
|
- `(stroke ~shape)` Strokes a shape.
|
||||||
- `(fill ~rect)` Fills a shape.
|
- `(fill ~rect)` Fills a shape.
|
||||||
- `(clear ~rect)` Clears a rect.
|
- `(clear ~rect)` Clears a rect.
|
||||||
|
- `(concat ...items)`
|
||||||
- `(add ...args)` Adds values.
|
- `(add ...args)` Adds values.
|
||||||
- `(sub ...args)` Subtracts values.
|
- `(sub ...args)` Subtracts values.
|
||||||
- `(mul ...args)` Multiplies values.
|
- `(mul ...args)` Multiplies values.
|
||||||
@ -54,7 +61,7 @@ npm start
|
|||||||
- `(or a b ...rest)` Returns true if at least one condition is true.
|
- `(or a b ...rest)` Returns true if at least one condition is true.
|
||||||
- `(map fn arr)`
|
- `(map fn arr)`
|
||||||
- `(filter fn arr)`
|
- `(filter fn arr)`
|
||||||
- `(reduce fn arr ~acc)`
|
- `(reduce fn arr acc)`
|
||||||
- `(len item)` Returns the length of a list.
|
- `(len item)` Returns the length of a list.
|
||||||
- `(first arr)` Returns the first item of a list.
|
- `(first arr)` Returns the first item of a list.
|
||||||
- `(last arr)` Returns the last
|
- `(last arr)` Returns the last
|
||||||
@ -66,7 +73,7 @@ npm start
|
|||||||
- `(frame)` Returns a rect of the frame.
|
- `(frame)` Returns a rect of the frame.
|
||||||
- `(center)` Returns a position of the center of the frame.
|
- `(center)` Returns a position of the center of the frame.
|
||||||
- `(scale rect w h)`
|
- `(scale rect w h)`
|
||||||
- `(resize w h)` Resizes the canvas to target w and h, returns the rect.
|
- `(resize w h ~fit)` Resizes the canvas to target w and h, returns the rect.
|
||||||
- `(rescale w h)` Rescales the canvas to target ratio of w and h, returns the rect.
|
- `(rescale w h)` Rescales the canvas to target ratio of w and h, returns the rect.
|
||||||
- `(crop rect)`
|
- `(crop rect)`
|
||||||
- `(clone a b)`
|
- `(clone a b)`
|
||||||
@ -78,12 +85,16 @@ npm start
|
|||||||
- `(echo ...args)`
|
- `(echo ...args)`
|
||||||
- `(str ...args)`
|
- `(str ...args)`
|
||||||
- `(open path)` Imports a graphic file and resizes the frame.
|
- `(open path)` Imports a graphic file and resizes the frame.
|
||||||
- `(folder ~path)` Returns the content of a folder path.
|
- `(dir ~path)` Returns the content of a directory.
|
||||||
|
- `(file ~path)` Returns the content of a file
|
||||||
|
- `(dirpath ~path)` Returns the path of a directory.
|
||||||
|
- `(filepath ~path)` Returns the path of a file
|
||||||
- `(exit ~force)` Exits Ronin.
|
- `(exit ~force)` Exits Ronin.
|
||||||
- `(time)` Returns timestamp in milliseconds.
|
- `(time)` Returns timestamp in milliseconds.
|
||||||
- `(animate ~play)` Toggles animation.
|
- `(animate ~play)` Toggles animation.
|
||||||
- `(js)` Javascript interop.
|
- `(js)` Javascript interop.
|
||||||
- `(test name a b)`
|
- `(test name a b)`
|
||||||
|
- `(benchmark fn)` logs time taken to execute a function
|
||||||
|
|
||||||
## Extras
|
## Extras
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ app.on('ready', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
app.win.loadURL(`file://${__dirname}/sources/index.html`)
|
app.win.loadURL(`file://${__dirname}/sources/index.html`)
|
||||||
app.inspect()
|
// app.inspect()
|
||||||
|
|
||||||
app.win.on('closed', () => {
|
app.win.on('closed', () => {
|
||||||
win = null
|
win = null
|
||||||
|
@ -45,6 +45,7 @@
|
|||||||
ronin.controller.add("default","View","Zoom Out",() => { ronin.modZoom(-0.25) },"CmdOrCtrl+-")
|
ronin.controller.add("default","View","Zoom Out",() => { ronin.modZoom(-0.25) },"CmdOrCtrl+-")
|
||||||
ronin.controller.add("default","View","Zoom Reset",() => { ronin.modZoom(1,true) },"CmdOrCtrl+0")
|
ronin.controller.add("default","View","Zoom Reset",() => { ronin.modZoom(1,true) },"CmdOrCtrl+0")
|
||||||
ronin.controller.add("default","View","Toggle Commander",() => { ronin.commander.toggle(); },"CmdOrCtrl+K");
|
ronin.controller.add("default","View","Toggle Commander",() => { ronin.commander.toggle(); },"CmdOrCtrl+K");
|
||||||
|
ronin.controller.add("default","View","Expand Commander",() => { ronin.commander.toggle(true); },"CmdOrCtrl+Shift+K");
|
||||||
ronin.controller.add("default","Project","Run",() => { ronin.commander.run(); },"CmdOrCtrl+R");
|
ronin.controller.add("default","Project","Run",() => { ronin.commander.run(); },"CmdOrCtrl+R");
|
||||||
ronin.controller.add("default","Project","Reload Run",() => { ronin.source.revert(); ronin.commander.run(); },"CmdOrCtrl+Shift+R");
|
ronin.controller.add("default","Project","Reload Run",() => { ronin.source.revert(); ronin.commander.run(); },"CmdOrCtrl+Shift+R");
|
||||||
ronin.controller.add("default","Project", "Animate",() => { ronin.animate(!ronin.always); },"CmdOrCtrl+Shift+T");
|
ronin.controller.add("default","Project", "Animate",() => { ronin.animate(!ronin.always); },"CmdOrCtrl+Shift+T");
|
||||||
|
@ -7,6 +7,7 @@ body { margin:0px; padding:0px; overflow:hidden; font-family:"input_mono_regular
|
|||||||
#ronin #wrapper #commander { z-index: 9000;position: relative;width: 310px;height: calc(100vh - 60px);-webkit-app-region: no-drag;padding-right: 30px;transition: margin-left 250ms;}
|
#ronin #wrapper #commander { z-index: 9000;position: relative;width: 310px;height: calc(100vh - 60px);-webkit-app-region: no-drag;padding-right: 30px;transition: margin-left 250ms;}
|
||||||
#ronin #wrapper #commander textarea { background: none; width: 100%; height: calc(100vh - 105px); resize: none; font-size: 12px;line-height: 15px; padding-right: 15px}
|
#ronin #wrapper #commander textarea { background: none; width: 100%; height: calc(100vh - 105px); resize: none; font-size: 12px;line-height: 15px; padding-right: 15px}
|
||||||
#ronin #wrapper #commander div#status { position: absolute; bottom: 0px; text-transform: lowercase;}
|
#ronin #wrapper #commander div#status { position: absolute; bottom: 0px; text-transform: lowercase;}
|
||||||
|
#ronin.expand #wrapper #commander { width:100%; }
|
||||||
#ronin.hidden #wrapper #commander { margin-left:-331px; }
|
#ronin.hidden #wrapper #commander { margin-left:-331px; }
|
||||||
|
|
||||||
#ronin canvas#surface,#ronin canvas#guide { position: absolute; top:0px; -webkit-user-select: none;-webkit-app-region: no-drag; background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='20' height='20'><circle cx='10' cy='10' r='1' fill='%23555'></circle></svg>"); background-size: 10px 10px; background-position: -4px -4px; width:100%; height:100%; left:340px; transition: left 250ms}
|
#ronin canvas#surface,#ronin canvas#guide { position: absolute; top:0px; -webkit-user-select: none;-webkit-app-region: no-drag; background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='20' height='20'><circle cx='10' cy='10' r='1' fill='%23555'></circle></svg>"); background-size: 10px 10px; background-position: -4px -4px; width:100%; height:100%; left:340px; transition: left 250ms}
|
||||||
|
@ -105,37 +105,43 @@ function Commander (ronin) {
|
|||||||
|
|
||||||
this.onMouseDown = (e) => {
|
this.onMouseDown = (e) => {
|
||||||
this.mouseDown = true
|
this.mouseDown = true
|
||||||
this.mouseRect.x = e.offsetX
|
const offset = this.makeMouseOffset({ x: e.offsetX, y: e.offsetY })
|
||||||
this.mouseRect.y = e.offsetY
|
this.mouseRect.x = offset.x
|
||||||
this.mouseRect.a.x = e.offsetX
|
this.mouseRect.y = offset.y
|
||||||
this.mouseRect.a.y = e.offsetY
|
this.mouseRect.a.x = offset.x
|
||||||
|
this.mouseRect.a.y = offset.y
|
||||||
this.mouseRect.t = 'pos'
|
this.mouseRect.t = 'pos'
|
||||||
this.capture()
|
this.capture()
|
||||||
this.show()
|
this.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
this.onMouseMove = (e) => {
|
this.onMouseMove = (e) => {
|
||||||
if (this.mouseDown === true) {
|
if (this.mouseDown !== true) { return }
|
||||||
this.mouseRect.w = e.offsetX - this.mouseRect.x
|
const offset = this.makeMouseOffset({ x: e.offsetX, y: e.offsetY })
|
||||||
this.mouseRect.h = e.offsetY - this.mouseRect.y
|
this.mouseRect.w = offset.x - this.mouseRect.x
|
||||||
this.mouseRect.b.x = e.offsetX
|
this.mouseRect.h = offset.y - this.mouseRect.y
|
||||||
this.mouseRect.b.y = e.offsetY
|
this.mouseRect.b.x = offset.x
|
||||||
|
this.mouseRect.b.y = offset.y
|
||||||
this.commit()
|
this.commit()
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
this.onMouseUp = (e) => {
|
this.onMouseUp = (e) => {
|
||||||
this.mouseDown = false
|
this.mouseDown = false
|
||||||
this.mouseRect.w = e.offsetX - this.mouseRect.x
|
const offset = this.makeMouseOffset({ x: e.offsetX, y: e.offsetY })
|
||||||
this.mouseRect.h = e.offsetY - this.mouseRect.y
|
this.mouseRect.w = offset.x - this.mouseRect.x
|
||||||
this.mouseRect.b.x = e.offsetX
|
this.mouseRect.h = offset.y - this.mouseRect.y
|
||||||
this.mouseRect.b.y = e.offsetY
|
this.mouseRect.b.x = offset.x
|
||||||
|
this.mouseRect.b.y = offset.y
|
||||||
this.mouseRect.t = ''
|
this.mouseRect.t = ''
|
||||||
this.commit()
|
this.commit()
|
||||||
this._input.focus()
|
this._input.focus()
|
||||||
ronin.surface.clearGuide()
|
ronin.surface.clearGuide()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.makeMouseOffset = (pos) => {
|
||||||
|
return { x: pos.x * ronin.surface.ratio, y: pos.y * ronin.surface.ratio }
|
||||||
|
}
|
||||||
|
|
||||||
// Injection
|
// Injection
|
||||||
|
|
||||||
this.cache = ''
|
this.cache = ''
|
||||||
@ -188,9 +194,9 @@ function Commander (ronin) {
|
|||||||
|
|
||||||
// Display
|
// Display
|
||||||
|
|
||||||
this.show = function () {
|
this.show = function (expand = false) {
|
||||||
if (this.isVisible === true) { return }
|
if (this.isVisible === true) { return }
|
||||||
ronin.el.className = ''
|
ronin.el.className = expand ? 'expand' : ''
|
||||||
this.isVisible = true
|
this.isVisible = true
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -200,9 +206,9 @@ function Commander (ronin) {
|
|||||||
this.isVisible = false
|
this.isVisible = false
|
||||||
}
|
}
|
||||||
|
|
||||||
this.toggle = function () {
|
this.toggle = function (expand = false) {
|
||||||
if (this.isVisible !== true) {
|
if (this.isVisible !== true) {
|
||||||
this.show()
|
this.show(expand)
|
||||||
} else {
|
} else {
|
||||||
this.hide()
|
this.hide()
|
||||||
}
|
}
|
||||||
|
@ -60,6 +60,12 @@ function Library (ronin) {
|
|||||||
return rect
|
return rect
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Strings
|
||||||
|
|
||||||
|
this.concat = function (...items) {
|
||||||
|
return items.reduce((acc, item) => { return `${acc}${item}` }, '')
|
||||||
|
}
|
||||||
|
|
||||||
// Math
|
// Math
|
||||||
|
|
||||||
this.add = (...args) => { // Adds values.
|
this.add = (...args) => { // Adds values.
|
||||||
@ -319,7 +325,21 @@ function Library (ronin) {
|
|||||||
return ronin.surface.open(path)
|
return ronin.surface.open(path)
|
||||||
}
|
}
|
||||||
|
|
||||||
this.folder = (path = ronin.source.path) => { // Returns the content of a folder path.
|
// File System
|
||||||
|
|
||||||
|
this.dir = (path = ronin.source.path) => { // Returns the content of a directory.
|
||||||
|
return fs.existsSync(path) ? fs.readdirSync(path) : []
|
||||||
|
}
|
||||||
|
|
||||||
|
this.file = (path = ronin.source.path) => { // Returns the content of a file
|
||||||
|
return fs.existsSync(path) ? fs.readFileSync(p, 'utf8') : ''
|
||||||
|
}
|
||||||
|
|
||||||
|
this.dirpath = (path = ronin.source.path) => { // Returns the path of a directory.
|
||||||
|
return require('path').dirname(path)
|
||||||
|
}
|
||||||
|
|
||||||
|
this.filepath = (path = ronin.source.path) => { // Returns the path of a file
|
||||||
return fs.existsSync(path) ? fs.readdirSync(path) : []
|
return fs.existsSync(path) ? fs.readdirSync(path) : []
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@ function Surface (ronin) {
|
|||||||
this.ratio = window.devicePixelRatio
|
this.ratio = window.devicePixelRatio
|
||||||
// Contexts
|
// Contexts
|
||||||
this.context = this.el.getContext('2d')
|
this.context = this.el.getContext('2d')
|
||||||
this.guide = this.el.getContext('2d')
|
this.guide = this._guide.getContext('2d')
|
||||||
|
|
||||||
this.install = function (host) {
|
this.install = function (host) {
|
||||||
host.appendChild(this.el)
|
host.appendChild(this.el)
|
||||||
@ -15,9 +15,6 @@ function Surface (ronin) {
|
|||||||
this._guide.addEventListener('mousedown', ronin.commander.onMouseDown, false)
|
this._guide.addEventListener('mousedown', ronin.commander.onMouseDown, false)
|
||||||
this._guide.addEventListener('mousemove', ronin.commander.onMouseMove, false)
|
this._guide.addEventListener('mousemove', ronin.commander.onMouseMove, false)
|
||||||
this._guide.addEventListener('mouseup', ronin.commander.onMouseUp, false)
|
this._guide.addEventListener('mouseup', ronin.commander.onMouseUp, false)
|
||||||
// this.context.imageSmoothingEnabled = false
|
|
||||||
this.context.scale(this.ratio, this.ratio)
|
|
||||||
this.guide.scale(this.ratio, this.ratio)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.start = function () {
|
this.start = function () {
|
||||||
@ -151,8 +148,8 @@ function Surface (ronin) {
|
|||||||
context.clearRect(rect.x, rect.y, rect.w, rect.h)
|
context.clearRect(rect.x, rect.y, rect.w, rect.h)
|
||||||
}
|
}
|
||||||
|
|
||||||
this.clearGuide = function () {
|
this.clearGuide = function (rect = this.getFrame(), context = this.guide) {
|
||||||
this.clear(ronin.surface.getFrame(), ronin.surface.guide)
|
context.clearRect(rect.x, rect.y, rect.w, rect.h)
|
||||||
}
|
}
|
||||||
|
|
||||||
this.clone = function (a, b) {
|
this.clone = function (a, b) {
|
||||||
|
159
documentation.md
159
documentation.md
@ -1,159 +0,0 @@
|
|||||||
# Functions
|
|
||||||
|
|
||||||
## IO
|
|
||||||
|
|
||||||
`(open path)`
|
|
||||||
|
|
||||||
`(export path type quality)`
|
|
||||||
|
|
||||||
`(draw path rect)`
|
|
||||||
|
|
||||||
`(resize width height)`
|
|
||||||
|
|
||||||
`(crop rect)`
|
|
||||||
|
|
||||||
`(folder path)`
|
|
||||||
|
|
||||||
`(exit)`
|
|
||||||
|
|
||||||
## Logic
|
|
||||||
|
|
||||||
`(gt a b)` check if `a` is greater than `b`
|
|
||||||
|
|
||||||
`(lt a b)` check if `a` is lower than `b`
|
|
||||||
|
|
||||||
`(eq a b)` check if `a` is equal to `b`
|
|
||||||
|
|
||||||
`(and a b <c d...>)` returns true if all conditions are true
|
|
||||||
|
|
||||||
`(or a b <cd...>)` returns true if at least one condition is true
|
|
||||||
|
|
||||||
## Arrays
|
|
||||||
|
|
||||||
`(map function array)`
|
|
||||||
|
|
||||||
`(filter function array)`
|
|
||||||
|
|
||||||
`(reduce function array accumulator)`
|
|
||||||
|
|
||||||
`(len array)`
|
|
||||||
|
|
||||||
`(first array)`
|
|
||||||
|
|
||||||
`(last array)`
|
|
||||||
|
|
||||||
`(rest array)`
|
|
||||||
|
|
||||||
`(range start end step)`
|
|
||||||
|
|
||||||
## Shapes
|
|
||||||
|
|
||||||
`(pos x y)`
|
|
||||||
|
|
||||||
`(size w h)`
|
|
||||||
|
|
||||||
`(rect x y w h t)`
|
|
||||||
|
|
||||||
`(circle x y r)`
|
|
||||||
|
|
||||||
`(line start end)`
|
|
||||||
|
|
||||||
`(text x y g string font)`
|
|
||||||
|
|
||||||
`(svg data)`
|
|
||||||
|
|
||||||
## Helpers
|
|
||||||
|
|
||||||
`(frame)`
|
|
||||||
|
|
||||||
`(center)`
|
|
||||||
|
|
||||||
`(scale rect width height)`
|
|
||||||
|
|
||||||
## Copy/Paste
|
|
||||||
|
|
||||||
`(clone start end)` clone start `rect` into end `rect`
|
|
||||||
|
|
||||||
`(stroke shape thickness color)`
|
|
||||||
|
|
||||||
`(fill shape color)`
|
|
||||||
|
|
||||||
`(clear shape)`
|
|
||||||
|
|
||||||
## Objects
|
|
||||||
|
|
||||||
`(get item key <keys>)`
|
|
||||||
|
|
||||||
`(set item key val)`
|
|
||||||
|
|
||||||
## Colors
|
|
||||||
|
|
||||||
`(theme variable)`
|
|
||||||
|
|
||||||
`(gradient (x1,y1,x2,y2) colors)`
|
|
||||||
|
|
||||||
`(pixels rect function q)`
|
|
||||||
|
|
||||||
`(saturation pixel q)`
|
|
||||||
|
|
||||||
`(contrast pixel q)`
|
|
||||||
|
|
||||||
## Math
|
|
||||||
|
|
||||||
`(add ...values)`
|
|
||||||
|
|
||||||
`(sub...values)`
|
|
||||||
|
|
||||||
`(mul ...values)`
|
|
||||||
|
|
||||||
`(div ...values)`
|
|
||||||
|
|
||||||
`(mod a b)`
|
|
||||||
|
|
||||||
`(clamp value min max)`
|
|
||||||
|
|
||||||
`(step value step)`
|
|
||||||
|
|
||||||
`(min a b)`
|
|
||||||
|
|
||||||
`(max a b)`
|
|
||||||
|
|
||||||
`(ceil value)`
|
|
||||||
|
|
||||||
`(floor value)`
|
|
||||||
|
|
||||||
`(sin a)`
|
|
||||||
|
|
||||||
`(cos a)`
|
|
||||||
|
|
||||||
`PI, TWO_PI`
|
|
||||||
|
|
||||||
`(random)`
|
|
||||||
|
|
||||||
`(random start end)`
|
|
||||||
|
|
||||||
`(random max)`
|
|
||||||
|
|
||||||
## Generics
|
|
||||||
|
|
||||||
`(echo args)`
|
|
||||||
|
|
||||||
`(str args)`
|
|
||||||
|
|
||||||
`(test name value expectedValue)`
|
|
||||||
|
|
||||||
## Livecoding
|
|
||||||
|
|
||||||
`(time)` returns timestamp in milliseconds
|
|
||||||
|
|
||||||
`(animate)` start animation
|
|
||||||
|
|
||||||
`(animate false)` stop animation
|
|
||||||
|
|
||||||
## Javascript interop
|
|
||||||
|
|
||||||
`js`
|
|
||||||
|
|
||||||
## Client
|
|
||||||
|
|
||||||
`ronin`
|
|
@ -1,13 +1,17 @@
|
|||||||
; animate
|
; animate
|
||||||
|
|
||||||
(
|
(
|
||||||
(clear)
|
(clear)
|
||||||
(def t (sin (div (time) 100)))
|
(def t
|
||||||
|
(sin
|
||||||
(def pos (add 200 30 (mul 30 t)))
|
(div
|
||||||
(defn square (a) (rect a a a a))
|
(time) 100)))
|
||||||
(stroke (square pos) 1 "red")
|
(def pos
|
||||||
|
(add 200 30
|
||||||
|
(mul 30 t)))
|
||||||
|
(defn square
|
||||||
|
(a)
|
||||||
|
(rect a a a a))
|
||||||
|
(stroke
|
||||||
|
(square pos) 1 "red")
|
||||||
; set false to stop
|
; set false to stop
|
||||||
(animate true)
|
(animate true))
|
||||||
)
|
|
14
examples/fs.lisp
Normal file
14
examples/fs.lisp
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
; filesystem
|
||||||
|
(
|
||||||
|
; get files
|
||||||
|
(def files
|
||||||
|
(dir
|
||||||
|
(dirpath)))
|
||||||
|
; pick a random file
|
||||||
|
(def random-index
|
||||||
|
(floor
|
||||||
|
(random
|
||||||
|
(len files))))
|
||||||
|
; print random file name
|
||||||
|
(echo
|
||||||
|
(get files random-index)))
|
@ -1,29 +0,0 @@
|
|||||||
; animated recusive spiral
|
|
||||||
; by @local_guru
|
|
||||||
(
|
|
||||||
(def start (get ronin "animate"))
|
|
||||||
(clear)
|
|
||||||
(defn rec
|
|
||||||
(v)
|
|
||||||
(if (gt v 0)
|
|
||||||
((stroke
|
|
||||||
(circle
|
|
||||||
(add 300
|
|
||||||
(mul (cos (add (div v 17) (div (time) 2000)))
|
|
||||||
(div v 2)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
(add 300
|
|
||||||
(mul (sin (div v 11))
|
|
||||||
(div v 2)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
(div v 2))
|
|
||||||
1 "rgba(255,255,255,0.1")
|
|
||||||
(rec (sub v 0.3))
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
(start)
|
|
||||||
(rec 300)
|
|
||||||
)
|
|
30
examples/spiral.lisp
Normal file
30
examples/spiral.lisp
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
; animated recusive spiral
|
||||||
|
; by @local_guru
|
||||||
|
(
|
||||||
|
(clear)
|
||||||
|
(defn rec
|
||||||
|
(v)
|
||||||
|
(if
|
||||||
|
(gt v 0)
|
||||||
|
(
|
||||||
|
(stroke
|
||||||
|
(circle
|
||||||
|
(add 375
|
||||||
|
(mul
|
||||||
|
(cos
|
||||||
|
(add
|
||||||
|
(div v 17)
|
||||||
|
(div
|
||||||
|
(time) 2000)))
|
||||||
|
(div v 2)))
|
||||||
|
(add 300
|
||||||
|
(mul
|
||||||
|
(sin
|
||||||
|
(div v 11))
|
||||||
|
(div v 2)))
|
||||||
|
(div v 2)) 1 "rgba(114,222, 194,0.1)")
|
||||||
|
(rec
|
||||||
|
(sub v 0.3)))))
|
||||||
|
; set false to stop
|
||||||
|
(animate true)
|
||||||
|
(rec 300))
|
Loading…
x
Reference in New Issue
Block a user