• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1397
  • Last Modified:

create/display and access multiple rectangles

i am just learning actionscript 3.
goal: i want to create and display multiple rectangles inside of  a group and at runtime access and change the rect properties like background color etc when the users' mouse clicks on a specific rectangle.

below is my first attempt to create a rectangle.  but then I couldn't access it after I added it to the group.


      var rect1:Shape = new Shape();
      var group:Sprite = new Sprite();

      rect1.graphics.lineStyle(1);
      rect1.graphics.beginFill(0x0000FF,1);
                     rect1.graphics.drawRect(100,30,75,50);
      rect1.rotation = 45;

                addChild(rect1);

                 group.addChild(rect1);

then I saw this method
var rect2:Rectangle = new Rectangle();

but that seems to just create something in memory and not display.  but it seems this constructor is good for me becuase it gives me methods like containPoints()

thanks.
       

             


0
gotaquestion
Asked:
gotaquestion
  • 15
  • 13
1 Solution
 
julianopolitoCommented:
Hi!
Well, the Rectangle class is a non visual representation of rectangle. A shape is a visual representation of a shape. You can make your own class and have them do all this for you.

Here is a class I made for you. It s called InteractiveRectangle, and you can use it to create visual rectangles. This class extends Sprite, and so you can use the method getRect to get a Rectangle representing the object, and you can also use all those methods you need.
In this class I created a color property, so for example put this class file in the same folder of your application file or fla.
//This code goes in the first frame of your fla, or in the init function of your app
var rect1:InteractiveRectangle = new InteractiveRectangle (0,0,100,50,0xFF0000);
var rect2:InteractiveRectangle = new InteractiveRectangle (0,0,100,50,0xFF0000);
rect2.y = 80;
var rect3:InteractiveRectangle = new InteractiveRectangle (0,0,100,50,0xFF0000);
rect3.y = 210;
rect1.addEventListener("click",clickRect);
rect2.addEventListener("click",clickRect);
rect3.addEventListener("click",clickRect);

function clickRect(e:MouseEvent){
        InteractiveRectangle (e.target).color = Math.random()*16000;//sets a random color to the clicked rect

}

Here we create 3 rectangles, and set their click to change their color randomly by clicking. You can also call rect1.getRect(stage) for example to have a rectangle object representing it based on the stage coordinates.




//InteractiveRectangle.as
package{
	import flash.display.Sprite;
 
	public class InteractiveRectangle extends Sprite{
		private var w:Number;
		private var h:Number;
		
		public function InteractiveRectangle(x:Number,y:Number,width:Number,height:Number,color:Number = 0x000000){
			this.x = x;
			this.y = y;
			this.w = width;
			this.h = height;
			this.color = color;
		}
		public function set color(color):void{
			with(this.graphics){
				clear();
				lineStyle(0);
				beginFill(color);
				drawRect(0,0,w,h);
				endFill();
			}
		}
	}
}

Open in new window

0
 
julianopolitoCommented:
you can create another class extending Sprite, cause sprite is the lighest displayobjectcontainer class. Then you can add like an RectGroup.add method, where you accept a InteractiveRectangle as parameter, and do the addChild into the RectGroup. This mimics grouping behaviour. Just beware of the coordinates, cause when an object is in the display list of a sprite for example, it's coordinates are relative to that. Other solution would be to create a non visual RectGoup class, where you register the objets that are part of the group, and can have other methods to take action on all group objects, like the each method in the array class..
0
 
gotaquestionAuthor Commented:
I'm trying to apply your InteractiveRectangle and I'm not getting anything to show on the stage.  Don't you have to have some sort of draw command in the code?  here is what I'm doing.  Preloader is a class attached to the main stage.
package {
 	import flash.display.MovieClip;
 	import flash.events.*;
	import flash.text.TextField;
	import InteractiveRectangle;
	public class Preloader extends MovieClip {
		
		public function Preloader() {
		
			this.loaderInfo.addEventListener(Event.INIT, initApplication);
			this.loaderInfo.addEventListener(ProgressEvent.PROGRESS,showProgress);
		
		}
		
		public function showProgress(theProgress:ProgressEvent):void {
 
 			var percent:Number = Math.round((theProgress.bytesLoaded / theProgress.bytesTotal )*100 );
 
 			trace(percent + " %  loaded");
		}
 
		public function initApplication(myEvent:Event):void {
 			trace("Application fully loaded !");
			var rect1:InteractiveRectangle = new InteractiveRectangle (50,0,100,50,0xFF0000);
			var rect2:InteractiveRectangle = new InteractiveRectangle (50,0,100,50,0xFF0000);
			rect2.y = 80;
			var rect3:InteractiveRectangle = new InteractiveRectangle (50,0,100,50,0xFF0000);
			rect3.y = 210;
			rect1.addEventListener("click",clickRect);
			rect2.addEventListener("click",clickRect);
			rect3.addEventListener("click",clickRect);
			 			trace("Application fully loaded !!");
 
		}
			function clickRect(e:MouseEvent){
			InteractiveRectangle (e.target).color = Math.random()*16000;//sets a random color to the clicked rect
			
	}
 	
	}
 
 
	
}

