Animating a number of lines linking pairs of objects in AS3 - actionscript-3

I am trying to put together a match activity where word in one column are linked by a line to definitions in another column. Once all words have been linked to their definitions, you end up with a series of crossing lines so, so I want the definitions and their line to move so that each is level with their connected word and the lines have unravelled. I've got as far as connecting the words to their definitions using a line (as a sprite) and the definitions can then be moved using tweenlite -but I have no idea how I move the lines with their definition. Here is a much simplified section of code to give you an idea of what I am trying to do
import com.greensock.*;
import com.greensock.easing.*;
var wordArray:Array = [word1, word2, word3, word4];
var definitionArray:Array = [definition1, definition2, definition3,definition4];
for (var i:int = 0; i < wordArray.length; i++){
var line:Sprite = new Sprite();
line.graphics.lineStyle(2,0x000000);
line.graphics.moveTo(wordArray[i].x, wordArray[i].y);
line.graphics.lineTo(definitionArray[i].x, definitionArray[i].y);
this.addChild(line);
}
for (var j:int = 0; j < wordArray.length; j++){
TweenLite.to(definitionArray[j], 2, {delay:1, y:wordArray[j].y});
}
I am new to this so any help on how I would animate the lines to they follow the definitions would be very much appreciated.

Thanks for the help, it got me started - the errors occur because when onUpdate occurs, TweenLite needs to know the type of the arguments that are passed to the function. What I did was to call to a separate function and use onUpdateParams: to specify the nature of the arguments passed. Here is the code:
TweenLite.to(definitionArray[i], 3, {y:wordArray[j].y,onUpdate:refreshLines,
onUpdateParams:[lines,wordArray,definitionArray]});
with the function
function refreshLines(param1:Array,param2:Array,param3:Array):void{
for (var j:int = 0; j < param4.length; j++){
param1[j].graphics.clear();
}
for (var i:int = 0; i < param4.length; i++)
{
param1[i].graphics.lineStyle(2,0x000000);
param1[i].graphics.moveTo(param2[i].x, param2[i].y);
param1[i].graphics.lineTo(param3[i].x, param3[i].y);
}
}
Once again, many thanks for pointing me in the right direction, it saved me heaps of time.

Related

In Actionscript 3, how do I create movieclips through a looping statement?

