Cocos2d-x: CCmoveto move to opposite position - cocos2d-x

I have a lot of sprites. Then i use CCtouchMoved to move that sprites to a position ccp(0,0);
But when i run, theare are some sprite move to correct position, and some are move to the opposite of the position a want it to move to.Here is my function
void sample::moveto(CCSprite* sprite, CCPoint pointToMove){
CCFiniteTimeAction* moveTo = CCMoveTo::create(0.5f, pointToMove);
CCFiniteTimeAction* scale = CCScaleTo::create(0.5f, 0.0f);
sprite->runAction(scale);
CCFiniteTimeAction* finishMove = CCCallFuncN::create(this,
callfuncN_selector(NoteScene::swallowUpKeywordFinish));
sprite->runAction(CCSequence::create(moveTo,finishMove,NULL));
}
Any help will be appreciate

Use sprite->stopAllActions(); before starting new actions.

Related

setCenter() Method is not properly centering sprite texture on box2d fixture

The past few days I've been trying to figure out a display bug I don't understand. I've been working on a simple 2d platformer with box2d and orthogonal Tiled maps. So far so good, the physics work and using the b2d debug renderer I can assert proper player fixture and camera movement through the level.
Now next step I've tried to load textures to display sprites instead of debug shapes. This is where I stumble. I can load animations for my player body/fixture, but when I use the setCenter() method to center the texture on the fixture it is always out of center.
I've tried approaches via halving texture witdths and heights hoping to center the texture on the player fixture but I get the exact same off position rendering. I've played aorund with world/camera/screen unit coordinates but the misalignement persists.
I'm creating the player in my Player class with the following code.
First I define the player in box2d:
//define player's physical behaviour
public void definePlayer() {
//definitions to later use in a body
BodyDef bdef = new BodyDef();
bdef.position.set(120 / Constants.PPM, 60 / Constants.PPM);
bdef.type = BodyDef.BodyType.DynamicBody;
b2body = world.createBody(bdef);
//Define needed components of the player's main fixture
FixtureDef fdef = new FixtureDef();
PolygonShape shape = new PolygonShape();
shape.setAsBox(8 / Constants.PPM, 16 / Constants.PPM); //size of the player hitbox
//set the player's category bit
fdef.filter.categoryBits = Constants.PLAYER_BIT;
//set which category bits the player should collide with. If not mentioned here, no collision occurrs
fdef.filter.maskBits = Constants.GROUND_BIT |
Constants.GEM_BIT |
Constants.BRICK_BIT |
Constants.OBJECT_BIT |
Constants.ENEMY_BIT |
Constants.TREASURE_CHEST_BIT |
Constants.ENEMY_HEAD_BIT |
Constants.ITEM_BIT;
fdef.shape = shape;
b2body.createFixture(fdef).setUserData(this);
}
Then I call the texture Region to be drawn in the Player class constructor:
//define in box2d
definePlayer();
//set initial values for the player's location, width and height, initial animation.
setBounds(0, 0, 64 / Constants.PPM, 64 / Constants.PPM);
setRegion(playerStand.getKeyFrame(stateTimer, true));
And finally, I update() my player:
public void update(float delta) {
//center position of the sprite on its body
// setPosition(b2body.getPosition().x - getWidth() / 2, b2body.getPosition().y - getHeight() / 2);
setCenter(b2body.getPosition().x, b2body.getPosition().y);
setRegion(getFrame(delta));
//set all the boolean flags during update cycles approprietly. DO NOT manipulate b2bodies
//while the simulation happens! therefore, only set flags there, and call the appropriate
//methods outside the simulation step during update
checkForPitfall();
checkIfAttacking();
}
And my result is
this, facing right
and this, facing left
Update:
I've been trying to just run
setCenter(b2body.getPosition().x, b2body.getPosition().y);
as suggested, and I got the following result:
facing right and facing left.
The sprite texture flip code is as follows:
if((b2body.getLinearVelocity().x < 0 || !runningRight) && !region.isFlipX()) {
region.flip(true, false);
runningRight = false;
} else if ((b2body.getLinearVelocity().x > 0 || runningRight) && region.isFlipX()) {
region.flip(true, false);
runningRight = true;
}
I'm testing if either the boolean flag for facing right is set or the x-axis velocity of my player b2body has a positive/negative value and if my texture region is already flipped or not and then use libGDX's flip() accordingly. I should not be messing with fixture coords anywhere here, hence my confusion.
The coordinates of box2d fixtures are offsets from the position, the position isn't necessarily the center (although it could be depending on your shape definition offsets). So in your case i think the position is actually the lower left point of the box2d polygon shape.
In which case you don't need to adjust for width and height because sprites are also drawn from bottom left position. So all you need is ;
setPosition(b2body.getPosition().x , b2body.getPosition().y );
I'm guessing you flip the box2d body when the player looks left the position of the shape is now bottom right so the sprite offset of width/2 and height/2 is from the bottom right instead. So specifically when you are looking left you need an offset of
setPosition(b2body.getPosition().x - getWidth() , b2body.getPosition().y );
I think looking right will be fixed from this, but i don't know for sure how you handle looking left in terms of what you do to the body, but something is done because the offset changes entirely as shown in your capture. If you aren't doing some flipping you could add how you handle looking right to the question.
EDIT
It seems the answer was that the sprite wasn't centered in the sprite sheet and this additional space around the sprite caused the visual impression of being in the wrong place (see comments).

