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)
}
Related
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.
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
}
}
So let's say i have T, T = 1200. I also have A, A is an array that contains 1000s of entries and these are numerical entries that range from 1000-2000 but does not include an entry for 1200.
What's the fastest way of finding the nearest neighbour (closest value), let's say we ceil it, so it'll match 1201, not 1199 in A.
Note: this will be run on ENTER_FRAME.
Also note: A is static.
It is also very fast to use Vector.<int>instead of Arrayand do a simple for-loop:
var vector:Vector.<int> = new <int>[ 0,1,2, /*....*/ 2000];
function seekNextLower( searchNumber:int ) : int {
for (var i:int = vector.length-1; i >= 0; i--) {
if (vector[i] <= searchNumber) return vector[i];
}
}
function seekNextHigher( searchNumber:int ) : int {
for (var i:int = 0; i < vector.length; i++) {
if (vector[i] >= searchNumber) return vector[i];
}
}
Using any array methods will be more costly than iterating over Vector.<int> - it was optimized for exactly this kind of operation.
If you're looking to run this on every ENTER_FRAME event, you'll probably benefit from some extra optimization.
If you keep track of the entries when they are written to the array, you don't have to sort them.
For example, you'd have an array where T is the index, and it would have an object with an array with all the indexes of the A array that hold that value. you could also put the closest value's index as part of that object, so when you're retrieving this every frame, you only need to access that value, rather than search.
Of course this would only help if you read a lot more than you write, because recreating the object is quite expensive, so it really depends on use.
You might also want to look into linked lists, for certain operations they are quite a bit faster (slower on sort though)
You have to read each value, so the complexity will be linear. It's pretty much like finding the smallest int in an array.
var closestIndex:uint;
var closestDistance:uint = uint.MAX_VALUE;
var currentDistance:uint;
var arrayLength:uint = A.length;
for (var index:int = 0; index<arrayLength; index++)
{
currentDistance = Math.abs(T - A[index]);
if (currentDistance < closestDistance ||
(currentDistance == closestDistance && A[index] > T)) //between two values with the same distance, prefers the one larger than T
{
closestDistance = currentDistance;
closestIndex = index;
}
}
return T[closestIndex];
Since your array is sorted you could adapt a straightforward binary search (such as explained in this answer) to find the 'pivot' where the left-subdivision and the right-subdivision at a recursive step bracket the value you are 'searching' for.
Just a thought I had... Sort A (since its static you can just sort it once before you start), and then take a guess of what index to start guessing at (say A is length 100, you want 1200, 100*(200/1000) = 20) so guess starting at that guess, and then if A[guess] is higher than 1200, check the value at A[guess-1]. If it is still higher, keep going down until you find one that is higher and one that is lower. Once you find that determine what is closer. if your initial guess was too low, keep going up.
This won't be great and might not be the best performance wise, but it would be a lot better than checking every single value, and will work quite well if A is evenly spaced between 1000 and 2000.
Good luck!
public function nearestNumber(value:Number,list:Array):Number{
var currentNumber:Number = list[0];
for (var i:int = 0; i < list.length; i++) {
if (Math.abs(value - list[i]) < Math.abs(value - currentNumber)){
currentNumber = list[i];
}
}
return currentNumber;
}
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.
i have an array in as3 which has elements like
MyArray2[0] = 25;
MyArray2[1] = 31;
MyArray2[2] = 45;
MyArray2[3] = 50;
MyArray2[4] = 81;
MyArray2[5] = 90;
MyArray2[6] = 94;
i want to randmize this array and array may contain more values ...
what should i do??
i have made the dirty alogrithm for it...
i need some good optimize way??
Haven't looked at AS3 in a long while, but here's some basic code that you should be able to use pretty easily.
var tmpVal, tmpInd, len;
len = MyArray.length;
for(var i=0; i < len; i++) {
tmpInd = random(0,len);//grab a random index
tmpVal = MyArray[tmpInd];//store the value
//swap the values
MyArray[tmpInd] = MyArray[i];
MyArray[i] = tmpVal;
}
Basically, you're just iterating over the array and swapping each element with a random element.
Put all the possible numbers in a linked list. Then, create a destination array which will contain your results. For each element in the result array, select a random number between 0 and the length of your linked list. Take that item in the linked list, remove it from the list (so that you won't pick it in the future), and place its value in the result array. Repeat.
When you're done, all the original numbers will be randomly distributed in the result array, and you won't have had to do any comparisons along the way.