Jump to content

Sphere rotation


Recommended Posts

That can be an animation like any other. A set of sprites with the planet positions looping.

it's done via canvas animation in a div, but I need to make it only via Phaser without any divs at all

$(function(){        var pl_id = 'planet';	var image = new Image();	image.src = 'images/planets/1/1/map.jpg';        	var width = $('#'+pl_id).width();	var height = $('#'+pl_id).height();	var canvas = document.getElementById(pl_id);	var id = canvas.getContext("2d");	var newMoveWidth = 0;	var newMoveHeight = 0;	var drawPl = function(){	     id.clearRect(0, 0, width, height);	     id.drawImage(image, newMoveWidth, newMoveHeight, width, height, 0, 0, width, height); 	     if (newMoveWidth >= 899.5) newMoveWidth = 0; 	     else newMoveWidth = newMoveWidth+0.5; 	}        setInterval(drawPl, 50);  });
Link to comment
Share on other sites

You know you should really store those sin/cos values and not keep calculating them ;)

Nice demo, thanks

I think also you could probably just draw the texture straight, but simply give the Sprite a rotation. Also BitmapData move function lets you shift & wrap the texture . I'll try this with an alpha mask and post my results later

Link to comment
Share on other sites

Hi @weratius,


Not sure if you found a solution, but here is a jsFiddle that does what you want in Phaser: http://jsfiddle.net/chongdashu/eruvbu2t/


Thanks to @chg for pointing out the original source of the tutorial. Extremely useful.

Chong-U I keep seeing you around and I must say you seem like the most helpful person on the forums these days, almost too helpful but! It's only my opinion, but maybe you shouldn't be too eager to flat out write code for people (especially when they haven't even said where they are stuck).

On another note, if you do tweak your sample, I'd love to see you swap the Mercantor map for a Robinson one and have the latter divided into a bunch of thin strips that you parallax scroll with parallax to more accurately simulate a texture mapped sphere rotating

Link to comment
Share on other sites

@chongdashu, you'll need to scale the map height to the circle diameter.. check my example for that


@chg.. i reckon the best way to wrap the texture would be to write a shader. you could then do a device/performance check to check which method to use... ie fast machines that support WebGL shaders could use the full wrapped version. don't ask me how to do it though!

Link to comment
Share on other sites

Haha hey @chg, thanks for the kind words! I actually hang around the forums while procrastinating on doing work >.< 

Perhaps you are right, I'll be wary of doing code drops in cases where there's not much in the OP to begin with. :)

In this case, I actually was pretty intrigued to get that effect done. The tutorial you linked to was pretty interesting!


@jmp909: took a look at your demo. Much, much simpler. You are right that just rotating the sphere container itself makes things so much cleaner, easier, and better.

You seem to make really fun looking demos too.

Link to comment
Share on other sites

Me too. Just Interested in how to do it, and wanted to try an alternative method

I think also because I draw reduced size as a new bitmap, it then uses that smaller bitmap to shift around, which should improve performance. Really though you'd want to load an image at the maximum size you need to display to begin with.

Ironically your demo performs much faster on my iPad than mine does... It might be because sandbox is in a different mode though. I will have to do a fiddle then compare.

Link to comment
Share on other sites

I made a better performing version (than my sandbox example). it seems that bitmapdata moveH is slow on iOS



instead of move() i use copyRect() and a smaller target bitmap for the sprite (250x250)


what i do is this:


1) create a bitmap the size of my planet (250x250), then add this to my earth sprite. this is what we will finally copyRect to

2) create a bitmap that is a scaled down version of my map....625x250 high to match the planet diameter . using bitmap draw() to do the scaling

3) create a bitmap to use as a source to copy to the first bitmap. we copy the second scaled bitmap to this and then copy the first 250px of the map onto the end to allow for scroll wrapping

4) destroy the 2nd bitmap it is no longer needed

5) in my update loop i copyRect from an increasing x position, and then wrap the scroll when required



* you could avoid steps 2 to 4 by just starting with the texture below (the alpha section just shows the extra 250px portion i added with code)

* you could replace steps 2-4 by using copy() instead of draw() and copyRect(), instead providing the relevant scaling and transformation parameters to copy the various sections of the map. .. I'm just being lazy since draw() will scale for me...


in fact here's a version using copy() to scale, replacing steps 2-4 http://jsfiddle.net/znw7awmr/2/


Link to comment
Share on other sites

@chongdashu.. i learned a lot from my examples too! I like a good challenge :)


