Mid-Core Gamer Manifesto
A few weeks back, we here at 8bitrocket.com declared ourselves to be Mid-Core Gamers. Jeff's declaration was met with a smattering of agreement from other sites, but it was not an earth shaking response. Still, it was encouraging, and since we not only believe in the theory of Mid Core Gamers , but also live it every day, we have decided to explore this idea a bit further. us.
Also, we are putting together a Manifesto of the top-10 things that we Mid-Core Gamers would like to see in games targeted to our demographic. This is in no-way final, but it is our best first guess from what we currently know.
1. Save Anywhere/Autosave/Respect Our Time:
We only have time to play games in roughly 5-60 minute increments. We need the ability to save our game at a moment's notice. If a game's difficulty is designed around the fact that is cannot be saved anywhere, it is too hardcore for us. Not only do we need to save anywhere, but we don't want to waste the time we have invested in the game if we can't save any where. An alternative or addition to "Save Anywhere" is an intelligently used 'autosave' feature.
We would like something significant to happen in a game during the time period we have allotted to play. A plot point, new item, finished race, completed mission or task should take roughly 30 minutes (give or take 15 minutes) to achieve. This allows us to see progress in a game, and keeps us interested in continuing. Games with long cut scenes (i.e Final Fantasy X 30 minute intro) are rendered unplayable because we never have enough time to get past the exposition and into the game.
Our free time is precious, and it needs to be respected.
2. Games Should be Affordable
We are not suggesting that new games should cost $.99 nor are we suggesting that state-of-the-art releases should only cost $29.99. But we are saying this: We can't justify spending $59.99 on games each month unless they can also be played with the rest of our families (read: Wii). For games targeted to us, $19.99 is a perfect price, but $9.99 is nicer while $29.99 is our upper limit. $.99 is great price for downloadable classic games. Also, we Mid-Core Gamers can be very patient. When Elder Scroll Oblivion was released, it fit perfectly into our demographic (see below), but the price was far too high. Now, after nearly two years, the price has come-down to $29.99. Bingo. We can bide our time for a good game.
3. Reasonable Graphic Choices
We don't buy computer hardware like we used to. We don't upgrade for the sake of upgrading, we don't care too much about getting top FPS scores. In fact, many of our games are played on laptops with good (but not the latest) graphics cards. Games do not need to employ the latest 3D graphic technology just for the sake of having it, or require the latest OS. Games can have nice graphics (2D or 3D), but the most important aspect of the graphics is that they fit the game and serve it well.
4. We Love Single Player Games
Single-player games are our bread-and-butter. We understand that the gaming world is filled with amazing hard-core and multi-player gaming experiences. We also realize that those games usually take more time and resources than we have available. For this reason, we eat-up single-player games. Even single-player games that appear to be "hard core" would fit the Mid-Core mold if they adhere to the other parts of this manifesto. A great example of a single-player game that fits the Mid-Core is Elder Scrolls Oblivion. It is an expansive, yet "light" RPG that fits many of the aspects of this manifesto: (engrossing depth, $29.99 price point, works on a good laptop, can save anywhere, etc).
5. Cooperative Games On One Screen Are Gold
Cooperative two-player games are gold. If they are deep enough to appeal the hard-core portion of our gamer-personality, but easy enough so we can get the wife/husband/significant other and/or the kids involved, we can probably play them beyond the 60 minute barrier. A very good example of this type of game is Lego Star Wars. It's appeals to our inner geek, has long and interesting levels, but allows two people to play on the screen at once. Of course, Lego Star Wars did not allow the game to be "saved any where", but it fit many of the other aspects of this manifesto.
6. Multi-player Games: Play Anytime, Find Friends Easily, No Fees, Voice Chat Not Necessary
We do enjoy playing multi-player games online with friends and sometimes, even strangers. However, there is a limit to what we can handle. First off, an "instant and anonymous multi-player mode" similar to the Wii version of Guitar Hero can work very well because it means we can compete quickly, but each game only takes a few minutes. However, if we do want to play against friends, you need to make it very easy. We need to be able to tell very quickly if someone we know is online, and if so, connect with and challenge them instantly. The Wii is terrible for this purpose, XBox Live is better, but it requires a monthly fee (see below). If Playstation Home remains free, it might be the perfect model. Also, one more thing. We don't want to hear 13 year old kids curse at us for not moving quickly enough. If your multi-player games requires us to participate in voice-chat, we are probably not interested.
7. "Casual" Games Don't Have To Be Simple Games
We Mid-Core Gamers love all types of games. To some extent, Mid-Core gamers are "casual" gamers in that we do enjoy many of the types of games that are geared towards the "casual" demographic. However, we tend towards "casual" style games with a bit more depth. For instance, Bejeweled is a passable diversion, but Puzzle Quest is an obsession. Bookworm Deluxe is nice way to kill some minutes, but Bookworm Adventures is an unshakable addiction. Where there is depth, but with the aforementioned save anywhere feature, we will be there.
8. Size Does Not Matter
The last two commercial games I have installed on my computer have been just about 5.5 GB in size each. 5.5 Gigabytes! I believe just about every single game ever made before 1994, could fit in 5.5 GB with room for 1000's more. Graphically those games could never compare with the modern 5.5 GB behemoth, but game-play and depth wise? A lot of those pre 1994 games had much more than in some modern games. The point here is not that "retro games are better" but that the size of the game on the hard drive is not necessarily proportional to its quality as piece of entertainment. Most good Flash games download in less than 1 megabyte. Good, downloadable PC games can be had that are under 20 megabytes (i.e.: New Star Soccer). Mid-Core Gamers do not need bloat, they need well designed games with solid game-play. If a game is worth the 5.5 GB required, that is fine, but if not, it eill probably be removed fairly quickly and never played again.
9. No need to be "mature" for the sake of being "mature"
Mid-Core Gamers are mostly adults. Mid-Core Gamers were also once 13 years old, and also once laughed about the name Lake Titticaca" in Social Science class. However, that does not mean we need resort to only consuming "mature" material, or that our in-game humor has to be at the scatological level. Yes we do play games, but we don't want to have to hide them, their boxes, or the game magazines we read from our families simply because they might have a cover featuring, for example, an artist' rendition of scantily-clad female robot tearing the intestines out of space marine. Mature content is not necessarily taboo, it just needs to be used to serve the story, not in place of it.
10. Yes To One-Time Fees, Rarely To Monthly Fees,
Mid-Core Gamers are not fond of monthly fees. We can not always subscribe to your game, live service, player matching server, etc. if it means we have to pay for it month after month. We can't afford it, and we don't want to have to explain this fee to our husband/wife/significant other. For the rare game, a monthly fee might be workable, but we won't last very long. However, if there is a compelling reason, we will pay one-time fees. One-time fees for updates, new chapters, sequels, power boosts (i.e. Adventure Quest), add-on modules etc. are acceptable. However, the one-time fees must be reasonable, and offer a significant benefit. A One-time fee that allows us to buy things that should have been included in the game in the first place
(i.e. Horse Armor) is not acceptable.
Axioms
1. There Are Exceptions To All These Rules
2. Midcore Gamers can be of any age
3. Any game can be a Midcore Game.
4. In some cases Midcore is not the game, but how you play the game
More On Mid-Core:
- Check out the new Midcoregamer.com website!
- Help define Midcore Gamer by contributing to the Midcore Gamer Wiki
Flash Game Development Blog World : January 31, 2008
The latest in Blog entries that might interest Flash game developers.
Gaming Your Way has a new entry on Wii Game Development in Flash. It is basically a link to another site that has compiled 73 tips and tutorials for making home-brew Wii games. I've been itching to pimp Squize and nGFX's blog here and I finally got my chance. These guys are top class. They plain know how to make great games.
Mike Grundvig (of Multiplayer Flash engine GODS, Elecrotank) extends a thread he started on Flashkit with a healthy discussion on using Binary Data for maps in Flash. It's A great read. Nice work, Mike!
Our very own series on advanced blit techniques applied to an Asteroids game should also be checked out if you have time. I just put Part 2 up yesterday.
Tutorial: Using Flash CS3 and Actionscript 3 to create Atari 7800 Asteroids Part 2
In Part 1 we covered creating an array of pre-calculated vector values for 36 angles. These 36 angles were used to move the player ship on the screen in one of the 36 rotated directions. We also covered a basic animation cache from a library object by rotating its container and taking a BitmapData snapshot of each frame. We then created a simple game engine and got the player ship moving about the screen, thrusting in the right direction. We applied some simple friction and inertia principles and used a BLIT technique on every frame to to copyPixels to a single display object.
In Part 2, we will take a smaller bite and cover how to cache the animation of a library object with a frame based animation for our asteroid rocks. We will add the rocks to our game loop and see them animating on the screen, running through their cached animation frames and being BLITTED to our single display object with copy pixels.
I created the rock frames by in a round about manner. I am using the Atari 7800 version of Asteroids as my basis for this game, so I started by firing up my MESS emulator and playing the game. The 7800 version of Asteroids is not as well known as the arcade version, but it was my favorite version, and one of the best games released for the 7800. It has multiple different colored and shaded rocks to shoot, but I just need one for the tutorial, so I chose to model the green rock. To do this, I decided to record the screen while I played the game. I fired up my copy of Replay Video, and had it record the screen for 30 seconds while I played 7800 Asteroids in MESS. I then brought the video into Sony Vegas for editing. I dropped the video into the timeline in Vegas, and used the frame advance scroll bar to move a couple frames at a time through the video of the game play. I zoomed in on the green rock and at each key frame change, I saved a JPEG of the screen. I pulled all of these JPEGs into Fireworks and editing them each down to an 18x16 image. Then, I deleted the background of each frame (there were 12 good frames). I save each one out as a .PNG file and imported all of them into Flash CS3. I built clip in the library called "rock" with one frame by putting a PNG on each of 12 key frames.
The rock clip in the library looks like this (at 200% zoom):

