Confused about automatic instances and moving sprites in AS3 - actionscript-3

I created big Sprite called Space and big number of smaller sprites and keep them in array Cells.
Question 1.
When I trace Cell's names (like Cells[i].name) - it shows 'instance' and and even numbers 2,4,6,...
When I trace children of Space names for (...Space.numChildren; i++){trace(Space.getChildAt(i).name) it shows odd numbers 'instance1' 'instance3','instance5'
The question is why there are two sets of different sprites and with which one I need to work further - to change coordinates, colors and so on. How the two related to each other?
Question 2.
Both sets show x and y coordinates of all cells set to 0 although when I created them I set it to different values and I see them placed correctly on screen.
When I move (by mouse) one of the cells, I want to move the same way all of the group of cells w/o changing relative locations between them. I could do it with the second set of instances only, but strange way. I don't set new coordinates as one would expect - c.x += dx; c.y +=dy,
but c.x =dx; c.y = dy;
I need clarification on that.

Thank you all cared to answer.
I already figured it out. The problem was that I did not understand that in array I saved addresses of my as3 objects returned by new operator, but addresses of graphic objects has to be saved inside the class objects and I had to use them to access the images.

Related

How to find all distinct closed paths from a group of points

Is it possible to find out all possible closed paths with intersection. I have a set of points in an array. I need to process the points in the array and plot the closed areas.
This is building designing project. I know all the points (Shown as green dots in the images attached) x and y values. Here i need to know each rooms separately as shown in image2(room are labeled from 1-11). How can i find out the room's boundary points.
The points may vary this is just a sample.
http://demo.enfintech.net/BuildingImage/1.jpg
http://demo.enfintech.net/BuildingImage/2.jpg
What I suggest is that since all your connections are either vertical or horizontal, you can do the following:
Extend all connection lines in both directions so that you end up with a matrix of small cells.
Initially your number of rooms shall be the number of these small cells. Number them accordingly.
Now for each cell, check whether the boundary with its neighbour exists or not (whether the boundary line is an actual connection line or just an extrapolation).
If it is just an extrapolation, then join these cells into a single cell.
Keep repeating this for all the cells until all extrapolated lines disappear.

MovieClip alignment (a character with multiple states) without using a meta-MovieClip

I'm working on a game where there are 4 characters on screen, each with several different states and corresponding MovieClips so that my library looks a little something like this:
Character 1:
IdleAnimation
SleepAnimation
..
Character 2:
IdleAnimation
SleepAnimation
..
Each animation (provided by a 3rd party) has a different anchor point, so when character A is at position 100, 100 on screen and moves from the idle to sleep animation he suddenly jumps 20 pixels to the right due to the anchor point.
Usually I would store all the different states in one MovieClip in separate frames and manually adjust the position of each one til they matched up, however I am also trying to port this to Android and therefore must keep the number of children on screen at once to a minimum.
Is there anything else I can do other than store offset x and y values for each character and each animation, and simple set the x/y via code whenever their state changes?
To keep the numChildren down I guess you have no choice
but to keep track of x- and y-offsets of the animations of each character
stored perhaps in an Object variable of form { state: registration_point }.
Then when changing states you can set the registration point
through this method by Emanuel Feronato:
http://www.emanueleferonato.com/2010/08/04/changing-a-movieclip-registration-point-on-the-fly-with-as3/
An idea to try though is to simply place the registration point to the center of each animation state:
var reg_x:Number = mc.width / 2;
var reg_y:Number = mc.height / 2;

How do I select a set of grid cells along a given angle quickly?

I have set up a grid class that contains theoretical cells.
I have a method collectCells() which accepts a starting point, radians and distance as arguments. I want this method to return an Array containing all the cells that are along a given angle and that are within the specified distance from the starting point, e.g.
The easiest way for me to do this is just loop through all the pixels in the given direction and pick cells up as I go, something like:
for(var i:int = 0; i<distance; i++)
{
startPoint.x += Math.cos(radians);
startPoint.y += Math.sin(radians);
if( start point falls within uncollected cell) collect cell;
}
This is obviously really poor, as the loop will be as long as the distance I specify - extremely slow.
I tried something different, creating a nextCell() method which accepts the last collected cell and radians. The method threw a point 25 pixels in the direction specified by radians, collected the resulting cell and then started over from that cell for a given amount of cells.
I didn't really think about this approach clearly enough, and once done realized that I had a problem, being that the actual path I'm testing gets broken each time the next cell is sought, e.g.
Where the green dotted line is the desired path, and the blue lines are the paths that make up each nextCell() call because the check is made from the centre of each cell.
What is the correct way to efficiently collect the cells in a given direction over a specified distance (pixels)?
Or you could use Bresenham's line drawing algorithm. Because literally you are trying to draw a pixel width line but with huge pixels.

Comparing two bitmaps against each other for match as3

I'm trying to position an image on top of another image based upon the make-up of the smaller image. The smaller image is a cut-out of a larger image and I need it to be positioned exactly on the larger image to make it look like a single image, but allow for separate filters and alphas to be applied. As the images are not simple rectangles or circles, but complex satellite images, I cannot simply redraw them in code. I have quite a few images and therefore do not feel like manually finding the position of each image every and hard setting them manually in actionscript. Is there any way for me to sample a small 5-10 sq. pixel area against the larger image and set the x and y values of the smaller image if a perfect match is found? All the images are in an array and iterating through them has already been set, I just need a way to sample and match pixels. My first guess was to loop the images pixel by pixel right and down, covering the whole bitmap and moving to the next child in the array once a match was found, leaving the matched child where it was when the perfect match was found.
I hope I understood your question correctly.
There may be an option that uses copypixels to achieve what you want. You can use the bitmapdata.rect value to determine the size of the sample you want, and loop through the bigger bitmap using thet rectangle and a moving point. Let's see if I can code this out...
function findBitmapInBitmap(tinyimg:BitmapData, largeimg:BitmapData):Point {
var rect:Rectangle = tinyimg.rect;
var xbound:uint = largeimg.rect.width;
var ybound:uint = largeimg.rect.height;
var imgtest:BitmapData = new BitmapData(tinyimg.rect.width, tinyimg.rect.height);
for (var ypos:uint = 0, y <= ybound, y++) {
for (var xpos:uint = 0, x <= xbound, x++) {
imgtest.copyPixels(largeimg, rect, new Point(xpos, ypos);
if (imgtest.compare(tinyimg) == 0) return new Point(xpos, ypos);
}
}
return new Point(-1,-1); // Dummy value, indicating no match.
}
Something along those lines should work - I'm sure there's room for code elegance and possible optimization. However, it seems like something like this method would be very slow, since you'd have to check each pixel for a match.
There is a better way. Split your big image into layers, and use the blitting technique to composite them at runtime. In your case, you could create a ground texture without satellites, and then create the satellites separately, and use the copyPixels method to place them whereever you want. Google "blitting in as3" to find some good tutorials. I'm currently working on a game project that uses this technique and it's a very good method.
Good luck!
Edit: Forgot to code in a default return statement. Using this method, you'd have to return an invalid point (like (-1,-1)) and check for it outside the function. Alternatively, you could just copy your small bitmap to the big one within the function, which would be much more logical, but I don't know your requirements.
You need to find pixel sequence in the big image. BitmapData.getPixel gives you pixel value. So get first pixel from small image, find it in big image, then continue comparing until you find full match. If you have trouble to code that, feel free to ask.
For the actual comparison, there's BitmapData.compare which returns the number 0 if the BitmapData objects are equivalent.

Finding a free area in the stage

I'm drawing rectangles at random positions on the stage, and I don't want them to overlap.
So for each rectangle, I need to find a blank area to place it.
I've thought about trying a random position, verify if it is free with
private function containsRect(r:Rectangle):Boolean {
var free:Boolean = true;
for (var i:int = 0; i < numChildren; i++)
free &&= getChildAt(i).getBounds(this).containsRect(r);
return free;
}
and in case it returns false, to try with another random position.
The problem is that if there is no free space, I'll be stuck trying random positions forever.
There is an elegant solution to this?
Let S be the area of the stage. Let A be the area of the smallest rectangle we want to draw. Let N = S/A
One possible deterministic approach:
When you draw a rectangle on an empty stage, this divides the stage into at most 4 regions that can fit your next rectangle. When you draw your next rectangle, one or two regions are split into at most 4 sub-regions (each) that can fit a rectangle, etc. You will never create more than N regions, where S is the area of your stage, and A is the area of your smallest rectangle. Keep a list of regions (unsorted is fine), each represented by its four corner points, and each labeled with its area, and use weighted-by-area reservoir sampling with a reservoir size of 1 to select a region with probability proportional to its area in at most one pass through the list. Then place a rectangle at a random location in that region. (Select a random point from bottom left portion of the region that allows you to draw a rectangle with that point as its bottom left corner without hitting the top or right wall.)
If you are not starting from a blank stage then just build your list of available regions in O(N) (by re-drawing all the existing rectangles on a blank stage in any order, for example) before searching for your first point to draw a new rectangle.
Note: You can change your reservoir size to k to select the next k rectangles all in one step.
Note 2: You could alternatively store available regions in a tree with each edge weight equaling the sum of areas of the regions in the sub-tree over the area of the stage. Then to select a region in O(logN) we recursively select the root with probability area of root region / S, or each subtree with probability edge weight / S. Updating weights when re-balancing the tree will be annoying, though.
Runtime: O(N)
Space: O(N)
One possible randomized approach:
Select a point at random on the stage. If you can draw one or more rectangles that contain the point (not just one that has the point as its bottom left corner), then return a randomly positioned rectangle that contains the point. It is possible to position the rectangle without bias with some subtleties, but I will leave this to you.
At worst there is one space exactly big enough for our rectangle and the rest of the stage is filled. So this approach succeeds with probability > 1/N, or fails with probability < 1-1/N. Repeat N times. We now fail with probability < (1-1/N)^N < 1/e. By fail we mean that there is a space for our rectangle, but we did not find it. By succeed we mean we found a space if one existed. To achieve a reasonable probability of success we repeat either Nlog(N) times for 1/N probability of failure, or N² times for 1/e^N probability of failure.
Summary: Try random points until we find a space, stopping after NlogN (or N²) tries, in which case we can be confident that no space exists.
Runtime: O(NlogN) for high probability of success, O(N²) for very high probability of success
Space: O(1)
You can simplify things with a transformation. If you're looking for a valid place to put your LxH rectangle, you can instead grow all of the previous rectangles L units to the right, and H units down, and then search for a single point that doesn't intersect any of those. This point will be the lower-right corner of a valid place to put your new rectangle.
Next apply a scan-line sweep algorithm to find areas not covered by any rectangle. If you want a uniform distribution, you should choose a random y-coordinate (assuming you sweep down) weighted by free area distribution. Then choose a random x-coordinate uniformly from the open segments in the scan line you've selected.
I'm not sure how elegant this would be, but you could set up a maximum number of attempts. Maybe 100?
Sure you might still have some space available, but you could trigger the "finish" event anyway. It would be like when tween libraries snap an object to the destination point just because it's "close enough".
HTH
One possible check you could make to determine if there was enough space, would be to check how much area the current set of rectangels are taking up. If the amount of area left over is less than the area of the new rectangle then you can immediately give up and bail out. I don't know what information you have available to you, or whether the rectangles are being laid down in a regular pattern but if so you may be able to vary the check to see if there is obviously not enough space available.
This may not be the most appropriate method for you, but it was the first thing that popped into my head!
Assuming you define the dimensions of the rectangle before trying to draw it, I think something like this might work:
Establish a grid of possible centre points across the stage for the candidate rectangle. So for a 6x4 rectangle your first point would be at (3, 2), then (3 + 6 * x, 2 + 4 * y). If you can draw a rectangle between the four adjacent points then a possible space exists.
for (x = 0, x < stage.size / rect.width - 1, x++)
for (y = 0, y < stage.size / rect.height - 1, y++)
if can_draw_rectangle_at([x,y], [x+rect.width, y+rect.height])
return true;
This doesn't tell you where you can draw it (although it should be possible to build a list of the possible drawing areas), just that you can.
I think that the only efficient way to do this with what you have is to maintain a 2D boolean array of open locations. Have the array of sufficient size such that the drawing positions still appear random.
When you draw a new rectangle, zero out the corresponding rectangular piece of the array. Then checking for a free area is constant^H^H^H^H^H^H^H time. Oops, that means a lookup is O(nm) time, where n is the length, m is the width. There must be a range based solution, argh.
Edit2: Apparently the answer is here but in my opinion this might be a bit much to implement on Actionscript, especially if you are not keen on the geometry.
Here's the algorithm I'd use
Put down N number of random points, where N is the number of rectangles you want
iteratively increase the dimensions of rectangles created at each point N until they touch another rectangle.
You can constrain the way that the initial points are put down if you want to have a minimum allowable rectangle size.
If you want all the space covered with rectangles, you can then incrementally add random points to the remaining "free" space until there is no area left uncovered.