Getting/comparing Flash color filters dynamically - actionscript-3

I know I can apply a Color Filter in Flash by hand, and then copy it to other movieclips dynamically, like so:
newMovieClip.filters = oldMovieClip.filters;
What I would love to do now is be able to check if two movieclips have the same filter.
Something like this:
if (newerMovieClip.filters == oldMovieClip.filters)
...that always comes out as false, even if the two have the same filter. I know I can make this work if I use a colorTransform instead, but I can't in this case. The graphics have lines and shading that are all changing color together, and the brightness/hue/contrast are all important so filters are key.
(What I'm doing: I have clothing items in the menu that the user "colors" by picking a filtered button from a palette I made. When they click the item, and it's not already on the avatar in that color, I want it to appear and/or turn that color. If it's already on the avatar and the same color, I want it to come off... hence the filter check)

EDIT: I see now that you are only dealing with a Color Filter. Ahh. I understand what trying to do now.
this can make things a little easier if that is the only filter on each Movieclip.
In this case we can get each ColorMatrixFilter of each movieclip by moiveclip.filters[0]
then:
function compareColorFilters(a:ColorMatrixFilter, b:ColorMatrixFilter) : Boolean
{
var length:uint = (a.matrix.length > b.matrix.length)?a.matrix.length:b.matrix.length;
for(var i:uint = 0; i < length; ++i)
{
if(a.matrix[i] != b.matrix[i]) { return false; }
}
return true;
}
then to compare to movieclips would be
if(compareColorFilters(ColorMatrixFilter(oldClip.filters[0]), ColorMatrixFilter(newClip.filters[0])) {
//do stuff
}
As you can see you are getting each ColorMatrixFilters from each moveiClip. Then comparing there matrices (which is just an array) element by element. If the Matrices are the same... The colors, brightness, and hues are also the exact same. If confused at all by this, leave a comment.
Hope this helps!
-Travis

Related

how to connect a number variable to dynamic text in actionscript 3.0?

i know this might be simple but i have been searching everywhere for a fix but i just cannot find it!
i want to make something like a health #, so when you press whatever button the dynamic text # will go up or down. on my test project i have two layers, the first with the following code
var hp:Number = 100;
health.text = String hp;
hp being the variable, and health being the dynamic text. then i have the next layer with the button with:
function button(e:MouseEvent):void
{
hp -= 10;
}
without that second chunk of code, the dynamic text will appear, but once that is added it will disappear and the button is function-less.
how do i make this work??? once again sorry if this is a dumb question, i'm just very stumped.
The accepted answer is good, but I wanted to point out that your original code was actually very close to being correct, you just needed parenthesis:
health.text = String(hp);
For most objects String(object) and object.toString() has the same effect, except that object.toString() throws an error if object is null (which could be desirable or undesirable, depending on what you expect it to do).
This is not correct:
health.text = String hp;
use:
health.text = hp.toString();
and:
function button(e:MouseEvent):void
{
hp -= 10;
health.text = hp.toString();
}

Creating a maze in actionscript3

I4d like to create a maze in actionscript 3 but without drawing it because a lot of people are saying that timeline code and drawing things is bad so i'd like to create it with an array. I've searched on google and looked over a lot of tutorials, all doing it differently but not one of them uses classes and all that stuff and I'd really like to do it. I have the idea of how to do it, using an array filled with different numbers of characters if there's a wall, nothing etc... And i know how to draw the block with the graphics things then put a if loop and if the number is 0 put nothing if the number is 1 create the block and place it, but then i'm a bit lost on HOW to make the block appear at the same spot where there is a 1 in the array, I looked at tuts where they did something with rows but I couldn't really understand it clearly.
And also I'm not sure if i have to create a new class for the block, and what do I have to put in this class if i do create it? Do i need to create the block in the class, or outside of it? =/
If someone knows what I mean then all help is welcome.
If you need more details please tell me, sorry if it's confused. =3
It looks like your best bet, your path of least resistance in the long run, may lie in doing a little bit more study and some smaller programs before embarking on this. However if you want a 2D maze made with an Array, you could just do this:
private var m_arrMaze:Array = new Array(40);
private function someFunc():void
{
for (var i:int = 0; i < m_arrMaze.length; i++)
{
m_arrMaze[i] = new Array(50);
}
m_arrMaze[0][0] = 1;
m_arrMaze[0][1] = 1;
.
.
.
m_arrMaze[24][24] = 3;
.
.
.
m_arrMaze[49][49] = 0;
}
This is because you seemed to mention using an array and setting its elements to certain int values to denote what each little spot or room or whatever in the maze is or has. The reason a lot of tutorials may not use a whole lot of classes is because, if this is all you're doing with it, you really don't need too many different classes to denote the stuff in the maze. Just instead of using hard-coded int values, go ahead and put them in constants at the top of your maze class:
private static const EMPTY_SPACE:int = 0;
private static const WALL:int = 1;
.
.
.
private static const PLAYER:int = 3;
private var m_arrMaze:Array = new Array(40);
private function someFunc():void
{
for (var i:int = 0; i < m_arrMaze.length; i++)
{
m_arrMaze[i] = new Array(50);
}
m_arrMaze[0][0] = WALL;
m_arrMaze[0][1] = WALL;
.
.
.
m_arrMaze[24][24] = PLAYER;
.
.
.
m_arrMaze[49][49] = EMPTY_SPACE;
}
If each type of contents within the maze is liable to have a whole different set of nouns, verbs, and adjectives associated with it, instead of just being a different type of marker of where something's at like in the examples above, and if the program is going to do a lot of different things with those contents, that's when you want to use a whole bunch of different classes. Hopefully this will get you started.

How do i populate an Array in one class based on a textfield in another class?(Actionscript 3.0)

i have a class (TheList.as). in which i have an array "Data" and it has a couple of values. Then i have a loop through which i am creating a scrollable list which uses the values from "Data" array. [I am trying make a unit converter]
Then i have another class "Units.as". In that class i have created three instances of "TheList". A main list ("myList"), and to sublists "ListFrom" and "ListTo". They are using values from "Data" array. Now i have text field whose value changes to whatever item is clicked. When i click "Angle" in the main list, i want the sublists to get populated with ("Degree", "Radian" etc)..
Here is what i tried
if(myList._TextLabel.text == "Angle")
{
ListFrom.Data = ["Degree", "Radian"];
}
But nothing happens, i do not get any error either. When i do this in an "ENTER_FRAME" event and trace (ListFrom.Data), i can see that the values change, but they do not get assigned to the list items in the list. I would really appreciate the help. Thanks!
Here are complete Classes for understanding the situation better(the code is pretty messy, as i am a newbie to OOP)
TheList.as: http://pastebin.com/FLy5QV9i
Units.as : http://pastebin.com/z2CcHZzC
where you call ListFrom.Data = ["Degree","Radian"], make sure when the data changed, the renders in the ListFrom have been set new data. for example, you may use MyRender in ListFrom for show, you should debug in the set data method in MyRender.
you should call the code below after you call ListFrom.Data = ["Degree","Radian"];
for (var i:int = 0; i < Data.legnth;i++) {
var render:MyRender = ListFrom[i] as MyRender;
if (render) {
render.data = Data[i];
} else {
var render:MyRender = new MyRender();
render.data = Data[i];
ListFrom.addChild(render);
}
}
You can use event listeners, singleton classes or reference one class to another, depending on the style you want. All are equally valid and fast / efficient.

Using two eventlisteners for one function in Actionscript

I'm making a dots and boxes game in flash using actionscript 3.
Currently I'm completely stuck as I want the player to click two buttons before a line is displayed. I planned to do something like this using the if statement
if button1 and button2 clicked
line1 visible = true
I've also tried adding eventlisteners with one function
function showLine(e:Event):void {
blue0001.visible = true
}
dot00.addEventListener(MouseEvent.CLICK, showLine);
But as far as I know this can only be used when you want to click one button. Is there anyway to have two eventlisteners satisfyed before the function is carried out?
Also how would I (if i can) use the if statements to carry out this?
You would probably do something like this, pseudo-code:
Assume all of the dots are in a dots array.
for (var i: Number = 0; i < dots.length; i++) {
dots.addEventListener(MouseEvent.CLICK, dotClicked, false, 0, true);
}
dotSelected = null;
function dotClicked(evt:MouseEvent):void {
if (dotSelected && isNeighbor(evt.target, dotSelected)) {
showLineConnecting(evt.target, dotSelected)
dotSelected = null;
} else if (!dotSelected) {
highlightDot(evt.target);
dotSelected = evt.target;
} else {
showError("You must click an adjacent dot");
}
}
At the request of the OP, this is what's going on.
for (var i: Number = 0; i < dots.length; i++) {
dots.addEventListener(MouseEvent.CLICK, dotClicked, false, 0, true);
}
Add an event listener to every dot. Here I am assuming you already have an array of dots defined. Each instance in the Array would be a MovieClip (likely), Sprite, or another DisplayObject.
dotSelected = null;
We will use a variable to keep track of any currently selected dot. Since no dot will be selected when the game starts, we set it to null.
function dotClicked(evt:MouseEvent):void {
if (dotSelected && isNeighbor(evt.target, dotSelected)) {
showLineConnecting(evt.target, dotSelected)
dotSelected = null;
} else if (!dotSelected) {
highlightDot(evt.target);
dotSelected = evt.target;
} else {
showError("You must click an adjacent dot");
}
}
This is the function that will get called when any dot is clicked. For explanation's sake, let's take the first click of the game. dotSelected is null, so the first if is false. The second if though is true, because (!dotSelected) is true. So, we run some function I called highlightDot with the dot as the argument. That function could look something like this:
function hightlightDot(dot:Dot):void {
dot.gotoAndStop("selected");
}
Now a second click is made. Now the first part of the first if, dotSelected, is true. The second part is now evaluated. Again I put in a made up function isNeighbor. The isNeighbor function takes two arguments, the dot that was just clicked and the dot that has already been clicked. This function needs to make sure the two dots are adjacent. This could be something like...
function isNeighbor(dot1:Dot, dot2:Dot):void {
return ((dot1.xGrid == dot2.xGrid && Math.abs(dot1.yGrid - dot2.yGrid) == 1) || (Math.abs(dot1.xGrid - dot2.xGrid) == 1) && dot1.yGrid == dot2.yGrid));
}
The above function assumes that the instances of Dot have some properties xGrid and yGrid which defines where in the playing board they sit. If they are in the same row and 1 column apart they are neighbors. If they are in the same column and 1 row apart they are neighbors.
The last thing that happens in a function showLineConnecting is called. That function will again take the two adjacent dots as arguments. It will then draw a line between them in whatever way you choose to do that. Finally, dotSelected is set back to null, allowing another set of dots to be selected.
One thing I just realized, it would probably be helpful to have an additional property that gets triggered on a Dot when it is connected to all of its neighbors so it could no longer be selected.
You will also need logic to handle knowing that a box has been created. For that you would likely just iterate the possibilities given the line that was just drawn. For each line drawn there are only two possible boxes that have been created. So check them both. Watch out for edges.

Re-stacking MovieClips in an Array

I was trying to make a similar thing with the game SameGame (ie. the block above the removed blocks fall downward). Before trying this with an Array that contains MovieClips, this code worked (tried it with int values). With MovieClips on the array, it seems not working the same way.
With int values, example:
popUp(0, 4): Before: 1,2,3,4,5,6,7,8,9,10; After: 1,2,3,4,6,7,8,9,10
But with MovieClips:
popUp(0, 4): Before: 1,2,3,4,5,6,7,8,9,10; After; 1,2,3,4
// Assume the numbers are movieclips XD
Basically, it strips everything else, rather than just the said block >_<
Here's the whole method. Basically, two extra arrays juggle the values above the soon-to-be removed value, remove the value, then re-stack it to the original array.
What could be wrong with this? And am I doing the right thing for what I really wanted to emulate?
function popUp(col:uint, row:uint)
{
var tempStack:Array = new Array();
var extraStack:Array = new Array();
tempStack = IndexArray[col];
removeChild(tempStack[0]);
for(var ctr:uint = tempStack.length-(row+1); ctr > 0; ctr--)
{
removeChild(tempStack[ctr]);
extraStack.push(tempStack.pop());
trace(extraStack);
}
tempStack.pop();
for(ctr = extraStack.length; ctr > 0; ctr--)
{
tempStack.push(extraStack.pop());
//addChild(tempStack[ctr]);
}
IndexArray[col] = tempStack;
}
PS: If it's not too much to ask, are there free step-by-step guides on making a SameGame in AS3 (I fear I might not be doing things right)? Thanks in advance =)
I think you just want to remove an element and have everything after that index shift down a place to fill what you removed. There's an inbuilt function for this called splice(start:uint, length:uint);
Parameters:
start - the index to start removing elements from
length - the amount of elements to remove
var ar:Array = ["hello","there","sir"];
ar.splice(1, 1);
ar is now -> ["hello", "sir"];
As per question:
Here's an example with different types of elements:
var ar:Array = [new MovieClip(), "some string", new Sprite(), 8];
ar.splice(2, 1);
trace(ar); // [object MovieClip], some string, 8
And further example to display the indexes being changed:
trace(ar[2]); // was [object Sprite], is now 8