Monday, October 1, 2012

Word War VI zoetrope


An edge-lit acrylic zoetrope based on the linux game Word War VI. The game was written by Steve Cameron, a fellow member of hackerspace TX/RX Labs. I was looking to do a zoetrope project and his vector based game was perfect for a straight forward laser etched animation.

The display is a series of 12 frames on a spinning acrylic disk with a ring of LEDs around the edge that are flashed every 1/12th of a revolution to make the animation appear. A stepper motor directly drives the disk which is being controlled by an Adafruit motor shield on an Arduino UNO. The LEDs are switched by one of the extra h bridges on the motor shield. All the timing is done open loop with the Arduino just counting nanoseconds between when to flash and when to step the motor. (code)


Word War VI game
Extracting the player ship and "cron" enemy from Word War VIs souce code was straight forward.  They were stored as line segments in a few C arrays.  Some simple python and SVG resulted.  Capturing animations of an explosion and the player ship's thrust was not so simple.  The animations played way to fast to do a screen captures and the volume of stuff going on the screen would have made dealing with them very time consuming anyways.  Steve gave me a patch to the game that dumped out every line drawn to a log file.  Dealing with the volume of lines had its own challenges.  Doing a straight conversion to SVG resulted in a file large enough to crash Inkscape.  The game engine has a separation between drawing objects and "sparks", which make up explosions, exhaust trails, volcano eruptions.  Some tweaks to the logging and now I had only the sparks on the screen.  Now the SVG of screen captures was small enough to work with in Inkscape and get the frames I needed separated.  The end result was four frames of exhaust and five of an explosion.

The animation was constructed in Inkscape using a mind numbing method of 12 overlapping layers with each element hand tweened between frames.  Each of the elements started as an imported SVG file.  The first frame with 30 degree slice outlined, player ship location, and the starting and end location of the enemy was set in place.  This starter frame was copied and then pasted in place on each of the 11 other layers.  I now had 12 frames with the same outline perfectly overlapped.  Since the enemy was going to move 1/12th the distance each frame, the total travel distance was measured and then divided and moved each frame, as well as the scaling as it got bigger near the ship.

A small python program was written to generate the moving star field.  Fifteen stars were randomly generated with distance and angle.  The max distance was 1/2 the total frame length so the stars would take two rotations of the disk to move the full frame.  Render each point 12 times moving at 1/12 distance increments and you have a moving stars.

The end result is 12 frames, each being 30 degrees of the final circle, after a lot of manual work in Inkscape.  There must be an easier way to accomplish vector animation.  (svg) (dxf)
Animation ready to laser cut

Inkscape has the ability to output a PNG image of each layer.  Using a little Imagemagick and you have an animated GIF.  This proved very handy for doing the final tweaking of the movements and timings.
An animated GIF of the whole cycle.
The animation frames were rotated around to form a circle and etched and cut out of acrylic with a Buildlog 2.x laser cutter I built.  The final construction needed four rounds of 3 mm plywood, nema 17 stepper motor, two shaft stops to hold the acrylic, and some black paper to go behind the acrylic.  The two center rounds would hold the LED strip, back for support, and front to cover the LEDs by overhanging the acrylic slightly.
Base and acrylic disk

LED light ring

Top cover in place

Arduino UNO with Adafruit motor shield

10 comments:

  1. Nice, it makes me wanna make something it to decorate my living room.
    Any ideas of making other animations and possible to change them ?

    ReplyDelete
  2. The animation can be changed by just swapping out the acrylic disk as long as the frame count is the same. You can start by looking at my Inkscape SVG file which shows the layers and how I did it. http://wiki.inkscape.org/wiki/index.php/Animation-(Timeline) has a large list of vector animation programs that I found after I made mine, there should be a better solution on there than Inkscape.

    ReplyDelete
  3. Cool - you should *so* document this on Instructables.com!

    ReplyDelete
  4. Wondering why you used 12 LEDs? We can only view one frame at a time.

    Actually the spirals are cool to watch.

    ReplyDelete
  5. There are way more then 12 LEDs in the LED strip along the edge. I liked how it looked when the whole thing was lit up and then I don't have to register the location of the slice boundaries.

    ReplyDelete
  6. Great project! I hope you don't mind I have shared this on our blog also- http://www.razorlab.co.uk/2012/10/laser-cut-acrylic-zoetrope/ Thanks!

    ReplyDelete
  7. Hello. Awesome project. It is a real inspiration. I was thinking of making a handcranked one. Do you have an opinion about what is the best rpm to use?

    ReplyDelete
    Replies
    1. If you are going to use a strobe like I did then 60 RPM is about the minimum speed. Any slower and the flicker is just too bad. More conventional zoetropes using slits can probably get away with slower.

      Delete
  8. HI! I'm doing something similar but I'm having some problems with the leds. The image I get it's to blurry. What kind of led strip are you using? Did you have to change de pulse width to make it work? Thank's!

    ReplyDelete
    Replies
    1. My code says the on pulse is 0.8 ms. I vaguely recall playing around with the time to get a good trade off between bright and less smearing. I just used some generic white strip I had laying around from China. I don't think the LEDs really matter as long as they are not some smart strip with individual addressing. Mine just go on and off via a transistor (inside the motor shield).

      Delete