Scale from center point with Tween Class AS3 - actionscript-3

I need to scale a dynamic text box from it's center point using Tween class AS3.
Basically, I need to scale down to 50% in 300ms or so... and after finish I want to scale up again to 100% and stop animation.
I tried to set the center point to the center of the text box but it always scale from left.
Well I been trying hard to learn the basics of Tween class and I believe it's missing some good properties and methods like greensock!
Thank you.
title_txt.text = "Text";
var textScaleX:Tween;
var textScaleY:Tween;
title_txt.addEventListener(MouseEvent.MOUSE_OVER, scaleObj(1,2, 1));
function scaleObj(startUp:int, endUp:int, duration:int){
textScaleX = new Tween(title_txt, "scaleX", Strong.easeInOut, startUp, endUp, duration, true);
textScaleY = new Tween(title_txt, "scaleY", Strong.easeInOut, startUp, endUp, duration, true);
}

The oringin of a textfield will alwasy be in the top left corner. You could however calculate where the top left corner would be at 50% of the scale and the tween the x and y postion along with the scaleX and scaleY values.
A quick calculation of the 50% x and y would be something like:
50% x = 100% x position + (100% textfield width)/4
50% y = 100% y position + (100% textfield height)/4
Edit: Here is how this calculation in code would look like:
var targetScale:Number = .5; //scale 50% but any other scale would work here as well
var targetX:Number = title_txt.x + (title_txt.width - title_txt.width * targetScale) / 2;
var targetY:Number = title_txt.y + (title_txt.height - title_txt.height * targetScale) / 2;
I use my own tween class so I'm not sure how to implement this with either the Adobe tween class or the TweenLite class, but if you stick these numbers in any tween class the textfield (or any object with it's origin in the top left corner for that matter) will scale around is center point.

Number 1 tip for tweening:
Don't use adobe tweening classes: their functionalities are not good enough.
Use TweenLite: it's easier to use and has more features.
I realise it's not really an answer to your question, but others have already covered that.

Related

Libgdx / Physics Editor Rotation of body

