Chandra's Phone: I just had a real ugly creepy guy stare at me from a bus stop. Creepy
Nathan: stay away from my wife, creepy dude!
Chandra's Phone: No worries i was in my car so i could easily run him over
There's a new competition going on at TIGsource called the "Cockpit Compo," wherein the design constraint is using a cockpit (or similar HUD). I doubt that I will have time to actually make an entry, but since I'm using Actionscript/Flash as my language/platform of choice now-a-days, I'm trying to look into a 3D library for Actionscript. Papervision3D seems like a favorite, so my next step is to find some tutorials and give 'em a shot. First, though, we have to figure out how to actually compile projects with Papervision.
1. Obtain the (free) Flex SDK, and put it somewhere in your system path. I wrote a post about setting up your Actionscript development environment; check it out if you haven't done this already.
2. Download the Papervision3D compiled library (.swc) or source (.as). It doesn't really matter which one, as I will explain how to use 'em both.
3a. If you got the .swc, put it in the same directory as your project files and rename it to 'papervision3d.swc'. When you compile, add the flag -include-libraries papervision3d.swc. That's it!
3b. If you got the .as source, extract it and put the '/org' directory in the same directory as your project files. Compile as normal, you don't need to feed mxmlc any extra flags.
To test out the process, get the "Simple HelloWorld Example for Papervision3D 2.0" .zip that's on the Papervision3D downloads page. Drop in the .swc or the /org directory (depending on what you downloaded), then compile using the instructions above. I got the .swc, put it in a subdirectory called '/libs' within the /src, and compiled with mxmlc Main.as -include-libraries libs/papervision3d.swc. If everything goes the way it should, a .swf will be produced that displays a crazily-textured spinning sphere.
I didn't really have to play Twilight Princess. I'd already attempted to play through the game twice — once on a friend's Wii (he moved out and took my save with him), and once on my own (I got bored with the slow, tedious pace of the start of the game). Normally, two false starts would be enough for me to realize that a game probably wasn't good enough to play through. This time was different. For whatever reason, even though I had a better game to play, I felt a strange, compelling desire to finish Twilight Princess. It's not as if I've beaten all the previous Zelda games, and therefore had to finish this one to put a notch in my controller; I never finished Wind Waker, or the GameBoy Color iterations. My feelings were unquantifiable.
Anyway, for whatever reason, I did play it. I don't particularly regret playing. Zelda is Zelda, after all. Whatever faults a Zelda title may have, it's still been put together by one of the most talented game development groups in existence. The puzzles are sometimes clever, there's enough new content to feel like you're doing something new, and the nostalgia that Link evokes are enough to carry the player through.
Twilight Princess had enough to carry me through, but just barely. There's not a lot of really new things in the game. The art direction is a weird mashup between Zelda 64 and Shadow of the Colossus. The geography in the game is all rehashed. There's a dark, alternate world that alters your physical form. The few actual new items are kind of lame: you use them a couple times, and then forget about them. The antagonist turns out to be a puppet for Gannon (surprise!). The game is not difficult at all; even in boss fights, there are breakable jars all over the room that supply you with hearts up the wazoo.
There's a lot of "extra" stuff packed into the game, but I never felt compelled to get 100% of the items. It's mostly there just for it to be there, not because it adds any sort of fun. This time around, it takes five pieces of heart to get a heart container, instead of four. Why? Just for more tedious collection, I guess. You can collect fish, bugs, ghost souls, and who knows what else. I don't even have to resist my OCD tendencies to ignore this stuff; it's just filler content.
What kept me going? The idea of Zelda, I guess. The memories of how fun the other games in the series are. I transposed the fun I had with other titles to what I was currently playing. That and my natural gamer's desire to finish the game, just to be able to say I finished it. It's like reading a long, boring classic. I don't know if the experience itself made me better, but it's done with, and I never have to do it again.
Importing graphics into your Flash program is all well and good. You can create movies or animation, but the real interesting thing is taking user input and having your program react to it. The way to do that in Actionscript is to add "Event Listeners" to objects you create. Whenever an event occurs (such as a keypress, mouse movement, or whatever), your Event Listener checks to see if it's supposed to do anything. If so, then it runs a function with code that you specify. So for example, say the user presses the "left arrow" key. Your keyboard input event handler sees this, and runs appropriate code (in this case, it might move a game character left).
One of the most basic events in Actionscript is the "enter frame" event. This triggers every time the SWF is redrawn, and basically corresponds to the SWF frame rate. In the following example, we're going to create a new class, and add an "enter frame" event listener to it, so that whenever a new instance of that class is created, a function will run at frame rate.
package {
import flash.display.Sprite;
import flash.events.Event; // Required to add event listeners
// Set our SWF framerate, width, height, and background color
[SWF(frameRate='30', width='640', height='480', backgroundColor='0xffffff')]
public class EventListenerExample extends Sprite {
[Embed(source="ball.svg")]
public var BallGraphic:Class;
// Variables used to store movement data
private var dx:int = 5;
private var dy:int = 5;
public function EventListenerExample():void
{
// Create instance of imported graphic
var b:Sprite = new BallGraphic();
// Add to this display object
this.addChild(b);
// Attach event listener
// Listen for "ENTER_FRAME" event
// Run the "enterFrame" function
this.addEventListener(Event.ENTER_FRAME, enterFrame);
}
public function enterFrame(e:Event):void
{
// Increment position
this.x += this.dx;
this.y += this.dy;
// If object passes beyond SWF boundaries,
// reverse direction
if(this.x >= 640 - this.width || this.x <= 0)
this.dx *= -1;
if(this.y >= 480 - this.height || this.y <= 0)
this.dy *= -1;
}
}
}
Save this code in a file named 'EventListenerExample.as'. You can see that we've elaborated a bit on our last example, importing and displaying an SVG graphic. However, this time we add some variables to the class that represent speed (delta-x and delta-y). We attach the event listener by calling this.addEventListener (Event.ENTER_FRAME, enterFrame);. The first argument is the type of event the listener is triggered by, and the second is the name of the function to run when the event is detected.
In the declaration of the 'enterFrame' function, we pass it details of the event that triggered it by putting e:Event in the arguments list. The function doesn't actually use that information, but simply moves our graphic around, bouncing off the "walls" of the SWF. Movement is just one possible application of the 'enter frame' event; collision detection can also be calculated this way, among other things.
One of the big downsides about not using the Flash IDE for development is that
it’s much more of a hassle to bring graphics into your program. The IDE has a
built in vector illustration program, which allows the user to create graphical
objects (or import them from Illustrator) and link them right up to a
corresponding Actionscript object. If you’re making programs with the Flex SDK,
however, getting graphics is a bit more of a chore. Fortunately, it’s not nearly
as difficult as programming graphics via Actionscript.
First, you’ll want to get a vector illustration program. Adobe makes
Illustrator, which might be your first thought, but we’re trying to do things
on the cheap here, otherwise we’d just get the Flash IDE.
Inkscape is a free program which
can save files in the SVG (scalable vector graphics)
format. Grab a copy of Inkscape, and fire it up (OS X users prior to 10.5 will
need to install X11).
Inkscape starts up by creating a default document, which is much larger than
anything we would normally use. From the ‘File’ menu, navigate to the ‘New 32x32
Icon’ option. Now, in the smaller image, use the ‘Circle’ tool to create a
circle. Take some time here to play around with Inkscape: experiment with
changing the color of the circle, give it a border, do whatever you like. When
you’re satisfied with what you have, click ‘Save’ and save the image as a ‘Plain
SVG.’ Now, create a new Actionscript file in the same directory as the graphic
file called ‘SVGExample.as’, and enter the following code:
package {
import flash.display.Sprite;
public class SVGExample extends Sprite {
[Embed(source="ball.svg")]
public var BallGraphic:Class;
public function SVGExample():void
{
var b:Sprite = new BallGraphic();
b.x = 100;
b.y = 100;
addChild(b);
}
}
}
The way that graphics are embedded is as follows: first, you use the ‘Embed’
syntax to specify where the image is, and then you link that embedded asset to a
unique class name. Here, I call it “BallGraphic,” but you can use anything that
makes sense to you. Creating an instance of that class (when I call new
BallGraphic()) loads the graphic, and it can then be added to a display
object container and shown on the screen. When you compile this code and run the
SWF, you should see your graphic on the stage. You can now easily import SVG
graphics (or even other image types, such as .gif/.jpg) via Actionscript.