2
\$\begingroup\$

So I am doing a basic Asteroids clone as an intro to HTML5 canvas. I want to be able to rotate the main player while leaving the other objects on screen alone. Currently I am using transform and rotate on the canvas to allow the player to move, which works well.. but since it rotates the entire canvas it affects other shapes on screen. Is the general way to do this, to instead have each shape keep track of its own positions and perform manual transformations on the shape itself while leaving the canvas alone? Can I possibly give my shape a CSS class and control it on its own that way? Should I be using more than 1 canvas so that I can control rotations individually? Not sure what the accepted way is to handle multiple on screen images/shapes all with their own movement and rotation patterns simultaneously. My gut is telling me to have each shape track its own positions and just perform the math on the shape object itself... but then I would not be using the Canvas APIs rotate at all.

My app currently: https://jsfiddle.net/0o2pwLhn/

And a code snippet for the rotation:

// player draw test
    function drawShip() {
        ctx.beginPath();
        ctx.moveTo(shipStartX, shipStartY);
        ctx.lineTo(shipStartX + 8, shipStartY + 20);
        ctx.lineTo(shipStartX, shipStartY + 15);
        ctx.lineTo(shipStartX - 8, shipStartY + 20);
        ctx.lineTo(shipStartX, shipStartY);
        ctx.translate(shipStartX, shipCenterY);
        ctx.rotate((Math.PI / 180) * shipMoveDegree)
        ctx.translate(-shipStartX, -shipCenterY);
        ctx.stroke();
        ctx.closePath();
    }

Do the save() and restore() methods on the CanvasRenderingContext2D maybe come into play here? I have tried experimenting with it but havent gotten anywhere. I tried using save() and restore() but the issue is that once I restore, the player just gets set right back to its original spot.. since I am never actually changing its position... just rotating the entire canvas. The similar question here Is it possible to rotate an image on an HTML5 canvas, without rotating the whole canvas? explains how to use save() and rotate() which I think is on the right track.. but does not solve the issue I have because the player location is reset back to the start when the key is lifted, because I set the degrees back to 0 on keyup. How can I maintain the current rotation of a single shape regardless of the rest of the canvas?

\$\endgroup\$
  • 2
    \$\begingroup\$ Possible duplicate of Is it possible to rotate an image on an HTML5 canvas, without rotating the whole canvas? \$\endgroup\$ – Jay Jun 5 at 3:10
  • \$\begingroup\$ Yes I saw that. Problem is it doesnt solve this issue. I can save the state of the canvas, do the rotate, draw, and then restore. But once I get back in this method on the next frame, the coordinates of the player are starting back where they were initialized. I need a way to store the state of the previous rotation in the player so that I do not keep starting over after calling restore() if that makes sense \$\endgroup\$ – JParrilla Jun 5 at 11:15
  • \$\begingroup\$ I don't get how restoring the canvas to the original state would affect the position or rotation of the player. \$\endgroup\$ – Bálint Jun 5 at 13:16
  • \$\begingroup\$ Because I am not actually changing the position of the player, ever. The player coordinates themselves are never being rotated/translated. I am just moving the canvas origin to the center of the player, rotating on that, then returning the canvas back to 0,0. The issue is that everything on the screen also rotates with it. I can solve this by using save() and restore() around the rotation part, but once I restore, everything just goes back to the start. This is the example using save and restore: jsfiddle.net/824getou \$\endgroup\$ – JParrilla Jun 5 at 13:46
1
\$\begingroup\$

You should not use the translate method to change the position of the player between frames. Change the shipStartX and shipStartY variables to move the ship and store the current rotation somewhere. This not only gives you a better control over everything, but you won't be able to easily determine collisions with the translate method

\$\endgroup\$
  • \$\begingroup\$ I was using translate() in order to move the canvas origin so that when I called rotate() I was rotating on the center axis of the player, and not on 0, 0 of the canvas. To me this seems necessary because by default rotate() will perform its rotation on the point at 0,0 so I need to change that before rotating \$\endgroup\$ – JParrilla Jun 5 at 13:25
  • \$\begingroup\$ @JParrilla I wasn't talking about that, you don't use translate there to change the position of the player, you use it to change the origin of the canvas. You can do that, even after resetting the canvas without problems. \$\endgroup\$ – Bálint Jun 5 at 13:28
  • \$\begingroup\$ Should I maybe just forget about canvas rotate, and do the math manually on the x and y of the player? Maybe rotating the whole canvas is the wrong approach.. and I should instead perform manual translate and rotate on the triangular player shape and have it store its own location between frames? \$\endgroup\$ – JParrilla Jun 5 at 13:49
  • \$\begingroup\$ @JParrilla Yes, definitely. That's what I said in the answer. The current approach would limit you a lot \$\endgroup\$ – Bálint Jun 5 at 14:15
  • \$\begingroup\$ I think you may be right. I am going to work on it and see how it goes. Ill accept your answer if it works out. Can you maybe edit your answer a bit to also include the fact that using rotate() may not be the best approach here? It may help others in the future that are trying to use the built in rotate() Thanks! \$\endgroup\$ – JParrilla Jun 5 at 14:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.