as3 getting object coordinates - actionscript-3

Hello everyone so i have a piece of code witch creates some circles, and after i move them with another function i want to get their center coordinates so i can draw lines from center to center of circles, but i don`t have any idea how to do it ... if you can suggest me 1 , here is the code witch creates the circle :
function new_sond(event:MouseEvent):void
{
if (i<9)
{
i++;
q=i;
var btn:Sprite = new Sprite();
btn.graphics.beginFill(0x0099FF, 1);
btn.graphics.drawCircle(400, 300, 15);
btn.graphics.endFill();
var s:String = String(q);
btn.name=s;
var textField = new TextField();
textField.mouseEnabled=false;
textField.text = i;
textField.width = 10;
textField.height = 17;
textField.x = 395; // center it horizontally
textField.y = 292; // center it vertically
btn.addChild(textField);
this.addChild(btn);
}
}
the code with is mooving them is :
this.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownH);
this.addEventListener(MouseEvent.MOUSE_UP, mouseUpH);
function mouseDownH(evt:MouseEvent):void {
var object = evt.target;
object.startDrag();
}
function mouseUpH(evt:MouseEvent):void {
var obj = evt.target;
obj.stopDrag();
}
And the code where i draw the lines between them :
function click1(e:MouseEvent):void{
e.currentTarget.removeEventListener(MouseEvent.CLICK, click1);
var i:int;
i=1;
if (e.target.name!=null){
trace(e.target.name);
sx=mouseX;
sy=mouseY;
stage.addEventListener(MouseEvent.CLICK,click2);
}
}
function click2(e:MouseEvent):void{
e.currentTarget.removeEventListener(MouseEvent.CLICK, click2);
fx=mouseX;
fy=mouseY;
var i:int;
i=2;
trace(e.target.name);
var line:Shape = new Shape();
line.graphics.lineStyle(1,0x0066FF,1);
line.graphics.moveTo(sx,sy);
line.graphics.lineTo(fx,fy);
this.addChild(line);
var inputField:TextField = new TextField();
inputField.border = true;
inputField.type = TextFieldType.INPUT;
str=inputField.text;
trace(str);
inputField.width = 23;
inputField.height = 18;
inputField.x = (sx+fx)/2;
inputField.y = (sy+fy)/2;
addChild(inputField);
}
The thing is i want to draw the line from center to center, but i get the mouseX and mouseY coordinates to draw, because i don`t know how to take the center coordinates of an object.... what i get is : http://gyazo.com/6003630d549209ec5e16ccfffe0ee689
But i want the lines to be drawn from center, if someone has any suggestions please help
Sorry for the long post, i just don`t know where i need to put the piece with will center them so i wanted to give the hole code where it can be placed.... I will appreciate very much any idea .

Well, if you drew the circle at 0,0 and moved the btn object .x and .y to 400,300 like this:
btn.graphics.drawCircle(0,0,15);
btn.x = 400;
btn.y = 300;
Then as you drag btn around the screen, btn.x , btn.x (or in the click handler, e.target.x and e.target.y) would always be the center of the circle.
Alternately, if you can't or don't want to do it that way, you can get the bounds of btn (with respect to this coordinate system, since that's where line is being drawn), and since it's a circle, then center of the bounds will be the center of the circle:
var btn:Sprite = e.target;
var bounds:Rectangle = btn.getBounds(this);
var center_x:Number = bounds.x + bounds.width/2;
var center_y:Number = bounds.y + bounds.height/2;

Related

Flash: get absolute position of e.currentTarget

Okay, wasn't sure about the title.
But here's what I am trying to achieve:
Basically i am trying to do something like a quiz, where you can drag and drop the answers into a field. And if they are correkt it should snap the answer field position.
It should be something like
if(myobject.hitTestObject(targetField) && isCorrectAnswer()) {
myobject.x = targetField.x;
myobject.y = targetField.y;
}
But it's not really working.
So here is what I have:
/**
* Generating dragable answer fields based on an array.
**/
function generateAnswer():void {
// creating text format
var myFormat:TextFormat = new TextFormat();
myFormat.color = 0x0066FF;
myFormat.size = 24;
myFormat.align = TextFormatAlign.CENTER
// reference array to store all textfields
var referenceArray:Array = new Array();
// iterate through all answers in vocabListItems and generate textfields
var i:int;
for (i = 0; i < vocabListItems.length; i++) {
var answerField:TextField = new TextField();
// Setting text to current answer
answerField.text = vocabListItems[i];
answerField.width = 140;
answerField.height = 40;
answerField.x = 60+ i*150;
answerField.y = 410;
answerField.background = true;
answerField.backgroundColor = 0xffffff;
answerField.setTextFormat(myFormat);
answerField.selectable = false;
answerField.type = TextFieldType.DYNAMIC
// store the textfield in a container so drag and drop
// will work
var textContainer:Sprite = new Sprite();
textContainer.addChild(answerField);
addChild(textContainer);
referenceArray.push(textContainer);
}
for each (var item in referenceArray) {
item.addEventListener(MouseEvent.MOUSE_DOWN, startDragging);
item.addEventListener(MouseEvent.MOUSE_UP, stopDragging);
}
}
And then I start my drag
var start_x:Number;
var start_y:Number;
function startDragging(e: MouseEvent):void {
var object = e.currentTarget;
start_x = e.currentTarget.x;
start_y = e.currentTarget.y;
object.startDrag();
}
And my stop dragging
function stopDragging(e:MouseEvent):void {
e.currentTarget.stopDrag();
if (e.currentTarget.hitTestObject(targetField)) {
e.currentTarget.x = targetField.x;
e.currentTarget.y = targetField.y;
} else {
e.currentTarget.x = start_x;
e.currentTarget.y = start_y;
}
}
So the problem however is, that e.currentTarget.x is starting from 0. And not from the absolute position on the screen. Its always a relative value, so if i drag it to the targetField its x and y is something like -100, -40
If I set it to the targetField x and y it disappears somewhere in the nirvana of the screen.
targetField is in this case just a rectangle drawn on the stage with a x and y of 160
How can I position it to the absolute x and y?
Here's a screenshot
So the top field is the targetField which is only a rectangle with x 161 and y 191.
The field on the bottom are the dragable fields which are the e.currentTarget. But currentTarget.x is always 0.
EDIT
Your e.currentTarget is going to be the textContainer, which you haven't set an x/y on so it will naturally be 0.
It would seem to make more sense to move the container, and not the actual text field when you create it, like so:
for (i = 0; i < vocabListItems.length; i++) {
var answerField:TextField = new TextField();
// Setting text to current answer
answerField.text = vocabListItems[i];
answerField.width = 140;
answerField.height = 40;
//answerField.x = 60+ i*150; //don't move the text field, move the container later
//answerField.y = 410;
answerField.background = true;
answerField.backgroundColor = 0xffffff;
answerField.setTextFormat(myFormat);
answerField.selectable = false;
answerField.type = TextFieldType.DYNAMIC
// store the textfield in a container so drag and drop
// will work
var textContainer:Sprite = new Sprite();
textContainer.x = 60+ i*150;
textContainer.y = 410;
textContainer.addChild(answerField);
addChild(textContainer);
referenceArray.push(textContainer);
//Also, as an aside, there is no reason to loop through the array after this, just add the listeners here
textContainer.addEventListener(MouseEvent.MOUSE_DOWN, startDragging);
textContainer.addEventListener(MouseEvent.MOUSE_UP, stopDragging);
}
End Edit
To translate the coordinates from one object to another, you can use the localToGlobal and globalToLocal methods of a display object.
Something like this:
var globalPoint:Point = targetField.localToGlobal(new Point());
var destinationLocalPoint:Point = e.currentTarget.parent.globalToLocal(globalPoint);
e.currentTarget.x = destinationLocalPoint.x;
e.currentTarget.y = destinationLocalPoint.y;
What I'm doing here, is first, getting the global coordinates of the targetField. So it's taking a point (at 0,0) relative to targetField and translating that relative to the stage.
Then I'm making a new Point object that takes that global coordnate set, and translate that to the parent of e.currentTarget.

Remove sprite from stage in as3

I have this code for a message to appear on stage when player finishes drag and drop. I would like this sprite to be removed when a button is clicked for the next frame. Can someone help me with the code?
stage.addEventListener(Event.ENTER_FRAME, EntFrame);
function EntFrame (e:Event):void
{
if (CntP1+CntP2+CntP3+CntP4+CntP5+CntP6+CntP7+CntP8 == 40)
{
var w:int = 400, h:int = 200;
var win:Sprite = new Sprite();
win.name = "Mywin";
addChild(win);
// draw rounded rect with subtle vertical linear gradient fill and blue stroke
win.graphics.lineStyle(4,0x0077ff);
var mat:Matrix = new Matrix();
mat.createGradientBox(w, h, 90 * (Math.PI / 180));
win.graphics.beginGradientFill(GradientType.LINEAR,[0xffffff,0xeeeeee],[1.00,1.00],[0,255],mat);
win.graphics.drawRoundRect(0,0,w,h,15,15);
// show center "YOU WIN!" text
var tf:TextField = new TextField();
tf.autoSize = TextFieldAutoSize.LEFT;
tf.antiAliasType = AntiAliasType.ADVANCED;
tf.defaultTextFormat = new TextFormat("Arial, Verdana",36,0x454545,true);
tf.text = "Κέρδισες!";
tf.selectable = false;
win.addChild(tf);
tf.x = w/2 - tf.width/2;
tf.y = h/2 - tf.height/2;
// add a drop shadow
var dropShadow:DropShadowFilter = new DropShadowFilter(3,45,0,.35,8,8,1,3);
win.filters = [dropShadow];
// center the graphic
win.x = stage.stageWidth/2 - win.width/2;
win.y = stage.stageHeight/2 - win.height/2;
}
}
Your code isn't written well and needs rewriting to ensure reuse or scalability of your project, but here's a quick way out.
make a holder Sprite, something like
var messageHolder:Sprite = new Sprite();
addChild(messageHolder);
add all the messages to that holder in any fashion you like. When you need to erase the contents of that holder, call following method:
function clearHolderContents(holder:DisplayObjectContainer):void
{
if (holder.numChildren < 1)
return; // no need to continue this method if the target is empty
for (var i:int = holder.numChildren - 1; i >= 0; i--)
removeChild(holder.getChildAt(i));
}
This method can clear contents of any DisplayObjectContainer => use it for your messageHolder:
clearHolderContents(messageHolder);
Hope that helps!

Draw Text on a generated Sprite object as3

Everyone, I'm just a beginner and I have question. The idea of my program is that when the user clicks a button a circle is generated and it should be counting for each additional circle it should look something like this :
The number should be in center and I should be able to move the object with the number together this is my code:
add_s.addEventListener(MouseEvent.CLICK,new_sond);
function new_sond(event:MouseEvent):void
{
var btn:Sprite = new Sprite();
btn.graphics.beginFill(0x00FF00, 1);
btn.graphics.drawCircle(400, 300, 25);
btn.graphics.endFill();
this.addChild(btn);
}
//----------------------------Drag And Drop----------------------
this.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownH);
this.addEventListener(MouseEvent.MOUSE_UP, mouseUpH);
function mouseDownH(evt:MouseEvent):void {
var object = evt.target;
object.startDrag();
}
function mouseUpH(evt:MouseEvent):void {
var obj = evt.target;
obj.stopDrag();
}
I will be very thankful if someone can help me.
How do i make the text to apear on the center of the circles and i still will be able to move them with the text
This is what Vesper should have posted as an answer :)
Add a TextField object to your Sprite. Since the TextField is a child of the Sprite, it will move w/the Sprite. All you need to do is position the text in the middle of the circle:
function new_sond(event:MouseEvent):void
{
var btn:Sprite = new Sprite();
btn.graphics.beginFill(0x00FF00, 1);
btn.graphics.drawCircle(400, 300, 25);
btn.graphics.endFill();
var textField = new TextField();
textField.text = "1";
textField.width = textField.textWidth; // default width is 100
textField.height = textField.textHeight;
textField.x = (25 - textField.textWidth)/2; // center it horizontally
textField.y = (25 - textField.textHeight)/2; // center it vertically
btn.addChild(textField);
this.addChild(btn);
}
Note, as suggested by #Joeson Hwang, you could use a Shape object instead of a Sprite to draw the circles. The Shape is more lightweight than a Sprite. However, since Shape does not extend DisplayObjectContainer, you cannot add child objects to a Shape like you can with a Sprite.
#Joeson Hwang's answer suggests to add the Shape and the text to a Sprite. But that won't be saving you anything, so just draw the graphics directly to the Sprite as you are doing now.
use btn:Shape (saves a lot of system resources). and then put the Shape and your text into a Sprite. You could also add a Sprite into another Sprite.
You can use also flash.text.engine package:
function new_sond(event:MouseEvent):void
{
var btn:Sprite = new Sprite();
btn.graphics.beginFill(0x00FF00, 1);
btn.graphics.drawCircle(cx, cy, cr);
btn.graphics.endFill();
// Font format
var fontDescription:FontDescription = new FontDescription("Arial");
var format:ElementFormat = new ElementFormat(fontDescription, 16, 0x000088);
// Display text
var textElement:TextElement = new TextElement('1', format);
var textBlock:TextBlock = new TextBlock();
textBlock.content = textElement;
// New display object containing text
var textLine:TextLine = textBlock.createTextLine(null, 500);
// Centers the text inside the circle
textLine.x = cx + (cr - textLine.width) / 2;
textLine.y = cy + (cr - textLine.height) / 2;
// Add text into button
btn.addChild(textLine);
this.addChild(btn);
}
More info about creating text: Creating and displaying text in ActionScript 3.0 Developer’s Guide

ActionScript 3.0 Getting Size/Coordinates From Loader Content

i'm attempting to position a textfield to the bottom left of an image that is added to the display list from the Loader() class. i don't know how to access the width/height information of the image.
var dragSprite:Sprite = new Sprite();
this.addChild(dragSprite);
var imageLoader:Loader = new Loader();
imageLoader.load(new URLRequest("picture.jpg"));
imageLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, displayPic, false, 0, true);
function displayPic(evt:Event):void
{
dragSprite.addChild(evt.target.content);
evt.target.removeEventListener(Event.COMPLETE, displayPic);
}
var tf:TextField = new TextField();
tf.text = "Picture Title";
tf.width = 200;
tf.height = 14;
tf.x //same x coordinate of dragSprite
tf.y //same y coordinate of dragSprite, plus picture height, plus gap between picture and text
addChild(tf);
within the displayPic function, i could assign the evt.target.content.height and evt.target.content.width to variables that i could use to position the text field, but i assume there is a more appropriate and direct way?
There is no direct way since you have to wait the image to be loaded to access width, and height.
But you can place you text as soon as the complete is done if it`s fit your design. Store the value into some var so you can reuse it when moving the sprite.
//...
var tf:TextField = new TextField();
tf.text = "Picture Title";
tf.width = 200;
tf.height = 14;
addChild(tf);
var imageLoader:Loader = new Loader();
imageLoader.load(new URLRequest("picture.jpg"));
imageLoader.contentLoaderInfo.addEventListener(
Event.COMPLETE, displayPic, false, 0, true
);
var offsetX:Number=0;
var offsetY:Number=0;
function positionText():void {
tf.x=dragSprite.x + offsetX;
tf.y=dragSprite.y + offsetY;
}
function displayPic(evt:Event):void {
var li:LoaderInfo=evt.target as LoaderInfo;
if (li===null)
return;
li.removeEventListener(Event.COMPLETE, displayPic);
var dob:DisplayObject=li.content;
if (dob!==null) {
dragSprite.addChild(dob);
// set only once the offset depending on the loaded image
offsetX = ...//
offsetY = dob.height+gap //...
// position text using the offset setted
// so you can reuse the function when moving your sprite
positionText();
}
}