what I'm actually trying to work out is if we can do away with the mask and use blendmodes/alpha masking between the shadow and the texture. (although as mentioned before you don't want the shadow to rotate with the planet, so only good if it's staying at a fixed angle)


I'm also keen to know what's happening at a GPU level. I think with my 1st option on my last link (useScaledEarthBitmap), only the scaled-down map is used for shifting pixels around as it's essentially a separate bitmap from the original texture, and the TileSprite is just a 'viewport' to that new texture.

Link to comment
Share on other sites

Hmm tilesprite version is broken under iOS canvas mode :S

@Jmp909, can I ask you something?


If I want to move this object, I need to move a mask, it's shadow and also the sprite, of course...


I've done something like that:

        // some code here of planet's creation        var shadow = game.make.sprite(x, y, 'sphere');        shadow.anchor.set(0.5, 0.5);        somePlanet.shadow = shadow;               var mask = game.add.graphics(0, 0);        mask.beginFill(0xFF0000, 0.5);        mask.drawCircle(x, y, 140);        somePlanet.maska = mask;//and here is an animationanimatePlanets: function() {        for(var planet in createdPlanets) {            if(planet != null) {                //some Math, here I get rotatedX, rotatedY                createdPlanets[planet].planet.x = rotatedX;                createdPlanets[planet].planet.y = rotatedY;                createdPlanets[planet].planet.shadow.x = rotatedX;                createdPlanets[planet].planet.shadow.y = rotatedY;                createdPlanets[planet].planet.maska.x = rotatedX;                createdPlanets[planet].planet.maska.y = rotatedY;                createdPlanets[planet].nickName.x = rotatedX - 30;                createdPlanets[planet].nickName.y = rotatedY - 90;            }        }    }

Is it ok?


Thank you)

Link to comment
Share on other sites

i put the earth, mask and shadow into a "planet" group so i could avoid that issue and just move the group... also you don't really want to rotate the shadow (unless you're rotating it around the sun)


and i'm not sure you need to rotate the mask either if it's a circle

@Jmp909, I have put everything in group in such a method:

initPlanet: function(x, y, planetKey, angle, name, speed, radius, race) {        this.layers.ourPlanets = game.add.group();                var newW = (1200 / 300) * 200;        var newH = 200;                var earthBMD = game.make.bitmapData(newW, newH, 'earthBMD');        earthBMD.draw('map1', 0, 0, newW, newH);                        var somePlanet = game.add.sprite(x, y, earthBMD);        // somePlanet.angle = -15;        somePlanet.anchor.set(0.5, 0.5);                game.physics.arcade.enable(somePlanet, Phaser.Physics.ARCADE);        somePlanet.inputEnabled = true;        somePlanet.angle = angle;        somePlanet.name = name;        somePlanet.speed = speed;        somePlanet.radius = radius;        somePlanet.race = race;        somePlanet.earthBMD = earthBMD;                var shadow = game.make.sprite(x, y, 'sphere');        shadow.scale.set(0.47, 0.47);        shadow.anchor.set(0.5, 0.5);        somePlanet.shadow = shadow;                       var mask = game.add.graphics(0, 0);        mask.beginFill(0xFF0000, 0.5);                mask.drawCircle(x, y, 140);        somePlanet.mask = mask;                           this.layers.ourPlanets.add(somePlanet);        this.layers.ourPlanets.add(mask);        this.layers.ourPlanets.add(shadow);        this.layers.ourPlanets.mask = mask;        return somePlanet;    }

But when the somePlanet rotates and mask stands still with the shadow, I see a somePlanet only when it is on the mask's coords (once on each circle)


In other words I can't see planet at all when I don't change shadow's and mask's coords


Thank you

Link to comment
Share on other sites

can you do a jsfiddle?


what is 'ourPlanets'? that group should be a container for one planet only. 


in my example the 'planet' group contains my earth sprite, shadow and mask. it's to hold those 3 together as one unit. i don't put anything else into it... i could have eg called it 'earthGroup' not 'planet'


when you return somePlanet you're not returning the shadow and mask along with it.. although I see you do have a reference to them so i guess that's ok.


maybe you could return somePlanet still but when you want to move it around your solar system I would move the group that contains the planet, the shadow and the mask rather than move them all separately. 


i'm wondering why you have ourPlanets (plural).... it sounds like you are putting other planets in.


and i'd be wary of using custom keywords as a reference


also this doesn't seem right to me? you're trying to mask the planet and the group? you can only use the mask on one display object

somePlanet.mask = mask;this.layers.ourPlanets.mask = mask;
Link to comment
Share on other sites


  • Recently Browsing   0 members

    • No registered users viewing this page.
  • Create New...