24 Replies Latest reply on Nov 20, 2009 4:07 AM by nikos101

# I want to use the new graphics declarations to draw a bunch of 5px wide circles onto this canvas

I'm learning this FB 2 IDE.

Could someone help me out here for a project I want to do.

Basically what I have is this

<?xml version="1.0" encoding="utf-8"?>
xmlns:mx="library://ns.adobe.com/flex/halo" layout="absolute" minWidth="1024" minHeight="768" width="432" height="382">
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<mx:Canvas width="100%" height="100%" backgroundColor="#FFFFFF">
</mx:Canvas>
</mx:Application>

I want to use the new graphics declarations to draw a bunch of 5px wide circles onto this canvas but I don't know how. I want to evalve this into a strategy game

Any code tips would be appreciated

Is Canvas the best choice to draw stuff onto?

looking forward to your input and help as this app grows

• ###### 1. Re: I want to use the new graphics declarations to draw a bunch of 5px wide circles onto this canvas

You can use the spark Ellipse graphic element.  Graphic elements must be inside of a spark container like Group or SkinnableContainer.

Here is an example that shows how to add an Ellipse to a Group via ActionScript and MXML:

<?xml version="1.0" encoding="utf-8"?>
<fx:Script>
<![CDATA[
import spark.primitives.Ellipse;
import mx.graphics.SolidColor;

// adds a new ellipse via ActionScript

var newEllipse:Ellipse = new Ellipse();

newEllipse.width = 5;
newEllipse.height = 5;

var fill:SolidColor = new SolidColor();
fill.color = 0x0000FF;
newEllipse.fill = fill;

}
]]>
</fx:Script>

<s:VGroup id="containingGroup">
<!-- an Ellipse declared in MXML -->
<s:Ellipse id="mxmlEllipse" width="5" height="5">
<s:fill><s:SolidColor color="0xFF0000" /></s:fill>
</s:Ellipse>
</s:VGroup>

</mx:Application>
• ###### 2. Re: I want to use the new graphics declarations to draw a bunch of 5px wide circles onto this canvas

Or, you could also create a custom component using <fx:Component> and then create new insteances of your component:

<?xml version="1.0" encoding="utf-8"?>
<s:controlBarContent>
autoRepeat="true"
buttonDown="button1_clickHandler(event);" />
</s:controlBarContent>

<fx:Script>
<![CDATA[
import mx.graphics.SolidColor;
protected function button1_clickHandler(evt:Event):void {
var c:Circ = new Circ();
SolidColor(c.fill).color = Math.random() * 0xFFFFFF; // random fill color
c.alpha = Math.random(); // random alpha
c.x = uint(Math.random() * 400); // random X position
c.y = uint(Math.random() * 300); // random Y position
}
]]>
</fx:Script>

<fx:Declarations>
<fx:Component className="Circ">
<s:Ellipse width="50" height="50">
<s:fill>
<s:SolidColor color="red" />
</s:fill>
</s:Ellipse>
</fx:Component>
</fx:Declarations>

</s:Application>



Peter

• ###### 3. Re: I want to use the new graphics declarations to draw a bunch of 5px wide circles onto this canvas

Thanks very much so far, awesome code:)

I now have added some animation and logic.

If compile this and press start animation you will see what I mean

I would now like to draw a line from every gray ellipse to every blue ellipse but am not sure of the best way to do this using fxg.(connecting centers and behind the ellipsis)

<?xml version="1.0" encoding="utf-8"?>
<s:creationComplete>
<![CDATA[
setupScene();
]]>
</s:creationComplete>
<s:controlBarContent>
<s:Button label="start Animation"
buttonDown="startAnimation();" />
<s:Button label="stop Animation"
buttonDown="stopAnimation();" />

</s:controlBarContent>

<fx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
import mx.core.IVisualElement;
import mx.graphics.SolidColor;

private var FPS:uint = 20;

private var delay:uint = 1000/ FPS;

private var repeat:uint = 100;
private var myTimer:Timer = new Timer(delay, repeat);

private var blueTeam:ArrayCollection =  new ArrayCollection();