Open in new window

0
The new generation of project management tools

With monday.com’s project management tool, you can see what everyone on your team is working in a single glance. Its intuitive dashboards are customizable, so you can create systems that work for you.

 
gotaquestionAuthor Commented:
ah, the code was missing the addChild(rect1);
0
 
julianopolitoCommented:
that's it, you need to add it to the display list using addchild. have another doubt?
0
 
gotaquestionAuthor Commented:
I've gotten far.  I've created my container called GroupMatrix that contains all my rectangles. But now I'm trying to get the name of those rectangles inside the container when the user clicks.  I've named them rect1.name = "rect 1"

I've gotten this far...

in my init code I have
var Group1:GroupMatrix = new GroupMatrix();

                  function clickRect(e:MouseEvent):void {
                  var curSprite:GroupMatrix;
                  curSprite=GroupMatrix(e.currentTarget);
            I need the syntax that returns the current rectangle name.
      

}

any ideas?
0
 
julianopolitoCommented:
You can addEventListeners for click events for each rect that you register to GroupMatrix. And in that hendler you dispatch another event to notify. Or if rectangles are added inside the groupmatrix, you do this:

var rect1:InteractiveRectangle = new InteractiveRectangle();
var Group1:GroupMatrix = new GroupMatrix();
Group1.addChild(rect1);
Group1.addEventListener("click",clickGroup);
function clickGroup(e:MouseEvent):void {
       trace(InteractiveRectangle(e.target).name);//Here you have the name for the clicked rect      
}


0
 
gotaquestionAuthor Commented:
so cool.  thanks!!! i tried everything but that.  I got it working with e.target.name and then did e.target.parent.name and that worked too.  
flash should totally have a way to hit the period (.) for something like this and see all the methods
0
 
julianopolitoCommented:
in flash you can't but in Flex Builder you have that functionality. That's because flash editor is dumb.it is only  text editor not a really IDE. Just don't forget to cast the e.target when you need access to specifics of the InterativeRectangle, because e.target is a DisplayObject, not a interactiveRectangle, so InteractiveRectangle(e.target) turns the DisplayObject target, into your object. And do not try to cast other Objects to Interactiverect, you get a cast exception

function clickGroup(e:MouseEvent):void {
       var objTarget:InteractiveRectangle;
       if(e.target is InteractiveRectangle)objTarget = InteractiveRectangle(e.target);//here we check to see if it is Interactive rectangle, before casting. For example, if user clicks in the group, not on any rect, target will be the group, and so, not a rectangle but a GroupMatrix, ok?
       trace(objTarget.name);//Here you have the name for the clicked rect      
}

0
 
gotaquestionAuthor Commented:
that's good to know.  I'm going to check out Flex builder.  say one more thing.  I'm going crazy about this one.

I'm doing something stupid.   I keep getting
1136: Incorrect number of arguments.  Expected 1.
why?
my Preloader.as file
 
package{
 	import flash.display.MovieClip;
 	import flash.events.*;
	import flash.text.TextField;
 
import myotherclass;
 
public class Preloader extends MovieClip {
 
//make the call to the other function
myotherclass(1,2);
}
}
 
myotherclass.as
package{
 import flash.display.MovieClip;
	public class myotherclass {
 
	public var S1:Array;
	public var S2:Array;
 
 
		public function myotherclass(P:int,Q:int):void {
			
			switch (P){
				case 1:
				S1.push(Q);
				break;
				case 2:
				S2.push(Q);
				break;
			
			}
			
		}
 
	}
}

Open in new window

0
 
julianopolitoCommented:
first, both of your classes are in the same default package. So you don't need, and must not to import myotherclass.

