Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
998 views
in Technique[技术] by (71.8m points)

javascript - Why is camera's position not correctly calculated (canvas)

I am making a clone of agar.io and I am stuck in my code. I can't understand why my camera's position is not correctly calculated. I want my camera's position to half the vector between the farthest blob and the closest blob.

Below is a picture and my code:

enter image description here

<html>
<head>
<title>Play Agario Clone</title>

<style>
body {
margin: 0;
padding: 0;
}
</style>
</head>
<body>
<canvas id="game">
kindly update your browser.
</canvas>

<script>
var 
canvas, 
ctx, 
width = innerWidth, 
height = innerHeight,
mouseX = 0,
mouseY = 0;

var

camera = {
x: 0,
y: 0,

// camera
update: function(obj) {
var farthestBlobX = Math.max.apply(0, obj.blobs.map(function(cell) { return cell.x }));
var farthestBlobY = Math.max.apply(0, obj.blobs.map(function(cell) { return cell.y }));
var closestBlobX = Math.min.apply(0, obj.blobs.map(function(cell) { return cell.x }));
var closestBlobY = Math.min.apply(0, obj.blobs.map(function(cell) { return cell.y }));
var x = farthestBlobX - closestBlobX;
var y = farthestBlobY - closestBlobY;
var length = Math.sqrt(x * x + y * y);

this.x = length/2 - width/2;
this.y = length/2 - height/2;
}
},

player = {
defaultMass: 54,
x: 0,
y: 0,
blobs: [],

update: function () {
for (var i = 0; i < this.blobs.length; i ++) {
var x = mouseX + camera.x - this.blobs[i].x;
var y = mouseY + camera.y - this.blobs[i].y;
var length = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));
var speed = 54/this.blobs[i].mass;

this.blobs[i].velX = x/length * speed * Math.min(1, Math.pow(x / this.blobs[i].mass, 2));
this.blobs[i].velY = y/length * speed * Math.min(1, Math.pow(x / this.blobs[i].mass, 2));

this.blobs[i].x += this.blobs[i].velX;
this.blobs[i].y += this.blobs[i].velY;

for (var j = 0; j < this.blobs.length; j ++) {
if (j != i && this.blobs[i] !== undefined) {
            var blob1 = this.blobs[i];
            var blob2 = this.blobs[j];
            var x = blob2.x - blob1.x;
            var y = blob2.y - blob1.y;
            var dist = Math.sqrt(x * x + y * y);

            if (dist < blob1.mass + blob2.mass) {
              x /= dist;
              y /= dist;
              blob1.x = blob2.x - x * (blob1.mass + blob2.mass);
              blob1.y = blob2.y - y * (blob1.mass + blob2.mass);
            }
          }
}
}

this.x += (mouseX - width/2)/(width/2) * 1;
this.y += (mouseY - height/2)/(height/2) * 1
},

split: function (cell) {
cell.mass /= 2;

this.blobs.push({
x: cell.x,
y: cell.y,
mass: cell.mass
});
},

draw: function () {
for (var i = 0; i < this.blobs.length; i ++) {
ctx.fillStyle = "red";

ctx.beginPath();
ctx.arc(-camera.x + this.blobs[i].x, -camera.y + this.blobs[i].y, this.blobs[i].mass, 0, Math.PI*2);
ctx.fill();
ctx.closePath();
}
}
};

function handleMouseMove (e) {
mouseX = e.clientX;
mouseY = e.clientY;
}

function setup () {
canvas = document.getElementById("game");
ctx = canvas.getContext("2d");
canvas.width = width;
canvas.height = height;

addEventListener("mousemove", handleMouseMove);

player.blobs.push({
x: 0,
y: 0,
mass: player.defaultMass
});
player.blobs.push({
x: 100,
y: 100,
mass: player.defaultMass/2
});
player.blobs.push({
x: 100,
y: 100,
mass: player.defaultMass*2
});

var loop = function () {
update();
draw();
requestAnimationFrame(loop);
}
requestAnimationFrame(loop);
}

function update () {
camera.update(player);
player.update();
}

function draw () {
ctx.fillStyle = "#fff";
ctx.fillRect(0, 0, width, height);

player.draw();
}

setup();
</script>
</body>
</html>
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Instead of computing everything relative to your camera, use your camera to set the global transformation matrix of your canvas, and only for this.
This way, your blobs' updates will be cleaner, and your camera easier to manage.

Now to get the middle position between two points, do (pt1 + pt2) / 2.
You were not clear in your question, if fartherstX and fartherstY should represent the same blob. In your code it wasn't, so I didn't change it.

