cocos 2dx getPosition() , always returns initial position instead of current position - cocos2d-x

I have a sprite with having an action through which, it moves towards right side.
CCSprite *spaceShip1=CCSprite::create("ufo_1.png");
spaceShip1->setPosition(ccp(visibleSize.width/8,visibleSize.height/2));
this->addChild(spaceShip1, 3);
CCMoveBy* moveleft1 = CCMoveBy::create(3, ccp(visibleSize.width, 0));
spaceShip1->runAction(moveleft1);
I want to get the current visual position of sprite, as it is moving due to runAction, it should return its updated position.
I am using:
spaceShip1->getPosition();
and this position is utilizing here:
CCParticleSystemQuad* _spaceShip1 = new CCParticleSystemQuad();
_spaceShip1 = CCParticleSystemQuad::create("growingFlare.plist");
_spaceShip1->setPosition(spaceShip1->getPosition());
_spaceShip1->setAngle(180);
_spaceShip1->setScale(5);
_spaceShip1->stopSystem();
this->addChild(_spaceShip1, 4);
That particle effect must take place at the current position of spaceship, but it always took effect at initial position of spaceship.
I'm trying to get the current position of sprite. but it always returns the initial position instead of its current moving position.
What I have to do to get its current position?

float xPos = spaceShip->getPositionX();
float yPos = spaceShip->getPositionY();
CCLog("%f %f", xPos, yPos);
Try this in the method where you want to get the current x,y position of the moving sprite. It won't get the initial position what you get now.

That particle initialization happens during init(). Animation is not live then, hence will always give initial position.
You have 2 options.
In your update method. SetPosition() of your particle system every frame to the updated spaceship getPostion.
Make particle system as a child of spaceship.
In case of, "this->addChild()", do "_firstSpaceShip->addChild(_particleSystem)" and give it a initial x position like -10, so it always follow behind your spaceship.

May be this will help you out
CCParticleSystemQuad* _spaceShip1 = new CCParticleSystemQuad();
_spaceShip1 = CCParticleSystemQuad::create("growingFlare.plist");
_spaceShip1->setPosition(spaceShip1->getPositionX(), spaceShip1->getPositionY());

Related

LibGDX ModelInstance - can't reset scale, setting the transform while scaled deforms the model

Is there any way to reset a modelInstance's scale or set a modelInstances position without using transform.set? I'm making a 3D monster maker, When a part is selected a set of 3D arrows move to the part and become visible allowing the part to be dragged around. It's come to my attention that setting an arrow's position while scaled heavily deforms the arrow for whatever reason. This is a huge problem as I need the arrows to be different sizes depending on the size of the part. Without setting position, with setting position. Using transform.set on a non-scaled ModelInstance (or one scaled by 1) works fine.
I thought a solution would be to reset the size of the arrow before moving it and then re-scaling it after it was moved but there doesn't seem to be any method to do this and using transform.scale(-currentScale, -currentScale, -currentScale) inverts the arrow and increases its size rather than decreasing it.
Here is how I change the arrow's position: arrow[j].transform.set(modelInstance[i].transform.getTranslation(new Vector3(), arrow[j].transform.getRotation(new Quaternion());
Ok, I did some logging and found that scaling changes all values within the matrix4 not just the size of the modelInstance. I didn't find a way to only scale rotation but I figured a way around this: I created an empty Matrix4 and set that to a copy of the arrows matrix before scaling. When the arrows need to be positioned at a part I set the arrow's matrix to the baseMatrix, used transform.set to change the arrows' position, and then rescaled the arrow.
if(Intersector.intersectRayBoundsFast(pickRay, modelInstance[i].boundingBox)) {
modelInstance[i].transform.getTranslation(modelInstance[i].position);//get the part's position and store it
for(int j = 0 ; j < 3 ; j++) {
arrow[j].transform = arrow[j].baseTransform.cpy();//reset the arrows transform
arrow[j].transform.getRotation(arrow[j].rotation);//get the arrow's (unscaled) rotation and store it
arrow[j].transform.set(modelInstance[i].position, arrow[j].rotation);//set the arrow's position and rotation
arrow[j].changeSize('S');//rescale the arrow
}
break;
}
You can use transform.scale(1f/currentScale, 1f/currentScale, 1f/currentScale) to revert the scaling or the function ModelInstance.calculateTransforms()

Scale, Position & Rotate Parent object to make child object take up entire stage

