Going for a fast-prototype Lisp based language

Started by
29 comments, last by HairyTroll 18 years, 3 months ago
Quote:Original post by Anonymous Poster
Nope, it looks like Lisp to me with your own library bindings. Was there something revolutionary about this other than that it might be a Lisp that actually might really work?


Eh? Of course it works. It works perfectly fine right now and compiles and runs in Lispworks.

Advertisement
Quote:Original post by flangazor
My head doesn't explode when reading it but it's annoying having to figure out what the magic umbers are for. Abstract those into meaningful concepts and it will be nicer.


You mean like:

(rm::new-box <x1> <y1> <z1>              <x2> <y2> <z2>              <r>  <g>  <b>             <x-pos> <y-pos> <z-pos>)


?
OK.... I've changes things a wee bit. The following code (yes, it runs just fine) will:

1) Initialize SDL
2) Initialise OpenRM (OpenGL Scene Graph Manager)
#2.1) Create an OpenGL rendering pipeline, and assign a default root node (root-node)
#2.2) Set up the default scene and camera.
3) Create a new 'cube' of a random color.
3.1) Specify that this cube should be rotated around the x, y and z axis's by 1 angle respectively each frame rendered.
#4) Handle events & message pump
#4.1) The exit event (user closes the window) terminates the game loop.
#5) Update the script (rotate the cube) each frame
#7) Render the OpenGL frame
#8) Swap the buffers
#9) Goto 4
#10) Upon exit
#10.1) Close the rendering pipeline
#10.2) Shut down and release resources for OpenRM
#10.3) Shut down SDL.

Of the steps above, only 1, 2, and 3 are performed by the coder, everything else is buried and handled automatically.

(defun rotating-cube ()  (let ((screen-width 320) (screen-height 200))    (sdl::with-init ()      (rm::with-engine (sdl::window screen-width screen-height :flags sdl::sdl-opengl) root-node           (add-actor root-node  (define-actor a-cube                                    (primitives (rm::new-box :x1 -1.0 :y1 -1.0 :z1 -1.0				                             :x1  1.0 :y1  1.0 :z1  1.0                                                             :r (random 1.0) :g (random 1.0) :b (random 1.0)                                                             :cx  0.0 :cy  0.0 :cz  0.0))                                    (script (defscript ()         	                               (rotate-actor actor :dx 1.0 :dy 1.0 :dz 1.0)))	   (rm::set-default-scene root-node screen-width screen-height)))))
Quote:Original post by HairyTroll
Quote:Original post by flangazor
My head doesn't explode when reading it but it's annoying having to figure out what the magic umbers are for. Abstract those into meaningful concepts and it will be nicer.


You mean like:

(rm::new-box <x1> <y1> <z1>              <x2> <y2> <z2>              <r>  <g>  <b>             <x-pos> <y-pos> <z-pos>)


?


No, i meant more like setting up a record structure (list, struct, vector) of coordinates to pass to the box construction. And then define it in the let statement.
Quote:Original post by NoahAdler
Are you aware of Fluxus?


No, and thank you for the link. I'll definitely have a look at this.

Looks good, but the following things aren't obvious from the code:

* Why "with-init"/"with-engine" and not "init"/"engine"?

* What is the null list passed as the first argument to sdl::with-init?

* Where are 'root-node and 'actor defined?

* What's the point of calling "primtives" and "script" in add-actor?

-Alex

Quote:Original post by HairyTroll
(defun rotating-cube ()  (let ((screen-width 320) (screen-height 200))    (sdl::with-init ()      (rm::with-engine (sdl::window screen-width screen-height :flags sdl::sdl-opengl) root-node           (add-actor root-node  (define-actor a-cube                                    (primitives (rm::new-box :x1 -1.0 :y1 -1.0 :z1 -1.0				                             :x1  1.0 :y1  1.0 :z1  1.0                                                             :r (random 1.0) :g (random 1.0) :b (random 1.0)                                                             :cx  0.0 :cy  0.0 :cz  0.0))                                    (script (defscript ()         	                               (rotate-actor actor :dx 1.0 :dy 1.0 :dz 1.0)))	   (rm::set-default-scene root-node screen-width screen-height)))))


Quote:Original post by cypherx
* What is the null list passed as the first argument to sdl::with-init?


My guess is that sdl::with-init takes an association list that includes optional flags/settings/whatever ... it's pretty much standard stuff to either take an alist as an argument in this situation, or to have some weird plist "optional arguments" passed (this is common in the Common Lisp community, not recommended).
Quote:Original post by The Reindeer Effect
Quote:Original post by cypherx
* What is the null list passed as the first argument to sdl::with-init?


My guess is that sdl::with-init takes an association list that includes optional flags/settings/whatever


Half right. By default WITH-SDL is initialized using sdl::SDL-INIT-VIDEO which initializes the video subsystem. If I wanted to initialize both video and audio then I would do this: (sdl:with-init (sdl::SDL-INIT-VIDEO sdl::SDL-INIT-AUDIO) (STUFF-HERE))

Quote:Original post by cypherx
* Why "with-init"/"with-engine" and not "init"/"engine"?


Good points, the current names do not make sense. I'll change these.

Quote:Original post by cypherx
* What is the null list passed as the first argument to sdl::with-init?


sdl::wih-init can takes several parameters to initialize the various SDL subsystems. A null list means that SDL should be initialized using the default sdl::SDL-INIT-VIDEO which initializes the video subsystem. If I wanted to initialize both video and audio then I would do this: (sdl:with-init (sdl::SDL-INIT-VIDEO sdl::SDL-INIT-AUDIO) (STUFF-HERE))

Quote:Original post by cypherx
* Where are 'root-node and 'actor defined?


root-node is the root node of the scene graph and is implicitly defined by RM:WITH-ENGINE. The scene graph root node must be bound to a variable that the programmer can refer to as it is used to define camera pointing etc. In this code RM:WITH-ENGINE binds the root node to 'root-node', but this variable can be named anything (e.g. top-node, node etc.)

ACTOR is is little more complicated, as it is defined as a side effect of DEFSCRIPT.

DEFSCRIPT does five things:

1) It creates a new class, for example (DEFSCRIPT (SIN-BOUNCE) (STUFF-HERE))
2) It creates the object initializer function
3) It creates the UPDATE function that the engine calls every frame to update the state of the script.
4) It creates a new instance of the class and returns that.
5) It uses symbol-macrolet to create references to all members of the class; things like ACTOR, TRIGGER, TIMESCALE, CURRENT-FRAME are all implicitly defined. See below for an example of a slightly more complicated rotate script [1].