Also, I didn't gone into all your logics, but beware NaN values, I got some while doing the edit.

function draw() {
  var cw = ctx.canvas.width / 2;
  var ch = ctx.canvas.height / 2;
  // reset transform to clear the canvas
  ctx.setTransform(1, 0, 0, 1, 0, 0);
  ctx.fillStyle = "#fff";
  ctx.fillRect(0, 0, width, height);
  // here we really set the camera position
  ctx.setTransform(1, 0, 0, 1, -camera.x + cw, -camera.y + ch);
  ctx.strokeRect(0, 0, width, height); // just to show the original area
  player.draw();
}

var
  canvas,
  ctx,
  width = innerWidth,
  height = innerHeight,
  mouseX = 0,
  mouseY = 0;

var camera = {
    x: 0,
    y: 0,

    // camera
    update: function(obj) {
      var farthestBlobX = Math.max.apply(0, obj.blobs.map(function(cell) {
        return cell.x
      }));
      var farthestBlobY = Math.max.apply(0, obj.blobs.map(function(cell) {
        return cell.y
      }));
      var closestBlobX = Math.min.apply(0, obj.blobs.map(function(cell) {
        return cell.x
      }));
      var closestBlobY = Math.min.apply(0, obj.blobs.map(function(cell) {
        return cell.y
      }));
      this.x = (closestBlobX + farthestBlobX) / 2 || 0;
      this.y = (closestBlobY + farthestBlobY) / 2 || 0;
    }
  },

  player = {
    defaultMass: 54,
    x: 0,
    y: 0,
    blobs: [],

    update: function() {
      for (var i = 0; i < this.blobs.length; i++) {
        var x = mouseX - this.blobs[i].x || 0;
        var y = mouseY - this.blobs[i].y || 0;
        var length = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));
        var speed = 54 / this.blobs[i].mass;

        this.blobs[i].velX = x / length * speed * Math.min(1, Math.pow(x / this.blobs[i].mass, 2));
        this.blobs[i].velY = y / length * speed * Math.min(1, Math.pow(x / this.blobs[i].mass, 2));

        this.blobs[i].x += this.blobs[i].velX;
        this.blobs[i].y += this.blobs[i].velY;

        for (var j = 0; j < this.blobs.length; j++) {
          if (j != i && this.blobs[i] !== undefined) {
            var blob1 = this.blobs[i];
            var blob2 = this.blobs[j];
            var x = blob2.x - blob1.x;
            var y = blob2.y - blob1.y;
            var dist = Math.sqrt(x * x + y * y);

            if (dist < blob1.mass + blob2.mass) {
              x /= dist;
              y /= dist;
              blob1.x = blob2.x - x * (blob1.mass + blob2.mass);
              blob1.y = blob2.y - y * (blob1.mass + blob2.mass);
            }
          }
        }
      }

      this.x += (mouseX - width / 2) / (width / 2) * 1;
      this.y += (mouseY - height / 2) / (height / 2) * 1;
    },

    split: function(cell) {
      cell.mass /= 2;

      this.blobs.push({
        x: cell.x,
        y: cell.y,
        mass: cell.mass
      });
    },

    draw: function() {
      for (var i = 0; i < this.blobs.length; i++) {
        ctx.fillStyle = "red";

        ctx.beginPath();
        ctx.arc(this.blobs[i].x, this.blobs[i].y, this.blobs[i].mass, 0, Math.PI * 2);
        ctx.fill();
        ctx.closePath();
      }
    }
  };

function handleMouseMove(e) {
  mouseX = e.clientX;
  mouseY = e.clientY;
}

function setup() {
  canvas = document.getElementById("game");
  ctx = canvas.getContext("2d");
  canvas.width = width;
  canvas.height = height;

  addEventListener("mousemove", handleMouseMove);

  player.blobs.push({
    x: 10,
    y: 10,
    mass: player.defaultMass
  });
  player.blobs.push({
    x: 100,
    y: 100,
    mass: player.defaultMass / 2
  });
  player.blobs.push({
    x: 100,
    y: 100,
    mass: player.defaultMass * 2
  });

  var loop = function() {
    update();
    draw();
    requestAnimationFrame(loop);
  }
  requestAnimationFrame(loop);
}

function update() {
  camera.update(player);
  player.update();
}

setup();
body {
  margin: 0;
  padding: 0;
}
<canvas id="game">kindly update your browser.</canvas>

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...