Using the first photo below, let's say:
The red outline is the stage bounds
The gray box is a Sprite on the stage.
The green box is a child of the gray box and has a rotation set.
both display object are anchored at the top-left corner (0,0).
I'd like to rotate, scale, and position the gray box, so the green box fills the stage bounds (the green box and stage have the same aspect ratio).
I can negate the rotation easily enough
parent.rotation = -child.rotation
But the scale and position are proving tricky (because of the rotation). I could use some assistance with the Math involved to calculate the scale and position.
This is what I had tried but didn't produce the results I expected:
gray.scaleX = stage.stageWidth / green.width;
gray.scaleY = gray.scaleX;
gray.x = -green.x;
gray.y = -green.y;
gray.rotation = -green.rotation;
I'm not terribly experienced with Transformation matrices but assume I will need to go that route.
Here is an .fla sample what I'm working with:
SampleFile
You can use this answer: https://stackoverflow.com/a/15789937/1627055 to get some basics. First, you are in need to rotate around the top left corner of the green rectangle, so you use green.x and green.y as center point coordinates. But in between you also need to scale the gray rectangle so that the green rectangle's dimensions get equal to stage. With uniform scaling you don't have to worry about distortion, because if a gray rectangle is scaled uniformly, then a green rectangle will remain a rectangle. If the green rectangle's aspect ratio will be different than what you want it to be, you'd better scale the green rectangle prior to performing this trick. So, you need to first transpose the matrix to offset the center point, then you need to add rotation and scale, then you need to transpose it away. Try this set of code:
var green:Sprite; // your green rect. The code is executed within gray rect
var gr:Number=green.rotation*Math.PI/180; // radians
var gs:Number=stage.stageWidth/green.width; // get scale ratio
var alreadyTurned:Boolean; // if we have already applied the rotation+scale
function turn():void {
if (alreadyTurned) return;
var mat:flash.geom.Matrix=this.transform.matrix;
mat.scale(gs,gs);
mat.translate(-gs*green.x,-gs*green.y);
mat.rotate(-1*gr);
this.transform.matrix=mat;
alreadyTurned=true;
}
Sorry, didn't have time to test, so errors might exist. If yes, try swapping scale, translate and rotate, you pretty much need this set of operations to make it work.
For posterity, here is what I ended up using. I create a sprite/movieClip inside the child (green) box and gave it an instance name of "innerObj" (making it the actually content).
var tmpRectangle:Rectangle = new Rectangle(greenChild.x, greenChild.y, greenChild.innerObj.width * greenChild.scaleX, greenChild.innerObj.height * greenChild.scaleY);
//temporary reset
grayParent.transform.matrix = new Matrix();
var gs:Number=stage.stageHeight/(tmpRectangle.height); // get scale ratio
var mat:Matrix=grayParent.transform.matrix;
mat.scale(gs,gs);
mat.translate(-gs * tmpRectangle.x, -gs * tmpRectangle.y);
mat.rotate( -greenChild.rotation * Math.PI / 180);
grayParent.transform.matrix = mat;
If the registration point of the green box is at one of it's corners (let's say top left), and in order to be displayed this way it has a rotation increased, then the solution is very simple: apply this rotation with negative sign to the parent (if it's 56, add -56 to parent's). This way the child will be with rotation 0 and parent -> -56;
But if there is no rotation applied to the green box, there is almost no solution to your problem, because of wrong registration point. There is no true way to actually determine if the box is somehow rotated or not. And this is why - imagine you have rotated the green box at 90 degrees, but changed it's registration point and thus it has no property for rotation. How could the script understand that this is not it's normal position, but it's flipped? Even if you get the bounds, you will see that it's a regular rectangle, but nobody know which side is it's regular positioned one.
So the short answer is - make the registration point properly, and use rotation in order to display it like in the first image. Then add negative rotation to the parent, and its all good :)
Edit:
I'm uploading an image so I can explain my idea better:
 
As you can see, I've created a green object inside the grey one, and the graphics INSIDE are rotated. The green object itself, has rotation of 0, and origin point - top left.
#Vesper - I don't think that the matrix will fix anything in this situation (remember that the green object has rotation of 0).
Otherwise I agree, that the matrix will do a pretty job, but there are many ways to do it :)

ActionScript 3: Zoom into movieclip while not scaling its childrens

I've included a zoom functionality similar to the one explained at this website:
http://www.flashandmath.com/howtos/zoom/
This works perfectly on my background image(a map, that is), but I want to keep the symbols on my map the same size while zooming in.
I probably could work this out by changing all the children's size when calling the zoom-function, but I am hoping there is some kind of easy code adapt in my children class to make the size of the instances unchangable. Is there?
Thanks!
One crude way, so you don't have to calculate the symbols scale, would be to remove the symbols from the mapDisplayObject so they're no longer a child and instead put symbol placeholders. Then match each symbol's x and y to each place holder, using localToGlobal...
If your children are not scaled or skewed or rotated you can iterate all of them and set transformation matrix to 1/parentScale. Something like:
for each (var child:DisplayObject in parent) {
var matrix:Matrix = child.transform.matrix;
matrix.a = 1/parentScale;
matrix.d = 1/parentScale;
child.transform.matrix = marix;
}

