PencilCode / jquery-turtle

Turtle Graphics for JQuery
Other
44 stars 25 forks source link

jQuery-turtle

version 2.0.9

jQuery-turtle is a jQuery plugin for turtle graphics.

With jQuery-turtle, every DOM element is a turtle that can be moved using turtle graphics methods like fd (forward), bk (back), rt (right turn), and lt (left turn). The pen function allows a turtle to draw on a full-document canvas as it moves.

$('#turtle').pen('red').rt(90).fd(100).lt(90).bk(50).fadeOut();

jQuery-turtle provides:

The plugin can also create a learning environment with a default turtle that is friendly for beginners. The following is a complete CoffeeScript program that uses the default turtle to draw a grid of sixteen colored polygons.

eval $.turtle()  # Create the default turtle.

speed 100
for color in [red, gold, green, blue]
  for sides in [3..6]
    pen color
    for x in [1..sides]
      fd 100 / sides
      lt 360 / sides
    pen null
    fd 40
  slide 40, -160

Try an interactive demo (CoffeeScript syntax) here.

JQuery Methods for Turtle Movement

The turtle API is briefly summarized below. All the following turtle-oriented methods operate on any jQuery object (including the default turtle, if used):

$(q).fd(100)      // Forward relative motion in local coordinates.
$(q).bk(50)       // Back.
$(q).rt(90)       // Right turn.  Optional second arg is turning radius.
$(q).lt(45)       // Left turn.  Optional second arg is turning radius.
$(q).slide(x, y)  // Slide right by x while sliding forward by y.
$(q).jump(x, y)   // Like slide, but without drawing.
$(q).moveto({pageX:x,pageY:y} | [x,y])  // Absolute motion on page.
$(q).jumpto({pageX:x,pageY:y} | [x,y])  // Like moveto, without drawing.
$(q).turnto(bearing || position)        // Absolute direction adjustment.
$(q).play("ccgg") // Plays notes using ABC notation and waits until done.

// Methods below happen in an instant, but line up in the animation queue.
$(q).home()       // Jumps to the center of the document, with bearing 0.
$(q).pen('red')   // Sets a pen style, or 'none' for no drawing.
$(q).pu()         // Pen up - temporarily disables the pen (also pen(false)).
$(q).pd()         // Pen down - starts a new pen path.
$(q).pe()         // Uses the pen 'erase' style.
$(q).fill('gold') // Fills a shape previously outlined using pen('path').
$(q).dot(12)      // Draws a circular dot of diameter 12.  Color second arg.
$(q).label('A')   // Prints an HTML label at the turtle location.
$(q).speed(10)    // Sets turtle animation speed to 10 moves per sec.
$(q).ht()         // Hides the turtle.
$(q).st()         // Shows the turtle.
$(q).wear('blue') // Switches to a blue shell.  Use any image or color.
$(q).scale(1.5)   // Scales turtle size and motion by 150%.
$(q).twist(180)   // Changes which direction is considered "forward".
$(q).mirror(true) // Flips the turtle across its main axis.
$(q).reload()     // Reloads the turtle's image (restarting animated gifs)
$(q).done(fn)     // Like $(q).promise().done(fn). Calls after all animation.
$(q).plan(fn)     // Like each, but this is set to $(elt) instead of elt,
                  // and the callback fn can insert into the animation queue.

// Methods below this line do not queue for animation.
$(q).getxy()      // Local (center-y-up [x, y]) coordinates of the turtle.
$(q).pagexy()     // Page (topleft-y-down {pageX:x, pageY:y}) coordinates.
$(q).bearing([p]) // The turtles absolute direction (or direction towards p).
$(q).distance(p)  // Distance to p in page coordinates.
$(q).shown()      // Shorthand for is(":visible")
$(q).hidden()     // Shorthand for !is(":visible")
$(q).touches(y)   // Collision tests elements (uses turtleHull if present).
$(q).inside(y)// Containment collision test.
$(q).nearest(pos) // Filters to item (or items if tied) nearest pos.
$(q).within(d, t) // Filters to items with centers within d of t.pagexy().
$(q).notwithin()  // The negation of within.
$(q).cell(y, x)   // Selects the yth row and xth column cell in a table.
$(q).hatch([n,] [img]) // Creates and returns n turtles with the given img.

