0

Creating an Agar clone, and it pretty much works now, but I want to improve it by making it so if the player leaves the screen, the screen follows them, which is done with a viewport. Only problem is I have no idea how to do it. I tried ctx.translate() but that just resulted in some weird stuff. (granted, I'm using a regular background, and I've heard an actual image is required for it to work, but I don't know how to do that either, so...) Here's my jsFiddle. Initializing canvas-related variables:

var canvas = document.createElement("canvas");
canvas.width = innerWidth;
canvas.height = innerHeight;
canvas.style.display = "none";
document.body.appendChild(canvas);
var ctx = canvas.getContext("2d");
Raiden
  • 311
  • 3
  • 17

1 Answers1

2

You use translate to set the origin. Where on the canvas, or off, the coordinates X = 0, y = 0 are.

Your character is wandering about a game world which is many times bigger than the canvas. You also have many other items and players each with their own coordinates in the game world..

One way to render this is... For each item in the game, find the distance you are from the origin and subtract that from each item as you draw them. Then draw your own character at the center of the screen. But that is slow, and requires all that extra math for each item/player.

So let the hardware do it with the transform. The transform holds the scales (x,y) the rotation (ang), and the translation (origin offset). Every time an object is drawn on the canvas the transformation matrices is applied to it, you can't avoid it, it has to happen. So if you dont use it to your advantage its just wasted.

How to use it. Your playfield is top left -10,000,-10,000 pixels to bottom right 10,000, 10,000 pixels. Every one has a location on the map between those numbers, including your player, which may be at 5,000, 6,000 pixels. If you ctx.drawImage(playerImage,5000,6000) the image will not appear, its way of the bottom right of the canvas, but you want him in the center of the screen.

To do this move the origin (currently at the upper left corner of the canvas (0,0)) so you at 5000,6000 appear in the center.

var playerX = 5000;  // your position
var playerY = 6000;
var screenWidth = 1920;  // size of the screen
var screenHeight = 1080;
var originX = 0;   // where the origin is
ver originY = 0

To center yourself move the origin so that it subtracts you position.

originX -= playerX;
originY -= playerY;

now you are at the top left corner of the canvas, but you want the center. So move it back a bit by half the screen size.

originX += screenWidth/2;
originY += screenHeight/2;

Combine it all into one. Assume the origin is alway 0,0 and you get

originX = -(playerX-screenWidth/2);
originY = -(playerY-screenHeight/2);

Now you have the numbers that you can put into the translate.

But its much better if you put it straight into the transformation matrix, and you don't really need the origin variables.

Thus in one step.

ctx.setTransform(1,0,0,1,-(playerX-screenWidth/2),-(playerY-screenHeight/2));

Now when you draw your player at

ctx.drawImage(payerImage,5000,6000);

You appear at the center of the canvas. The bad guy at 5500,6200 draw with

ctx.drawImage(enemyImage,5500,6200);

will appear on the canvas as well 500 pixels right and 200 down from you.

Now you don't have to mess around with anyones coordinates and just render them where they are, you have moved everything in the game with only one line of code. It has not slowed your game down at all, because the transform is always applied, you just made sure its doing what you want.

Set the transform near the start of every frame, after you have updated your position and everything will follow your character.

Blindman67
  • 51,134
  • 11
  • 73
  • 136
  • Alright, tried this out and it works, but it's quite slow, and since you explicitly mentioned it shouldn't be slow, I'm assuming I'm doing something wrong. [Here's](http://jsfiddle.net/khanfused/7xd16msf/16/) my updated fiddle. – Raiden Nov 13 '15 at 04:10
  • Not the transform but to make sure ill look through the code.Quite a bit there. I kinda know what your problem is. but I will have a look in a bit, just to make sure.. But to get you started you need to do some render culling.. Each item should be tested if it should be drawn. So your playerX,Y has a screen around. Anything outside that screen cant be seen so you should not try to draw it. Drawing something offscreen is still a GPU job, and thats where its getting bogged down. But Ill double check. – Blindman67 Nov 13 '15 at 04:28
  • Ok you have some serious errors that need fixing, event handlers are being called each frame (very bad) and you have manage to pick the slowest way to do most things. But over all very good effort so far. this link https://jsfiddle.net/blindman67/8p0j4y4p/ are my thoughts on how to improve, and where the errors are. Should keep you busy for some time, just in the javascript panel I put it on jsFiddle as its convenient.. Good luck – Blindman67 Nov 13 '15 at 05:27
  • Bit tired so only skimmed it but it looks good; will have a proper look at it tomorrow. Thank you for putting the effort into doing that. However, regarding your comment about the canvas size - how else would I make it so the player can go outside of the boundaries? – Raiden Nov 13 '15 at 05:39
  • The canvas is a veiwport. Making it bigger then the screen you are displaying it on if pointless. How can they see the canvas past the edge of the screen. 5000 by 5000 is very large. 100Mbs just for the viewport. You should not use more pixels in the canvas than there are the screen it is being displayed on "ever" – Blindman67 Nov 13 '15 at 06:04
  • Ah, okay. I implemented a bunch of your performance-increasing tips. Used to run at ~10 FPS. Now it runs at ~60 FPS. I cut 1 player mode out for now but I will add it back later. http://jsfiddle.net/khanfused/eubnqgyg/3/ – Raiden Nov 17 '15 at 06:37