and a nice evening.
I've the following problem:
A Box2d dynamic body with one fixture all vertices placed with positiv x / y from the origin of the body.
http://i.stack.imgur.com/MXQRr.png
But the rotation is on body origin 0/0 not on mass center..
So I tried these approaches:
1:
Set origin of Body in the Middle of the body(vertices positive and negativ)
Problem: rotation works, Sprite positioning is nearly impossible
2:
Set mass data center =
originOfBody.x + width / 2, originOfBody.y + height / 2
Problem: It's like I'm doing nothing, still rotation around origin of body at 0, 0
In the following Code snippet you can see my instantiation.
BodyDef bodyDef = new BodyDef();
bodyDef.type = BodyDef.BodyType.DynamicBody;
bodyDef.position.set(new Vector2(200, 2));
body = world.createBody(bodyDef);
FixtureDef fixtureDef = new FixtureDef();
fixtureDef.density = 0.6f;
fixtureDef.friction = 0.4f;
fixtureDef.restitution = 0.2f;
bodyLoader.attachFixture(body, "Rocket1n2", fixtureDef, WIDTH);
originOfBody = bodyLoader.getOrigin("Rocket1n2", WIDTH);
MassData data = body.getMassData();
data.center.set(Box2DUtils.getWidth(body) / 2, 0);
data.I = body.getMassData().I; //without this line programm fails with assertion
body.setMassData(data);
Vector2 cpy = data.center.cpy();
I rotate the player with following code:
body.setAngularVelocity(addition); //addition is predefined(atm 1 / -1)
I currently use Body Physics Editor from aurelia(?) with some hacks it worked, I dont have any Problems with other objects, because I dont rotate them. Placement works like a charm..
I wish I do a significant error.. Normally box2d must calculate the rotationcenter (Mass Center) automatically?
I cant help myself this time.. :(
I'd recommend getting your first approach to work.
Set origin of Body in the Middle of the body(vertices positive and
negativ) Problem: rotation works, Sprite positioning is nearly
impossible
The rotation works fine, but the sprite positioning is difficult. I had this same problem when I was making a physics game last year. What helped me was seeing exactly how the positioning worked.
Box2D bodies are center-focused. That means that calling the position of the body will give you the object's middle. Sprites are corner focused, meaning a sprite's position is it's bottom-left corner. Thus, you can't just set each of them as the same thing. I recommend shifting the sprite from the body's position down and to the left by half the body's height and width, respectively.

How to rotate all objects of canvas at once using Fabric.js?

I am working on custom product designer which uses Fabric.js. I want to rotate all objects of canvas at once by pressing one button (rotate left, rotate right).
I have achieved this using this code :
stage.forEachObject(function(obj){
obj.setAngle(rotation).setCoords();
});
stage.renderAll();
But it has one bug that every element rotates with its own center point. I want that every element rotates with respect to whole canvas element.
Grouping and rotating the group did not work so well for me. Here is another solution based on this js fiddle.
rotateAllObjects (degrees) {
let canvasCenter = new fabric.Point(canvas.getWidth() / 2, canvas.getHeight() / 2) // center of canvas
let radians = fabric.util.degreesToRadians(degrees)
canvas.getObjects().forEach((obj) => {
let objectOrigin = new fabric.Point(obj.left, obj.top)
let new_loc = fabric.util.rotatePoint(objectOrigin, canvasCenter, radians)
obj.top = new_loc.y
obj.left = new_loc.x
obj.angle += degrees //rotate each object buy the same angle
obj.setCoords()
});
canvas.renderAll()
},
You could add all the objects to a group an then rotate the group. This way you can also set the center for rotation.
This is how it could be solved
function rotate(a) {
var group = new fabric.Group(canvas.getObjects());
//angle is var with scope out of this function,
//so you can use this function as rotate(90) and keep rotating
angle = (angle + a) % 360;
group.rotate(angle);
canvas.centerObject(group);
group.setCoords();
canvas.renderAll();
}
FabricJS rotate everything and maintain the relative position also.
You can download the files here - https://drive.google.com/file/d/1UV1nBdfBk6bg9SztyVoWyLJ4eEZJgZRf/view?usp=sharing

Increase width without moving image

I'm developing a drawing app, and I ran into a problem, and a possible solution would be to be able to resize horizontally (increase or decrease the width) of an image without altering it's pivot, but ending with a "directional resize", it means, that if I start dragging the right resize anchor, the image starts increasing it's width to the right, instead of always taking into consideration the pivot.
So, what I'm doing now is to increase the width and at the same time I move the image width/2, it works, however when I have to rotate the image.. everything starts to get broken, and even if I set the pivot in the middle of the sprite, since the image (that is contained inside the sprite) x is altered, it doesn't matter.
I've read some about matrices, but I'm not sure if this is possible.
Thanks.
There a few ways you can accomplish this. The first is to use a transform matrix.
Here is a function I use to rotate an object around a point in that fashion:
*You'll need to import fl.motion.MatrixTransformer, if not using flashPro you can get it here: https://code.google.com/p/artitem-as3/source/browse/trunk/ArtItem/src/fl/motion/MatrixTransformer.as?r=3
/**
* Rotates a displayObject around the passed local point.
* #param displayObj
* #param relativeDegrees - the relative amount of degrees to rotate the object
* #param point - a local point to rotate the object around, if null, center of bounding box will be used.
*/
public static function rotateAroundPoint(displayObj:DisplayObject, relativeDegrees:Number, point:Point = null):void {
var m:Matrix = displayObj.transform.matrix.clone();
if (!point) {
//default is center of bounding box
var r:Rectangle = displayObj.getBounds(displayObj);
point = new Point(r.x + (r.width * .5), r.y + (r.height * .5));
}
MatrixTransformer.rotateAroundInternalPoint(m, point.x, point.y, relativeDegrees);
displayObj.transform.matrix = m;
}
Another more lazy way to do this, is to use a dummy parent object and just rotate that:
var dummy:Sprite = new Sprite();
dummy.addChild(yourObjectToRotate);
//this effectively makes the anchor point of dummy in the center, so when you rotate it it rotate from the center.
yourObjectToRotate.x = -(yourObjectToRotate.width * .5);
yourObjectToRotate.y = -(yourObjectToRotate.height * .5);
dummy.rotation = 90;

Resize as a function of distance between mc's

I hope this hasn't been asked too much before. When I search I only get questions pertaining to rescaling to window size.
Now my question. I got one space ship firing a beam against another ship. I want the beam to show for some time and I want it to "bridge" the two ships. In other words, I want the beam to extend its width between the two ships.
I try to do this with a dot movie clip that is 1 pixel wide and high (and aligned left edge). I try to resize it with the following code: (target is the ship to be fire at and owner is the ship firing)
dist.vx = target.x - owner.x;
dist.vy = target.y - owner.y;
dist.dist = Math.sqrt(dist.vx*dist.vx + dist.vy*dist.vy);
width = dist.dist;
x = owner.x;
y = owner.y;
rotation = Math.atan2(target.y-y, target.x-x)*180/Math.PI;
This doesn't work as intended because 1) dot also gets alot bigger in the other dimension - how can I "turn off" this behavior? and 2) sometimes it seems to get way to wide - but only in certain angles...
Any suggestions on either solving the heigh/width scaling or on another way to achieve the same effect?
(I'm new to coding and flash.) Thanks!
By resizing a dot, you will have a rectangle...
You can dynamically create a sprite covering both ships and moveTo the hit point of one ship then lineTo the other ship... You do not need distance calculation at all. What you have to do is being careful on the placement of the sprite. So that you can calculate relative hitting points by simple math.
Suppose you have mc space contining mc ship1 and mc ship2, and hit point coords on ships are named hx, hy and you will use sprite s, calculation will be as follows.
// calculate hit points relative to mc space
var s1HX:int = ship1.x + ship1.hx,
s1HY:int = ship1.y + ship1.hy,
s2HX:int = ship2.x + ship2.hx,
s2HY:int = ship2.y + ship2.hy,
// sprite relative moveTo lineTo coords will be these.
mX: int, mY: int,
lX: int, lY: int;
// top left of sprite will be minimum of the hit coords.
s.x = (s1HX <= s2HX)? s1HX : s2HX;
s.y = (s1HY <= s2HY)? s1HY : s2HY;
// now we can get sprite relative moveTo lineTo coordinates:
mX = s1HX - s.x;
mY = s1HY - s.y;
lX = s2HX - s.x;
lY = s2HY - s.y;
The rest is implementation with using these with fancy line styles etc...
To create a new sprite:
var s:Sprite = new Sprite();
Adding / removing it to/from mc space:
space.addChild(s);
space.removeChild(s);
For graphics use the graphics object of sprite.
s.graphics
For setting line styles you can use:
s.graphics.lineStyle(...) ,
s.graphics.lineBitmapStyle(...),
s.graphics.lineGradientStyle(...)
Functions, please read the manual for usage.
After setting the line style to draw the line use:
s.graphics.moveTo(mX,mY);
s.graphics.lineTo(lX,lY);
For pulsating effects you have to do a little more complicated things such as using tween class which you can read about here: http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/fl/transitions/Tween.html
Note that:
Sprites are no complicated magic, they are like mc's but they do not have timelines etc.
Sprites try to scale when width or height change programmatically. So do not touch them, moveTo lineTo automatically sets the size of a sprite...

AS3 sprite with rectangle is empty and returns 0 for width and other properties

I have an array of sprites:
for (i = 0; i < 3; i++) {
var newLine:Sprite = new Sprite();
newLine.graphics.beginFill(0xFFFFFF);
newLine.graphics.drawRect((uiSizeX * (.25 + .25 * i)) + (doorSizeX - lineLengths[0][i]) / 2, uiSizeY * .5, lineLengths[0][i], lineHeight);
newLine.name = "lines" + i;
lines.push(newLine);
}
I later add each to a background Sprite:
for (i = 0; i < 3; i++) {
uiContainer.addChild(doors[i]);
uiContainer.addChild(lines[i]);
}
And later wish to change the width of the rectangles contained in each. When I set the width property using the array reference:
lines[i].width = lineLengths[trialNumber][i];
The rectangle moves towards the center of the stage and uiContainer. Trying to set the x value results in even stranger behavior. I've gathered from answers to other questions that this is because the sprite is empty, which is confusing since it seems like it should have a rectangle in it. How do I access or change the properties of the rectangle or make it so the sprite is not empty?
Never try to directly change the width or height of a sprite, unless you really really have to, because it leads to all sorts of unexpected behavior.
If you want to resize the sprite, then redraw the rectangle:
var sprite = lines[i];
sprite.graphics.beginFill(0xFFFFFF);
sprite.graphics.drawRect(newWidth, newHeight);
Also don't forget to call endFill:
sprite.graphics.endFill();
You should probably wrap all this logic into a separate class so that you can redraw your sprites more easily. Even better, create a class that extends Sprite and that contains all the logic to redraw/resize.