start building out p5 adapter

This commit is contained in:
Scott Richmond 2024-07-22 11:39:57 -04:00
parent 4ca1da1240
commit 2c9f6f8279
2 changed files with 209 additions and 2 deletions

View File

@ -6,7 +6,7 @@ let result = null
export function run (source) { export function run (source) {
const output = mod.ludus(source).value const output = mod.ludus(source).value
console.log(output) // console.log(output)
result = JSON.parse(output) result = JSON.parse(output)
return result return result
} }
@ -19,3 +19,204 @@ export function turtle_commands () {
return result.io.turtle.data return result.io.turtle.data
} }
export function p5_calls () {
return p5_call_list
}
export function svg () {
}
const turtle_init = {
position: [0, 0],
heading: 0,
pendown: true,
pencolor: "white",
penwidth: 1,
visible: true
}
const colors = {
black: [0, 0, 0, 255],
silver: [192, 192, 192, 255],
gray: [128, 128, 128, 255],
white: [255, 255, 255, 255],
maroon: [128, 0, 0, 255],
red: [255, 0, 0, 255],
purple: [128, 0, 128, 255],
fuchsia: [255, 0, 255, 255],
green: [0, 128, 0, 255],
lime: [0, 255, 0, 255],
olive: [128, 128, 0, 255],
yellow: [255, 255, 0, 255],
navy: [0, 0, 128, 255],
blue: [0, 0, 255, 255],
teal: [0, 128, 128, 255],
aqua: [0, 255, 25, 255],
}
let turtle_states = [turtle_init]
let background_color = "black"
function last_state () {
return turtle_states[turtle_states.length - 1]
}
function add (v1, v2) {
const [x1, y1] = v1
const [x2, y2] = v2
return [x1 + x2, y1 + y2]
}
function mult (vector, scalar) {
const [x, y] = vector
return [x * scalar, y * scalar]
}
function unit_of (heading) {
const turns = -heading + 0.25
const radians = turn_to_rad(turns)
[Math.cos (radians), Math.sin(radians)]
}
function command_to_state (previous, command) {
const verb = command[0]
switch (verb) {
case "goto": {
const [_, x, y] = command
return {...previous, position: [x, y]}
}
case "home": {
return {...previous, position: [0, 0], heading: 0}
}
case "right": {
const [_, angle] = command
const {heading} = previous
return {...previous, heading: heading + angle}
}
case "left": {
const [_, angle] = command
const {heading} = previous
return {...previous, heading: heading - angle}
}
case "forward": {
const [_, steps] = command
const {heading, position} = previous
const unit = unit_of(heading)
const move = mult(unit, steps)
return {...previous, position: add(position, move)}
}
case "back": {
const [_, steps] = command
const {heading, position} = previous
const unit = unit_of(heading)
const move = mult(unit, -steps)
return {...previous, position: add(position, move)}
}
case "penup": {
return {...previous, pendown: false}
}
case "pendown": {
return {...previous, pendown: true}
}
case "pendwith": {
const [_, width] = command
return {...previous, penwidth: width}
}
case "pencolor": {
if (command.length = 2) {
const [_, color] = command
return {...previous, pencolor: color}
} else {
const [_, r, g, b, a] = command
return {...previous, pencolor: [r, g, b, a]}
}
}
case "setheading": {
const [_, heading] = command
return {...previous, heading: heading}
}
case "loadstate": {
const [_, x, y, heading, visible, pendown, penwidth] = command
// there are 7 fixed-arity arguments
// color will either be the last one or four
let pencolor = command.slice(7)
// if there's one, it's a string, unpack it
if (pencolor.length = 1) pencolor = pencolor[0]
return {position: [x, y], heading, visible, pendown, penwidth, pencolor}
}
case "show": {
return {...position, visible: true}
}
case "hide": {
return {...position, visible: false}
}
case "background": {
let color = command.slice(1)
if (color.lengh = 1) color = color[0]
background_color = color
return
}
}
}
function are_eq (v1, v2) {
const [x1, y1] = v1
const [x2, y2] = v2
return (x1 === x2) && (y1 === y2)
}
function state_to_call (prev, curr) {
}
const turtle_radius = 20
const turtle_angle = 0.385
const turtle_color = [255, 255, 255, 150]
let p5_call_list = []
function add_p5_call (call) {
p5_call_list.push(call)
}
function rotate (vector, heading) {
const radians = turn_to_rad(heading)
const [x, y] = vector
return [
(x * cos (radians)) - (y * sin (radians)),
(x * sin (radians)) + (y * cos (radians))
]
}
function turn_to_rad (heading) {
heading * 2 * Math.PI
}
function render_turtle () {
const state = last_state ()
if (!state.visible) return
const [r, g, b, a] = turtle_color
add_call("fill", r, g, b, a)
const {heading, pencolor: [pen_r, pen_g, pen_b, pen_a], position: [x, y], pendown} = state
const origin = [0, turtle_radius]
const [x1, y1] = origin
const [x2, y2] = rotate(origin, turtle_angle)
const [x3, y3] = rotate(origin, -turtle_angle)
add_p5_call(["push"])
add_p5_call(["translate", x, y])
add_p5_call(["rotate", turn_to_rad(heading)])
add_p5_call(["noStroke"])
add_p5_call(["beginShape"])
add_p5_call(["vertex", x1, y1])
add_p5_call(["vertex", x2, y2])
add_p5_call(["vertex", x3, y3])
add_p5_call(["endShape"])
add_p5_call(["stroke", pen_r, pen_g, pen_b, pen_a])
if (pendown) add_p5_call(["line", 0, 0, x1, y1])
add_p5_call(["pop"])
}

View File

@ -1,3 +1,9 @@
import {run} from "./ludus.mjs" import {run} from "./ludus.mjs"
console.log(run(`let foo = 42; "{foo} bar"`)) console.log(run(`
forward! (100)
right! (0.25)
print! ("foobar")
`))