private var blueLeaders:ArrayCollection =  new ArrayCollection();

private function startAnimation():void{

myTimer.start();

}

private function stopAnimation():void{
myTimer.stop();
}

protected function setupScene():void {
for (var i :int = 0;i< 8;i++){
var c:bCirc = new bCirc();
c.x = uint(Math.random() * 400); // random X position
c.y = uint(Math.random() * 300); // random Y position
}
for (i = 0;i< 2;i++){
c2.x = uint(Math.random() * 400); // random X position
c2.y = uint(Math.random() * 300); // random Y position
}
}

for each (var o:IVisualElement  in blueTeam ){
o.x ++;
}
for each (o  in blueLeaders ){
o.x ++;
}
render();

}

private function render():void{

//clear all items from displaylist
removeAllElements();

for each (var o:IVisualElement in blueTeam ){
}
}

]]>
</fx:Script>

<fx:Declarations>
<fx:Component className="bCirc">

<s:Ellipse width="30" height="30" alpha="0.8">
<s:fill>
<s:SolidColor color="0x0000ff" />
</s:fill>
</s:Ellipse>
</fx:Component>

<s:Ellipse x="0" y="0" width="30" height="30">
<s:fill>
<s:entries>
</s:entries>
</s:fill>
</s:Ellipse>

</fx:Component>
<fx:Component className="RCirc">
<s:Ellipse width="30" height="30" alpha="0.8">
<s:fill>
<s:SolidColor color="0xff0000" />
</s:fill>
</s:Ellipse>
</fx:Component>
</fx:Declarations>

</s:Application>

• ###### 4. Re: I want to use the new graphics declarations to draw a bunch of 5px wide circles onto this canvas

I'm sure there are a bunch of different ways of doing this and I don't know which is best, but here is a sample that uses two AnimateProperty effects in parallel to animate a Line GraphicElement between the center of two Ellipses.

<?xml version="1.0" encoding="utf-8"?>

<fx:Script>
<![CDATA[
public function animateLine():void {

var startPosX:Number = startEllipse.x + (startEllipse.width / 2);
var startPosY:Number = startEllipse.y + (startEllipse.height / 2);
var endPosX:Number = endEllipse.x + (endEllipse.width / 2) - startPosX;
var endPosY:Number = endEllipse.y + (endEllipse.height / 2) - startPosY;

lineToAnimate.x = startPosX;
lineToAnimate.y = startPosY;

animateX.toValue = endPosX;
animateY.toValue = endPosY;

animatePosition.play();
}
]]>
</fx:Script>

<fx:Declarations>
<s:Parallel id="animatePosition" target="{lineToAnimate}" duration="1000">
<mx:AnimateProperty id="animateX"  property="xTo" />
<mx:AnimateProperty id="animateY" property="yTo" />
</s:Parallel>

</fx:Declarations>

<s:Line id="lineToAnimate">
<s:stroke>
<s:SolidColorStroke color="0x000000" />
</s:stroke>
</s:Line>

<s:Ellipse id="startEllipse" width="30" height="30">
<s:fill>
<s:SolidColor color="0x0000ff" />
</s:fill>
</s:Ellipse>

<s:Ellipse id="endEllipse" width="30" height="30" x="100" y="100">
<s:fill>
<s:SolidColor color="0xff0000" />
</s:fill>
</s:Ellipse>

<s:Button label="start animation" x="300" y="200" click="animateLine()" />

</s:Application>

• ###### 5. Re: I want to use the new graphics declarations to draw a bunch of 5px wide circles onto this canvas

Here is another sample that uses the new spark Animate class with two SimpleMotionPaths.

<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"

<fx:Script>
<![CDATA[
public function animateLine():void {

// figure where to draw the line from and to
var startPosX:Number = startEllipse.x + (startEllipse.width / 2);
var startPosY:Number = startEllipse.y + (startEllipse.height / 2);
var endPosX:Number = endEllipse.x + (endEllipse.width / 2) - startPosX;
var endPosY:Number = endEllipse.y + (endEllipse.height / 2) - startPosY;

// reset the line to start at the start position
lineToAnimate.x = startPosX;
lineToAnimate.y = startPosY;
lineToAnimate.xTo = 0;
lineToAnimate.yTo = 0;

// animate xTo/yTo to the end position
animateX.valueTo = endPosX;
animateY.valueTo = endPosY;
animatePosition.play();
}
]]>
</fx:Script>

