Having trouble with zooming the view closer to the player

Hi!
I am new to cocos2d, but otherwise an experienced programmer.

In my project, I currently have a player sprite, that has a child sprite, in the middle of the view. The player sprite is moving around.
I have another sprite, Indicator, that follows the child sprite. I do this by

Indicator->setPosition(player->convertToWorldSpace(child->getPosition()));

This works just fine - Except when I try to zoom towards the player, using

this->setScale(3)

Using this command, my Indicator sprite goes berserk, and somewhat “amplifies” the movements of the child sprite, when before setting the scale of the scene (zooming), it worked just fine, and stayed on target. Once more, the indicator sprite is the one, that should be following the child sprite using convertToWorldSpace

Is there another way to zoom the view, that would work with convertToWorldSpace? Is there someway I could combat this “amplification” of motion that is caused by convertToWorldSpace, when the scene is scaled (zoomed)?

Thank you!

Edit: https://streamable.com/2fx0c5
Here is a video, that shows before scaling the scene, and after scaling the scene.
Notice the small yellow cross. That is the sprite that is following the child object of the player using convertToWorldSpace.

What type of graphics are the sprites?

Hi,
I am not exactly sure, what you mean by that question, but if you check out this vid (explained in edit in that post) https://streamable.com/2fx0c5 , you might get some answer?
I create them somewhat like this:

auto body = Sprite::create("Player.png");
	_player->body = body;
auto leg = Sprite::create("Leg.png");
        _player->leg = leg;
this->addChild(body);
body->addChild(leg);

“Player.png” and “Leg.png” are small PNG files.

So they are png. I see. Are you using vector art or pixel?

Pixel (raster), I don’t think it is even possible to store vector graphics in a png?
Anyway, I don’t think it should be relevant, what kind of graphics are used in a node, since the problem I’m facing has to do with the workings of convertToWorldSpace when the scene or layer is scaled.

Also could someone consider approving me now? This conversation is rather slow since all my comments need moderator approval.

Well bitmap doesn’t seem to scale well. I use vector as a png without issue.

I don’t see in the video the exact cause. If you zip your project I can at least test on macOS and see what I can see.

World space can sometimes be tricky. I don’t use it so often since I never seem to need to.

Anything useful in the console?

I approved this as well. You actually met the requirements already perhaps a logout and login would have helped. It should have triggered automatically

Thank you for your attention
Ok, the video might have been a bit tricky to understand the problem from. Anyway, the problem isn’t with the scaling of the sprites.
The project is currently a bit of a mess, but I’ll try to explain the problem the best I can:

Let’s say, that my goal is to create a 2D worm, that is composed of many sprites in a chain, for animation purposes. Each one of these sprites is a segment in the worm. Creating the segments would look something like this:

wormHead = Sprite::create("WormHead.png");

wormSegment1 = Sprite::create("WormSegment.png");
wormSegment2 = Sprite::create("WormSegment.png");
wormSegment3 = Sprite::create("WormSegment.png");

//Somewhere here we would set each segements positions so they form a horizontal chain.

//Create the worm
this->addChild(wormHead);

wormHead->addChild(wormSegment1);
wormSegment1->addChild(wormSegment2);
wormSegment2->addChild(wormSegment3);

Now let’s say we want to show some sprite on top of the worm, that follows the worm as it moves around. Let’s say, we want to add it on it’s tail.
What I would do here is this:

wormSprite = Sprite::create("wormSprite.png");
this->addChild(wormSprite);

Then in update function, where we for example, rotate the worm segments or move it around, I make the wormSprite sprite follow the tail of the worm like this:

wormSprite->setPosition(wormSegment2->convertToWorldPosition(wormSegment3->getPosition()));

Now if we run the application, we could see the worm and all it’s segments rotating or moving around, provided that kind of code is written.
We would also see wormSprite follow the tail of the worm - more specifically the transformations of wormSegment3.

However, all this breaks, when we try to scale the scene - e.g Zoom closer to the worm like this:

this->setScale(3);

Now we can see, that the wormSprite is moving around a lot faster and more erratically - as if it’s transformations have somehow been amplified due to the zooming.

Once more, if you check this video you can see exactly that happening at around 0:22

In that time, the view is zoomed, and the small yellow cross is moving a lot faster and doing larger movements than the player, which it followed just fine, when it wasn’t zoomed (beginning of the video)

Let’s just make sure we are using the same terms.

Scale changes the size of the Sprite. It doesn’t zoom, so to speak.

If you want to zoom, I’d consider changing the Camera.

I do see at :22 better now what you mean. Why do you need to convert to world space?

Let’s also ask @r101, they are really good with thoughts/solutions.

1 Like

Ok! My goal is to “Zoom”, and currently I can achieve that by scaling the scene or a layer that has all the sprites as it’s children. Perhaps there is a better way? I researched that Camera feature a bit before, but I thought it was only used for 3D environments? I will have to check that out a bit more, do you think it could be used to view and zoom in a 2D environment?
I think using the Camera will be the thing that ultimately solves the problem I am experiencing, if I can get it to work.
I need to convert to world space, because in my game I create a character using multiple sprites in an hierarchy, and I do some procedural animations with those sprites, and for calculating those animations it would be really helpful and more efficient to just get the world space coordinates of different sprites, instead of having to calculate all the transformations myself.

Thank you for the hint of using the Camera.
Using the default camera of the scene it was pretty easy to implement the zoom functionality, without screwing up the convertToWorldSpace() function. However, perhaps the unreliable behaviour of the convertToWorldSpace() - function when a parent or layer is scaled could be an issue for someone else in the future?

Perhaps you are right. I’ll put this in front of engineering.

Would you mind sharing your camera code for everyone to benefit in the future?

And I’d be happy to play your game when you are ready :slight_smile:

Sure!
So when I searched online on how people implemented zooming the view in a 2D scene, most people suggested doing it by scaling the scene or layer, that all the sprites are the children of. For example like this:

this->setScale(5) // Larger the value, the more you zoom

However, this caused some errors. A better way is to change the zPosition of the scene’s defaultCamera. This code might be slightly incorrect - doing it from memory:

scene->getDefaultCamera()->setPositionZ(300) // Smaller the value, the more you zoom
2 Likes

You can scale fov parameter for Perspective camera or zoomX and zoomY for Ortographic camera to perform scaling. It could be done in some Action to achieve smooth transition for instance.

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.