Rotating one sprite around another in Phaser using Point.rotate

So far this week I have been expanding my content on Phaser ce with the Point Class. This is a very helpful Class that helps with common issues that developers run into when dealing with points in a 2d space. In this post I will be writing about the Point.rotate methods, that can be used to rotate a sprite around another sprite, or any object that has exposed x, and y properties for that matter. This should be fun, so lets get into it.

1 - What to know before continuing

This is a post on the Point.rotate static method, and it’s Point Class prototype equivalent method in the HTML 5 game framework know as phaser ce. This is not a getting started post on Phaser in general, if you are new to phaser you might want to start with a getting started post on phaser, and brush up more on more general concepts with phaser, before getting into more specific posts like this. Also In this post I am using phaser 2.x, and not the newer phaser 3.x.

2 - Some very basic examples of the Phaser.Point.rotate method

So lets start off by playing around with a few very simple examples of the Point.rotate method in both it’s static, and prototype form. Once we have a good feel for how to work with this method we can get into some more interesting examples with it.

2.1 - Using the static method form of Point.rotate

So like many of the methods in the Point class, they can be used in both a static, and prototype form, out of the gate, without having to do something fancy with call. In most cases I will want to use the static form of the method, because there are a lot of things in Phaser that are not instances of Phaser.Point, but do have exposed x, and y properties in the object, and I will want to use those objects with these methods.

The Phaser.Point.rotate methods works by first giving the object that I want to rotate around another object, I then give the x, and y values of the point that I want this object to rotate around. Then I give the angle in radians or degrees depending on the state of the next argument that is a boolean to set to degrees or radians. Then at least the final sixth argument is the distance between the two points.

So then an example of the static from of Point.rotate might look like this.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// objects for centerPoint, and a thing that
// I want to rotate around it.
var thing = {
x: 100,
y: 100
},
center = {
x: 0,
y: 0
};
// Using the static method
Phaser.Point.rotate(thing, center.x, center.y, 45, true, 100);
console.log(Math.floor(thing.x), Math.floor(thing.y)); // 0 100

So then the static method version is great for working with any kind of object that has exposed x, and y values. No need to use the prototype version with call or apply.

2.2 - Using the prototype form of the method

So then there is also the prototype version of the same method, that works the same way as the static method, but I do not have to give the object that I want to rotate as the first argument, because that is the instance of Point that I am calling the method off of.

1
2
3
4
5
6
7
8
9
// objects for centerPoint, and a thing that
// I want to rotate around it.
var thing = new Phaser.Point(100, 100),
center = new Phaser.Point(0, 0);
// Using the prototype method
thing.rotate(center.x, center.y, 45, true, 100);
console.log(Math.floor(thing.x), Math.floor(thing.y)); // 0 100

This method can also be used in the same manor as the static method if I use Function.call. However why bother with that when I have the static version there before hand?

3 - Some examples using sprites

So when it comes to using this method in an actual project of some kind it will of course involve a relationship between two or more sprites. In this section I will be covering a few examples that involving doing just this.

3.1 - The main game object, and the boot state

So I started off my project by doing the usual call to Phaser.Game to create an instance of a phaser game object. I often do not pass a default state object, and instead add states to the game via the game.state.add method. This allows me to set up a complex project consisting of many states, and then start a main boot state when, and where I want to.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
var game = new Phaser.Game(320, 240, Phaser.AUTO, 'gamearea');
// make a sprite sheet, and start sprites state
game.state.add('boot', {
create: function () {
// sprite sheet generated by canvas
var canvas = document.createElement('canvas'),
ctx = canvas.getContext('2d');
canvas.width = 64;
canvas.height = 32;
// blue frame
ctx.fillStyle = '#0000ff';
ctx.fillRect(0, 0, 32, 32);
// red frame
ctx.fillStyle = '#ff0000';
ctx.fillRect(32, 0, 32, 32);
game.cache.addSpriteSheet('sheet-block', null, canvas, 32, 32, 2, 0, 0);
game.state.start('sprites_1');
}
});

So in the boot state I create a simple sprite sheet using a canvas element, which is my preferred method when it comes to simple examples like these. Once my sheet is cached, I then start the first state for the first example. The additional states, helper methods and so forth will be defined later in my project, as this boot state will not be stared until everything is all set.

3.2 - A mkSprites method