<fx:Declarations>
<s:Animate id="animatePosition" target="{lineToAnimate}" duration="1000">
<s:SimpleMotionPath id="animateX" property="xTo" />
<s:SimpleMotionPath id="animateY" property="yTo" />
</s:Animate>
</fx:Declarations>

<s:Line id="lineToAnimate">
<s:stroke><s:SolidColorStroke color="0x000000" /></s:stroke>
</s:Line>

<s:Ellipse id="startEllipse" width="30" height="30">
<s:fill><s:SolidColor color="0x0000ff" /></s:fill>
</s:Ellipse>

<s:Ellipse id="endEllipse" width="30" height="30" x="100" y="100">
<s:fill><s:SolidColor color="0xff0000" /></s:fill>
</s:Ellipse>

<s:Button label="play animation" x="300" y="200" click="animateLine()" />

</s:Application>


The spark Animate class is very powerful.  You can learn more about it and other effects here:

• ###### 6. Re: I want to use the new graphics declarations to draw a bunch of 5px wide circles onto this canvas

Hi again,

I can't seem to add listeners to the graphics:

<fx:Component className="BCirc">
<s:Ellipse width="30" height="30" alpha="0.8">
<s:fill>
<s:SolidColor color="0xff0000" />
</s:fill>
</s:Ellipse>
</fx:Component>

protected function setupScene():void {
for (var i :int = 0;i< 8;i++){
var c:bCirc = new bCirc();
c.x = uint(Math.random() * 400); // random X position
c.y = uint(Math.random() * 300); // random Y position

}

}

• ###### 7. Re: I want to use the new graphics declarations to draw a bunch of 5px wide circles onto this canvas

> I can't seem to add listeners to the graphics.

GraphicElements like Ellipse are not DisplayObjects; they are considerably lighter-weight than DisplayObjects, and multiple GraphicElements can draw into a single DisplayObject. But the Player's mouse-interaction works only at the level of DisplayObjects. So one solution is to wrap things in an <s:Group> (which is a DisplayObject) and handle the mouse events there.

Gordon Smith

• ###### 8. Re: I want to use the new graphics declarations to draw a bunch of 5px wide circles onto this canvas

thanks very much Gordon for explaining. I'm writing a RTS game and I

hope the way you propose will still allow me to control upto say 400

elipses.

The next stage is to give each elipse (wrapped in a group) a green

health meter like in Red alert wheb selected. how best could I do

this? a rectangle object with a stroke inside in the top part of the

group?

• ###### 9. Re: I want to use the new graphics declarations to draw a bunch of 5px wide circles onto this canvas

I can't remember what the red alert health bars looked like, but I think you might want to use two Rects, see attached HealthMeterExample.mxml

Also see PerformanceTest.mxml for an example of the performance of moving 400 Groups at once.

• ###### 10. Re: I want to use the new graphics declarations to draw a bunch of 5px wide circles onto this canvas

wow your code is so cool. 400 seems to be about the most I could comfortrably run. However I intend to write my own animation code as the movement of the shphere will be directed by a mouse click at a distant point. I will also need to keep the circles a certain distance apart and apply logic to when the program realises that all the selected units have arrived at their destination. This likely means I will need to have less than 400 max units in the end game. I'll post more code

• ###### 11. Re: I want to use the new graphics declarations to draw a bunch of 5px wide circles onto this canvas

What is the best way for each group to control its own state? Also how much performance am I likely to get in my app compared to the original Red Alert game that was run on desktops in the late nineties?

• ###### 12. Re: I want to use the new graphics declarations to draw a bunch of 5px wide circles onto this canvas

I'm trying to keep all my code in the one mxml file (for ease of sharing with you guys )