The statement for takes a triple as an argument
(initial value of i, condition to cease looping, i increment)
I want to create a different movie clip each time the loop goes on.
So, I tried:
for (i = 0; i < 9; i++){
var Unit+i:MovieClip = new MovieClip()
}
But, this triggers the following error:
1086: Syntax error: expecting semicolon before plus"
What's the correct syntax, then?
To address the issue. You cannot create a var dynamically by using the var keyword. So doing var Unit+i will give you a syntax error.
You can create an array ahead of time and put your objects in that (as per #Panzercrisis's answer which is perfectly acceptable).
Other ways you can do this:
If you current context is dynamic (like if this is timeline code or part of a dynamic class like MovieClip), you do something like this:
this["Unit"+i] = new MovieClip();
From a compile time checking and code maintenance perspective, this is a little sloppy in my opinion, but for quick timeline projects it's certainly acceptable.
You could also just not store the clip anywhere but the display list:
for(var i:int=0;i<9;i++){
var mc:MovieClip = new MovieClip();
//do whatever you need to do to the clip
//like draw something for instance
mc.graphics.beginFill(0xFF0000);
mc.graphics.drawRect(0,0,100,100);
addChild(mc); //add to the display list so you can see it
}
If you never need to remove this clip, this way is great.
Or, you could add them to a container display object
var clipContainer:Sprite = new Sprite(); //Sprite is the same as movie clip but without the timeline stuff
addChild(clipContainer);
for(var i:int=0;i<9;i++){
var mc:MovieClip = new MovieClip();
//do whatever you need to do to the clip
//like draw something for instance
mc.graphics.beginFill(0xFF0000);
mc.graphics.drawRect(0,0,100,100);
clipContainer.addChild(mc);
}
The clipContainer would then act the same as an array, where you can access all it's children. Also, moving/scalling the container would in turn move/scale all it's children
Basically this is what you want to do:
var arrMovieClips:Array = new Array(9);
for (var i:int = 0; i < arrMovieClips.length; i++)
{
arrMovieClips[i] = new MovieClip();
}
This will create an array with nine elements, so you essentially have nine variables in a row:
arrMovieClips[0]
arrMovieClips[1]
arrMovieClips[2]
...
arrMovieClips[8]
Then it will go through and loop 0, 1, 2, etc. When it gets to the length of arrMovieClips, which is 9, then it'll stop. As it goes through 0-8, it'll create a new MovieClip and store it in each spot.

Instance-Generic Collision Detection in Actionscript

I've tried using hitTestObject(), but that seems to require that I make the call using a specific instance, rendering it more or less useless unless I want to have dozens of objects making dozens of collision checks each frame, which just seems wasteful and annoying to implement.
Is there any way to do collision check based on class rather than instance?
Maybe Something equivalent to this:
http://docs.yoyogames.com/source/dadiospice/002_reference/movement%20and%20collisions/collisions/place_meeting.html
Alternatively, is there any function that returns whatever a list of objects that share overlapping coordinates with the one I'm checking?
If I'm understanding your question correctly, you have several objects of that same class that each need to check for collisions against each other?
Yes, you would have to go through each object and perform a collision check against the other objects. I suppose you could write a hitTestClass function yourself, but behind the scenes it would still be the same. As far as implementing it, it's not so bad:
for( var i:int = 0; i < asteroids.length -1; ++i )
{
var a:Asteroid = asteroids[ i ];
for( var j:int = i+1; j < asteroids.length; ++j )
{
var b:Asteroid = asteroids[ j ];
var isColliding:Boolean = a.hitTestObject( b );
//Code here to do whatever in the case of collision
}
}
If computational speed becomes a concern, then there are broad-phase collision detection techniques to chunk down the time. Quad trees are one example.

Add iterations to loop AS3

Hi something simple is annoying me and I'd like some help!
function highlight(textField:TextField):void
{
var l:int = textField.text.length
for(var i:int = 0; i < l; i++)
if (!highlightChar(textField, i))
l++;
}
This loops through a character string to add a box behind the character for a highlighter affect. Some of the characters fail (the bounding box is null, assume these are returns etc) and in the example I'm looking at it returns false 5 times, and the boxes are 5 characters short. I'm attempting to add another iteration when it fails to keep going for another 5 characters, but this loop never stops.
Is there another way of doing this?
Hacky solution - collecting the fail count and then doing another loop after the first one finished has fixed it
if(fails > 0)
for(var f:int = i; f < fails + i; f++){
var box:Shape = highlightChar(textField, f);
if(box) boxes.addChild(box)
}

Using byteArray with getPixel (no 's') then setPixelS

Here is what I am trying to do:
one byteArray (colorsByteArray) holds color values, that I created with the "getPixels" method;
for every pixel on screen, I make calculations and depending on that I get a rank that I use to retrieve the proper color value inside colorsByteArray;
finally, I write inside a second byteArray (pixelsByteArray) the color I just retrieved. Then I 'draw' this byteArray using the "setPixels" method.
Problem is I do not find the same image as if I simply wrote a "setPixel" for every pixel in my loop. The image I get is missing one line out of two, and is kind of repeated three times horizontally. Of course I guess I must be writing (or reading) something wrong from my second byteArray, but can someone explain me what I am doing wrong? Or even if my efforts are worth anything actually :-) cause I didn't find anything quite like this so far...
Thanks!
Here is a bit of my code to make things clearer:
colorsByteArray = bitmDext.getPixels(new Rectangle(0, 0, myShadeBMD.width, 1));
canvas.lock();
for(var i:int = 0; i < STAGE_WIDTH; i++)
{
for(var j:int = 0; j < STAGE_HEIGHT; j++)
{
//make some calculation on each pixel to get the 'colorRank' uint value
colorsByteArray.position = colorRank * 4;//unsigned int is 32 bytes, representing 4 slots of a byteArray
var colorValue:uint = colorsByteArray.readUnsignedInt();
//canvas.setPixel(i, j, colorValue);//works just fine
pixelsByteArray.writeUnsignedInt(colorValue);
}
}
pixelsByteArray.position = 0;
var myRect:Rectangle = new Rectangle(0, 0, STAGE_WIDTH, STAGE_HEIGHT);
canvas.setPixels(myRect, pixelsByteArray);
canvas.unlock();
added a picture that may help:
http://www.oghel.com/pictures/stackOverflow/example3
the expected part is on the right, the wrong one on the left.

As3 - Get Movieclips That The Name Start With A Specific String

I'm making a tile based game where ta_*(number)* and ca_*(number)* acts like bins. You drag things towards it and drop. But the level may put several these tiles.
I am not going to make something like:
if (my_mc.hitTestObject(ta_0) || my_mc.hitTestObject(ta_1) || my_mc.hitTestObject(ta_2).........)
Because some may not exist and throw an error at me, and I don't want to make like hundreds of them.
Is there a way to find movieclips on stage that start with the name "ta_" and "ca_"?
So that I can get: ta_1, ta_2.....?
No, you can't. Unless you loop on getChildAt() and check all children's names.
But, why don't you add your bins to an array when creating them?
(I assume you create them dynamically)
var myBinArray:Array = new Array(10);
for (var i:int = 0; i < myBinArray.length; i++)
{
var myBin = new Bin();
myBinArray[i] = myBin;
}
Then you simply loop on your array:
for (var i:int = 0; i < myBinArray.length; i++)
{
if (mybinArray[i] != null)
if (my_mc.hitTestObject(mybinArray[i])
{
// statements
// and here I assume you want to break for loop
}
}