For these examples I made a helper method that will create some sprites using the sprite sheet I made in the boot state.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// make sprites function
var mkSprites = function () {
var sprite,
x,
y,
cx = game.world.centerX,
cy = game.world.centerY;
// thing
x = cx + 100 - 16;
y = cy - 16;
sprite = game.add.sprite(x, y, 'sheet-block', 0);
sprite.name = 'thing';
// center
x = cx - 16;
y = cy - 16;
sprite = game.add.sprite(x, y, 'sheet-block', 1);
sprite.name = 'center';
};

This method helps to keep me from repeating code for each example in which I just want two sprites to work with.

3.3 - A state switcher

I then have another helper method that will set up some simple controls that will cycle the examples each time the canvas is souched or clicked.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// switch states
var stateSwitcher = function () {
game.input.onDown.add(function () {
demoNum = Number(game.state.current.split('_')[1]);
demoNum += 1;
demoNum = Phaser.Math.wrap(demoNum, 1, 4);
game.state.start('sprites_' + demoNum);
});
};

3.4 - Example 1 - just rotate around another sprite

So for the first example I just wanted to have one sprite rotate around another. I just call my helper methods in the create method of the state. Once I have everything set up, I then just grab some references to the sprites using the World.getByName method, and use Phaser.Point.rotate to rotate the ‘thing’ sprite, around the ‘center’ sprite in the update method of the state.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// sprites1 state in which the thing sprite, just rotates around center
game.state.add('sprites_1', {
create: function () {
mkSprites();
stateSwitcher();
},
update: function () {
var thing = game.world.getByName('thing'),
center = game.world.getByName('center');
Phaser.Point.rotate(thing, center.x, center.y, 1, true, 100);
}
});

3.5 - Example 2 - Heart shaped pattern with dynamic distance

So In this example I now experimented with moving the ‘center’ sprite, and making the distance of the rotation variable, by adding a distance property to the data object of the sprite. If you are not familiar with the data object of a sprite, it is simply the standard official way of appending some project specific properties to a sprite.

In this example I am also using the Phaser.Point.angle method, another great method that can be used to find the angle between two points. I am then using the angle to influence the distance variable of the rotation.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
// sprites2 state, heart shaped pattern of thing rotating around
// center, and center is on the move
game.state.add('sprites_2', {
create: function () {
var thing;
mkSprites();
stateSwitcher();
thing = game.world.getByName('thing');
thing.data.dist = 50;
},
update: function () {
var thing = game.world.getByName('thing'),
center = game.world.getByName('center'),
angle = Phaser.Point.angle({
x: thing.x + 16,
y: thing.y + 16
}, {
x: center.x + 16,
y: center.y + 16
}),
per = Math.abs(angle) / Math.PI;
thing.data.dist = per * 75 + 50;
// rotate
Phaser.Point.rotate(thing, center.x, center.y, 10, true, thing.data.dist);
center.x += 2;
center.x = Phaser.Math.wrap(center.x, -125, game.world.width + 125);
}
});

Notice that I am also using the Phaser.Math.wrap method, another great method in phaser that is useful for setting up a game world in which a display object wraps back around to the beginning when crossing a boundary.

3.6 - Example 3 - A vanilla js alternative

So there is not much need to bother with any kind of vanilla js alternative to Point.rotate, unless for some reason you need to. Doing so is not too hard, you just need to have an understanding of Math.cos, and Math.sin. These trigonometry functions come in handy for situations like this.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
// sprites3 is a vanilla js solution
game.state.add('sprites_3', {
create: function () {
var thing;
mkSprites();
stateSwitcher();
thing = game.world.getByName('thing');
thing.data = {
a: 0,
f: 0,
fMax: 50,
dist: 50
};
},
update: function () {
var thing = game.world.getByName('thing'),
center = game.world.getByName('center');
// some variables that have to do with
// the current state of a movement
var per = thing.data.f / thing.data.fMax,
bias = Math.abs(per - 0.5) / 0.5,
offset = Math.PI;
// set angle based on the above variables
thing.data.a = Math.PI - (Math.PI / 2) + Math.PI * bias + offset;
// set the x, and y position of thing, relative to center
// using Math.cos, and Math.sin, as well as the angle found above,
// and a distance variable
thing.x = center.x + Math.cos(thing.data.a) * thing.data.dist;
thing.y = center.y + Math.sin(thing.data.a) * thing.data.dist;
thing.data.f += 1;
thing.data.f = Phaser.Math.wrap(thing.data.f, 0, thing.data.fMax - 1);
center.x += 2;
center.x = Phaser.Math.wrap(center.x, -125, game.world.width + 125);
}
});
game.state.start('boot');

4 - Conclusion

The Point.rotate method is just one of many useful methods in the point class that comes in handy when trying to make quick work of these kinds of things, so one can move on with what really matters with there project.