so I tried this in my code and I wasn't allowed, I guess I'l have to create seperate files for these groups to do what I'm trying: Parse error: '<s:Group>' is not allowed to follow '</s:states>'

<fx:Component className="bCirc">
<s:states>
<s:State name="state1" />
<s:State name="state2" />
</s:states>

<s:Group width="23" height="23" click="(currentState == 'state1') ? currentState='state2': currentState='state1'">

<s:Ellipse width="30" height="30" alpha="0.8">
<s:fill>
<s:SolidColor color="0x0000ff" />
</s:fill>
</s:Ellipse>

<s:Rect left="5" right="5" top="5" height="1" includeIn="state2">
<s:fill>
<s:SolidColor color="0x006600" />
</s:fill>
</s:Rect>
<s:Rect left="5" right="5" bottom="5" top="6" includeIn="state2">
<s:fill>
<s:SolidColor color="0x00FF00" />
</s:fill>
</s:Rect>

</s:Group>

</fx:Component>

• ###### 13. Re: I want to use the new graphics declarations to draw a bunch of 5px wide circles onto this canvas

The first child of 'fx:Component' serves as the base class of your new generated component.  So your Group needs to be parented by fx:Component.  The 's:states' tag (note the lower case) is a property of your new component so place the s:states block inside the Group.  e.g.

<fx:Component className="bCirc">
<s:Group >
<s:states>
<s:State name="state1" />
<s:State name="state2" />
</s:states>

• ###### 14. Re: I want to use the new graphics declarations to draw a bunch of 5px wide circles onto this canvas

Awesome thanks

best wishes

Nikos Katsikanis (Msci)

Web Developer

• ###### 15. Re: I want to use the new graphics declarations to draw a bunch of 5px wide circles onto this canvas

The game is comming along nicely now, if only FB4 didn't crash as often lol

• ###### 16. Re: I want to use the new graphics declarations to draw a bunch of 5px wide circles onto this canvas

OK I've got a component the way  I like with a health meter

<fx:Component className="bCirc">

<s:Group width="30" height="30" click="(currentState == 'state1') ? currentState='state2': currentState='state1'">

<fx:Script>
<![CDATA[
[bindable]
private static var healthBarWidth:int = 30;
[bindable]
private static var healthBarHeight:int = 10;
[bindable]
private var health:int = 80;
]]>
</fx:Script>

<s:states>
<s:State name="state1" />
<s:State name="state2" />
</s:states>

<s:Ellipse  width="100%" height="100%" alpha="0.8">
<s:fill>
<s:SolidColor color="0x0000ff" />
</s:fill>
</s:Ellipse>

<s:Group left="5"   top="5" height="10" width="{healthBarWidth}" includeIn="state2">
<s:Rect width="100%" height="100%">

<s:fill>
<s:entries>

</s:entries>

</s:fill>

</s:Rect>
<s:Rect width="{((100-health)/100)*healthBarWidth}" height="100%">

<s:fill>
<s:SolidColor color="0x000000" />
</s:fill>
</s:Rect>
</s:Group>

</s:Group>

</fx:Component>

how do I get round the

Data binding will not be able to detect assignments to "healthBarWidth".

Problem

cheers

• ###### 17. Re: I want to use the new graphics declarations to draw a bunch of 5px wide circles onto this canvas

Capitalize the 'b' in Bindable?

• ###### 18. Re: I want to use the new graphics declarations to draw a bunch of 5px wide circles onto this canvas

yep

need to show that as an error in fb4

best wishes

Nikos Katsikanis (Msci)

Web Developer

• ###### 19. Re: I want to use the new graphics declarations to draw a bunch of 5px wide circles onto this canvas

Ok I'm working on changing the mouse coursor. I think I want something like you see here on youtube

when a unit is not selected and the mouse is over empty terrain you see a cursor with 4 white arrows at the corners and green bars that glow down the sides. I would like to emulate this in FB4 but my animation skills are not too up to scratch. Could the long hand of Adobe lend a hand

Should I make this in flash cs3 or do it all in spark?

• ###### 20. Re: I want to use the new graphics declarations to draw a bunch of 5px wide circles onto this canvas