As you can see, it is at 0,0 on the stage. To actually cache a library clip with timeline animation, we must add this clip to a holder clip that we can export. The holder clip is called "rockToCache" in the library, and its stage looks like this:

The "rockToCache" clip has an instance of the "rock" clip set at 0,0. I increased the size from 18x16 to 36x32. That will make it more pixilated, but I think the other version was too small. If this was for a commercial game, I might clean up all of the frames by tracing over vectors before and then zoom in if needed. I gave the ":rock" clip an instance name of "clip" and set the "rockToCache" linkage class name to "RockToCache".
Now, on to the Actionscript needed to cache he animation ands add rocks to our game loop.
In our Main.as class, I have added these lines in the variable declaration section (below the class definition and before the constructor).
[cc lang="javascript" width="550"]
//** part 2 variables
var aAsteroidAnimation:Array=[];
var asteroidAnimationTimer:Timer;
var asteroidHolder:RockToCache;
var asteroidFrames:int=12;
var aRock:Array=[];
var level:int=1;
var rockPoint:Point=new Point(0,0);
var rockRect:Rectangle=new Rectangle(0,0,36,36);
var levelRocksCreated:Boolean=false;
[/cc]
aAsteroidAnimation is an array that will hold 12 BitmapData objects representing the 12 frames of animation in the rock clip.
asteroidAnimationTimer is a Timer object that that will count up to 12.
asteroidHolder is an instance of the RockToCache library clip. We only need one and it will be used exclusively as a holder to run through the "rock" frames.
aRock is an array that will hold all of the instances of our rock objects for game play.
level is a integer that will hold the current game play level. Eventually, when we add in collision detection, we will have the game move to a new level when all of the rocks are cleared.
rockPoint is a pre instantiated point object used in the copyPixels operation for all rocks to the canvasBD. The rockPoint will be changed to the x and y coordinates of the current rock before the copyPixels is completed.
rockRect is a static rectangle instance that simply represents a bounding box for the max size of our rock (36x36).
levelRocksCreated is the first of our game control variables. When we start a new level, this will need to be set to false;
[cc lang="javascript" width="550"]
private function animationTimerCompleteHandler(e:TimerEvent):void {
createAsteroidAnimation();
//startGame();
}
[/cc]That sets up the variables needed for this part. Now, there was a change to the animationTimerCompleteHandler from part 1. We have commented out the startGame() call and have replaced it with a call to a new createAsteroidAnimation() function.
[cc lang="javascript" width="550"]
private function createAsteroidAnimation():void {
animationCounter=1; // match frame on timeline
asteroidHolder=new RockToCache();
asteroidHolder.x=100;
asteroidHolder.y=100;
addChild(asteroidHolder);
asteroidAnimationTimer=new Timer(1,asteroidFrames);
asteroidAnimationTimer.addEventListener(TimerEvent.TIMER, cacheAsteroid);
asteroidAnimationTimer.addEventListener(TimerEvent.TIMER_COMPLETE,
asteroidAnimationTimerCompleteHandler);
asteroidAnimationTimer.start();
}
[/cc]
The createAsteroidAnimation() function sets up the Timer based loop that will jump to each frame of the "ship" library clip and cache (or store) the pixel data from that frame in a BitmapData object. In part 1, we stored all of the rotations of the ship clip my manipulating the rotation property of its holder clip called "shipHolder". For the rock, we will use a different method. On each iteration we will "gotoAndStop()" the next frame on the timeline and "draw()" those pixels to a BitmapData object, and then add that object to our aAsteroidAnimation. I did the rock this way because it is the most likely delivery method that a designer might give you for a tween-like animation. We will explore one more method of creating an array of BitmapData objects when we use a sprite sheet to create the animation loop for the playerShip's missiles.
animationCounter=1;
First we set out animationCounter to be 1. We don't start with 0 because we want to make it easier on ourselves to follow the timeline frame of the rock. Since the timeline is "1 based" rather than "0 based" we set this to 1.
asteroidHolder=new RockToCache();
We create an new instance of out RockToCache library item. Remember, this is basically a holder for a instance of our rock library item named "clip".
asteroidHolder.x=100;
asteroidHolder.y=100;
addChild(asteroidHolder);
These merely put the holder on the screen in a place we can see it. If we set the frame rate of the movie very low, we can see the actual cache happen. If not, this location doesn't matter. We also add the asteroidHolder to the display list to make sure we can see it and cache its contents.
asteroidAnimationTimer=new Timer(1,asteroidFrames);
asteroidAnimationTimer.addEventListener(TimerEvent.TIMER, cacheAsteroid);
asteroidAnimationTimer.addEventListener(TimerEvent.TIMER_COMPLETE, asteroidAnimationTimerCompleteHandler); asteroidAnimationTimer.start();
These 4 lines create a timer that will run 12 times. On each of the 12 iterations it will call the cacheAsteroid method and when it is complete with the 12 iterations it will call the asteroidAnimationTimerCompleteHandler. The final line starts the timer on its way.
[cc lang="javascript" width="550"]
private function cacheAsteroid(e:TimerEvent):void {
asteroidHolder.clip.gotoAndStop(animationCounter);
var spriteMapBitmap:BitmapData=new BitmapData(36,36,true,0x00000000);
spriteMapBitmap.draw(asteroidHolder,new Matrix());
aAsteroidAnimation.push(spriteMapBitmap);
//trace("caching " + animationCounter);
animationCounter++;
}
private function asteroidAnimationTimerCompleteHandler(e:TimerEvent):void {
trace("cacheAsteroid 7");
startGame();
}
[/cc]
The cacheAsteroid() method is called 12 times and on each call it draws the current frame of the rock clip (referenced as asteroidHolder.clip) to a new Bitmapdata object. That object is added to the aAsteroidAnimation array.
asteroidHolder.clip.gotoAndStop(animationCounter);
This line simply instructs the clip instance of the "rock" clip inside the asteroidHolder to move to the current frame represented by the animationCounter;
var spriteMapBitmap:BitmapData=new BitmapData(36,36,true,0x00000000);
Here we create a new BitmapData object and set it to 36x36 with transparency. And set the transparency threshold at 0 and the background fill color to black. Since the threshold is 0, we don't see any of the background color show through.
spriteMapBitmap.draw(asteroidHolder,new Matrix());
Here we draw the current state of the asteroidHolder to the new BitmapData object. The asteroidHolder contains the "clip" which is an instance of the rock library item that has been moved to the current frame of animation.
aAsteroidAnimation.push(spriteMapBitmap);
animationCounter++;
These two lines simply add the BitmapData object to the aAsteroidAnimation array and increase the animationCounter so the gotoAndStop will go to the next frame on the next interval.
The asteroidAnimationTimerCompleteHandler() method simply starts our game. The method that starts our game will change as we add to the game. It will always be the last method of the setup phase that calls startGame.
[cc lang="javascript" width="550"]
private function runGame(e:TimerEvent) {
checkKeys();
updatePlayer();
updateRocks();
drawBackground();
drawPlayer();
drawRocks();
}
[/cc]
The runGame() method has been modified from the part 1 version. We have added 2 functions to handle rocks. The updateRocks() method does all of the work in creating the initial rocks for the game (or level) and also updates all of the rocks on the screen based on their individual dx,dy, and speed variables.
[cc lang="javascript" width="550"]
private function updateRocks():void {
if (!levelRocksCreated) {
for (var ctr:int=0;ctr
var tempRock:Object=new Object();
var randInt:int=int(Math.random()*36);
var randInt2:int=int(Math.random()*asteroidFrames);
tempRock.dx=aRotation[randInt].dx;
tempRock.dy=aRotation[randInt].dy;
tempRock.x=20;
tempRock.y=20;
tempRock.animationIndex=randInt2;
tempRock.frameDelay=3;
tempRock.frameCount=0;
tempRock.speed = (Math.random()*level)+1;
trace("tempRock.speed=" + tempRock.speed);
aRock.push(tempRock);
}
levelRocksCreated=true;
}
for each (tempRock in aRock) {
tempRock.x+=tempRock.dx*tempRock.speed;
tempRock.y+=tempRock.dy*tempRock.speed;
if (tempRock.x > stage.width) {
tempRock.x=0;
}else if (tempRock.x < 0) {
tempRock.x=stage.width;
}
if (tempRock.y > stage.height) {
tempRock.y=0;
}else if (tempRock.y < 0) {
tempRock.y=stage.height
}
}
}
[/cc]
The updateRocks() method takes care of two main duties for the rocks. Currently, the first thing it does is create rocks for the level and once it is does, it sets levelRocksCreated to true; We do this here out of convenience, but in a later part of this tutorial, it will probably be moved to a section that inits all new levels. We haven't implemented our gameLoop or game control structure, so it is fine here for now.
The other important task for this method is to loop through all for our rocks on each game loop timer tick and update their x and y properties.
if (!levelRocksCreated) {
for (var ctr:int=0;ctr
These two lines begin the iteration to create the rocks for the level. I chose to create 3 rocks for the first level and then add one for each additional level. At some point we will put a cap on the total to start with, but for now we will not do so.
var tempRock:Object=new Object();
var randInt:int=int(Math.random()*36);
var randInt2:int=int(Math.random()*asteroidFrames);
tempRock.dx=aRotation[randInt]. dx;
tempRock.dy=aRotation[randInt]. dy;
tempRock.animationIndex=randInt2;
Here we create a generic object to hold our rock. Next we randomly choose a random number from 0-35. We will use this to index our aRotation array do obtain random dx and dy vectors for this rock. We also choose a random frame of animation for our rock to start on so all of the rocks don't rotate in sync.
tempRock.x=20;
tempRock.y=20;
tempRock.frameDelay=3;
tempRock.frameCount=0;
tempRock.speed = (Math.random()*level)+1;
aRock.push(tempRock);
This set of code takes care of some setup for the new rock. First, we currently are starting all new rocks at 20,20 on the screen. We set the frameDelay for the rock at 3. This will count 3 frames between each animation change so our rock won't appear to spin too fast. The final setup for the rock is to give it a random speed to multiply the dx and dy values by. We randomly choose a number between 0 and the current level, then add 1 so if a number below 1 is randomly selected . We do this so our multiple won't create a speed slower than the basic dx and dy values. Lastly, we push the rock to the aRock array.
The last part of this method moves the rock to its new position in memory and then checks to see if it is off the screen. If it is, it warps it back to the other side. I haven't put in the centerx and centery values for the rocks yet, but we we add them for collision detection in a later part of this tutorial series. When we do that, we will revisit this code and update the centerx and centery before.
tempRock.x+=tempRock.dx*tempRock.speed;
tempRock.y+=tempRock.dy*tempRock.speed;
These two lines multiply the rock's current movement vectors by the current rock speed. The final lines of the method handle the warping off the sides of the screen based on the current x and y values for the rock.
[cc lang="javascript" width="550"]
private function drawRocks() {
var rockLen:int=aRock.length-1;
var ctr:int;
for each (var tempRock:Object in aRock) {
rockPoint.x=tempRock.x;
rockPoint.y=tempRock.y;
canvasBD.copyPixels(aAsteroidAnimation[tempRock.animationIndex],
rockRect, rockPoint);
tempRock.frameCount++;
if (tempRock.frameCount > tempRock.frameDelay){
tempRock.animationIndex++;
if (tempRock.animationIndex > asteroidFrames-1) {
tempRock.animationIndex = 0;
}
tempRock.frameCount=0;
}
}
}
[/cc]
The final new method in part 2 draws the rocks to the canvasBD. It's basic job is to loop through all of the rocks, set the rockPoint variable to be the location of the current rocks upper left-hand corner, and then BLIT the pixels of the rock to the canvasBD.
Finally, after the BLIT, it increases the frameCount for the rock. If the frameCount is greater than the frameDelay, it changes the animation index for the next game timer tick. It checks to make such it hasn't increased passed its upper bounds, and if it has, it sets the animationIndex to 0.
That's it, below is the new working example. Use the up arrow to apply the thrust, and the right and left arrows to simulate the rotation of the ship.
The source files are here: 7800 Asteroids Tutorial Part 2 source files
Flash Game Development Blog Finds : January 23, 2008
The latest in Blog entries that might interest Flash game developers.
Jobe Makar's Blog has a very interesting entry on enemy AI and predictive shooting. He is creating a Tower Defense like game and needed to figure out at what angle to fire off a projectile at a moving target. He has created a system that is perfect every time, but randomness can be added to make it some what less intelligent.
Interactive Crap has a great new entry on applying Event Bubbling in AS3, and it is especially applicable to Event Driven code for games.
http://www.sebleedelisle.com/ has a wealth of new posts, but the most recent has to do with seamlessly looping video in Flash. This is something we need to do in games once in a while. It is a similar idea to what I have been doing with many pre-rendered clips in my games - use BitmapData to hold the frames and quickly flip through them. It is an interesting experiment and one that should interest many developers. Jobe has been doing this for a while with video.
flashconnections.com has a very exciting post about a Tyler Larson created SWF Swapper for HTML/CSS based content. Basically, it creates a SWF on the fly out of your HTML/CSS content and it is fully open source. I'm not quite sure yet what this might means for games, but it is very interesting, none the less.
Keith Peter's Bit-101 Blog has many new entries. The latest is on re-dispatching custom events. Like Jobe, but for math based coding instead of just games, Keith is a master. His code and ideas can be applied to any type of Flash content, especially games.
Grant Skinner has some very useful code on creating a seeded random value in AS3. Grant is also an old-hand master, and his brilliance is always an interesting read.
At The O'Reiily site (but linked to from his blog) Colin Moock (a fellow Atari head) has a great article on whether or not AS3 is difficult to use and or learn. He debunks many of the ms-conceptions on how difficult AS3 actually is. I agree with him 100%. The problem is not with AS3, but those who choose to code in a specific manner in AS3. Sure, you can do a full MVC model in AS3 (you also could have in AS2 and AS1), but you can also write very simple control code if you need to. There are some advantages to doing it in AS3. The document class is something that all developers should embrace. Especially since it can be used like a class version of embedded timeline code if you need it. Anyway, read what Colin has to say on the matter.
Mochiland has new leader boards!!! And s $25K contest to boot. Talk about the best thing to happen for the little guy in a long time...
Tutorial: Using Flash CS3 and Actionscript 3 to create Atari 7800 Asteroids Part 1
In this series of tutorials, we will explore some optimization techniques to create a fully blitted Asteroids style game. Although the game we will create will be a relatively simple version of Asteroids, the techniques we will use to optimize it will be advanced. We will explore these optimization techniques:
1. Pre-calculating and storing rotation and thrust delta x and delta y values in an array (so they don't need to be calculated on the fly)
2. Pre-caching sprite rotation animations in an array of BitmapData objects
3. Using one display object to "blit" (bit block transfer) all graphic images to.
In part 1, we will tackle all three of these and get the player ship moving about the screen. In part 2, we will add in blitted asteroid rocks animations. In part 3, we will add blitted ship missiles. In part 4, we will add the bitmap collision detection a simple particle emitter and a pool/farm of particles.
I am modeling some of my graphics for this game from the Atari 7800 version of Asteroids. I am doing this because I want to create a version that might be familiar to some people but also because I don't plan to license or sell this game. If you plan to use this as a base for a game that you will submit for license opportunities, then you must change all of the graphics.
Getting Started
Usually I would create a series of classes for a game like this, but to show an optimized game, and for space reasons, I will forego this. I am going to create the entire game in one class called Main. I don't plan to use any other classes for game objects.
Main will be the "document class" of my .fla file. In my library for part 1, I have 4 basic objects:

The background is a 400x400 vector image of a black sky and various stars. It has a linkage id of Background. I want a semi-complicated background to show how to blit game objects on top with transparency. This is not the most complicated image, but it has enough detail for a demonstration. The stars are made with the white circle clip called star.

The player ship is a 20x20 png I imported called flash0.png. I actually will rename this later. This ship png file has been placed inside ship movieClip a -10,-10. The clip has an linkage id of Ship. We have placed it at its center on on 0,0. That will be the point of rotation.

The stage for the game is 400x400 with a white background, running at 120FPS. The 120 is important because it will allow us to "pre-cache" our animations as fast as our plug-in version will allow. The document class will be called Main.

The Main class
The Main class will be stored in a file called Main.as. We will go over some specific parts of the class next in detail. Afterward, I will give the full text of the current version for part one and the .fla file for download.
[cc lang="javascript" width="550"]
package {
import flash.display.Bitmap;
import flash.display.MovieClip;
import flash.events.TimerEvent;
import flash.utils.Timer;
import flash.display.BitmapData;
import flash.geom.*;
import flash.events.KeyboardEvent;
public class Main extends MovieClip {
var aRotation:Array=[];
var aShipAnimation:Array=[];
var shipAnimationArrayLength:int;
var ship:Ship;
var shipHolder:MovieClip;
var animationTimer:Timer;
var animationCounter:int;
var playerObject:Object;
var canvasBD:BitmapData;
var canvasBitmap:Bitmap;
var backgroundBD:BitmapData;
var backgroundSource:Background;
var gameTimer:Timer;
var backgroundRect:Rectangle;
var backgroundPoint:Point;
var playerRect:Rectangle;
var playerPoint:Point;
var aKeyPress:Array=[];
var spriteHeight:int=20;
var spriteWidth:int=20;
public function Main() {
trace("main");
createObjects();
createRotationArray();
createShipAnimation();
}
[/cc]
The Main() constructor initializes the game by creating objects, and caching values and Bitmaps needed for rotation and animation. There are quite a few imported classes and variables that need initializing. I will go into detail on their use in the following sections.
[cc lang="javascript" width="550"]
private function createObjects():void {
//create generic object for the player
playerObject=new Object();
playerObject.arrayIndex=0;
playerObject.x=200;
playerObject.y=200;
playerObject.dx=0;
playerObject.dy=0;
playerObject.movex=0;
playerObject.movey=0;
playerObject.acceleration=.3;
playerObject.maxVelocity=8;
playerObject.friction=.01;
playerObject.centerx=playerObject.x+spriteWidth;
playerObject.centery=playerObject.y+spriteHeight;
playerRect=new Rectangle(0,0,spriteWidth*2,spriteHeight*2);
playerPoint=new Point(playerObject.x,playerObject.y);
//init canvas and display bitmap for canvas
canvasBD=new BitmapData(400,400,false,0x000000);
canvasBitmap=new Bitmap(canvasBD);
//init background
backgroundSource=new Background();
backgroundBD=new BitmapData(400,400,false,0x000000);
backgroundBD.draw(backgroundSource,new Matrix());
backgroundRect=new Rectangle(0,0,400,400);
backgroundPoint=new Point(0,0);
}
[/cc]
The createObjects() method begins by using a generic object called playerObject to hold attributes for our player ship.
playerObject.arrayIndex=0;
This is the current index of animation for the player. We will store 36 individual BitmapData images an array and this will be the index of that array to use for display. We will also store a pre-calculated array of delta x and delta y values for thrusting and firing to each of these 36 angles. This index will be used in that array also.
playerObject.x=200;
playerObject.y=200;
We will start that player at 200,200 on the screen. These will store the players x and y values as he moves across the play screen.
playerObject.dx=0;
playerObject.dy=0;
These hold the current delta x and delta y values for the player associated with the direction he is floating on the screen. Since the player is not floating at the beginning of the game, these values are set to 0.
playerObject.movex=0;
playerObject.movey=0;
These hold the current speed and direction that the player is heading. This combines the current acceleration with current direction and speed of the player ship.
playerObject.acceleration=.3;
This is the number of pixels added to the player x and y values when the UP arrow is pressed.
playerObject.maxVelocity=8;
This will limit the maximum speed of the ship in any x or y direction.
playerObject.friction=.01;
Air friction is added each frame to the player ship so inertia will not have it float on forever with out more acceleration.
playerObject.centerx=playerObject.x+spriteWidth;
playerObject.centery=playerObject.y+spriteHeight;
We will keep a calculation of the center x and y of the player because the current x an y represent the top left corner of the ship Bitmap. We need the center value to make calculations easier.
playerRect=new Rectangle(0,0,spriteWidth*2,spriteHeight*2);
playerPoint=new Point(playerObject.x,playerObject.y);
The playerRect and playerPoint are used in blitting with copyPixels to our display canvas. We pre-create these so they don't need to be created each frame.
Next we create a canvas to blit all of our game objects to.
//init canvas and display bitmap for canvas
canvasBD=new BitmapData(400,400,false,0x000000);
canvasBitmap=new Bitmap(canvasBD);
The canvasBD is a non transparent BitmapData object that will hold the current display. canvasBitmap is the only display object in the game. It holds the canvas, which in turn holds the ship and the background blitted images.
Finally, we create our background image.
//init background backgroundSource=new Background();
backgroundBD=new BitmapData(400,400,false,0x000000);
backgroundBD.draw(backgroundSource,new Matrix());
backgroundRect=new Rectangle(0,0,400,400);
backgroundPoint=new Point(0,0);
The background is initialized by creating an instance of the Background object in the library. It is a 400x400 non-transparent vector MovieClip. Because the background is a vector in the library, it needs to be drawn onto the backgroundBD with the draw() method. The backgroundRect and backgroundPoint are pre-created and pre-calculated to save cycles when we blit this back to the canvasBd each frame.
[cc lang="javascript" width="550"]
private function createRotationArray():void {
shipAnimationArrayLength=36;
var rotation:int=0;
for (var ctr:int=0;ctr
var tempObject:Object={};
tempObject.dx=Math.cos(2.0*Math.PI*(rotation-90)/360.0);
tempObject.dy=Math.sin(2.0*Math.PI*(rotation-90)/360.0);
trace(ctr+":dx=" + Math.cos(2.0*Math.PI*(rotation-90)/360.0));
trace(ctr+":dy=" + Math.sin(2.0*Math.PI*(rotation-90)/360.0));
aRotation.push(tempObject);
rotation+=10;
}
trace("aRotation[5].dx=" + aRotation[5].dx);
}
[/cc]
The createRotationArray() method is used to pre-calculate the delta x and delta y value for rotation and movement at a specific angle. The 36 angles we will create correspond to the 360 degrees in a circle, taken in 10 degree increments. If you want more precise rotation animation, you can change the shipAnimationArrayLength to be a multiple of 36 (such as 180. If you do that, you will need to change the rotation+=10; to rotation+=2; (180*2=360). The product of the 2 much be equal to 360. The loop calculates to dx and dy values in radians and places them into a generic object and then pushes that generic object into the aRotation array;
[cc lang="javascript" width="550"]private function createShipAnimation():void {
shipHolder=new MovieClip();
shipHolder.x=50;
shipHolder.y=50;
ship=new Ship();
ship.x=spriteWidth;
ship.y=spriteHeight;
shipHolder.addChild(ship);
addChild(shipHolder);
animationCounter=0;
animationTimer=new Timer(1,36);
animationTimer.addEventListener(TimerEvent.TIMER, cacheShip);
animationTimer.addEventListener(TimerEvent.TIMER_COMPLETE, animationTimerCompleteHandler);
animationTimer.start();
}
[/cc]
The createShipAnimation() sets up our timer based cache of the ship. The ship will start at rotation=0 and be moved 10 pixels each iteration until all 36 rotated images can be placed in an array of BitmapData objects. First we create a display object (in this case a MovieClip) to hold the Ship from our library. We do this because if we simply added the ship to the display list and tried to rotate it, Flash would not cache the rotations and we would get 36 BitmapData objects of the Ship pointed up (the original position). Also, a BitmapData object uses only the positive portion of the coordinate system. To rotate an object around its center, 1/2 of it needs be be in the negative x and y space. So, we placed the ship at -10,-10 in its MoveiClip, but we can't just cache that because even if the rotation worked, it would only cache 1/2 of our ship (the portion in the positive coordinate space). So, we place the ship in the shipHolder, and then rotate the ship inside the shipHolder to get a clean rotation.
We create a Ship object called ship and place it at spriteWidth, spriteHeight. Those have been preset to be 20,20. The reason we do this to to accommodate for the changes in width and height as the ship is rotated. To be safe, use double the ships actual height and width as the size of the BitmapData to cache. So, we put the ship at 20,20 in a 40x40 BitmapData object and it has the freedom rotate without clipping the corners.. The ship is added to the shipHolder display list and the shipHolder to the main timeline display list.
Next, we create an timer object and some events that will allow us to move through 36 ticks of animation as fast as the frame rate will allow. On each of the 36 ticks, we call the cacheShip method, and when all 36 are complete, we call the animationTimerCompleteHandler.
[cc lang="javascript" width="550"]private function cacheShip(e:TimerEvent):void {
var spriteMapBitmap:BitmapData=new BitmapData(spriteWidth*2,spriteHeight*2,true,0x00000000);
spriteMapBitmap.draw(shipHolder,new Matrix());
aShipAnimation.push(spriteMapBitmap);
trace("caching " + animationCounter);
animationCounter++;
ship.rotation+=10;
}
private function animationTimerCompleteHandler(e:TimerEvent):void {
startGame();
}
[/cc]
After all of the set up, the cacheShip method is relatively simple. On each of the 36 timer events (ticks), it creates a new Bitmapdata object called spriteMapBitmap that is 40x40 (or the spriteWidth * 2, spriteHeight *2) and is transparent. Next it takes the current contents of the shipHolder movie clip and calls the draw() method of the BitmapData class to place it inside the fresh spriteMapBitmap Bitmapdata object. Its last jobs are to push the new BitmapData object to the ship's array pf animation frames (aShipAnimation), and set the ship up for the next frame by increasing the rotation by 10 (ship.rotation+=10);
The animationTimer calls the animationTimerCompleteHandler when it has moved through all 36 timer ticks. We are now complete with part 1's animation caching, and will now move onto the beginning of our game loop. We will have more animation and Bitmap Caching to perform as we add the rocks, and missiles, and the simple particle explosions.
[cc lang="javascript" width="550"]
private function startGame():void {
removeChild(shipHolder);
addChild(canvasBitmap);
stage.addEventListener(KeyboardEvent.KEY_DOWN,keyDownListener);
stage.addEventListener(KeyboardEvent.KEY_UP,keyUpListener);
gameTimer=new Timer(50);
gameTimer.addEventListener(TimerEvent.TIMER, runGame);
gameTimer.start();
}
private function runGame(e:TimerEvent) {
checkKeys();
updatePlayer();
drawBackground();
drawPlayer();
}
[/cc]
The startGame() method begins the actual game loop. The loop is a method called runGame and it is called every 50 milliseconds. This can be increased or decreased as needed. We do this with the new AS3 Timer class here, but I have also had success with using the EnterFrame event. We also add a listener for both keyboard up and down events, remove the shipHolder from the main time line, and add in our canvas. The canvas is just a 400x400 BitmapData holder that all of our BitmapData images will be drawn to. It is the ONLY display object in the game.
The runGame method is currently pretty basic. It runs through checking for changes in keyboard input, updating the player ship position based on any key changes, and inertia, then it draws our objects to the screen in the order desired. First we draw the space star background, and then we draw the player. Effectively this is akin to setting depths on them in AS2.
[cc lang="javascript" width="550"]
private function keyDownListener(e:KeyboardEvent) {
//trace("down e.keyCode=" + e.keyCode);
aKeyPress[e.keyCode]=true;
}
private function keyUpListener(e:KeyboardEvent) {
//trace("up e.keyCode=" + e.keyCode);
aKeyPress[e.keyCode]=false;
}
private function checkKeys():void {
if (aKeyPress[38]){
trace("up pressed");
playerObject.dx=aRotation[playerObject.arrayIndex].dx;
playerObject.dy=aRotation[playerObject.arrayIndex].dy;
var mxn:Number=playerObject.movex+playerObject.acceleration*(playerObject.dx);
var myn:Number=playerObject.movey+playerObject.acceleration*(playerObject.dy);
var currentSpeed:Number = Math.sqrt ((mxn*mxn) + (myn*myn));
if (currentSpeed < playerObject.maxVelocity) {
playerObject.movex=mxn;
playerObject.movey=myn;
} // end speed check
}
if (aKeyPress[37]){
playerObject.arrayIndex ;
if (playerObject.arrayIndex <0) playerObject.arrayIndex=shipAnimationArrayLength-1;
}
if (aKeyPress[39]){
playerObject.arrayIndex++;
if (playerObject.arrayIndex ==shipAnimationArrayLength) playerObject.arrayIndex=0;
}
}
[/cc]
To avoid the pause created when a key is held down (the old key.up and key.down global methods have been removed in AS3) we have created an array called aKeyPress that will act somewhat like those global methods. When a key is pressed ( the UP arrow keyCode= 38, the LEFT arrow keyCode= 37, and the RIGHT arrow keyCode= 39) we store a Boolean true in our array at that index. When the the key is not pressed anymore, we store a Boolean false in the index of the aKeyPress array.
The checkKeys() method is actually quite complicated because it contains most of our logic for the rotation and forward motion of the ship.
First, if the up arrow is being held down : if (aKeyPress[38]) : we need to check what the dx (delta x) and dy (delta y) values are for that direction. We already pre-calculated all of these and placed them in the aRotation array. The current index for the player, playerObject.arrayIndex holds a number 0 to 35 referring to the current rotated position of the playerObject. That same index is used in the aRotation array to find the .dx and .dy values that will be applied to the playerObject.movex and playerObject.movey variables. When the game starts, the playerObject.movex and playerObject.movey values are both set to 0, but as soon as the up arrow is pressed we start to calculate what the new movex and movey values will be. That is done with these two lines:
var mxn:Number=playerObject.movex+playerObject.acceleration*(playerObject.dx);
var myn:Number=playerObject.movey+playerObject.acceleration*(playerObject.dy);
We create two temp variables to hold our new movex and movey values called mxn and myn. To create the new value we add our acceleration value (.3) * the new dx value and add it to the current movex value. We also do this with myn, the dy and movey values. These now equal our new delta x and y values or the change in x and y that will be applied to our x and y values respectively when the ship is put on the screen this frame timer tick. But wait a minute, we have something called playerObject.maxVelocity which keeps out ship from accelerating so fast that we can't see it.
Our next step is to test the mxn and myn values against the max velocity. To get our current speed we must use a little math. This is because we have essentially two vectors in dx and dy and we must add them together and take their square root of their squares to find a number that is our current constant velocity. That is done here:
var currentSpeed:Number = Math.sqrt ((mxn*mxn) + (myn*myn));
Now, our currentSpeed is a value that we can compare to our playerObject.maxVelocity value, if it is less than our max, we assign the playerObject.movey and movex to the respective mxn and myn values. If it is not (the ship is moving at the max velocity), we do nothing and the movex and movey remain unchanged and our ship continues to move in its current direction at max velocity.
The last two key checks are for the left and right arrow keys. If the left arrow is pressed, we change the playerObject.arrayIndex by subtracting one from it. If it goes below zero, we set it to the 35 (array length of 36 - 1). If we press the right arrow key, we do the opposite and add 1 to the playerObject.arrayIndex. If it goes above 35, we set it to be 0. We don't change the playerObject.dx and dy values yet. If we did that, then the ship would start to move off in the direction we rotate too, and not continue its inertia in the current thrusted direction. We only change the playerObject.dx and dy, and the movex and movey when the up arrow is pressed. This gives us an approximation of the classic Asteroids movement. I have no idea how Ed Logg actually programmed Asteroids, so I have to assume this is relatively close.
[cc lang="javascript" width="550"]
private function updatePlayer():void {
//add friction
if (playerObject.movex > 0) {
playerObject.movex-=playerObject.friction;
}else if (playerObject.movex < 0) {
playerObject.movex+=playerObject.friction;
}
if (playerObject.movey > 0) {
playerObject.movey-=playerObject.friction;
}else if (playerObject.movey < 0) {
playerObject.movey+=playerObject.friction;
}
playerObject.x+=(playerObject.movex);
playerObject.y+=(playerObject.movey);
playerObject.centerx=playerObject.x+spriteWidth;
playerObject.centery=playerObject.y+spriteHeight;
if (playerObject.centerx > stage.width) {
playerObject.x=-spriteWidth;
playerObject.centerx=playerObject.x+spriteWidth;
}else if (playerObject.centerx < 0) {
playerObject.x=stage.width - spriteWidth;
playerObject.centerx=playerObject.x+spriteWidth;
}
if (playerObject.centery > stage.height) {
playerObject.y=-spriteHeight;
playerObject.centery=playerObject.y+spriteHeight;
}else if (playerObject.centery < 0) {
playerObject.y=stage.height-spriteHeight;
playerObject.centery=playerObject.y+spriteHeight;
}
trace("centerx=" + playerObject.centerx);
}
[/cc]
We are hitting the home stretch of part 1 now. The updatePlayer() method is called every interval in our game loop to make sure that the ship is placed on the screen at the correct location. That location changes most interval ticks because we simulate inertia and friction with this function. The first thing we do is add friction with the appropriate sign to each of the movex and movey values. We ADD the friction value to a negative value and SUBTRACT it from a positive value. We do this each frame, and eventually, if the up arrow if not pressed again, the ship will stop moving.
Next, we add the movex and movey values to the current x and y values for the playerObject. This simulates our inertia. The x and y values are changed every tick no matter if the up arrow is pressed or not. We also recalculate the centerx and centery values for the playerObject.We need these recalculated every time the x and y values change to ensure that we have a proper center of our object. This is used for warping from left to right and up and down, but also used in collision detection and explosion placement. We don't want to use the upper left-hand corner x and y values for these calculations.
Next we check the centerx value against the stage.width value. If the centerx is greater than stage.width, we place the ship at the other side of the screen at -spriteWidth. That gives the illusion that the ship is floating from the right side to the left side of the screen. We do the same with the x value and the left side of the screen by checking if the centerx is less than 0, and then changing the it to be the stage.width - the spriteWidth. We do this in the y direction by checking the centery values also.
[cc lang="javascript" width="550"]
private function drawBackground():void {
canvasBD.copyPixels(backgroundBD,backgroundRect, backgroundPoint);
}
private function drawPlayer():void {
playerPoint.x=playerObject.x;
playerPoint.y=playerObject.y;
canvasBD.copyPixels(aShipAnimation[playerObject.arrayIndex],playerRect, playerPoint);
}
[/cc]
We have made it to the last two methods in part one. Every frame tick, with the drawBackground() method, we need to redraw the background image, and this is done by using the copyPixels() method of the canvasBD BitmapData object We copy all of the pixels from the backgroundBD BitmapData object to the canvasBD by specifying the pre-calculated rectangle of 0,0,400,400 and always using the point 0,0.
The drawPlayer() method is slightly more complicated. We need to first set the playerPoint x and y values to equal the current playerObject x and y values. Once we have done that, we again call the copyPixels method of the canvasBD. This time we specify the current ship animation frame in the aShipAnimation array using the playerObject.arrayIndex value. Then we use the pre-calculated rectangle of 0,0,40,40 and the point calculated above.
If all of that code is correct, we get the below exported .swf file. Use the up arrow to apply the thrust, and the right and left arrows to simulate the rotation of the ship.
The source files are here: 7800 Asteroids Tutorial Part 1 source files
Moving From Flash AS2 To Flash AS3: MovieClip Buttons In MovieClip Classes
(Note: I'm converting my Flash game "Spin City" from AS2 to AS3 so it can be re-skinned for another project. I've decided to document this activity in a series of tutorials so they might benefit anyone else who is going through the same development process)
OK, this one drove me crazy today, but I finally discovered the answer. I try as hard as possible to keep all actions related to my Flash code in my classes and not place any code on the time line. this includes buttons and their related code for handling events. I got it to work in AS3, but I could not get the hand cursor to show-up when hovering over buttons. Here is what I found out.
| Flash AS2 |
In AS2, handling button actions in a class that is associated with a MovieClip that contained that button (i.e. A TitleScreen class that includes a [PLAY] button) was done like this:
- Define a variable for the button in your class so you can set its properties. The name must be the same name as you named the button in your MovieClip. Even though you never define the variable, at run-time it will be associated with the button because they have the same name.
- Set the onRelease handler of the button to a function in your class
- Have the button handler call _parent[function] so that you can operate within the scope of your class (and not the button) (Note: You can eliminate this by using a delegate)
- Perform action
| [cc lang="javascript" width="550"] class TitleScreen extends MovieClip { var button_play:MovieClip; function TitleScreen() { function play_button_release() { [/cc] |
AS2 considers the MovieClip defined by button_play as a "button" because we have assigned a call-back function to its onRelease handler. This means that when hovering over the button, the cursor will change to the "hand" that instantly informs the user that this is a button than can be pressed.
| Flash AS3 |
In AS3, there are few more steps you have to take to simulate the same functionality. In some ways it is much simpler than AS2, and in some ways, a bit more involved. At any rate, it is different than AS2, and that is why I'm covering it in this blog. Here are the steps you need to perform to make it work:
Easier:
AS3 is easier for two reasons:
- The event handler you assign to your button is called in the context of where that function exists. This means you no longer have to call _parent[function] or use a delegate to get back into the context of your class.
- You do not have to define a MovieClip that exists in the MovieClip associated with your class as a variable in your class. These MovieClips are already defined for you.
However, there are a couple complications with AS3:
- There are no longer onRelease and onPress events to handle. You use MouseEvent.CLICK, MouseEvent.MOUSE_DOWN, MouseEvent.MOUSE_UP and MouseEvent.DOUBLE_CLICK (among others) for this purpose.
- You need to set the useHandCursor property to true so the cute little useful hand will show-up when the cursor hovers over the button.
- You need to set the buttonMode property to true so the MovieClip that defines the button will act like one (i.e. the useHandCursor property will actually have an effect)
Here is what the code looks like:
| [cc lang="javascript" width="550"] package fashiondash { import flash.events.MouseEvent; public class TitleScreen extends flash.display.MovieClip { public function TitleScreen() { button_play.addEventListener(MouseEvent.CLICK, playagainButtonRelease); button_play.useHandCursor = true; button_play.buttonMode = true; } function playagainButtonRelease(e:MouseEvent) { } } |
So there goes another short lesson. I had no idea that little things I took for granted such as the hand cursor would pose problems like this in AS3. There certainly is a lot to re-learn with this generation of ActionScript.
Moving From Flash AS2 To Flash AS3: GetURL()
(Note: I'm converting my Flash game "Spin City" from AS2 to AS3 so it can be re-skinned for another project. I've decided to document this activity in a series of tutorials so they might benefit anyone else who is going through the same development process)
| Flash AS2 |
One of the most basic functions in AS1 & AS2 was getURL() . The simple ability to send users to another page in the same browser window ( or a new instance of one) is also one of the very foundations of web functionality. AS1 and AS2 used a very simple implementation for it, and we were all happy because it was all so simple. The basic, global function call looked like this
| [cc lang="javascript" width="550"] getURL("catalog.aspx", "seetoys", "GET"); [/cc] |
The three parameters were:
- URL (where to go)
- target (the name of browser to open the page into)
- method (GET or POST)
That was it. Simple, easy, straightforward, nobody got hurt.
| Flash AS3 |
In AS3 there is no global getURL() function, there is no easy, one line equivalent that you can replace it with. A simple getURL() style action takes a 4 lines of code (2 lines if you want to minimize your code, but make it unreadable). Here are the steps you need to take to simulate getURL()
- Everything required for URL actions is AS3 is contained in the flash.net package. So the first thing you need to do is import that package into your class.
- Second, you need to create an instance of a URLRequest object and set it's url property
- Third you must use the new navigateToURL() function is a close approximation to to getURL();
| [cc lang="javascript" width="550"] import flash.net.*; ... var url:String = "catalog.aspx"; |
Of course, you could economize that code like this and make it one line (plus the import)
| [cc lang="javascript" width="550"] import flash.net.*; ... navigateToURL(new URLRequest("catalog.aspx"), 'seetoys'); [/cc] |
URLRequest is actually a very useful class, as it allows you to so things that were never possible in AS2, like set HTTP Headers for the request. Still, it's a bit disconcerting when something so simple and basic as getURL() needs to be updated along with everything else. However, that seems to be the norm with converting AS2 to AS3.
Moving From Flash AS2 To Flash AS3: Update
This is just a quick update to say that the Moving From Flash AS2 To Flash AS3 series will continue this week. I had to spend some time implementing the things I learned last week, and work on a few more changes. I've now tackled adding movie clips to the screen, events, MovieClip properties, replacement for getURL and a few other things that I will start blogs on tomorrow. Thanks for being patient.
-Steve
Flash Game Programming Inter-Web Round up
I like to search the inter-web for juicy nuggets of Flash Game programming wisdom in my free time (what a boring date I must be). Here are some essential new and recent blog entries for Flash Game Programmers and Developers.
Interactive Crap has a pretty recent entry called Common Problems in AS3 Game Programming #3 Swarm Behavior (Following).
I really like simple to understand AI articles and this is a great one.
Mochiland is chock full of great stuff. The most recent being:
5 Simple Tips to Optimizing Your Flash Games Site
ActionScript Physics Engine Tutorial: Lesson 1
ActionScript Physics Engine Tutorial: Lesson 2
Our very own Steve Fulton, wrote this first part in a series on making games. - Anatomy of a Flash Game: Lesson 1 - Setting up the game
http://www.zeuslabs.us has a nice collection of tips on how to learn AS3 in this article: 12 Great Ways to Learn ActionScript 3 in Flash
Gary Rosenzweig's latest (and greatest) Flash Game Programming book as spawned a web site where he helps budding game programmers with all sorts of problems and questions. His site, http://www.flahsgameu.com/ some great new stuff since the last time I visited. For those interested in his methods behind making the classic SNAKE game, he has provided a two part video tutorial:
FlashGameU.com Video Tutorial: Creating a Snake Game, Part 1
FlashGameU.com Video Tutorial: Creating a Snake Game, Part 2
Gary's
site is chock full of great tid bits. He also has another video tutorial on making a matching card pairs game. I really like it when someone spends the time making a full game and then creates a tutorial around it.
http://www.tutorialized.com is another AWESOME resource for game and Flash game Tutorials. Their latest include:
Making a Catapult Game
Making a Turret Game
Making a Maze Game





