5
\$\begingroup\$

My project is a 2D tactics game with a square grid. It's all HTML5/Javascript/JQuery.

I have been able to draw out the grid and have a system where I can load different maps with tiles where units can and cannot move. Now I would like to make it so only a portion of the map is displayed in the canvas and the player can scroll around to different characters and stuff (like in normal tactical games).

However I have no idea even where to get started doing this with an HTML5 canvas. I did something similar in Unity but the level of abstraction with the cameras basically did it for me.

\$\endgroup\$

2 Answers 2

3
\$\begingroup\$

You can accomplish this with CanvasRenderingContext2D's methods setTransform, save, and restore. Together they allow you to create a draw transform stack, which permits you to draw all your tiles at their (unchanging) world position, but have them move around on screen.

If you have a position of the left-top world-position of your viewport, you can create a simple camera object:

var camera = {x: xPosition, y: yPosition};

Then you can update only that value and use it to offset your view by setting an initial base-transform. (Pay attention to argument order, as they comprise a 2x2 matrix followed by a 2d translation vector):

context.setTransform(
  1, 0,
  0, 1,
  -1 * camera.x, 
  -1 * camera.y);

Then when you draw individual objects, you can add another transform, draw the image, and then pop that transform back off the stack:

var tile = {pos: {x: xPosition, y:yPosition}, img: tileImage };
context.save();
context.translate(tile.pos.x, tile.pos.y);
context.drawImage(tile.img, 0, 0);
context.restore();

Adding zoom and rotation can be accomplished with the same technique, but they require more terms in the transform. Clamping the motion of the camera, as well as picking items in screenspace, are more complicated. But those would all be separate topics.

\$\endgroup\$
2
  • \$\begingroup\$ Why use the complicated setTransform when you can achieve the same effect in this case by using the much more readable translate? \$\endgroup\$
    – Philipp
    Commented Nov 4, 2014 at 12:26
  • \$\begingroup\$ setTransform is absolute, so it gives you a definite base from which to start, or to reset to. translate, rotate, and scale are relative to the existing transform, which lets them stack onto each other and be de-applied with restore. setTransform can also be de-applied with restore, if for some reason a totally different coordinate system was needed in between world-space draws. \$\endgroup\$ Commented Nov 4, 2014 at 20:03
0
\$\begingroup\$

If I understand the question correctly, you want a camera that you can move, which is not a standard with vanilla canvas. To emulate this, you should create two variables for the x and y position of the camera. You can then manipulate these values for instance if you want the camera to move when the player moves. To make all your scenes objects act properly with the camera, you should offset all of your draw calls with the x and y of the camera, simply by subtracting the cameras position with the objects position. This can turn messy having to put the offset on everything you draw, so you might want to write some code that you can call to offset all the values automatically.

\$\endgroup\$
2
  • \$\begingroup\$ That weird glitch preventing you from commenting is the rules of the site, you need at least 50 reputation to comment everywhere. I'd suggest fleshing out this answer a bit more. In the future, please don't use answers as a substitute for a comment. \$\endgroup\$
    – House
    Commented Nov 4, 2014 at 0:04
  • \$\begingroup\$ Alright, sorry I used to being on stack overflow where I have enough reputation to comment, and I won't answer in place of a comment again :). \$\endgroup\$
    – 5Mixer
    Commented Nov 4, 2014 at 0:12

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .