module turtle

module lib/turtle.mu

import "turtle"

turtle provides simple Logo-style turtle graphics using SDL2.

The implementation intentionally uses only Mu's existing integer/pointer FFI surface. Heading math is integer CORDIC, so no f32/f64 FFI support is needed.

Imports

Functions

background#

fn background(t, r, g, b)

Undocumented.

Source lib/turtle.mu:334
fn background(t, r, g, b) {
  t["bg"] = [r, g, b]
  _render(t)
  return nil
}

backward#

fn backward(t, distance)

Undocumented.

Source lib/turtle.mu:297
fn backward(t, distance) {
  return forward(t, -distance)
}

clear#

fn clear(t)

clear removes all drawn segments without moving the turtle.

Source lib/turtle.mu:362
fn clear(t) {
  t["segments"] = []
  _render(t)
  return nil
}

close#

fn close(t)

Undocumented.

Source lib/turtle.mu:399
fn close(t) {
  if t["renderer"] != nil {
    _call(t["api"], "SDL_DestroyRenderer", "void", ["ptr"], [t["renderer"]])
    t["renderer"] = nil
  }
  if t["window"] != nil {
    _call(t["api"], "SDL_DestroyWindow", "void", ["ptr"], [t["window"]])
    t["window"] = nil
  }
  _call(t["api"], "SDL_Quit", "void", [], [])
  t["closed"] = true
  return nil
}

done#

fn done(t)

done keeps the window responsive until the user closes it.

Source lib/turtle.mu:389
fn done(t) {
  while poll(t) {
    // Redraw while idle so expose/resize events never leave a stale canvas.
    _render(t)
    _call(t["api"], "SDL_Delay", "void", ["u32"], [16])
  }
  close(t)
  return nil
}

forward#

fn forward(t, distance)

forward moves the turtle by distance pixels, drawing when the pen is down.

Source lib/turtle.mu:270
fn forward(t, distance) {
  if !poll(t) {
    return false
  }

  old_x := t["x"]
  old_y := t["y"]
  next := _project(old_x, old_y, t["heading"], distance)
  t["x"] = next[0]
  t["y"] = next[1]

  if t["pen"] {
    c := t["color"]
    append(t["segments"], [
      _pixel(old_x), _pixel(old_y),
      _pixel(next[0]), _pixel(next[1]),
      c[0], c[1], c[2],
    ])
  }

  _render(t)
  if t["delay"] > 0 {
    _call(t["api"], "SDL_Delay", "void", ["u32"], [t["delay"]])
  }
  return true
}

hide#

fn hide(t)

Undocumented.

Source lib/turtle.mu:346
fn hide(t) {
  t["visible"] = false
  _render(t)
  return nil
}

home#

fn home(t)

home returns to the centre and points north, drawing the journey if needed.

Source lib/turtle.mu:369
fn home(t) {
  old_heading := t["heading"]
  target_x := (t["width"] / 2) << 16
  target_y := (t["height"] / 2) << 16
  if t["pen"] {
    c := t["color"]
    append(t["segments"], [
      _pixel(t["x"]), _pixel(t["y"]),
      _pixel(target_x), _pixel(target_y),
      c[0], c[1], c[2],
    ])
  }
  t["x"] = target_x
  t["y"] = target_y
  t["heading"] = 0
  _render(t)
  return old_heading
}

left#

fn left(t, degrees)

Undocumented.

Source lib/turtle.mu:307
fn left(t, degrees) {
  t["heading"] = math.normalise_degrees(t["heading"] - degrees)
  _render(t)
  return poll(t)
}

open#

fn open(width, height, title...)

open creates a turtle canvas. The turtle starts in the centre, facing north.

