8bitrocket.com
29Apr/070

Advanced Flash 8 Game Programming : Pixel level collision detection Part III (or let's start a real game)

In Part 1 - Advanced Flash 8 Game Programming : Pixel level collision detection I discussed the very basics of doing Pixel level hit detection with the bitmapData object. In Advanced Flash 8 Game Programming : Pixel level collision detection Part II (or let's add Bitmap animation caching) I added in a simplified version of animation loop caching. In part III, we will start to make a simple game. This is what we are going to tackle:

1. We will use a play screen, created in Fireworks (or any other graphics program), as the maze or room the player is in. It will be viewed from the top. It will be a little odd looking because the Ari Feldman's Sprite Lib GPL sprites we are going to use are viewed from the side. In any case it doesn't look much worse than many commercial early 80's games. This screen will be used as our wall map and we will use bitmap hitTest on the entire bitMap. This is a alternative to "tile-based" detection that has been a staple of game development for years. This isn't to say that tile-based detection is bad or wrong, this is just a different method to accomplish the same thing. In fact, a combination of the two will be discussed in a later lesson.

2. Next we will add in animations for moving the player in 4 distinct directions and cache the animations for each. We will also add in variables for the player's speed and an animation delay to help the player look a little more realistic.

3. We will start to create a more proper game loop with code more organized. We will also add in a Frame Rate counter, and use temp variables to hold current player position info before rendering the screen.

I will be doing a lot more explaining this time around as much has changed.

[cc lang="javascript" width="550"]
//hitpixels_with_bitmap_animationloop3.fla
//Jeff Fulton 2007
//www.8bitrocket.com
//pixel level collision detection with bitmap data object

import flash.display.*;
import flash.geom.*;

var keyPressed:Boolean=false;
var timeOfLastFPS:Number = 0;
var FPSCOUNT:Number = 0;
//pixel level collision detection with bitmap data object

//1. load in spriteMap from library
var spriteMapBitmap:BitmapData = BitmapData.loadBitmap("actionMap");
//mc.attachBitmap(spriteMapBitmap, this.getNextHighestDepth());

[/cc]

***** *****
The above section of code imports the in the internal Flash classes needed for manipulating bitmaps and the math classes needed for creating a rectangle of screen data needed from a bitmap. We are also creating variables to hold if a key has been pressed and to calculate the current frame rate.
*****
*****

[cc lang="javascript" width="550"]//2 create an array of bitmaps for the player sprite
//in this example, the player has two frames of animation
//this is a simple example, so we won't do 2 frames for every direction of movement, we'll just use these two

[cc lang="javascript" width="550"]
// copy two sprite images for left movement
var aPlayerLeftSpriteArray:Array=new Array();
var tempSprite:BitmapData=new BitmapData(32,32,true,0x00000000);
tempSprite.copyPixels(spriteMapBitmap, new Rectangle(0, 72, 32, 32), new Point(0, 0));
aPlayerLeftSpriteArray.push(tempSprite);
var tempSprite2:BitmapData=new BitmapData(32,32,true,0x00000000);
tempSprite2.copyPixels(spriteMapBitmap, new Rectangle(0, 102, 32, 32), new Point(0, 0));
aPlayerLeftSpriteArray.push(tempSprite2);

[/cc]

***** *****
Here we have created an array to hold two animation frames for the left movement of our player. We are copying these frames from our imported spritemap. Below we will do the same thing for right, up, and down movement.
*****
*****

[cc lang="javascript" width="550"]
// copy two sprite images for left movement
var aPlayerRightSpriteArray:Array=new Array();
var tempSprite:BitmapData=new BitmapData(32,32,true,0x00000000);
tempSprite.copyPixels(spriteMapBitmap, new Rectangle(36, 72, 32, 32), new Point(0, 0));
aPlayerRightSpriteArray.push(tempSprite);
var tempSprite2:BitmapData=new BitmapData(32,32,true,0x00000000);
tempSprite2.copyPixels(spriteMapBitmap, new Rectangle(36, 102, 32, 32), new Point(0, 0));
aPlayerRightSpriteArray.push(tempSprite2);

// copy two sprite images for up movement
var aPlayerUpSpriteArray:Array=new Array();
var tempSprite:BitmapData=new BitmapData(32,32,true,0x00000000);
tempSprite.copyPixels(spriteMapBitmap, new Rectangle(72, 72, 32, 32), new Point(0, 0));
aPlayerUpSpriteArray.push(tempSprite);
var tempSprite2:BitmapData=new BitmapData(32,32,true,0x00000000);
tempSprite2.copyPixels(spriteMapBitmap, new Rectangle(72, 102, 32, 32), new Point(0, 0));
aPlayerUpSpriteArray.push(tempSprite2);

// copy two sprite images for down movement
var aPlayerDownSpriteArray:Array=new Array();
var tempSprite:BitmapData=new BitmapData(32,32,true,0x00000000);
tempSprite.copyPixels(spriteMapBitmap, new Rectangle(180, 72, 32, 32), new Point(0, 0));
aPlayerDownSpriteArray.push(tempSprite);
var tempSprite2:BitmapData=new BitmapData(32,32,true,0x00000000);
tempSprite2.copyPixels(spriteMapBitmap, new Rectangle(180, 102, 32, 32), new Point(0, 0));
aPlayerDownSpriteArray.push(tempSprite2);
[/cc]***** *****
Notice above we have created single dimensional arrays to hold each position. We easily could add all of these to another array to create one multi-dimensional array to hold all movement animation for our player. That is exactly what we will do on a later lesson.
*****
*****

//3. put player on screen, copy pixels from sprite to mc1

[cc lang="javascript" width="550"]
var playerSprite:BitmapData=new BitmapData(32,32,true,0x00000000);
//playerSprite.copyPixels(spriteMapBitmap, new Rectangle(0, 72, 32, 32), new Point(0, 0));
this.createEmptyMovieClip("player_mc",this.getNextHighestDepth());
var aPlayerSpriteArray:Array=aPlayerLeftSpriteArray;
var playerSpriteIndex:Number=0;
player_mc.attachBitmap(aPlayerSpriteArray[0],100);
playerSprite=aPlayerSpriteArray[playerSpriteIndex];
player_mc._x=32;
player_mc._y=32;
player_mc.tempx=32;
player_mc.tempy=32;
player_mc.speed=3; //how many pixels to move with each key press
player_mc.delay=5; //how many keypresses to wait until moviing to the next animation frame
player_mc.delayCount=0;
[/cc]

***** *****
Now, here is where we start to add some meat. We create a bitmap object (playerSprite) that will hold a reference to the current bitmap data object that is attached to put player movieClip. We do this because once we have attached a bitmap to a clip, there is no way to access it directly. We need to access it for hit detection. Also we add in some new variables called tempx, tempy, speed, delay, and delayCount. Tempx and tempy will be used to hold the position our player WILL be at in the next interval. We will test this position in our hitTest rather than moving the player then testing. This is the start of our more organized game loop design. The speed variable is the number of pixels the player will move with each key press. The delay variable is the number of key presses that need to pass before we jump to the next animation frame for our player. The combination of these two will let you refine the player animation and allow things like speed power ups or traps where the player's speed is slowed. The delayCount is used to keep a count of the number of key presses that have passed since the last animation frame.
*****
*****

[cc lang="javascript" width="550"]//4. create a walls sprite
var screen2:BitmapData = BitmapData.loadBitmap("screen2");
var sprite2:BitmapData=new BitmapData(400,400,true,0x00000000);
sprite2.copyPixels(screen2, new Rectangle(0, 0, 400, 400), new Point(0, 0));
this.createEmptyMovieClip("sprite2_mc",this.getNextHighestDepth());
sprite2_mc.attachBitmap(sprite2,100);
sprite2_mc._x=0;
sprite2_mc._y=0;
[/cc]

***** *****
In the above code snippet, we load a 400 x 400 bitmap into a holder clip and then place the clip on the screen. This bitmap contains the walls for our game room. The bitmap has a transparent background and we will use pixel level hit detection to determine a hit on any wall.
*****
*****

[cc lang="javascript" width="550"]

this.onEnterFrame=function() {

getKeys();
checkCurrentFrameRate();
if (keyPressed) {
checkCollisions();
render();
keyPressed=false;

}

}
[/cc]

***** < Code Explanation> *****
The onEnterFrame is now our simplified game loop. We new are separating our loop into very distinct functions. First we check for key presses. Next we calculate and display the current frame Rate. If a key was pressed, then we check for collisions between the player and the walls and render the player back to the screen. If we were to have other objects on the screen such as collectibles and enemy sprites, our game loop would need to be organized differently. We'll get to that in a later lesson.
***** *****

[cc lang="javascript" width="550"]
function render() {

player_mc.delayCount++;

if (player_mc.delayCount > player_mc.delay) {
player_mc.delayCount=0;
playerSpriteIndex++;
if (playerSpriteIndex > aPlayerSpriteArray.length-1) playerSpriteIndex=0;
player_mc.attachBitmap(aPlayerSpriteArray[playerSpriteIndex],100);
playerSprite=aPlayerSpriteArray[playerSpriteIndex];
sprite_txt.text=playerSpriteIndex;
}
//trace("player_mc.tempx=" + player_mc.tempx);
//trace("player_mc.tempy=" + player_mc.tempy);
player_mc._x=player_mc.tempx;
player_mc._y=player_mc.tempy;

}

[/cc]
***** < Code Explanation> *****
The render function role is to update the player on the screen. It first checks to see if it needs to update the player animation loop (based on the delayCount varbaible), and then it changes the player's position to represent the next calculated position.
***** *****

[cc lang="javascript" width="550"]function checkCurrentFrameRate():Void {
if (timeOfLastFPS+1000 frame_txt.text = FPSCOUNT;
timeOfLastFPS = getTimer();
FPSCOUNT = 0;
} else {
FPSCOUNT++;
}
}
[/cc]

***** *****
The checkCurrentFrameRate function uses a getTimer call to check for the number of milliseconds that have passed since the last frame. If it has been 1000 or more (1 second = 1000 milliseconds) then we reset the number of frames counted. If not, it adds 1 to the frame rate counter. This is a pretty accurate way to calculate the frame rate and it will be within 1 or 2 frames of being correct.
*****
*****
[cc lang="javascript" width="550"
]function getKeys() {
if (Key.isDown(Key.UP)) {
player_mc.tempy-=player_mc.speed;
aPlayerSpriteArray=aPlayerUpSpriteArray
keyPressed=true;
}
if (Key.isDown(Key.DOWN)) {
player_mc.tempy+=player_mc.speed;
aPlayerSpriteArray=aPlayerDownSpriteArray;
keyPressed=true;
}
if (Key.isDown(Key.LEFT)) {
player_mc.tempx-=player_mc.speed;
aPlayerSpriteArray=aPlayerLeftSpriteArray;
keyPressed=true;
}
if (Key.isDown(Key.RIGHT)) {
player_mc.tempx+=player_mc.speed;
aPlayerSpriteArray=aPlayerRightSpriteArray;
keyPressed=true;
}

}
[/cc]
***** *****
The getKeys function has been modified from the previous 2 versions. First, instead of automatically changing the player's _x and _y right away, we store the next values to temp variables. Also, we make sure to change to aPlayerSpriteArray to reference the array for the direction the player if headed. This code is very simple but works well here because each direction contains only two animation frames.
*****
*****

[cc lang="javascript" width="550"]

function checkCollisions() {

var myPoint:Point = new Point (sprite2_mc._x, sprite2_mc._y);
if (playerSprite.hitTest (new Point (player_mc.tempx , player_mc.tempy), 255, sprite2, myPoint, 255)){
bitmap_txt.text="true";
//trace("bitMap hit detected");
player_mc.tempx=player_mc._x;
player_mc.tempy=player_mc._y;
}else{
bitmap_txt.text="false";
}

}

[/cc]

***** *****
Our collision detection function has been modified to look almost nothing like the previous two. We have done away with the movieClip hitTest from before because the player is ALWAYS on the room bitMap (sprite2). Because of this, the hitTest would ways be true and there is no reason to waste time doing it. Also, we have changed the point we check in the bitmapData.hitTest call to reference the NEXT point for the player. If a hit is detected, we resent tempX and tempY to be the original values before the render function is called. This stops the player from moving into an area that he/she is not supposed to occupy.
*****
*****

That's it for this time. Check out the .fla and example below for more info.

hitpixels_with_bitmap_anmationloop.swf (2007)
A demo of using bitmapData to do pixel level collision detection and bitmap animation caching.

Use the arrow keys to move the spaceman around the room.

The bitmap hit will become true only if the spaceman collides with a walls (green), even through he is actually colliding with the wall bitmap all the time.

The Player Sprite number in the text box represents the current sprite in the array (bitmapData object).

The frame rate tells the current frame rate.

download the fla file

Ari Feldman's Sprite Lib used via GPL

24Apr/070

Advanced Flash 8 Game Programming : Pixel level collision detection Part II (or let's add Bitmap animation caching)

In Part 1 - Advanced Flash 8 Game Programming : Pixel level collision detection I discussed the very basics of doing Pixel level hit detection with the bitmapData object. In this second part, I am going to add one more small feature that hopefully will improve the performance of your games. This technique will work in CS3 as well as Flash 8, but I have not used CS3 yet, so I can't yet explain any differences in syntax or usage.

Action games need SPEED. Flash is actually very slow when rendering the screen, and the biggest culprit are the math calculations that are needed when using the timeline to run through a key frame vector animation. If your movie clip contains no animation, and just needs to move from point x1,y1 to point x2,y2, you can use bitmap surface caching (movieClip.cacheAsBitmap=true) to see a noticeable increase in performance. But, what do you do if the movieClip actually needs to run through a timeline animation? My theory is to eliminate as many timeline and vector animations as possible by caching them all before they are needed. If you play my game Retroblaster , you will notice that I spend a inordinate amount of time at the beginning doing something called "Preparing System Warps". What I am actually doing is pre-caching all of the game animations to be used later. This allows me to have many more explosions, enemy ships, etc on the screen than if I tried to render vector timeline based animations in real-time.

I have taken the Part 1 code and modified it to add in this feature. Again, I am using Ari Feldman's Sprite Lib GPL for my quick and dirty animation. I have changed the player and enemy objects to be a spaceman (player) and scorpion (enemy). I have pre-cached two frames of animation for the spaceman, and when you press the arrows keys in any direction the animation will run through one iteration of the loop. It looks a little weird because I haven't spent any time adding frames of animation for the various directions, but rest assured, the sprite library contains then. (thanks Ari) They are not necessary for this demo though.

 

[cc lang="javascript" width="550"]//hitpixels.fla
//Jeff Fulton 2007
//www.8bitrocket.com
//pixel level collision detection with bitmap data object and animation caching
import flash.display.*;
import flash.geom.*;

//1. load in spriteMap from library
var spriteMapBitmap:BitmapData = BitmapData.loadBitmap("actionMap");
//mc.attachBitmap(spriteMapBitmap, this.getNextHighestDepth());

//2 create an array of bitmaps for the player sprite
//in this example, the player has two frames of animation
//this is a simple example, so we won't do 2 frames for every direction of movement, we'll just use these two
var aPlayerSpriteArray:Array=new Array();
var tempSprite:BitmapData=new BitmapData(32,32,true,0x00000000);
tempSprite.copyPixels(spriteMapBitmap, new Rectangle(0, 72, 32, 32), new Point(0, 0));
aPlayerSpriteArray.push(tempSprite);
var tempSprite2:BitmapData=new BitmapData(32,32,true,0x00000000);
tempSprite2.copyPixels(spriteMapBitmap, new Rectangle(0, 102, 32, 32), new Point(0, 0));
aPlayerSpriteArray.push(tempSprite2);

//3. put player on screen, copy pixels from sprite to mc1
var playerSprite:BitmapData=new BitmapData(32,32,true,0x00000000);
//playerSprite.copyPixels(spriteMapBitmap, new Rectangle(0, 72, 32, 32), new Point(0, 0));
this.createEmptyMovieClip("player_mc",this.getNextHighestDepth());
player_mc.attachBitmap(aPlayerSpriteArray[0],100);
playerSprite=aPlayerSpriteArray[0];
player_mc._x=100;
player_mc._y=100;
var playerSpriteIndex:Number=0;

//4. copy pixels from spriteMap to enemy
var sprite2:BitmapData=new BitmapData(32,32,true,0x00000000);
sprite2.copyPixels(spriteMapBitmap, new Rectangle(409, 72, 32, 32), new Point(0, 0));
this.createEmptyMovieClip("sprite2_mc",this.getNextHighestDepth());
sprite2_mc.attachBitmap(sprite2,100);
sprite2_mc._x=200;
sprite2_mc._y=200;

function updatePlayerAnimation() {
playerSpriteIndex++;
if (playerSpriteIndex > aPlayerSpriteArray.length-1) playerSpriteIndex=0;
player_mc.attachBitmap(aPlayerSpriteArray[playerSpriteIndex],100);
playerSprite=aPlayerSpriteArray[playerSpriteIndex];
sprite_txt.text=playerSpriteIndex;
}

this.onEnterFrame=function() {

if (Key.isDown(Key.UP)) {
player_mc._y ;
updatePlayerAnimation();
}
if (Key.isDown(Key.DOWN)) {
player_mc._y++;
updatePlayerAnimation();
}
if (Key.isDown(Key.LEFT)) {
player_mc._x ;
updatePlayerAnimation();
}
if (Key.isDown(Key.RIGHT)) {
player_mc._x++;
updatePlayerAnimation();
}

if (player_mc.hitTest(sprite2_mc)) {
normal_txt.text="true";
//trace("basic hit detected");
//test for pixel level hit
var myPoint:Point = new Point (sprite2_mc._x, sprite2_mc._y);
if (playerSprite.hitTest (new Point (player_mc._x , player_mc._y), 255, sprite2, myPoint, 255)){
bitmap_txt.text="true";
//trace("bitMap hit detected");
}else{
bitmap_txt.text="false";
}
}else{
normal_txt.text="false";
bitmap_txt.text="false";

}

}

[/cc]

hitpixels_with_bitmap_anmationloop.swf (2007)
A demo of using bitmapData to do pixel level collision detection and bitmap animation caching.

Use the arrow keys to move the spaceman to the scorpion sprite.

When the spaceman enters the 32x32 area for the scorpion, the normal hit becomes true.

The bitmap hit will become true only if the spaceman collides with a non-trnasprant pixel in the scorpion.

The Player Sprite number in the text box represents the current sprite in the array (bitmapData object).

download the fla file

Ari Feldman's Sprite Lib used via GPL

1. First we create a spriteMap in memory from a bitmap (png with transparency) that I have in the library.
2. Next, I use some very very rudimentary code to pull two 32x32 images from the spriteMap and place them in an array called "aPlayerSpriteArray". This can be done with loops, etc, but I just wanted to demonstrate it as clearly as possible here.
3. I put the player on the screen by creating a holder clip for the player and attaching the first bitmap in the array to the clip. I also make sure to place a reference to the attached bitmap in the variable "playerSprite". This is necessary to make sure hit detection can be performed on the bitmap.
4. I copy some more pixels from the spriteMap to a bitmap data object named "sprite2" and then attach it to a movieClip. This will represent our enemy (scorpion) sprite.
5. Next I have a basic function for updating the player sprite. This is called when ever a key is pressed, notice that I have to re-reference the playerSprite on each change to make sure hit detection is done properly.
6. The onEnterFrame is the main loop. It checks for key input. I don't use a key Listener object here because key repeats are difficult to detect with that object.
7. The hitTesting is the final part of the code. I first look for a basic hit. This can be done with hitTest, or one of a number of math based detections (circle - circle, rect - rect, etc). If that hit is true, then I check for the pixel level hit. Hopefully this will save cycles in your game.

Good luck, I'm off to use this code in a new game I am making based on the Atari classic called Gravitar (or OIDS if you had an Amiga or Atari ST back when that was the cool thing to do).

 

24Apr/070

Wii Opera Browser: A Storm In A Tea Cup?

I've been creating a few demos of Flash games designed for the Nintendo Wii Opera browser, and writing a few blog entries about the process for the past few months. I even convinced the people at my Day Job to create a section highlighting all the games we currently offer that can be played reasonably well with a Wii-mote. I jumped on the Wii Opera Browser very early. The day it was released to beta on Dec. 24th I pushed this demo live for my first test with my Wii. Most of developer friends, the ones lucky enough to own a Wii, have all connected to the internet through WiiConnect24, shared Miis, used Opera, etc.

However, a thought struck me today that I cannot shake. It was spawned over the weekend when I talked to my brother-in-law, another happy Wii owner. My brother-in-law is a construction contractor. He spends his days building actual houses for people, and is as far from spending his days with his ass planted in chair looking at computer screen as I am close to it. He bought the Wii to play Wii Sports with his wife and kids. That's it. They have not bought any more Wii games (I have eight), nor Virtual Console games (I have five), they have not bought any GameCube games (I have six), they have not connected to WiiConnect24 (I have Wireless G with WPA encryption enabled), and they have certainly not downloaded Opera, or used the Wii Browser (my favorites list scrolls through 2 pages). It suddenly occurred to me today that, while I am plugged into every nuance of Wii news and Wii releases, my brother-in-law and his family could not care less.  They are not connected to the internet through their Wii, they don't know they can connect, and will probably never try to connect to the internet. If they typify the casual, game players that are flocking to the Wii, then is it really a waste of time (at this instant) to try to create Flash-based games that appeal to Wii users and utilize the Wii-mote?  Is it worth spending the time to dumbed-down Flash 7 games when hardly anyone will ever see them? I simply don't know the answer.

However, maybe you can help. If you own a Wii, or know anyone who does own one, have you/they connected it to the internet? Have they downloaded the browser? Have they played any games on the internet through the Wii Opera Browser with a Wii-mote?

Email any information you have us. We'll compile it and reveal the results next week.

We here at 8bitrocket.com love the Wii. We think the the Wii Browser with a Wii-mote is the best internet experience that any game console has been able to create to date. However, what we don't know is if the Wii Opera Browser is just a "storm in a tea cup" that few people will ever experience, or if it will really amount to something worth talking about.

19Apr/070

Advanced Flash 8 Game Programming : Pixel level collision detection

I had to take a little break after finishing Retroblaster to unwind before I started making games again. I plan to re-write my game loop and much of my game code in this public forum for a couple reasons. One is the selfish need of a cathartic outlet, and the other is to help aide other fledgling Flash game programmers. You will be learning as I learn. I will post my examples here, complete with code explanations and .fla files to download. The first lesson will be in collision detection. If you have tried the many popular methods of collision detection (hitTest, circle to circle, hitTest with a shape flag, etc) you will find none of them as accurate as pixel level detection. The downside is that pixel level detection will probably slow down a game with many objects all interacting at once. I have not done any frame rate tests, but a future post will compare the methods and see.

The bitmapData object, introduced in Flash 8, makes this possible. There are other methods to do pixel level collision detection, but they are either very math intensive (matrix math scares me), or use something like Grant Skinner Does here.

My version will be much easier for novices to understand. Basically it will be done in these steps

1. Create 2 sprites using a sprite map and the bitmapData object.
2. Attach those sprites to movieClips
3. Provide a reference to the attached sprite
4. While the user moves one of the clips with the keyboard, first check for a basic hitTest collision.
5. After a basic collision is detected, then and only then, do a pixel level hitTest with the bitMapdata.hitTest() function.

That's it. The code is below. I have added comments where needed. After the code there is a link to the example swf page and a .fla to download and try for yourself. I am using as sprite map from Ari Feldman's Sprite Lib GPL . Ari made this library and lets anyone use it for free as long as the abide by the GPL license.

 

[cc lang="javascript" width="550"]//hitpixels.fla
//Jeff Fulton 2007
//www.8bitrocket.com
//pixel level collision detection with bitmap data object

import flash.display.*;
import flash.geom.*;

//1. load in spriteMap from library
var spriteMapBitmap:BitmapData = BitmapData.loadBitmap("spriteMap");
var mc:MovieClip = this.createEmptyMovieClip("mc", this.getNextHighestDepth());
//mc.attachBitmap(spriteMapBitmap, this.getNextHighestDepth());

//2. copy pixels from spriteMap to mc1
var sprite1:BitmapData=new BitmapData(32,32,true,0x00000000);
sprite1.copyPixels(spriteMapBitmap, new Rectangle(495, 33, 32, 32), new Point(0, 0));
this.createEmptyMovieClip("sprite1_mc",this.getNextHighestDepth());
sprite1_mc.attachBitmap(sprite1,sprite1_mc.getNextHighestDepth);
sprite1_mc._x=100;
sprite1_mc._y=100;

//2. copy pixels from spriteMap to mc2
var sprite2:BitmapData=new BitmapData(32,32,true,0x00000000);
sprite2.copyPixels(spriteMapBitmap, new Rectangle(33, 33, 32, 32), new Point(0, 0));
this.createEmptyMovieClip("sprite2_mc",this.getNextHighestDepth());
var sprite2_bitmap:BitmapData=sprite2_mc.attachBitmap(sprite2,sprite2_mc.getNextHighestDepth);
sprite2_mc._x=200;
sprite2_mc._y=200;

this.onEnterFrame=function() {

if (Key.isDown(Key.UP)) {
sprite1_mc._y ;
}
if (Key.isDown(Key.DOWN)) {
sprite1_mc._y++;
}
if (Key.isDown(Key.LEFT)) {
sprite1_mc._x ;
}
if (Key.isDown(Key.RIGHT)) {
sprite1_mc._x++;
}

if (sprite1_mc.hitTest(sprite2_mc)) {
normal_txt.text="true";
//trace("basic hit detected");
//test for pixel level hit
var myPoint:Point = new Point (sprite2_mc._x, sprite2_mc._y);
if (sprite1.hitTest (new Point (sprite1_mc._x , sprite1_mc._y), 255, sprite2, myPoint, 255)){
bitmap_txt.text="true";
//trace("bitMap hit detected");
}else{
bitmap_txt.text="false";
}
}else{
normal_txt.text="false";
bitmap_txt.text="false";

}

}
[/cc]

hitpixels.swf - demo of using bitmapData to do pixel level collision detection(2007).

Use the arrow keys to move the tank to the orange splotch sprite.

When the tank enters the 32x32 area for the splotch, the normal hit becomes true.

The bitmap hit will become true only if the tank collides with a non-trnasprant pixel in the splotch.

download the fla file

Ari Feldman's Sprite Lib used via GPL

1. When you attach a bitmapData object to a movieClip, a reference to the bitmapData object is passed, not the actual object. For hit testing purposes, you must use the original bitmapData object.
2. Here I have just used an object named sprite1, copied pixels from a png (with transparency) from the library to it, and have attached it to a movieClip.
3. if (sprite1.hitTest (new Point (sprite1_mc._x , sprite1_mc._y), 255, sprite2, myPoint, 255) is the function invoked. You must specify a point in both movieClip holders for the sprites tested, and the value (255) for the transparency threshold of each bitmap object.. This number represents the alpha threshold for the transparent areas. You can increase the :"sensitivity" of the collision test by lowering the number below 255. 255 means that ALL transparent areas, no matter the actual alpha value will be ignored in the hitTest. This gives you the best overall pixel level control.
4. To make a real game with this code (where multiple enemy sprites are needed) you would need to make sure to store a reference to to actual bitmapData object that makes up each enemy sprite and replace that with the sprite2 value as you loop through all of the enemy sprites.

The next lesson will be a simple way to add cached animation from the sprite map to this engine and you will see how a game will start to take shape.

 

18Apr/070

Final Wii Browser: Thoughts Redux

Last week I complained that the final version of the Wii Opera Browser did not support anything greater than Flash 7.0    Now it, it turns out, that this was neither Nintendo or Opera's fault. 

This information was brought to my attention earlier this week by fellow deveoper Chris Cutler (the programmer for the immensely popular game Pixel Chix Hamster Jam ) and confirmed today by nintendowiifanboy.com.   It turns out, that Adobe is really at fault here.  They have not released a dev kit for either Flash 8 or Flash 9, and until they do this, it will be impossible for vendors such as Opera to add Flash 8 or Flash 9 functionality into their software.

I was worried about issues like this when Adobe bought Macromedia (just after Flash 8 was released).   At the time I heard chilling rumors that they were going to create a Frankenstein's monster hybrid platform of Flash and Acrobat (not yet confirmed) and they would not be supporting ASP.NET 2.0 with the next version of Flash Remoting (still true).   The decisions are made because (IMHO) Adobe thinks of themselves as an "Enterprise" software vendor, when really they are vendor of excellent tools.   Enterprise vendors strive to make huge corporate deals, sometimes at the expense of their loyal, more individualize customer base.

Adobe has their own agenda and it not necessarily developer friendly.  Let's hope they can come to their senses and realize that Flash is popular because it has been such and open, developer friendly, platform, and any attempts they make to "reign it in" will only lead to developers jumping to the next platform that gives them the creative freedom and flexibility that is now, and has always been part of Macromedia Flash.

13Apr/070

Final Wii Browser: Thoughts

The "final" Opera browser was released for the Wii yesterday, and after using it I have mixed feelings. They added and fixed a few things that must be noted:

  • better interface
  • more responsive button clicks
  • better performance

However, one glaring omission is support for Flash 8.   With tons of Flash 9/Actionscript 3 content already being developed, it is very disappointing that Nintendo decided to not add support for, at least, Flash 8.   One of the main features of Flash 8 that would really improve Wii/Browser games is "External Interface" which would allow calls to JavaScript from Flash to support more buttons on the Wii-mote than just (A).   There have been some kludgy work-arounds for this involving two Flash movies and "Local Connection", but the performance is not good enough to make usable games that require quick access to the controller buttons.

As it stands right now, the improved performance of Flash 7 content, as well as the much more responsive (A) button will add greatly to already existing Games and content, but without support for Flash 8, it looks like Wii/Browser games will remain a curious and interesting area of development, but not the ideal playground that it could have been.

 

12Apr/070

Atari Nerd Chronicles: The Apple Adventure

Sometime around 1981 a wonderful event took place in the lives of two lower-middle class twin boys. Eric Barth, a cool little kid down the street from our house, was given an Apple IIe. Steve and I spent almost every waking minute with Eric exploring the machine and all it had to offer. Without Eric and his Apple, this site would not exist in its current form. There definitely would be a site made by Steve and I, but it would have a named pertaining to some other exciting first time programming or computer game experiment. It could have been the Price Is Right game, random sentence generator, or some other Atari 800 programming adventure.

It might have been called PERTEC-Rocket.com in reference to the VMS (or CPM) based machines our Junior High was given in the 7th grade. Steve and I made a historical adventure game in the modest Junior High computer lab and were featured in Forbes magazine because of it. It might have been named after one of the all time great gaming experiences on the Atari ST : Phantasie I, Dungeon Master, Kick Off II, or Megaroids. It might have been named after a great VCS, 7800, Master System or Lynx game.

It might have been named after one of the Genesis or Nintendo games we played with Ian Legler, one of the Coleco Vision games with Played with Brandon Crist, or one of the Atari 400 games with typed in with Kenny Brown. It might have been an early PC or Fairchild game we played at Wesley Crew's house. All of those times were defining moments in our computer and game creation education. None of them though can hold a candle to that first year with Eric's Apple IIe.

The three of us almost went blind staring at that beautiful green screen monitor. We played great games like Apple Panic and Ceiling Zero. We cobbled together pieces of random basic code to make the namesake 8bitrocket programs. We made all kinds of games. We had pretend phone dialers and our own early versions of the a hacker simulator well before the Hacker games were released. We spent countless hours creating machines in Pinball Construction set. I remember that Eric was an exceptional math student and started to create awesome graphical games well before Steve and I could. Anyway, I mention all of this as a thanks to Eric. In the funny world we live in where anyone can Google themselves for fun, Eric found us last week. After almost 20 years with no contact, Eric sent an email to the info@8bitrocket.com box over the weekend. I want to publicly thank him and his father for letting Steve and I ride their Apple IIe coat tails until we got our Atari 800 in 1983. Without Eric, there would be no 8bitrocket. Thanks Eric, and let's not make it another 20 years before we talk again. You know where to find us.

   
This site is protected by Comment SPAM Wiper.