How to place multiple bitmaps in a scrollable rectangle? AS3 - actionscript-3

This code builds a palette of tiles for use in a map maker program. It takes in an array set by its parent and uses the bitmaps(from the objects) in that array to display a grid of tiles. Right now it only does a 5x5 grid, but what if there are more than 25 tiles in my tileSet? I want to display only the 5x5 tile grid, but be able to scroll through the images. I imagine that I need to make another rectangle to use as its mask and use a ScrollBar to make it scrollRect, but I can't get this working. Please Help.
public function Palette(X:uint, Y:uint, tileSet:Array)
{
addChild(handleGraphics);
var palette:Rectangle = new Rectangle(X, Y, 5*32, tileSet.length*32); //Default size is 5x5 tiles.
handleGraphics.DrawGrid(32,palette.x,palette.y,5,5);
var counter:int = 0;
for(var i:int = 0; i < 5; i++)
{
paletteArray[i] = [];
for(var u:int = 0; u < 5; u++)
{
if(counter >= tileSet.length)
{
counter = 0; //Which frame to show?
}
var b:Bitmap = new Bitmap(tileSet[counter].Graphic);
b.x = (palette.x) + 32 * u; //Align with palette Rectangle.
b.y = (palette.y) + 32 * i; ///////////////////////////////
addChild(b);
var tileObj:Object = new Object();
tileObj.Name = tileSet[counter].Name;
tileObj.Frame = tileSet[counter].Frame;
tileObj.Graphic = tileSet[counter].Graphic;
paletteArray[i].push(tileObj);
setChildIndex(b, 0); //Under grid.
counter++;
}
}
ActivatePaletteListeners();
}
This code works great for a tileSet array that has less than 25 objects. It loops and shows them continuously until it hits 25. I could do without this I guess, but it is a neat affect.
In another class (HandleTiles) I cycle through my tileSet MovieClip and use each frame to create a new object for each tile.
public function GetPaletteTiles(MC:MovieClip)
{
if (tileArray != null)
{
tileArray.length = 0;
}
for(var i:int = 1; i <= MC.totalFrames; i++)
{
MC.gotoAndStop(i); //Change frame for new info.
var tileObj:Object = new Object(); //The object to push to an array of tiles.
var graphicData:BitmapData = new BitmapData(32,32);
graphicData.draw(MC); //Graphic data from sampleTS.
tileObj.Name = MC.currentFrameLabel;
tileObj.Frame = MC.currentFrame;
tileObj.Graphic = graphicData;
tileArray.push(tileObj);
}
BuildIndexArray(15, 20); //Default size 15 x 20.
}
And here I set the tileSet to use
private function ChangeActiveTileset(Mc:MovieClip)
{
activeTileset = Mc;
GetPaletteTiles(activeTileset);
UpdatePalette();
}
I can change the tileSet with a comboBox. That's why I tear down the tileArray every time I call GetPaletteTiles(). Each tileSet is a different MovieClip, like Buildings, Samples, InTheCity, etc.