public class Preloader extends MovieClip {
 
//make the call to the other function
myotherclass(1,2);//HERE YOU CAN'T CALL FUNCTION OUTSIDE METHOD
}
}
Should be in the constructor method for the class for example:
package{
         public class Preloader extends MovieClip {
              public function Preloader (){
                     //make the call to the other function
                     var myInstanceOfOtherClass = new myotherclass(1,2);//Should use new operator to create instance of your class
               }
        }
}




0
 
gotaquestionAuthor Commented:
but what if I want to call myotherclass function in a for loop?

will this work?
var i:int;
for (i = 0; i < 5; i++)
{
    var myInstanceofOtherClass = new myotherclass(1,i);
}
 




 
0
 
gotaquestionAuthor Commented:
i figured out what I wanted to do.  I really want to call a function inside a class over and over again.  I think I go it doing this.

var mytest= new myotherclass();
for (i = 0; i < 5; i++)
{
var myFunc:Function = mytest.pos(i);
}
 
0
 
julianopolitoCommented:
var mytest= new myotherclass();
for (i = 0; i < 5; i++)
{
mytest.pos(i);
}

you don't use var myFunc:Function = , unless your method pos() returns a function, which I'm sure it does not. For example if your function is like this:
public function pos(index:int):int{
     return index*2;
}
look at the first line of the function declaration. The parameters inside the parnthesis together with the int word after the colon are called the signature of the method. In this signature I can tell that this method receives one argument index of type INTEGER ( look inside parenthesis), and returns a INTEGER value (look after the column). So if it returns an INTEGER, I can capture it's results in this way:

var myInt:int = pos(23);
trace(myInt).//This outputs 46;
0
 
julianopolitoCommented:
*column = colon
0
 
