symof Posted June 16, 2016 Share Posted June 16, 2016 var game = new Phaser.Game(1024, 600, Phaser.auto, 'phaser-example', { preload: preload, create: create, update: update, render: render }); var result = 'Press a key'; function preload() { //load assets game.load.image("single_turret","./img/single_turret_64x64.png"); game.load.image("mouse","./img/mouse.png"); } function create() { //start physics game.physics.startSystem(Phaser.Physics.P2JS); single_turret = game.add.sprite(400,300,'single_turret'); mousep = game.add.sprite(50,50,'mouse'); //enable psysics on all items and enable debugged game.physics.p2.enable([single_turret,mousep], true); mousep.body.setCircle(4); mousep.body.kinematic = true; single_turret.body.setCircle(4); single_turret.body.kinematic = true; } function update() { } function render(){ game.debug.text(result, 32, 32); mousep.body.x = game.input.x; mousep.body.y = game.input.y; lookAtObject(single_turret, mousep, 0.005); } function lookAtObject(obj, target, rotspeed){ var angle = Math.atan2(target.body.y - obj.body.y, target.body.x - obj.body.x); result = obj.body.rotation + '**'+ (angle + game.math.degToRad(90))+ '**'+obj.body.angle; obj.body.rotation = angle + game.math.degToRad(90); } The code above rotates the "turret" to always be pointed towards the mouse so that it can fire at the mouse position. The code works, but I want to add a rotation speed to it, however I can't figure out how to code that in. The lookAtObject() function is where I have the problem. function lookAtObject(obj, target, rotspeed){ var angle = Math.atan2(target.body.y - obj.body.y, target.body.x - obj.body.x); result = obj.body.rotation + '**'+ (angle + game.math.degToRad(90))+ '**'+obj.body.angle; if (obj.body.rotation <= angle + game.math.degToRad(90)){ obj.body.rotation += rotspeed; }else{ obj.body.rotation -= rotspeed; } } This statement does not work as intended because of how p2js works, so when It gets at ( -x , 0) the radians go from -1.5 to 4.7 and the rotation will reverse. I am really stumped atm, so any ideas on how to approach this? Quote Link to comment Share on other sites More sharing options...
zeke_chan Posted June 23, 2016 Share Posted June 23, 2016 Hi symof, Try this out: function lookAtObject(obj, target, rotspeed){ var angle = Math.atan2(target.body.y - obj.body.y, target.body.x - obj.body.x); var da = angle - obj.body.rotation; if (da > Math.PI) { da -= game.math.PI2; } else if (da < -Math.PI) { da += game.math.PI2; } result = (angle - obj.body.rotation) + " : " + da; if (da < 0){ obj.body.rotation -= rotspeed; } else { obj.body.rotation += rotspeed; } if (obj.body.rotation > Math.PI) { obj.body.rotation -= game.math.PI2; } else if (obj.body.rotation < -Math.PI) { obj.body.rotation += game.math.PI2; } } Here's the explanation. At line 3: var da = angle - obj.body.rotation; We're getting the difference between the angle of the mouse compared to the target and the target's current rotation. If you were to output the result of da right after line 3, you would get a value of -4 or +4 when you attempt to rotate more than 180 degrees. This happens especially when you cross the 180 degree rotation point that turns into -180 degrees. As a result you get the values constantly jumping between a positive and negative value. I'm guessing you would already know this. The value of PI is 3.14159265359 and this represents 180 degrees. The top half goes from 0 to -180 degrees while the bottom goes from 0 to 180 degrees like so: If the difference in angle happens to be more than 180 degrees or more than the value of PI, your sprite ends up rotating in the wrong direction. That's currently happening with your code. That's where this part comes in: if (da > Math.PI) { da -= game.math.PI2; } else if (da < -Math.PI) { da += game.math.PI2; } The first if checks for counter clockwise movement. The else if checks for clockwise movement. Let's look at the da < -Math.PI condition. Before you cross the 180 degree line: When you cross the 180 degree line: The arrow indicates the direction your sprite rotates in. Which is not what we want. To correct it we need to offset the result of da by 360 degrees. That's where the da += game.math.PI2 or da -= game.math.PI2 part comes in. The result looks like this now: Make sense?? Okay, the last part here: if (obj.body.rotation > Math.PI) { obj.body.rotation -= game.math.PI2; } else if (obj.body.rotation < -Math.PI) { obj.body.rotation += game.math.PI2; } This part is crucial. Missing it out would make your sprite rotate correctly only for one 360 degree turn. You can try leaving it out and rotate more than 2 turns and you'll see what I mean. To keep the values and calculations correct, we need to ensure that when the sprite crosses the 180 degree line, we need to reset it back to its correct value. Using the attached image example above, let's say the sprite has rotated towards the mouse cursor. Assume the value of obj.body.rotation = 4. We need to correct that value so it doesn't keep adding up if the sprite continues rotating clockwise. Looking at the code above, the correction is the same as what we did for the da variable. Now you sprite can rotate as much as it wants without causing any problems. Let me know if you need further clarification. symof and mattstyles 2 Quote Link to comment Share on other sites More sharing options...
dimumurray Posted June 26, 2016 Share Posted June 26, 2016 I think you can simplify things a bit by using the vector dot product to find the shortest angle of rotation and then the vector cross product to find the direction of rotation (CW or CCW). You'll eliminate all those checks for direction. I touched on the topic in an older thread : But the best resource I've found on this and related topics is the following : http://natureofcode.com/book/chapter-6-autonomous-agents/ zeke_chan 1 Quote Link to comment Share on other sites More sharing options...
zeke_chan Posted June 27, 2016 Share Posted June 27, 2016 Thanks for sharing the link =) Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.