diff --git a/build/ludus.mjs b/build/ludus.mjs index a731a42..4c70165 100644 --- a/build/ludus.mjs +++ b/build/ludus.mjs @@ -6,7 +6,7 @@ let result = null export function run (source) { const output = mod.ludus(source).value - console.log(output) + // console.log(output) result = JSON.parse(output) return result } @@ -19,3 +19,204 @@ export function turtle_commands () { 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"]) +} + + diff --git a/build/test.mjs b/build/test.mjs index e946c71..adbe62a 100644 --- a/build/test.mjs +++ b/build/test.mjs @@ -1,3 +1,9 @@ import {run} from "./ludus.mjs" -console.log(run(`let foo = 42; "{foo} bar"`)) +console.log(run(` + +forward! (100) +right! (0.25) +print! ("foobar") + +`))