localToGlobal/globalToLocal AS3 confusion

I want to move a display object from one container to another, but have it appear in the same place on screen.
I thought I'd understood this years ago, but the following does not work:
function moveToNewContainer(obj:DisplayObject, newParent:DisplayObjectContainer):void {
var pos:Point = new Point(obj.x, obj.y);
var currentParent:DisplayObjectContainer = obj.parent;
pos = currentParent.localToGlobal(pos);
currentParent.removeChild(obj);
newParent.addChild(obj);
pos = newParent.globalToLocal(pos);
obj.x = pos.x;
obj.y = pos.y;
}
This doesn't position the object in the same place as I would have expected.
Does anyone know what I am doing wrong, please?
Thanks,
James
Using localToGlobal/globalToLocal and setting the x and y properties like you showed calculates the correct position for the object in its new parent, but does not adjust for other aspects of the transformation such as scaling or rotation. In other words, the object's registration point will indeed remain in the same place, but the object may be rotated, scaled, or sheared differently.
The solution to your problem will need to take into account the transform.concatenatedMatrix properties of the old and new parents--you'll need to multiply the object's transformation matrix by one and then by the inverse of the other, or something along those lines. Leave a comment if you need help working out the math.
There is nothing wrong with your code, provided that both containers have no transformations applied. If your clips are scaled, rotated, etc.. you need to handle that in addition to the coordinate space transformations that localToGlobal and globalToLocal do.
You have to check if your containers are actually placed on stage. If your new container isn't added as a child to stage, function globalToLocal fails, just because it doesnt know how to correctly calculate that data.

Difference between defining sprite's x, y coordinates, and painting object in some location

I have a task:
I need to place about 100 sprites on one canvas (with prepared grid on it). I need to place them as invisible (circles) stones, on the board, and make visible only on mouseover.
The problem I come across is following, I can't place those objects accurately into the nodes on the grid.
E.g.
if I define stones (it's just a sprite, as I said earlier) this way:
var stone:StoneSprite = new StoneSprite();
stone.x = this.x + 2*cellWidth;
stone.graphics.beginFill( 0x000000 );
stone.graphics.drawCircle(stone.x , this.y + cellWidth, cellWidth/3 );
stone.graphics.endFill();
rawChildren.addChild(stone);
They don't sit on the node...
See image:
http://img.skitch.com/20091014-kuhfyjeg1g5qmrbyxbcerp4aya.png
And if I do it this way:
var stone:StoneSprite = new StoneSprite();
stone.graphics.beginFill( 0x000000 );
  stone.graphics.drawCircle(this.x + 2*cellWidth , this.y + cellWidth, cellWidth/3 );
  stone.graphics.endFill();
rawChildren.addChild(stone);
The stone is displayed correctly in the grid node... See image 2:
http://img.skitch.com/20091014-f595tksjxramt98s7yfye591bh.png
So I wonder what is the difference between these 2 approaches.
Also, I think I need to pass correct coordinates to the stone class... In case I would like to change some properties of the stone object. E.g. visibility, or radius.
Could you please suggest, what's wrong in defining coordinates as stone.x, stone.y
How to fix the problem with incorrect positioning.
Would really appreciate ideas about the problem, I am trying to solve for so long :(
Assume x & y are 30 and cellWidth is 30.
First Example:
stone.x = 30 + 60; //90
drawCircle(90, 60, 10);
This means if you were to draw a rectangle around your circle, it would be at [170,50]. (x,y).
Second Example:
stone.x = 0;
drawCircle(90, 60, 10)
This means the rectangle around your circle is at [80,50];
In the first example, you are moving the sprite to position x==90. Then drawing a circle whose center is at x==90 inside the sprite. So relative to this, you're at x==180. But because a circle's x,y coords are the center, subtract 10 for the radius to get the boundary x position.
In the second example, the sprite defaults to position x==0 relative to this and you're drawing the circle inside the sprite at position x==90. (therefore it begins at x==80).
I am not sure what's causing the issue - might be some padding induced by the container - can't say without testing. But I believe that adding a Sprite (say board) to canvas.rawChildren and using it as the parent for the grid and stones would fix the issue.