Re: 2D graphics/turtle lib suitable for kids?
Posted: Fri Jan 07, 2011 5:48 am
I wrote a simple turtle graphics library based on lispbuilder-sdl. The code can be found here: https://github.com/johanberntsson/cl-tu ... urtle.lisp
Discuss and learn Lisp programming of all dialects. NOTICE: Site locked. No new users or posts.
http://www.lispforum.com/
I like this topic =). Grid drawing is called pixel art: http://www.pixeljoint.com/pixels/new_ic ... ?ob=rating, I did it all the time to make sprites. Flexibility of the output isn't important here, simplicity of ideas is (she'll ask "How can I make it red?" long before she'll ask "How can I make it 1024x768 triple buffered with 32 bits, an alpha channel and a Z buffer?" -- hyperbole I know)You're not teaching trigonometry, but basic geometry. You're still working from coordinates, just abstract ones. fd 1 (forward one, in a hypothetical dialect) could be one pixel (it was in Apple Logo) but it could also be an arbitrary distance, with 1.235 as a possibility, as well.
Advocating direct pixel manipulation seems... archaic, and non-portable to higher/lower resolutions.
SVG is much more flexible than (insert bitmapped format).
NeWS was much more flexible than X.
Artists don't draw on graphing paper, yo.
Code: Select all
gfx.so : gfx.c
gcc -c -fPIC `sdl-config --cflags` `sdl-config --libs` gfx.c && ld -shared -o gfx.so gfx.o
Code: Select all
#include "SDL/SDL.h"
SDL_Surface* screen = NULL;
int sdl_start (int x, int y, int d) {
if (SDL_Init( SDL_INIT_VIDEO | SDL_INIT_EVENTTHREAD ) != 0) { return -1; }
screen = SDL_SetVideoMode( x, y, d, SDL_SWSURFACE );
if (screen == NULL) { return -1; }
return 0;
}
void sdl_stop () {
SDL_FreeSurface( screen );
screen = NULL;
SDL_Quit();
}
char* gfx_error () { return SDL_GetError(); }
void gfx_show () { SDL_Flip(screen); }
void* gfx_raw () { return screen->pixels; }
void gfx_lock () { SDL_LockSurface(screen); }
void gfx_unlock () { SDL_UnlockSurface(screen); }
Code: Select all
(defpackage :gfx
(:use :common-lisp :sb-alien)
(:export ;; +width+ +height+ +depth+
+wide+ +tall+ +white+ +black+ +red+ +green+ +blue+
gfx-start gfx-stop gfx-show put))
(in-package :gfx)
(load-shared-object "libSDL.so")
(load-shared-object (car (directory "gfx.so"))) ;; Get the abs path of gfx.so.
(define-alien-variable screen system-area-pointer)
(define-alien-routine sdl-start int (width int) (height int) (depth int))
(define-alien-routine sdl-stop void)
(define-alien-routine gfx-error c-string)
(define-alien-routine gfx-show void)
(define-alien-routine gfx-raw system-area-pointer)
(define-alien-routine gfx-unlock void)
(define-alien-routine gfx-lock void)
(defconstant +width+ 800)
(defconstant +height+ 600)
(defconstant +depth+ 32)
(defconstant +white+ #xFFFFFF)
(defconstant +black+ #x000000)
(defconstant +red+ #xFF0000)
(defconstant +green+ #x00FF00)
(defconstant +blue+ #x0000FF)
(defun gfx-start ()
(if (zerop (sb-sys:sap-int screen))
(or (zerop (sdl-start +width+ +height+ +depth+))
(error (gfx-error)))
(error "Graphics are already initialized")))
(defun gfx-stop ()
(if (zerop (sb-sys:sap-int screen))
(error "Graphics are not initialized.")
(sdl-stop)))
(defun dot (color x y)
(setf x (min (max x 0) +width+) y (min (max y 0) +height+))
(let ((offset (ash (+ (* y +width+) x) 2)))
(setf (sb-sys:sap-ref-32 (gfx-raw) offset) color)))
(defconstant +wide+ (/ +width+ 8))
(defconstant +tall+ (/ +height+ 8))
(defun put (color x y)
"Puts an 8x8 pixels on the screen."
(setf x (* x 8) y (* y 8) color (truncate color))
(gfx-lock)
(dotimes (dx 8) (dotimes (dy 8) (dot color (+ x dx) (+ y dy))))
(gfx-unlock)
(gfx-show))
(gfx-start)
(push #'gfx-stop sb-ext:*exit-hooks*)
I'm recommending a more high-level programming technique.Warren Wilkinson wrote:I like this topic =). Grid drawing is called pixel art: http://www.pixeljoint.com/pixels/new_ic ... ?ob=rating, I did it all the time to make sprites. Flexibility of the output isn't important here, simplicity of ideas is (she'll ask "How can I make it red?" long before she'll ask "How can I make it 1024x768 triple buffered with 32 bits, an alpha channel and a Z buffer?" -- hyperbole I know)You're not teaching trigonometry, but basic geometry. You're still working from coordinates, just abstract ones. fd 1 (forward one, in a hypothetical dialect) could be one pixel (it was in Apple Logo) but it could also be an arbitrary distance, with 1.235 as a possibility, as well.
Advocating direct pixel manipulation seems... archaic, and non-portable to higher/lower resolutions.
SVG is much more flexible than (insert bitmapped format).
NeWS was much more flexible than X.
Artists don't draw on graphing paper, yo.
Direct pixel manipulation is the simplist, most primitive and most portable way of doing graphics. All other interfaces are just predefined pixel plotting routines. Algebra is the arithmatic as vectors are to pixels. My suggestion is to start at the logical beginning (pixels) and grow upwards to turtles (or gradients, or boxes, or triangles, or sprites, or text or whatever your kid is interested in).
What good is turtles when you want gradients? I'd bet she'd prefer making gradient rainbows to manipulating a turtle. Pixel plotting can, with equal ease, do both.
Ah, I see.Warren Wilkinson wrote:I'm all for simplicity, and I'll take it in whatever form it comes in, low level or high.
Resolution independence shouldn't be that hard: turn +width+ and +height+ to *width* and *height*, set them to your resolution and rerun the program. That is how postscript does it, it's just a variant of Forth.
A high level approach might incorrectly teach her that computers are the abstractions they implement. Instead, teach the real comp-sci stuff, because in this case its just as easy (or easier) than turtle graphics (which is a dead-end API) -- why not go with the facts?