How to stop a sprite at exact touchdown position coordinates

I want to move a sprite (which happens to be a Rectangle) from any position of the screen and make it stop at exactly the touched position of the screen. Now, I can stop my sprite already, but not at the exact touched position. I cannot find a good way of doing this without sacrificing either accuracy or risking the sprite to not stop at all.
Naturally - the problem arises because the current position is Float, so that Vector will never (or extremely rarely) have the exact same coordinates as the touch point (which is an int).
In the code below, I stop my sprite by simply checking the distance between the current position and the target position (i.e. the touched position Vector3), like so if (touch.dst(currentPsition.x, currentPosition.y, 0) < 4).
For example, if the sprite is at position (5,5) and I touch the screen at (100,100), it will stop at like (98.5352,96.8283).
My question is, how do I stop the sprite at exactly the touch position, without having to approximate?
void updateMotion() {
if (moveT) {
movement.set(velocity).scl(Gdx.graphics.getDeltaTime());
this.setPosition(currentPosition.add(movement));
if (touch.dst(currentPosition.x, currentPosition.y, 0) < 4)
moveT = false;
}
}
public void setMoveToTouchPosition(boolean moveT) {
this.moveT = moveT;
this.touch = new Vector3(Gdx.input.getX(), Gdx.input.getY(), 0);
GameScreen.getCamera().unproject(touch);
currentPosition = new Vector2(this.x, this.y);
direction.set(new Vector2(touch.x, touch.y)).sub(currentPosition).nor();
velocity = new Vector2(direction).scl(speed);
}
Of course sprite can't move smoothly to touch position and then stop in exactly the same position because of many reasons. Just change this
if (touch.dst(currentPosition.x, currentPosition.y, 0) < 4)
moveT = false;
to this
if (touch.dst(currentPosition.x, currentPosition.y, 0) < 2) {
currentPosition.x = touch.x;
currentPosition.y = touch.y;
moveT = false;
}
A quick yet acceptable solution to this could be the use of the Rectangle class. Considering you make a Rectangle surrounding the moving entity and constantly update it's bounds based on its current location, it's texture width, and it's texture height. You could stop it when it overlaps with the "target position". If you do this you guarantee yourself that it will stop exactly at that position. For example:
Texture entityTexture = new Texture("assets/image.png");
Rectangle entityBounds = new Rectangle();
entityBounds.set((currentPosition.x, currentPosition.y, entityTexture .getWidth(), entityTexture .getHeight()));
Rectangle targetBounds = new Rectangle();
targetBounds.set((targetPosition.x, targetPosition.y, 1, 1)); // make width and height 1 by 1 for max accuracy
public void update(){
// update bounds based on new position
entityBounds.set((currentPosition.x, currentPosition.y, entityTexture.getWidth(), entityTexture.getHeight()));
targetBounds.set((targetPosition.x, targetPosition.y, 1, 1));
if(entityBounds.overlaps(targetBounds)){
// do something
}
}

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

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...

Camera movement in AS3

OK so i have a character that moves with the mouse. I need it to stay in the center of the screen(kind of like a platformer game). I can't figure out how to access the camera and move it. (Note: I have tried Vcam and moving all of the other objects but Vcam makes the file slow or something [or so i have heard] and moving the other objects in kind of like cheating [and for my needs is insufficient]) I don't have any code because i don't know where to start. Maybe someone can point me into the right direction.
Thanks,
Thor
One way is to store everyhting in one DisplayObject and then move that single object based on the camera movement. Instead of moving the camera, move the main container the opposite direction of the camera. I'm not sure why you seem to suggest a strategy like this is "cheating" as it is a perfectly suitable way to doing this.
This is my previous answer on a similar question found here.
What I do here is:
Create a Map class with a property camera which is another custom class MapCamera.
The MapCamera has five properties:
_x
_y
map - a reference to the instance of Map owning this MapCamera
offsetX
offsetY
The offset values represent the x and y spacing from the left and top edges of the screen, which should be set to half of the stage width and height so that the camera will centre on the stage correctly.
The _x and _y properties are private, and have getters and setters.
The getters are pretty basic:
public function get x():Number{ return _x; }
public function get y():Number{ return _y; }
The setters are where the viewport will be altered, like so:
public function set x(n:Number):void
{
_x = n;
map.x = -(_x + offsetX);
}
public function set y(n:Number):void
{
_y = n;
map.y = -(_y + offsetY);
}
From here, you add your children into the Map container and then can simply go:
map.camera.x = player.x;
map.camera.y = player.y;
Which will cause the player to always be in the centre of the screen.
Your camera is only a vector that modifies position of all renderable objects.
myMovieClip.x = movingClipPosition.x + camera.x
So if the camera.x is moved to the right, this will make the object move the left, giving the impression of a "camera".