Anna

melonjs zooming and panning

Recommended Posts

Hi,

Yes, zooming and panning are just transformation functions. This can be done by carefully controlling the renderer matrix at the correct points in your scene hierarchy.

For example, if you have a HUD element in your scene, you probably don't want the zoom function to affect it. If you use a Container element that is a sibling of the HUD and apply your transformations to that container, then everything inside of it will inherit those transformations. Scale/translate the renderer at the top of the Container's draw method, draw all of its children, and reset the transformation matrix on the way out of the draw method.

Something like that, anyway. It's actually incredibly simple.

Share this post


Link to post
Share on other sites

it's actually as simple as applying any transformation to a container, that would be in this case the "world" container, or a child container if you want  (as @parasyte was saying) split the level itself from the HUD.

 

me.Container, extends me.Renderable, and therefore has the following property http://melonjs.github.io/melonJS/docs/me.Renderable.html#currentTransform

Share this post


Link to post
Share on other sites

there is an example that add a zooming effect to the viewport here :

https://github.com/melonjs/melonJS/issues/399

but it then zoom literally everything.  As we were saying before the same can be done to a me.Container, as they both implement the currentTransform property : http://melonjs.github.io/melonJS/docs/me.Renderable.html#currentTransform

it's basically a matrix object, so you you can get crazy as much as you want with it : http://melonjs.github.io/melonJS/docs/me.Matrix2d.html

 

 

 

Share this post


Link to post
Share on other sites

i do agree though that we should have a small example somewhere showcasing all that. I 'll check to add one, in the mean time you can experiment on your side, it's really straightforward

Share this post


Link to post
Share on other sites

Hi, if I do it like described in your example:

keyPressed: function (action /*, keyCode, edge */) {
        
        if (action === "add") {
            this.scale(+0.02);
            return;
        }

        if (action === "substract") {
            this.scale(-0.02);
            return;
        }
},

scale: function(scale) {
        game.data.scale += scale;
        game.data.scale = game.data.scale.round(2);

        var viewport = me.game.viewport;
        viewport.currentTransform.translate(
            viewport.width * viewport.anchorPoint.x,
            viewport.height * viewport.anchorPoint.y
        );

        viewport.currentTransform.scale(game.data.scale);
        viewport.currentTransform.translate(
            -viewport.width * viewport.anchorPoint.x,
            -viewport.height * viewport.anchorPoint.y
        );
    },

It looks like this:

58a3191e977c2_Screenshot(1).png.9b61108cf30ecc411a342b9f273ed797.png

Share this post


Link to post
Share on other sites

I needed the zoom as well today and came across this post. I copied in your code above and the plan didn't really work right away....simple quick fix for me was to use a constant value of 1.02 for zoom out and .98 for zoom in.

Seems like, from the partial code above, your idea is to keep a scale variable which you are incrementing and then applying. Which doesnt seem correct becuase [viewport.currentTransform.scale(game.data.scale) ] doesn't set a scale value it just multiplies the current values in the transform matrix.

Hopefully that helps....maybe not. 

 

 

Share this post


Link to post
Share on other sites
1 hour ago, chris.daniel said:

[viewport.currentTransform.scale(game.data.scale) ] doesn't set a scale value it just multiplies the current values in the transform matrix.

 

 

indeed,  our scale function (as for all matrix functions) follows the standard one :  https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/scale

Share this post


Link to post
Share on other sites

@obiot @Parasyte

My viewport.move() and viewport.moveTo() functions aren't working.

 Correct me if I'm wrong, but after looking at the Melon 2.1.1 me.Viewport code (haven't upgraded yet), it seems if I follow the player: 

me.game.viewport.follow(this.pos, me.game.viewport.AXIS.BOTH); // set inside the player entity class

the follow function in melon sets this.target to the player, then calls this.updateTarget(), which is called on each frame, which sets this._followH(this.target), this._followV(this.target).

Therefore it's constantly overwriting any coordinates you set in viewport.moveTo(). Is the idea that I somehow set this.target = null, then move the camera, then reset viewport.follow back on the player?

Like:

me.game.viewport.follow(null, null);
viewport.moveTo(100, 100); // I'll add a timer on this to slowly pan
me.game.viewport.follow(player.pos, me.game.viewport.AXIS.BOTH);

 

Share this post


Link to post
Share on other sites

 

Correct, if the entity the camera is following is constantly moving, calling moveTo won't basically have any effect....  but calling `me.game.viewport.follow(null, null)`; won't work as the method won't assign anything if the give first argument is not an instance of a renderable or a vector object.

unfortunately we do not have a unfollow() method (i see it could be usefull though), but as a hack you can manually unassign the private target property by doing `me.game.viewport.target = undefined;`

that should do the trick, and you can then move the viewport where you want.

Share this post


Link to post
Share on other sites

@obiot lol I already tried that exact code. 

I'm trying to pan the view (camera) across to a certain location of interest, slowly, for beautiful cinematics.

To do this, I've tried using viewport.moveTo(x, y); at an interval.

The problem is on the initial call of moveTo - it sets the viewport at the location of the player, but the viewport isn't centered on the player, rather it's top left is the location of the player.

To fix this I added

            var x = playerMoveCoords.x - viewport.width/2;
            var y = playerMoveCoords.y - viewport.height/2;

It's still a bit jerky though. Any thoughts?


			var viewport = me.game.viewport;
			viewport.unfollow();
			var playerCoords = $.extend({}, game.state.getPlayer().coordinates());
			var playerMoveCoords = $.extend({}, game.state.getPlayer().coordinates());
			var newLocX = playerCoords.x += 200;
			var newLocY = playerCoords.y += 200;
			var x = playerMoveCoords.x - viewport.width/2;
			var y = playerMoveCoords.y - viewport.height/2;;

			var myInt = me.timer.setInterval(function() {

				if (x < newLocX) {
					x++;
				} else {
					x--;
				}
				if (y < newLocY) {
					y++;
				} else {
					y--;
				}

				viewport.moveTo(x, y);

				if (x === newLocX && y === newLocY) {
					me.timer.clearInterval(myInt);
					myInt = null;
				}
			}, 50);

 

Share this post


Link to post
Share on other sites

I have some really old code that does non-linear interpolations (tweening) between camera positions. Some of it should still be usable. You can see it in action on the Neverwell Moor title screen, and the code is available here: https://github.com/blipjoy/nm-prototype/blob/gh-pages/js/objects/screens.js#L349-L384 Maybe it will help you out.

Share this post


Link to post
Share on other sites

@Growler I actually wrote a crazy bit of logic that can animate tile layers for that... Each frame is on its own layer, and the animation just cycles the layer visibility. The code for that is here: https://github.com/blipjoy/nm-prototype/blob/gh-pages/js/objects/screens.js#L43-L55 There are better ways to do this now that melonJS and Tiled both support tile animations. But back then, this was a really impressive feat.

BTW the original windmill assets are available here: https://opengameart.org/content/lpc-cnilsson

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now


  • Recently Browsing   0 members

    No registered users viewing this page.