Speed and Turtle Animation

When the speed of a turtle is nonzero, the first nine movement functions animate at that speed (in moves per second), and the remaining mutators also participate in the animation queue. The default turtle speed is a leisurely one move per second (as appropriate for the creature), but you may soon discover the desire to set speed higher.

Setting the turtle speed to Infinity will make its movement synchronous, which makes the synchronous distance, direction, and hit-testing useful for realtime game-making.

Pen and Fill Styles

The turtle pen respects canvas styling: any valid strokeStyle is accepted; and also using a space-separated syntax, lineWidth, lineCap, lineJoin, miterLimit, and fillStyle can be specified, e.g., pen('red lineWidth 5 lineCap square'). The same syntax applies for styling dot and fill (except that the default interpretation for the first value is fillStyle instead of strokeStyle).

The fill method is used by tracing an invisible path using the pen('path') style, and then calling the fill method. Disconnected paths can be created using pu() and pd().

Conventions for Musical Notes

The play method plays a sequence of notes specified using a subset of standard ABC notation. Capital C denotes middle C, and lowercase c is an octave higher. Pitches and durations can be altered with commas, apostrophes, carets, underscores, digits, and slashes as in the standard. Enclosing letters in square brackets represents a chord, and z represents a rest. The default tempo is 120, but can be changed by passing a options object as the first parameter setting tempo, e.g., { tempo: 200 }. Other options include volume: 0.5, type: 'sine' or 'square' or 'sawtooth' or 'triangle', and envelope: which defines an ADSR envelope e.g., { a: 0.01, d: 0.2, s: 0.1, r: 0.1 }.

The turtle's motion will pause while it is playing notes.

Planning Logic in the Animation Queue

The plan method can be used to queue logic (including synchronous tests or actions) by running a function in the animation queue. Unlike jquery queue(), plan arranges things so that if further animations are queued by the callback function, they are inserted (in natural recursive functional execution order) instead of being appended.

Turnto and Absolute Bearings

The turnto method can turn to an absolute bearing (if called with a single numeric argument) or towards an absolute position on the screen. The methods moveto and turnto accept either page or graphing coordinates.

Moveto and Two Flavors of Cartesian Coordinates

Graphing coordinates are measured upwards and rightwards from the center of the page, and they are specified as bare numeric x, y arguments or [x, y] pairs as returned from getxy().

Page coordinates are specified by an object with pageX and pageY properties, or with a pagexy() method that will return such an object. That includes, usefullly, mouse events and turtle objects. Page coordinates are measured downward from the top-left corner of the page to the center (or transform-origin) of the given object.

Hit Testing

The hit-testing functions touches() and inside() will test for collisions using the convex hulls of the objects in question. The hull of an element defaults to the bounding box of the element (as transformed) but can be overridden by the turtleHull CSS property, if present. The default turtle is given a turtle-shaped hull.

The touches() function can also test for collisions with a color on the canvas - use touches('red'), for example, or for collsisions with any nontransparent color, use touches('color').

Turtle Teaching Environment

A default turtle together with an interactive console are created by calling eval($.turtle()). That call exposes all the turtle methods such as (fd, rt, getxy, etc) as global functions operating on the default turtle. It will also set up a number of other global symbols to provide beginners with a simplified programming environment.

In detail, after eval($.turtle()):

Beyond the functions to control the default turtle, the globals added by $.turtle() are as follows:

lastclick             // Event object of the last click event in the doc.
lastmousemove         // The last mousemove event.
lastmouseup           // The last mouseup event.
lastmousedown         // The last mousedown event.
keydown               // The last keydown event.
keyup                 // The last keyup event.
keypress              // The last keypress event.
hatch([n,] [img])     // Creates and returns n turtles with the given img.
cs()                  // Clears the screen, both the canvas and the body text.
cg()                  // Clears the graphics canvas without clearing the text.
ct()                  // Clears the text without clearing the canvas.
defaultspeed(mps)     // Sets $.fx.speeds.turtle to 1000 / mps.
timer(secs, fn)       // Calls back fn once after secs seconds.
tick([perSec,] fn)    // Repeatedly calls fn at the given rate (null clears).
done(fn)              // Calls back fn after all turtle animation is complete.
random(n)             // Returns a random number [0..n-1].
random(list)          // Returns a random element of the list.
random('normal')      // Returns a gaussian random (mean 0 stdev 1).
random('uniform')     // Returns a uniform random [0...1).
random('position')    // Returns a random {pageX:x, pageY:y} coordinate.
random('color')       // Returns a random hsl(*, 100%, 50%) color.
random('gray')        // Returns a random hsl(0, 0, *) gray.
remove()              // Removes default turtle and its globals (fd, etc).
see(a, b, c...)       // Logs tree-expandable data into debugging panel.
write(html)           // Appends html into the document body.
read([label,] fn)     // Makes a one-time input field, calls fn after entry.
readnum([label,] fn)  // Like read, but restricted to numeric input.
readstr([label,] fn)  // Like read, but never converts input to a number.
button([label,] fn)   // Makes a clickable button, calls fn when clicked.
table(m, n)           // Outputs a table with m rows and n columns.
play('[DFG][EGc]')    // Plays musical notes.
send(m, arg)          // Sends an async message to be received by recv(m, fn).
recv(m, fn)           // Calls fn once to receive one message sent by send.

Here is another CoffeeScript example that demonstrates some of the functions:

eval $.turtle()  # Create the default turtle and global functions.

speed Infinity
write "Catch blue before red gets you."
bk 100
r = hatch red
b = hatch blue
tick 10, ->
  turnto lastmousemove
  fd 6
  r.turnto turtle
  r.fd 4
  b.turnto direction b
  b.fd 3
  if b.touches(turtle)
    write "You win!"
    tick off
  else if r.touches(turtle)
    write "Red got you!"
    tick off
  else if not b.inside(document)
    write "Blue got away!"
    tick off

The turtle teaching environment is designed to work well with either Javascript or CoffeeScript.

JQuery CSS Hooks for Turtle Geometry

Underlying turtle motion are turtle-oriented 2d transform jQuery cssHooks, with animation support on all motion:

$(q).css('turtleSpeed', '10');         // speed in moves per second.
$(q).css('turtleEasing', 'linear');    // animation easing, defaults to swing.
$(q).css('turtlePosition', '30 40');   // position in local coordinates.
$(q).css('turtlePositionX', '30px');   // x component.
$(q).css('turtlePositionY', '40px');   // y component.
$(q).css('turtleRotation', '90deg');   // rotation in degrees.
$(q).css('turtleScale', '2');          // double the size of any element.
$(q).css('turtleScaleX', '2');         // x stretch after twist.
$(q).css('turtleScaleY', '2');         // y stretch after twist.
$(q).css('turtleTwist', '45deg');      // turn before stretching.
$(q).css('turtleForward', '50px');     // position in direction of rotation.
$(q).css('turtleTurningRadius, '50px');// arc turning radius for rotation.
$(q).css('turtlePenStyle', 'red');     // or 'red lineWidth 2px' etc.
$(q).css('turtlePenDown', 'up');       // default 'down' to draw with pen.
$(q).css('turtleHull', '5 0 0 5 0 -5');// fine-tune shape for collisions.

Arbitrary 2d transforms are supported, including transforms of elements nested within other elements that have css transforms. For example, arc paths of a turtle within a skewed div will transform to the proper elliptical arc. Note that while turtle motion is transformed, lines and dots are not: for example, dots are always circular. To get transformed circles, trace out an arc.

Transforms on the turtle itself are used to infer the turtle position, direction, and rendering of the sprite. ScaleY stretches the turtle sprite in the direction of movement also stretches distances for motion in all directions. ScaleX stretches the turtle sprite perpendicular to the direction of motion and also stretches line and dot widths for drawing.

A canvas is supported for drawing, but only created when the pen is used; pen styles include canvas style properties such as lineWidth and lineCap.

A convex hull polygon can be set to be used by the collision detection and hit-testing functions (inside, touches). The turtleHull is a list of (unrotated) x-y coordinates relative to the object's transformOrigin. If set to 'auto' (the default) the hull is just the bounding box for the element.

License (MIT)

Copyright (c) 2014 Pencil Code, Google Inc., and other contributors

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.