Sorry I didn't have time to get this code together earlier. Here's tiling code pieces. Because you're using rectangle and you have to stay under max dimensions you have to move the source mc. I think you already know everything else in there.
// set the bmp dimensions to device screensize to prevent exceeding device's max bmp dimensions
if (bStagePortrait) {
iTileWidth = Capabilities.screenResolutionX;
iTileHeight = Capabilities.screenResolutionY;
} else {
iTileWidth = Capabilities.screenResolutionY;
iTileHeight = Capabilities.screenResolutionX;
}
// mcList.mcListVector is the source mc - a regular mc containing mcs, jpgs, dynamic text, vector shapes, etc.
// mcList.mcListBmp is an empty mc
aListTiles = new Array();
iNumberOfTiles = Math.ceil(mcList.height / iTileHeight);
for (i = 0; i < iNumberOfTiles; i++) {
var bmpTile: Bitmap;
// move the source mc
mcList.mcListVector.y = -(i * iTileHeight);
bmpTile = fDrawTile(mcList, 0, 0, iTileWidth, iTileHeight);
mcList.mcListBmp.addChild(bmpTile);
bmpTile.x = 0;
bmpTile.y = (i * iTileHeight);
aListTiles.push(bmpTile);
}
// remove the regular mc
mcList.mcListVector.removeChild(mcList.mcListVector.mcPic);
mcList.mcListVector.mcPic = null;
mcList.removeChild(mcList.mcListVector);
mcList.mcListVector = null;
}
function fDrawTile(pClip: MovieClip, pX: int, pY: int, pWidth: int, pHeight: int): Bitmap {
trace("fDrawTile: " + pX + "," + pY + " " + pWidth + "," + pHeight);
var rectTemp: Rectangle = new Rectangle(pX, pY, pWidth, pHeight);
var bdClip: BitmapData = new BitmapData(pWidth, pHeight, true, 0x00000000);
var bdTemp: BitmapData = new BitmapData(pWidth, pHeight, true, 0x00000000);
bdClip.draw(pClip, null, null, null, rectTemp, true);
bdTemp.copyPixels(bdClip, rectTemp, new Point(0, 0));
var bmpReturn: Bitmap = new Bitmap(bdTemp, "auto", true);
return bmpReturn;
}

Related

Previous function is called/Event listener 'delayed' by one