Quote:Original post by cypherx
* What's the point of calling "primtives" and "script" in add-actor?


:primitives; OpenRM allows many different types of primitives to be added to a single node; cubes, cylinders, quads, and triangle meshes can all be added to a single node. So, for example 1000 cube primitives can be added to a single node allowing all 1000 cubes to be translated or rotated using a single OpenGL command.

:script; The engine will execute the contents of :script once every frame.

Thanks for the comments.

[1] This script will rotate an object around an axis by x degrees a second:

(defscript (rotate)     (init ((dx 1.0) (dy 0.0) (dz 0.0)))  (rotate-actor actor dx dy dz))


To create a new rotate script and override the defaults, just do the following:

(NEW-ROTATE :DX 0.0 :DY 1.0)


The DEFSCRIPT macro actually expands into the following:

(PROGN  (DEFCLASS ROTATE            (SCRIPT)            ((DX :ACCESSOR DX :INITFORM 1.0 :INITARG :DX)             (DY :ACCESSOR DY :INITFORM 0.0 :INITARG :DY)             (DZ :ACCESSOR DZ :INITFORM 0.0 :INITARG :DZ)))  (DEFUN NEW-ROTATE (&KEY (DX 1.0) (DY 0.0) (DZ 0.0)) (MAKE-INSTANCE 'ROTATE :DX DX :DY DY :DZ DZ))  (DEFMETHOD UPDATE-ACTOR    ((ACTOR ACTOR) (SCRIPT ROTATE) ENGINE::TIMESCALE ENGINE::TRIGGER)    (SYMBOL-MACROLET ((ENGINE::CURRENT-TIME (ENGINE::CURRENT-TIME SCRIPT))                      (DX (DX SCRIPT))                      (DY (DY SCRIPT))                      (DZ (DZ SCRIPT)))                     (ROTATE-ACTOR ACTOR DX DY DZ)))  (NEW-ROTATE))

Hey guys,

I consider LISP a write-only language. Few years ago I implemented few non-trivial algorithms (such as finding shortest path in a graph, or solving the 9-puzzle problem) using LISP and I have to say it wasn't easy at all, but I made it work with a pretty clean code. However, a month after finishing, I realized I had troubles reading the code again. I think this can happen to everyone, who's not in touch with LISP every day.

I have a question I need to ask: Why exactly do you want to use LISP? LISP is a functional language and that's what it should be used for. Clean LISP style means no variable declarations, for-loops or anything resembling stuctured programming. These features are included in LIPS for same reasons as e.g. global variables in C++ i.e. you can always avoid using them, however in some cases they make your job a lot easier (I have never used any global variables in a C++ code). I believe using a scripting language would be a better choice than LISP.

Anyway, good luck with your experiment :-)

bboyBladeJ





This topic is closed to new replies.

Advertisement