R – Finding Something lighter than Sprites!

actionscript-3bitmapsprite

I am making a Sim City like game. There are lots of tiles. When I first started. I was just using a tilesheet. I was copying the necessary pieaces from the tilesheet. on to a blank bitMapData. I then took the bitMapData and put it into a bitMap which I then put into a DisplayObject. It worked great!

tileSheet:BitMapData  <----- data is already in
loop { loop through and tiled
bg:bitMapData= new bitMapData();
bg.copyPixel(tileSheet,rect,point);
}

canvas.BitMap(bg);
addChild(canvas);

Only problem was I needed to make my tiles interactive. I needed to highlight them and change colors and stuff. So I used the Sprite object. It works great but I can only have so many on the stage at once. or else it moves slow when I scroll. I need something Lighter then a sprite, but yet I can still turn into a object to make interactive. Anyone have any ideas ???

Best Answer

If you have a lot of tiles, that will impact performance because Flash needs to update the transformations of a lot of display objects (which internally means a lot of matrix calculations, and subsequent redraws of big areas of the screen.)

There is another way to achieve interactivity, if you find that you must use a single bitmap data for performance. Keep an "abstract" (i.e. not graphical) data model in memory, that stores your game state. Make sure that you are able to read from your store where a certain element is positioned in the game world. Then you can use a flat bitmap data to render the game world, because the individual positions are stored elsewhere.

When the user clicks the DisplayObject containing the bitmap data (a Sprite in which the bitmap is drawn using a bitmap fill, or that wraps a Bitmap), look in your model which of your game elements was hit by that click.

// myTileSprite is a Sprite with a bitmap fill
myTileSprite.addEventListener(MouseEvent.CLICK, handleWorldClick);

function handleWorldClick(ev : MouseEvent) : void
{
  var i : int;

  // Loop through all game element data models
  for (i=0; i<myGameElements.length; i++) {
    // Test the mouse position against the element model
    if (myGameElements[i].hitTest(myTileSprite.mouseX, myTileSprite.mouseY)) {
      trace('this was the element that was clicked: '+myGameElements[i].toString());
    }
  }
}

Here, whenever the player clicks the world graphics, the loop tries to find that element which was directly under the mouse position. You will need to implement a hitTest() method on all your game element data models, of course. Such a method simply checks the supplied world space position against the tile's area:

// GameElement.hitTest():
/**
* Tests a world position against the position and area of this game
* element tile. Returns a boolean indicating whether this tile was hit.
*/
public function hitTest(mouseX : Number, mouseY : Number) : void
{
  var rect : Rectangle = new Rectangle(this.worldX, this.worldY, this.width, this.height);

  if (mouseX > rect.left && mouseX < rect.right
    && mouseY > rect.top && mouseY < rect.top) {
    return true;
  }
  else return false;
}

The GameElement class is not an display object, but has worldX and worldY properties indicating where it is located in the world. It's width and height properties define it's dimensions.

The trick from hereon is to make sure that the rendered bitmap and your model storage is synchronized, so that a tile's position on the bitmap really corresponds to it's worldX/worldY properties in the data model.

Related Topic