I have altered an image carousel I downloaded, to rotate to the next picture (left or right) when I click one of the two buttons I added. The original carousel was built to rotate according to mouse movement/position.
For some reason, whenever I click the 'right' or 'left' button, which each rotate the carousel in their respecive directions, the event listener/handler is one 'behind'. It does whatever it should've done the previous time I clicked a button. To put it more clearly, the first button click it does nothing. The second button click it responds to what I clicked the last time.
Example:
I click the left button, nothing happens.
Then I click the right button, the carousel rotates to the left (because I clicked the left button before this click)
Then I click the left button, the carousel rotates to the right (idem).
See the code below. It seems fairly simple; no complex structure or whatever.
You can ignore most vars and positioning (like focalLength,vanishingPointX,radius, etc), I suppose. I'm guessing this bug is either related to the importing/processing of the XML, the for() loops, or the structure the .as file has.
package {
//here are all the imports
public class Imagereel extends Sprite {
var imgurl:URLRequest = new URLRequest()
var loadedimgs:uint = 0;
var images_num = 0;
var imageHolders:Array = new Array();
var imageHolder:MovieClip;
var btnLeft:BtnLeft = new BtnLeft;
var btnRight:BtnRight = new BtnRight;
//Set the focal length
var focalLength:Number = 2000;
//Set the vanishing point
var vanishingPointX:Number = stage.stageWidth / 2;
var vanishingPointY:Number = stage.stageHeight / 2;
//The 3D floor for the images
var floor:Number = 40;
//Radius of the circle
var radius:Number = 350;
//We use 70x70 sized images (change this if different for your images)
const IMAGE_WIDTH:uint = 393;
const IMAGE_HEIGHT:uint = 249;
var xmlLoader:URLLoader = new URLLoader();
var xmlData:XML = new XML();
public function Imagereel() {
//here's the positioning of the buttons
//here are the button addChilds
xmlLoader.load(new URLRequest("carousel.xml"));
xmlLoader.addEventListener(Event.COMPLETE, LoadXML);
btnLeft.addEventListener(MouseEvent.CLICK, prevImg);
btnRight.addEventListener(MouseEvent.CLICK, nextImg);
}
function LoadXML(e:Event):void {
xmlData = new XML(e.target.data);
Parseimage(xmlData);
}
function Parseimage(imageinput:XML):void {
var imageurl:XMLList = imageinput.image.iurl;
images_num = imageurl.length();
for (var i:int = 0; i < images_num; i++) {
var urlElement:XML = imageurl[i];
imageHolder = new MovieClip();
var imageLoader = new Loader();
imageHolder.addChild(imageLoader);
imageHolder.mouseChildren = false;
imageLoader.x = - (IMAGE_WIDTH);
imageLoader.y = - (IMAGE_HEIGHT);
imageHolders.push(imageHolder);
imgurl.url = imageurl[i];
imageLoader.load(imgurl);
imageLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, imageLoaded);
}
}
function imageLoaded(e:Event) {
//Update the number of loaded images
loadedimgs++;
//Check to see if this is the last image loaded
if (loadedimgs == images_num) {
//Set up the carousel
initializeCarousel();
}
}
function initializeCarousel() {
//Calculate the angle difference between the images (in radians)
var angleDifference:Number = Math.PI * (360 / images_num) / 180;
//Loop through the images
for (var i:uint = 0; i < imageHolders.length; i++) {
//Assign the imageHolder to a local variable
var imageHolder:MovieClip = (MovieClip)(imageHolders[i]);
//Get the angle for the image (we space the images evenly)
var startingAngle:Number = angleDifference * i -0.30;
//Position the imageHolder
imageHolder.xpos3D = radius * Math.cos(startingAngle);
imageHolder.zpos3D = radius * Math.sin(startingAngle);
imageHolder.ypos3D = floor;
//Set a "currentAngle" attribute for the imageHolder
imageHolder.currentAngle = startingAngle;
var scaleRatio = focalLength/(focalLength + imageHolder.zpos3D);
//Position the imageHolder to the stage (from 3D to 2D coordinates)
imageHolder.x = vanishingPointX + imageHolder.xpos3D * scaleRatio;
imageHolder.y = vanishingPointY + imageHolder.ypos3D * scaleRatio;
//Add the imageHolder to the stage
addChild(imageHolder);
}
sortZ();
}
function prevImg(e:MouseEvent) {
//Loop through the images
for (var i:uint = 0; i < imageHolders.length; i++) {
var imageHolder:MovieClip = (MovieClip)(imageHolders[i]);
//Set a new 3D position for the imageHolder
imageHolder.xpos3D = radius * Math.cos(imageHolder.currentAngle);
imageHolder.zpos3D = radius * Math.sin(imageHolder.currentAngle);
var scaleRatio;
//Calculate a scale ratio
scaleRatio = focalLength/(focalLength + imageHolder.zpos3D);
//Update the imageHolder's coordinates
imageHolder.x = vanishingPointX+imageHolder.xpos3D * scaleRatio;
imageHolder.y = vanishingPointY+imageHolder.ypos3D * scaleRatio;
//spinning the carousel
imageHolder.currentAngle += 0.6285;
}
//Call the function that sorts the images so they overlap each others correctly
sortZ();
}
function nextImg(e:MouseEvent) {
//Loop through the images
for (var i:uint = 0; i < imageHolders.length; i++) {
var imageHolder:MovieClip = (MovieClip)(imageHolders[i]);
//Set a new 3D position for the imageHolder
imageHolder.xpos3D = radius * Math.cos(imageHolder.currentAngle);
imageHolder.zpos3D = radius * Math.sin(imageHolder.currentAngle);
var scaleRatio;
//Update the imageHolder's coordinates
imageHolder.x = vanishingPointX+imageHolder.xpos3D * scaleRatio;
imageHolder.y = vanishingPointY+imageHolder.ypos3D * scaleRatio;
//spinning the carousel
imageHolder.currentAngle -= 0.6285;
}
sortZ();
}
//This function sorts the images so they overlap each others correctly
function sortZ():void {
imageHolders.sortOn("zpos3D", Array.NUMERIC | Array.DESCENDING);
//Set new child indexes for the images
for (var i:uint = 0; i < imageHolders.length; i++) {
setChildIndex(imageHolders[i], i);
}
}
}
}
So what this code does:
carousel.xml is imported
The xml is processed so that the image paths there are converted to displayed images
A carousel is made out of the images
The sortZ() function makes sure that the images are aligned in 3D perspective properly; just like z-index in CSS would do.
When clicking btnLeft or btnRight, the carousel rotates to the left or right (this is done by updating the value of imageHolder.currentAngle).
When I put trace's inside the prevImg() and nextImg() functions, I do see the trace that
belongs to the right function, and not the previously clicked one. So it seems that Flash does call the right event.
So how do I get rid of this bug?
Help and tips are greatly appreciated!
Move imageHolder.currentAngle assignment (the line where you change it) BEFORE the code that alters imageHolder's 3D position.
for (var i:uint = 0; i < imageHolders.length; i++) {
var imageHolder:MovieClip = (MovieClip)(imageHolders[i]);
//Set a new 3D position for the imageHolder
imageHolder.currentAngle += 0.6285; // <== HERE
imageHolder.xpos3D = radius * Math.cos(imageHolder.currentAngle);
imageHolder.zpos3D = radius * Math.sin(imageHolder.currentAngle);
var scaleRatio;
//Calculate a scale ratio
scaleRatio = focalLength/(focalLength + imageHolder.zpos3D);
//Update the imageHolder's coordinates
imageHolder.x = vanishingPointX+imageHolder.xpos3D * scaleRatio;
imageHolder.y = vanishingPointY+imageHolder.ypos3D * scaleRatio;
//spinning the carousel
}
The same for the other function.