gotaquestionAuthor Commented:
thank you so much.  I understand classes and constructors and functions now.  but now I think I found a bug in flash.  Take a look at my code. when the user clicks a button I  want to remove the rectangles that are showing in a container and turn on other rectangles.  the code below behaves inconsistently.  the first couple of clicks work fine but on multiple clicks some of rectangles don't get removed.  any ideas? also you have helped me so much that  I want to give you more points for answering this.
function btnclick(e:MouseEvent){
//here i remove all the rectangles
	for each ( var rect:String in myarray)
			{
if (GroupMatrix1.getChildByName(rect) != null)
				{
InteractiveRectangle (GroupMatrix1.removeChild(GroupMatrix1.getChildByName(rect)));
//tried this too //GroupMatrix1.removeChild(GroupMatrix1.getChildByName(rect))
delete GroupMatrix1.getChildByName(rect);
				}
				
			}
 
//then i add new rectangles. 
for each ( var rect:int in anotherarray
			{
				GroupMatrix1.Show(rect,0x000000);
			}
}

Open in new window

0
 
julianopolitoCommented:
By looking at your code, I see there are inconsistencies. I need to see more of the code to be sure of the mistakes 'm seeing. Can you send the complete code? I think you are confusing the remove child methods, but to be sure what to tell you I need to see complete code. And thank you for wanting to give me more points.
0
 
gotaquestionAuthor Commented:
here is a sketch of what I'm doing.
//CreateRectangle.as
package {
	import flash.display.Sprite;
 
	public class CreateRectangle  extends Sprite{
		private var w:Number;
		private var h:Number;
		
		public function CreateRectangle (x:Number,y:Number,width:Number,height:Number,color:Number = 0x000000,rotation:Number=0){
			this.x = x;
			this.y = y;
			this.w = width;
			this.h = height;
			this.color2 = color;
			this.rotation = rotation;
		}
		public function set color2(color):void{
			with(this.graphics){
				clear();
				lineStyle(0);
				beginFill(color);
				drawRect(0,0,w,h);
				endFill();
			}
		}
		
 
		
		
		
	}
}
 
 
 
 
package {
	import flash.display.Sprite;
	//import CreateRectangle;
 
	public class GroupMatrix extends Sprite {
		private var w:Number = 100;
		private var h:Number = 55;
		private var base5hRatio:Number = (10/h) * h;
		private var base3hRatio:Number = (20/h) * h;
		private var base14hRatio:Number = (14/h) * h;
		
		private var baseX:Number = 50;
		private var baseY:Number = 0;
		//private var baseColor:Number = 0xFFFFFF;
		
		
		public function GroupMatrix() {
		
		}
		
			public function ShowPosition(pos:int,baseColor:Number) {
			
			switch (pos) {
			
			case 1:
			var rect1:CreateRectangle = new CreateRectangle (baseX,baseY,w,h,baseColor,0);
			rect1.name = "1";
			addChild(rect1);
			break;
			
			case 2:
			var rect2:CreateRectangle = new CreateRectangle (baseX + w,h+baseY,w,h,baseColor,-90);
			rect2.name = "2";
			addChild(rect2);
			break;
			
			case 3:
			var rect3:CreateRectangle = new CreateRectangle (baseX+h+w,baseY,w,h,baseColor,0);
			rect3.name = "3";
			addChild(rect3);
			break;
			
			case 4:
			var rect4:CreateRectangle = new CreateRectangle (baseX + w,baseY+w,w,h,baseColor,-90);
			rect4.name = "4";
			addChild(rect4);
			break;
			
			case 5:
			var rect5:CreateRectangle = new CreateRectangle (baseX+((h+w)/2),baseY,w,h,baseColor,0);
			rect5.name = "5";
			addChild(rect5);
			break;
			
			case 6:
			var rect6:CreateRectangle = new CreateRectangle (baseX + w,baseY+w,w,h,baseColor,-69);
			rect6.name = "6";
			addChild(rect6);
			break;
			
 
			
			}
 
		}
 
 
 
package {
 	import flash.display.MovieClip;
 	import flash.events.*;
	import flash.text.TextField;
	import fl.controls.Button;
	
		
	public class Preloader extends MovieClip {
 
	var GroupMatrix1:GroupMatrix = new GroupMatrix();
	var GroupMatrix2:GroupMatrix = new GroupMatrix();
 
 
	
 
	
	
		public function Preloader() {
		
			this.loaderInfo.addEventListener(Event.INIT, initApplication);
			this.loaderInfo.addEventListener(ProgressEvent.PROGRESS,showProgress);
		
		}
		
		public function showProgress(theProgress:ProgressEvent):void {
 
 			var percent:Number = Math.round((theProgress.bytesLoaded / theProgress.bytesTotal )*100 );
 
 			trace(percent + " %  loaded");
		}
 
		public function initApplication(myEvent:Event):void {
 			trace("Application fully loaded !");
		
			GroupMatrix1.addEventListener("click",clickRect);	
			GroupMatrix1.addEventListener(MouseEvent.MOUSE_OVER,mouseOverRect);
			GroupMatrix1.addEventListener(MouseEvent.MOUSE_OUT,mouseOutRect);
			//GroupMatrix1.addEventListener(Event.REMOVED, iveBeenRemoved, false, 0 , false);
			GroupMatrix1.name = "1"
			GroupMatrix1.scaleY = 1;
			GroupMatrix1.scaleX = 1;
			addChild(GroupMatrix1);
			
			
			GroupMatrix2.addEventListener("click",clickRect);	
			GroupMatrix2.addEventListener(MouseEvent.MOUSE_OVER,mouseOverRect);
			GroupMatrix2.addEventListener(MouseEvent.MOUSE_OUT,mouseOutRect);
			GroupMatrix2.name = "2"
			GroupMatrix2.scaleY = 1;
			GroupMatrix2.scaleX = 1;
			GroupMatrix2.x = 77
			addChild(GroupMatrix2);
			
			
			//CREATE START BUTTON
	
			btnStartGame.move(100,300);
			btnStartGame.label = "Start Game";
			btnStartGame.addEventListener(MouseEvent.CLICK,btnClick);
			addChild(btnStartGame);
			
						
 
		 
}
 
 
			function clickRect(e:MouseEvent):void {
			trace(e.target);
 
	
 
 
			CreateRectangle  (e.target).color2 =  Math.random()*16000;sets a random color to the clicked rect
 
 
			
	}
			function mouseOverRect(e:MouseEvent){
			CreateRectangle  (e.target).color2 = 0x000000;
			
	}
	
			function mouseOutRect(e:MouseEvent){
			CreateRectangle  (e.target).color2 = 0xFFFFFF;
			
	}
	
			function btnClick(e:MouseEvent){
			
			//removeChild(GroupMatrix1);
			
			
			//turn off positions
			for each ( var position:String in Array1)
			{
			if (GroupMatrix1.getChildByName(position) != null)
				{
 
				CreateRectangle (GroupMatrix1.removeChild(GroupMatrix1.getChildByName(position)));
				//GroupMatrix1.removeChild(GroupMatrix1.getChildByName(position))
				//delete GroupMatrix1.getChildByName(position);
				}
				
			}
 
			
			for each ( var letterPosition:int in Array2)
			{
				GroupMatrix1.ShowPosition(letterPosition,0x000000);
			}
 
			
 
			
			
			}
 
 	
 
	
	}
 
 
	
}

Open in new window

0
 
julianopolitoCommented:
for each ( var position:String in Array1){
             if (GroupMatrix1.getChildByName(position) != null)

this is what I can't understand cause I don't see any Array1 array. When you say getChildByName, you need to give a name to your childrn rectangles, which you are not doing, maybe it is the case you do:

GroupMatrix1.removeChild(position);
or
GroupMatrix1.removeChild(position);

Also you don't need to do this:

CreateRectangle (GroupMatrix1.removeChild(GroupMatrix1.getChildByName(position)));

Just do :

GroupMatrix1.removeChild(GroupMatrix1.getChildByName(position))

Because you don't need to cast the returned value from removeChild method, because you are not using the returned value.

0
 
gotaquestionAuthor Commented:
Array1 and Array2 are defined in my real code but not shown here.

Inside of GroupMatrix class showposition function I am naming all of my rectangles like this

                  var rect1:CreateRectangle = new CreateRectangle (baseX,baseY,w,h,baseColor,0);
                  rect1.name = "1";
                  addChild(rect1);

so when I loop through my positions I'm accessing my rectangle names.

the more I click the button the more this line of code doesn't really do its job.
GroupMatrix1.removeChild(GroupMatrix1.getChildByName(position))
0
 
gotaquestionAuthor Commented:
it was my array1.  it wasn't considering all the options.
0
 
julianopolitoCommented:
so now everything works correctly?
0
 
gotaquestionAuthor Commented:
yes.  it was my error.  I just posted a question with the subject julianopolito.  if you reply to it I'll be able to give you more points.
0
 
gotaquestionAuthor Commented:
hi -
got a dumb question for you.
I drag a button from component library on to my stage on it's own layer.   I name the button instance btnTest. btw, I only have one frame on the stage.  I test the movie and I can see the button no problem.  But once I reference the instance of the button in code doing something simple like btnTest.lable = "hello world";  and then I test the movie the button starts flickering and moving around.  Obviously, I don't understand something very basic here.  I also see that I can "edit" the button and when I do I see lots of different buttons with different backgrounds and such.  which is what it kind of looks like the button is looping through when I test the movie.  how can I fix this problem?   Also, if I create the button purely in code this problem doesn't happen but I'd like to create my buttons using the designer because it's easier to lay them out.
0
 
gotaquestionAuthor Commented:
did you see my last post?
0
 
julianopolitoCommented:
sorry I have not seen this before.
well it seems to be that there is an error in the code, so flash won't compile correctly giving you this kind of error. For example, you wrote above btnTest.lable ...... this is wrong, cause there is no "lable" property, but "label" is correct. So if you try to use a no existing property, flash will not compile, and everything will look kinda crazy on screen. Look to see if there are any more errors on code
0
 
julianopolitoCommented:
Sorry for the delay, haven't seen it.
It seems a compiler problem. If you make a mistake in your code, it won't compile, and components on screen will act crazy like you said.
In the post above you wrote":
btnTest.lable = "hello world"

But there is no lable property in buttons, that must be the problem. The correct is
btnTest.label = "hello world"

Check to see if there are any other code mispellings.... Whenever there is a problem, it will not compile and will act like it is kinda crazy


0
 
gotaquestionAuthor Commented:
this is great.  thank you.  with regards to grouping the rectangles.  is there a way to put these three rectangles in a GROUP1 class?  so then I can do something like

var group1:MakeInteractiveRectangles = new MakeInteractiveRectangles ();

var group2:MakeInteractiveRectangles = new MakeInteractiveRectangles ();

var group3:MakeInteractiveRectangles = new MakeInteractiveRectangles ();

so now I would have a total of nine rectangles on the stage with the same behavior.
and I could still access the second rectangle in group3
0
 
Computer101Commented:
Forced accept.

Computer101
EE Admin
0

Featured Post

The new generation of project management tools

With monday.com’s project management tool, you can see what everyone on your team is working in a single glance. Its intuitive dashboards are customizable, so you can create systems that work for you.

  • 15
  • 13
Tackle projects and never again get stuck behind a technical roadblock.
Join Now