I getting well with my app. Just to figure out some maths and get the

commands working and figure how how to tell the units to stop moving when

the've arrive at a command point (I'll try and get the units as close as

possible all around the point that they were told to go to).

One other thing I currently need help with, how do I draw a selection

rectangle in my app to select my  units?

• ###### 21. Re: I want to use the new graphics declarations to draw a bunch of 5px wide circles onto this canvas

I think what I need to do is get the first unit that arrives at the

destination to stop and not move and then get evry other unit to

within 2 pixels of the closest unit to the destination. However how to

I get the units to not collide. If I have 100 units moving towards  a

target there is going to have to be some pretty robust collision

detection.

• ###### 22. Re: I want to use the new graphics declarations to draw a bunch of 5px wide circles onto this canvas

im gonna code a heAt map  that will remember the location of every

unit the previous animation cycle. if a unit needs to move somewhere

He will need to tell the unit in front of him to move (the heat map

will basically mainain the collision information.

boy when u try and code something like this you really start to

realise the effort that has gone into games of the past

• ###### 23. Re: I want to use the new graphics declarations to draw a bunch of 5px wide circles onto this canvas

hmm a 10 pixel resolution heat map stored in a nested array structure

won't allow my  units to bunch together as close as I want to. I think

what I need ti do is calculate wether the bounds of the moving group

intersects with a stationary or slower moving group. These seems to be

really hard to do with low cpu cost

• ###### 24. Re: I want to use the new graphics declarations to draw a bunch of 5px wide circles onto this canvas

After googling a bit is I realize this is a typical computer science problem and I may have to go for a tile based collision detection system.  I read this interesting note in collision detection:

### Exploiting temporal coherence

In many applications, the configuration of physical bodies from one time step to the next changes very little. Many of the objects may not move at all. Algorithms have been designed so that the calculations done in a preceding time step can be reused in the current time step, resulting in faster algorithms.

At the coarse level of collision detection, the objective is to findpairs of objects which might potentially intersect. Those pairs willrequire further analysis. An early high performance algorithm for thiswas developed by M. C. Lin at U.C. Berkeley [1], who suggested using axis-aligned bounding boxes for all n bodies in the scene.

Each box is represented by the product of three intervals (i.e., a box would be $I_1 \times I_2 \times I_3=[a_1,b_1] \times [a_2,b_2] \times [a_3,b_3]$.) A common algorithm for collision detection of bounding boxes is sweep and prune. We observe that two such boxes, $I_1 \times I_2 \times I_3$ and $J_1 \times J_2 \times J_3$ intersect if, and only if, I1 intersects J1, I2 intersects J2 and I3 intersects J3. We suppose that, from one time step to the next, Ik and Jk intersect, then it is very likely that at the next time step, they will still intersect. Likewise, if they did not intersect in the previous time step, then they are very likely to continue not to.

So we reduce the problem to that of tracking, from frame to frame, which intervals do intersect. We have three lists of intervals (one for each axis) and all lists are the same length (since each list has length n, the number of boundingboxes.) In each list, each interval is allowed to intersect all otherintervals in the list. So for each list, we will have an $n \times n$ matrix M = (mij) of zeroes and ones: mij is 1 if intervals i and j intersect, and 0 if they do not intersect.

By our assumption, the matrix M associated to a list of intervals will remain essentially unchanged from one time step to the next. To exploit this, the list of intervals is actually maintained as a list of labeled endpoints. Each element of the list has the coordinate of an endpoint of an interval, as well as a unique integer identifying that interval. Then, we sort the list by coordinates, and update the matrix M as we go. It's not so hard to believe that this algorithm will work relatively quickly if indeed the configuration of bounding boxes does not change significantly from one time step to the next.

In the case of deformable bodies such as cloth simulation, it maynot be possible to use a more specific pairwise pruning algorithm asdiscussed below, and an n-body pruning algorithm is the best that can be done.

If an upper bound can be placed on the velocity of the physical bodies in a scene, then pairs of objects can be pruned based on their initial distance and the size of the time step.

This is  fun project

I hope to post code later