This codes in Actionscript-2, Can anyone help me translate it into AS-3 please ?.......a newby pulling her hair out !

this.createEmptyMovieClip('mask_mc',0);
bg_mc.setMask(mask_mc);
var contor:Number=0;
// function drawCircle draws a circle on mask_mc MovieClip of radius r and having center to mouse coordinates
function drawCircle(mask_mc:MovieClip):Void{
var r:Number = 20;
var xcenter:Number = _xmouse;
var ycenter:Number = _ymouse;
var A:Number = Math.tan(22.5 * Math.PI/180);
var endx:Number;
var endy:Number;
var cx:Number;
var cy:Number;
mask_mc.beginFill(0x000000, 100);
mask_mc.moveTo(xcenter+r, ycenter);
for (var angle:Number = Math.PI/4; angle<=2*Math.PI; angle += Math.PI/4) {
xend = r*Math.cos(angle);
yend = r*Math.sin(angle);
xbegin =xend + r* A *Math.cos((angle-Math.PI/2));
ybegin =yend + r* A *Math.sin((angle-Math.PI/2));
mask_mc.curveTo(xbegin+xcenter, ybegin+ycenter, xend+xcenter, yend+ycenter);
}
mask_mc.endFill();
}
// contor variable is used to hold if the mouse is pressed (contor is 1) or not (contor is 0)
this.onMouseDown=function(){
drawCircle(mask_mc);
contor=1;
}
// if the mouse is hold and moved then we draw a circle on the mask_mc
this.onMouseMove=this.onEnterFrame=function(){
if (contor==1){
drawCircle(mask_mc);
}
}
this.onMouseUp=function(){
contor=0;
}
var mask_mc:MovieClip = new MovieClip();
bg_mc.setMask(mask_mc);
var contor:Number=0;
// function drawCircle draws a circle on mask_mc MovieClip of radius r and having center to mouse coordinates
function drawCircle(mask_mc:MovieClip):void{
var r:Number = 20;
var xcenter:Number = mouseX;
var ycenter:Number = mouseY;
var A:Number = Math.tan(22.5 * Math.PI/180);
var endx:Number;
var endy:Number;
var cx:Number;
var cy:Number;
mask_mc.graphics.beginFill(0x000000, 100);
mask_mc.graphics.moveTo(xcenter+r, ycenter);
for (var angle:Number = Math.PI/4; angle<=2*Math.PI; angle += Math.PI/4) {
xend = r*Math.cos(angle);
yend = r*Math.sin(angle);
xbegin =xend + r* A *Math.cos((angle-Math.PI/2));
ybegin =yend + r* A *Math.sin((angle-Math.PI/2));
mask_mc.graphics.curveTo(xbegin+xcenter, ybegin+ycenter, xend+xcenter, yend+ycenter);
}
mask_mc.graphics.endFill();
}
// contor variable is used to hold if the mouse is pressed (contor is 1) or not (contor is 0)
addEventListener(MouseEvent.MOUSE_DOWN, mouseDown);
addEventListener(MouseEvent.MOUSE_MOVE, mouseMoved);
addEventListener(MouseEvent.MOUSE_UP, mouseUp);
function mouseDown(e:MouseEvent):void{
drawCircle(mask_mc);
contor=1;
}
function mouseMoved(e:MouseEvent):void{
if (contor==1){
drawCircle(mask_mc);
}
}
function mouseUp(e:MouseEvent):void{
contor=0;
}
see how simple it was to translate? You should try to translate it yourself first and post your attempt.
This is just a direct translation of your snippet. You will have to remove the event listeners or there will be a memory leak.
These links might be useful for you:
AS2 to AS3 Migration Cheatsheet
ActionScript Migration Cookbook
Well sometimes the best way to get started with something like is just try to compile it as AS-3 and see where it blows up. Some of the code will work and then you can type the errors into google (or if you get stuck post specific questions to SO). That will be a lot easier than just trying to "translate" it if you don't know AS very well and understand the differences.
put it in flex builder
try to compile
if you get some errors, fix them
if you don't know how to fix them, google or ask the pleps