AS3: can't addchild indexed movieclips into a sprite

I'm creating a dynamic blocked terrain in flash (AS3), and everything goes fine with it, the terrain is correctly placed. But I need to include collisions and I want the blocks to be within a movieclip (sprite), so I can test the collision with the terrain itself.
Ps: I don't know if it would be good to test the collisions with each block individually because I'll use a enterframe function and the block generation is dynamic.
The problem I'm facing is that I have a sprite called blockHolder, but I can't addChild the blocks to it.
Here's the code (I simplified it so we have the blocks being created in cascade if you addChild them into the stage directly, like addChild(clonedSquare).
The error I'm receiving:
TypeError: Error #1009: Can't access property or method of a null object reference.
var blockHolder:Sprite = new Sprite();
var clonedSquare = new square();
var lowestPoint:int = 10;
var highestPoint:int = 20;
var areaLenght:int = 10;
function createLvl():void
{
for (var i:Number = 0; i<(areaLenght); i++)
{
clonedSquare = new square();
clonedSquare.x = i * clonedSquare.width;
//sets the height of the first block
if (i == 0)
{
var firstY:Number = Math.ceil(Math.random()*((lowestPoint-highestPoint))+highestPoint)*clonedSquare.height;
clonedSquare.y = firstY;
trace("terrain begins " + firstY + " px down");
}
else
{
var previousId:Number = i - 1;
clonedSquare.y = getChildByName("newSquare"+previousId).y + clonedSquare.height;
}
//sets the entity (block) name based on the iteration
clonedSquare.name = "newSquare" + i;
//adds the cloned square
blockHolder.addChild(clonedSquare);
}
addChild(blockHolder);
}
createLvl();
Well I fixed the error. I am still not clear as to what you're asking for. Basically I add each block to an array and reference the block that way. Your clonedSquare.y = getChildByName("newSquare"+previousId).y + clonedSquare.height; was throwing the error. Also your firstY was placing the first block way off my stage so I just set it to 0 as firstY
var blockHolder:Sprite = new Sprite();
var squares:Array = [];
var lowestPoint:int = 10;
var highestPoint:int = 20;
var areaLenght:int = 10;
function createLvl():void
{
for (var i:Number = 0; i<(areaLenght); i++)
{
var clonedSquare = new square();
clonedSquare.x = i * clonedSquare.width;
if (i == 0)
{
var firstY:Number = Math.ceil(Math.random()*((lowestPoint-highestPoint))+highestPoint)*clonedSquare.height;
//clonedSquare.y = firstY;
clonedSquare.y = 0;
trace("terrain begins " + firstY + " px down");
}
else
{
clonedSquare.y = squares[i - 1].y + clonedSquare.height;
}
blockHolder.addChild(clonedSquare);
squares.push(clonedSquare);
}
addChild(blockHolder);
}
createLvl();

