178 lines
4.3 KiB
JavaScript
178 lines
4.3 KiB
JavaScript
export const turtle_init = {
|
|
position: [0, 0],
|
|
heading: 0,
|
|
pendown: true,
|
|
pencolor: "white",
|
|
penwidth: 1,
|
|
visible: true
|
|
}
|
|
|
|
export const turtle_radius = 20
|
|
|
|
export const turtle_angle = 0.385
|
|
|
|
let turtle_color = [255, 255, 255, 150]
|
|
|
|
export function get_turtle_color () {
|
|
return turtle_color
|
|
}
|
|
|
|
export function set_turtle_color (new_color) {
|
|
turtle_color = new_color
|
|
}
|
|
|
|
export const colors = {
|
|
black: [0, 0, 0, 255],
|
|
silver: [192, 192, 192, 255],
|
|
gray: [128, 128, 128, 255],
|
|
grey: [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, 255, 255],
|
|
}
|
|
|
|
export function resolve_color (color) {
|
|
if (typeof color === 'string') return colors[color]
|
|
if (typeof color === 'number') return [color, color, color, 255]
|
|
if (Array.isArray(color)) return color
|
|
return [0, 0, 0, 255] // default to black?
|
|
}
|
|
|
|
export let background_color = "black"
|
|
|
|
export function add (v1, v2) {
|
|
const [x1, y1] = v1
|
|
const [x2, y2] = v2
|
|
return [x1 + x2, y1 + y2]
|
|
}
|
|
|
|
export function mult (vector, scalar) {
|
|
const [x, y] = vector
|
|
return [x * scalar, y * scalar]
|
|
}
|
|
|
|
export function unit_of (heading) {
|
|
const turns = -heading + 0.25
|
|
const radians = turn_to_rad(turns)
|
|
return [Math.cos(radians), Math.sin(radians)]
|
|
}
|
|
|
|
export function command_to_state (prev_state, curr_command) {
|
|
const [verb] = curr_command
|
|
switch (verb) {
|
|
case "goto": {
|
|
const [_, x, y] = curr_command
|
|
return {...prev_state, position: [x, y]}
|
|
}
|
|
case "home": {
|
|
return {...prev_state, position: [0, 0], heading: 0}
|
|
}
|
|
case "right": {
|
|
const [_, angle] = curr_command
|
|
const {heading} = prev_state
|
|
return {...prev_state, heading: heading + angle}
|
|
}
|
|
case "left": {
|
|
const [_, angle] = curr_command
|
|
const {heading} = prev_state
|
|
return {...prev_state, heading: heading - angle}
|
|
}
|
|
case "forward": {
|
|
const [_, steps] = curr_command
|
|
const {heading, position} = prev_state
|
|
const unit = unit_of(heading)
|
|
const move = mult(unit, steps)
|
|
return {...prev_state, position: add(position, move)}
|
|
}
|
|
case "back": {
|
|
const [_, steps] = curr_command
|
|
const {heading, position} = prev_state
|
|
const unit = unit_of(heading)
|
|
const move = mult(unit, -steps)
|
|
return {...prev_state, position: add(position, move)}
|
|
}
|
|
case "penup": {
|
|
return {...prev_state, pendown: false}
|
|
}
|
|
case "pendown": {
|
|
return {...prev_state, pendown: true}
|
|
}
|
|
case "penwidth": {
|
|
const [_, width] = curr_command
|
|
return {...prev_state, penwidth: width}
|
|
}
|
|
case "pencolor": {
|
|
const [_, color] = curr_command
|
|
return {...prev_state, pencolor: color}
|
|
}
|
|
case "setheading": {
|
|
const [_, heading] = curr_command
|
|
return {...prev_state, heading: heading}
|
|
}
|
|
case "loadstate": {
|
|
// console.log("LOADSTATE: ", curr_command)
|
|
const [_, [x, y], heading, visible, pendown, penwidth, pencolor] = curr_command
|
|
return {position: [x, y], heading, visible, pendown, penwidth, pencolor}
|
|
}
|
|
case "show": {
|
|
return {...prev_state, visible: true}
|
|
}
|
|
case "hide": {
|
|
return {...prev_state, visible: false}
|
|
}
|
|
case "background": {
|
|
background_color = curr_command[1]
|
|
return prev_state
|
|
}
|
|
}
|
|
}
|
|
|
|
export function eq_vect (v1, v2) {
|
|
const [x1, y1] = v1
|
|
const [x2, y2] = v2
|
|
return (x1 === x2) && (y1 === y2)
|
|
}
|
|
|
|
export function eq_color (c1, c2) {
|
|
if (c1 === c2) return true
|
|
const res1 = resolve_color(c1)
|
|
const res2 = resolve_color(c2)
|
|
for (let i = 0; i < res1.length; ++i) {
|
|
if (res1[i] !== res2[i]) return false
|
|
}
|
|
return true
|
|
}
|
|
|
|
export function rotate (vector, heading) {
|
|
const radians = turn_to_rad(heading)
|
|
const [x, y] = vector
|
|
return [
|
|
(x * Math.cos (radians)) - (y * Math.sin (radians)),
|
|
(x * Math.sin (radians)) + (y * Math.cos (radians))
|
|
]
|
|
}
|
|
|
|
export function turn_to_rad (heading) {
|
|
return (heading % 1) * 2 * Math.PI
|
|
}
|
|
|
|
export function turn_to_deg (heading) {
|
|
return (heading % 1) * 360
|
|
}
|
|
|
|
export function last (arr) {
|
|
return arr[arr.length - 1]
|
|
}
|
|
|
|
|