Source lib/turtle.mu:192
fn open(width, height, title...) {
  lib := _open_sdl()
  if is_error(lib) {
    return lib
  }

  api := _bind_api(lib)
  if is_error(api) {
    return api
  }

  rc := _call(api, "SDL_Init", "i32", ["u32"], [_SDL_INIT_VIDEO])
  if rc != 0 {
    return error("turtle: SDL_Init failed")
  }

  caption := "Mu Turtle"
  if len(title) > 0 {
    caption = title[0]
  }

  window := _call(
    api,
    "SDL_CreateWindow",
    "ptr",
    ["cstr", "i32", "i32", "i32", "i32", "u32"],
    [
      caption,
      _SDL_WINDOWPOS_CENTERED,
      _SDL_WINDOWPOS_CENTERED,
      width,
      height,
      0,
    ],
  )
  if window == nil {
    _call(api, "SDL_Quit", "void", [], [])
    return error("turtle: SDL_CreateWindow failed")
  }

  renderer := _call(
    api,
    "SDL_CreateRenderer",
    "ptr",
    ["ptr", "i32", "u32"],
    [window, -1, 0],
  )
  if renderer == nil {
    _call(api, "SDL_DestroyWindow", "void", ["ptr"], [window])
    _call(api, "SDL_Quit", "void", [], [])
    return error("turtle: SDL_CreateRenderer failed")
  }

  t := {
    "lib": lib,
    "api": api,
    "window": window,
    "renderer": renderer,
    "event": buf(_EVENT_SIZE),
    "width": width,
    "height": height,
    "x": (width / 2) << 16,
    "y": (height / 2) << 16,
    "heading": 0,
    "pen": true,
    "color": [0, 0, 0],
    "bg": [255, 255, 255],
    "segments": [],
    "visible": true,
    "delay": 0,
    "closed": false,
  }

  _render(t)
  return t
}

pen_color#

fn pen_color(t, r, g, b)

Undocumented.

Source lib/turtle.mu:329
fn pen_color(t, r, g, b) {
  t["color"] = [r, g, b]
  return nil
}

pen_down#

fn pen_down(t)

Undocumented.

Source lib/turtle.mu:324
fn pen_down(t) {
  t["pen"] = true
  return nil
}

pen_up#

fn pen_up(t)

Undocumented.

Source lib/turtle.mu:319
fn pen_up(t) {
  t["pen"] = false
  return nil
}

poll#

fn poll(t)

poll processes pending window events and returns false once the window closes.

Source lib/turtle.mu:176
fn poll(t) {
  if t["closed"] {
    return false
  }

  event := t["event"]
  while _call(t["api"], "SDL_PollEvent", "i32", ["ptr"], [event]) != 0 {
    if _event_type(event) == _SDL_QUIT {
      t["closed"] = true
      return false
    }
  }
  return true
}

set_heading#

fn set_heading(t, degrees)

Undocumented.

Source lib/turtle.mu:313
fn set_heading(t, degrees) {
  t["heading"] = math.normalise_degrees(degrees)
  _render(t)
  return poll(t)
}

show#

fn show(t)

Undocumented.

Source lib/turtle.mu:340
fn show(t) {
  t["visible"] = true
  _render(t)
  return nil
}

speed#

fn speed(t, milliseconds)

speed sets a delay in milliseconds after each movement.

Source lib/turtle.mu:353
fn speed(t, milliseconds) {
  if milliseconds < 0 {
    milliseconds = 0
  }
  t["delay"] = milliseconds
  return nil
}

Internal helpers

Underscore-prefixed names are implementation detail. They are listed so the module's source reads without surprises, not as API — they may change at any time.

_EVENT_SIZE
_Q16
_SDL_INIT_VIDEO
_SDL_QUIT
_SDL_WINDOWPOS_CENTERED
_bind(lib, name)
_bind_api(lib)
_call(api, name, ret, arg_types, args)
_draw_turtle(t)
_event_type(event)
_line(t, x1, y1, x2, y2)
_open_sdl()
_pixel(q16)
_project(x, y, heading, distance)
_render(t)
_sdl_paths()
_set_color(t, r, g, b, a)