Monday, December 22, 2008

Flash Side Scroller / Platform Engine: Post 1.5

I've been working here and there on a side scroller engine in my spare time. I say post 1.5 in the title because I briefly mentioned the game at the end of a previous post.

In the previous post I just had a square for a character, general movement, and basic collision detection. Since then, Stan created a run animation and I changed my collision detection so that it can handle any shape (before it could only handle rectangles). So now I have ramps, stairs, and crazy spiral platforms. Its still very, very early and unfortunately fairly buggy.

The main thing I want to touch on is the collision detection. I have come up with a scheme to handle all the collisions using bitmapData objects. I choose this option for two reasons:
1. I wanted to stay away from grids because by the end of this I want the world and characters to be very fluid and animated. I didn't want to constrain the art and design to any rectangles or dimensions.
2. For speed purposes, I want to use blitting and only display 1 bitmap on the screen... this rules out any MovieClip/Vector hit test.

To accomplish this there will be three bitmapData objects: Floor, Walls, and Ceiling. As the character moves, I will store the character's x,y position and do a hitTest on the different bitmapData objects. That means that all the black walls/floors/etc that you currently see do not need to be displayed on the screen, I just need their bitmapData to use as reference. In the final product you will see some pretty scenery and all of these fugly black platforms will be referenced in the background.

If a hit occurs then I need to find the boundaries of the platform that is being hit. Obviously I can't just grab the boundaries of the entire bitmap because that would always be 0,0 for the top left and the width,height for the bottom right (since the bitmap takes up the entire level). I initially did a red floodfill on the contact point and then grabbed the bounds of the color red from the bitmap. This worked great when I was only using rectangular platforms. Once I made slopes and stairs, however, I was back to the same problem of getting the outer rectangle when the actual hit occurred somewhere within the bounds.

Therefore, I tweaked the process. After a hitTest returns true, I copy the pixels from that column into a 1 pixel wide bitmapData object. I then do the same floodFill operation on this object. By keeping it 1 pixel wide, I am guaranteed to not be impacted by the surrounding platform area.

This has worked much better than my initial collision detection... but I have run into one bug that I need to squash. It seems as though the hitTest and the floodFill are rounded a bit differently. Or possibly one is rounded and one is not. In any case, sometimes a hit is triggered but then the floodFill will fill the whitespace instead of a black platform. When this happens the character jumps to a higher platform or to the far side of the screen. It should be fairly easy to get around this by adding some constraints or possibly an extra check to make sure the floodFill is hitting a black area... but I hopefully with some extra time I will be able to figure out the rounding difference because the work-arounds I have in my head seem as though they would be slightly more processor intensive.

Anyways. I wanted to post my progress before the break. Not sure if I will be on here much until the 5th. You can check it out here.

Hope you found this interesting. There will be more to come.

Enjoy the Holidays.


Al said...

Perhaps you should post where your up to? Be interested to see it.

We made a Worms clone a while back, using bitmap's for our collision data - worked really well. The method we used basically involved testing between the players position and then players position plus it's current velocity using breshenham's algorithm to walk through each pixel until we got a hit. Once we found a hit, we then scanned the surrounding pixels (using a function similar to the way floodfill works) to find 2 points either side of the collision. This allowed us to calculate the angle of impact (or the normal), allowing us to resolve properly.

The cool thing about using bitmaps for hitTest-ing is that you can modify the bitmap to makes holes for things like explosions.

Ickydime said...

Thanks for the post.

I had the link hidden at the top... its funny, even when I hit submit I thought about adding the link at the bottom as well. I just did now.

I wikipedia'd Breshenham's algorithm. If I can't figure out an easy solution to this rounding bug I may give that a shot. And if I don't use it with the main character, I am definitely going to look into it for projectiles. It would ensure nothing flew right through the character.

Thanks for the tip.