AS3: Random Point on Irregular Shape

I have a MovieClip holding an irregular shape such as this one:
I need to generate a random point on this shape.
I can use brute force by generating points within the bounding box and then hitTesting to see if they reside on the irregular shape. However, I'm sure there's a more efficient way to tackle this problem.
What is the most efficient way to generate a random point on an irregular shape?
You mentioned hitTest, but I assume you meant hitTestPoint().
If so, a function go get the random points you mention, would look a bit like this:
function getRandomPointsInClip(target:MovieClip,numPoints:int):Vector.<Point>{
var points:Vector.<Point> = new Vector.<Point>(numPoints,true);
var width:Number = target.width,height:Number = target.height;
for(var i:int = 0; i < numPoints ; i++){
var point:Point = new Point(target.x+Math.random() * width,target.y+Math.random() * height);
if(target.hitTestPoint(point.x,point.y,true)) points[i] = point;//is the random coord inside ?
else i = i-1;//nope, go back one step - > retry above until it is inside
}
return points;
}
The other I hinted at in my comment involves looping through non transparent pixels in a bitmap data of your object. This method would insure you don't have many duplicates, as opposed to the previous method, but it also means, you have less control over the number of points created and there's extra memory used for creating the bitmap. Still, for documentation purposes, here is the function:
function getGridPointsInClip(target:MovieClip,res:int,offset:Number = 3):Vector.<Point>{
var points:Vector.<Point> = new Vector.<Point>();
var x:int,y:int,alpha:int,w:int = int(target.width),h:int = int(target.height);
var bmd:BitmapData = new BitmapData(w,h,true,0x00FFFFFF);bmd.draw(target);
var pixels:Vector.<uint> = bmd.getVector(bmd.rect),numPixels:int = w*h;
for(var i:int = 0; i < numPixels; i+=res) {
x = i%bmd.width;
y = int(i/bmd.width);
alpha = pixels[i] >>> 24;
if(alpha > 0) points.push(new Point(x+random(-offset,offset),y+random(-offset,offset)));
}
return points;
}
function random(from:Number,to:Number):Number {
if (from >= to) return from;
var diff:Number = to - from;
return (Math.random()*diff) + from;
}
And here'a very basic test:
var pts:Vector.<Point> = getRandomPointsInClip(mc,300);
//var pts:Vector.<Point> = getGridPointsInClip(mc,100,4);
for(var i:int = 0 ; i < pts.length; i++) drawCircle(pts[i].x,pts[i].y,3,0x009900);
function getRandomPointsInClip(target:MovieClip,numPoints:int):Vector.<Point>{
var points:Vector.<Point> = new Vector.<Point>(numPoints,true);
var width:Number = target.width,height:Number = target.height;
for(var i:int = 0; i < numPoints ; i++){
var point:Point = new Point(target.x+Math.random() * width,target.y+Math.random() * height);
if(target.hitTestPoint(point.x,point.y,true)) points[i] = point;//is the random coord inside ?
else i = i-1;//nope, go back one step - > retry above until it is inside
}
return points;
}
function getGridPointsInClip(target:MovieClip,res:int,offset:Number = 3):Vector.<Point>{
var points:Vector.<Point> = new Vector.<Point>();
var x:int,y:int,alpha:int,w:int = int(target.width),h:int = int(target.height);
var bmd:BitmapData = new BitmapData(w,h,true,0x00FFFFFF);bmd.draw(target);
var pixels:Vector.<uint> = bmd.getVector(bmd.rect),numPixels:int = w*h;
for(var i:int = 0; i < numPixels; i+=res) {
x = i%bmd.width;
y = int(i/bmd.width);
alpha = pixels[i] >>> 24;
if(alpha > 0) points.push(new Point(x+random(-offset,offset),y+random(-offset,offset)));
}
return points;
}
function random(from:Number,to:Number):Number {
if (from >= to) return from;
var diff:Number = to - from;
return (Math.random()*diff) + from;
}
function drawCircle(x:Number,y:Number,radius:Number,color:uint):void{
graphics.lineStyle(1,color);
graphics.drawCircle(x-radius,y-radius,radius);
}
HTH
If you think of some non-blob like shapes, it's clear the check random pixel, try again method isn't really a good way. The bounding box area could be huge compared to the shape area.
What you could do to improve the effectiveness is getting a vector of the BitmapData of the shape. It should contain all pixels of the bounding box. Update - it would be nice now if we could pick a random point, and remove it from the vector if it isn't inside the shape. Unfortunately the vector only contains the pixels' colour, not the position which is implicit and only correct if we don't change the vector's length. Since we don't need to know the actual colour, we can omit all transparent pixels and store an inside pixel's position as it's value in the vector. This way we don't need to create a new object for each pixel of the shape (that would be quite expensive!).
var v:Vector.<uint> shapeBoxBitmap.getVector(shapeBoxBitmap.rect);
var pixelNum:int = v.length;
for(var i:uint = 0; i < pixelNum; i++) {
if( v[i] && 0xFF000000 == 0) { // transparent pixel, outside off shape
v.splice(i,1);
} else {
v[i] = i;
}
}
//get random point
var randomPixel:int = v[Math.floor(Math.random()*v.length)];
var point:Point = new Point(randomPixel%shapeBitmap.width,int(randomPixel/shapeBitmap.width));

How to modify position of children inside loop in AS3

I'm trying to make a dynamic image gallery from and xml. From my tutorials, right now i've got it so it will constantly add the next thumbnail below the other, which is fine, but I'm trying to figure out how to make it that once it reaches a certain y coordinate, it will move the x coordinate over and stack them again. So that rather one long list of thumbs, it will be a side by side stack. For some reason, I can't get it in my head how something like this would work. My goal is to have a side by side stack that I will end up putting in a movie clip that will be masked to show only 2 stacks at a time. Then when clicking a button will slide it over. I was planning to use the "movieclip.length" to calculate how far over to move it, but i haven't gotten that far yet. This is what I got:
var gallery_xml:XML;
var xmlReq:URLRequest = new URLRequest("xml/content.xml");
var xmlLoader:URLLoader = new URLLoader();
var imageLoader:Loader;
function xmlLoaded(event:Event):void
{
gallery_xml = new XML(xmlLoader.data);
info_txt.text = gallery_xml.screenshots.image[0].attribute("thumb");
for(var i:int = 0; i < gallery_xml.screenshots.image.length(); i++)
{
imageLoader = new Loader();
imageLoader.load(new URLRequest(gallery_xml.screenshots.image[i].attribute("thumb")));
imageLoader.x = 0;
imageLoader.y = i * 70 + 25;
imageLoader.name = gallery_xml.screenshots.image[i].attribute("src");
addChild(imageLoader);
imageLoader.addEventListener(MouseEvent.CLICK, showPicture);
}
}
xmlLoader.load(xmlReq);
xmlLoader.addEventListener(Event.COMPLETE, xmlLoaded);
function showPicture(event:MouseEvent):void
{
imageLoader = new Loader();
imageLoader.load(new URLRequest(event.target.name));
imageLoader.x = 200;
imageLoader.y = 25;
addChild(imageLoader);
}
I can't seem to wrap my head around what I can do to move things over dynamically without having to write a custom if for each set of positions.. I get the feeling I've totally forgotten how to do algebra.
I'd suggest one of the following two solutions (untested):
var next_x:Number = 0.0;
var next_y:Number = 25.0;
for (var i:int = 0; i < gallery_xml.screenshots.image.length(); ++i)
{
// ...
imageLoader.y = next_y;
imageLoader.x = next_x;
next_y += 70;
if (next_y > THRESHOLD)
{
next_x += X_OFFSET;
next_y = 25.0;
}
}
That is, just keep track of where your next image will be placed and adjust that coordinate accordingly when you exceed thresholds. If you want to use your i variable, you'll have to calculate what row and column the image will be placed at:
for (var i:int = 0; i < gallery_xml.screenshots.image.length(); ++i)
{
// ...
var row:int = i % MAX_ITEMS_PER_COLUMN;
var column:int = i / MAX_ITEMS_PER_COLUMN;
imageLoader.y = 25 + row * 70;
imageLoader.x = column * COLUMN_WIDTH;
}

Single Loader to multiple Sprite Possible?

I've looked in various resources regarding this topic, and it seems to me that I need a Loader for every Sprite which contains an image file (png).
I'm trying to make a Tile Rendering System, and have created a grid of X by Y sprites, but all of them actually reference the same image file.
Is there any other way to do this? (Make the sprite share the same png data file)
Some sample code of what I have done.
// Create an array of X * Y Loaders
var cTileLoaders:Array = new Array( 100 ); // for example 10 by 10 grid
var cTiles:Array = new Array( 100 );
var nIndex:int = 0;
var nImgLoadCount:int = 0;
for ( ; 100 > nIndex; ++nIndex ) {
cTileLoaders[ nIndex ] = new Loader();
cTiles[ nIndex ] = new Sprite();
// perform more sprite initialization
....
cTileLoaders[ nIndex ].contentLoaderInfo.addEventListener( Event.COMPLETE, ImageLoaded
cTileLoaders[ nIndex ].Load( new URLRequest( "some image path" ) );
}
// handler for image loaded
function ImageLoaded( eEvent:Event ):void {
++nImgLoadCount;
// when all 100 sprite data are loaded
// assuming there is no i/o error
if ( 100 == nImgLoadCount ) {
cTiles[ nIndex ].addChild( cTileLoaders[ nIndex ].content );
}
}
I think the answer in your case is to utilise the Bitmap data contained within the image you're loading like this:
var tilesWide:uint = 10;
var tilesHigh:uint = 10;
var tileHolder:Sprite = new Sprite();
this.addChild(tileHolder);
var loader:Loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onImgLoaded);
loader.load(new URLRequest("tile.png"));
function onImgLoaded(e:Event):void
{
/* Create a template bitmap to hold the image info */
var templateBitmap:Bitmap = e.target.content;
var templateBitmapData:BitmapData = templateBitmap.bitmapData;
/* Loop through your tiles */
for (var a:uint = 0; a < tilesWide; a++)
{
for (var b:uint = 0; b < tilesHigh; b++)
{
var tile:Sprite = new Sprite();
/* Attach the template BitmapData to each tile */
var tileBitmap:Bitmap = new Bitmap(templateBitmapData);
tile.addChild(tileBitmap);
tile.x = a * tile.width;
tile.y = b * tile.height;
tileHolder.addChild(tile);
}
}
}
You could also use SpriteFactory, a little library I wrote specifically for this:
var tilesWide:uint = 10;
var tilesHigh:uint = 10;
var tileHolder:Sprite = new Sprite();
var tilePath:String = "some/image/path.png";
var factory:SpriteFactory = new SpriteFactory();
factory.loadBitmap("tile", tilePath);
for (var a:uint = 0; a < tilesWide; a++)
{
for (var b:uint = 0; b < tilesHigh; b++)
{
var tile:Sprite = factory.newSprite("tile");
tile.x = a * tile.width;
tile.y = b * tile.height;
tileHolder.addChild(tile);
}
}
The advantage here being that you can use the sprites right away, and they'll automatically be filled with the bitmap once it's loaded.