2017-05-13 4 views
4

Ich mache einen Klon von agar.io und ich stecke in meinem Code fest. Ich kann nicht verstehen, warum die Position meiner Kamera nicht korrekt berechnet wird. Ich möchte, dass die Position meiner Kamera den Vektor zwischen dem entferntesten und dem nächsten Fleck halbiert.Warum ist die Position der Kamera nicht korrekt berechnet (Canvas)

Unten ist ein Bild und mein Code:

enter image description here

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

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

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

 
\t var 
 

 
\t camera = { 
 
\t \t x: 0, 
 
\t \t y: 0, 
 

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

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

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

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

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

 
\t \t \t \t for (var j = 0; j < this.blobs.length; j ++) { 
 
\t \t \t \t \t 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); 
 
      } 
 
      } 
 
\t \t \t \t } 
 
\t \t \t } 
 

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

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

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

 
\t \t draw: function() { 
 
\t \t \t for (var i = 0; i < this.blobs.length; i ++) { 
 
\t \t \t \t ctx.fillStyle = "red"; 
 
\t \t \t \t 
 
\t \t \t \t ctx.beginPath(); 
 
\t \t \t \t ctx.arc(-camera.x + this.blobs[i].x, -camera.y + this.blobs[i].y, this.blobs[i].mass, 0, Math.PI*2); 
 
\t \t \t \t ctx.fill(); 
 
\t \t \t \t ctx.closePath(); 
 
\t \t \t } 
 
\t \t } 
 
\t }; 
 

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

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

 
\t \t addEventListener("mousemove", handleMouseMove); 
 

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

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

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

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

 
\t \t player.draw(); 
 
\t } 
 

 
\t setup(); 
 
\t </script> 
 
</body> 
 
</html>

+2

Würden Sie nicht lieber die Kamera die durchschnittliche Position aller Blobs haben ? etwas wie: 'camera.x = (player.blobs [0] .x + player.blobs [1] .x ... + player.blobs [n] .x)/player.blobs.length' (Pseudocode) . –

+0

nein, es funktioniert nicht –

Antwort

1

ich es sehe, ist eine Antwort schon ..

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

 
const camera = { 
 
    x : 0, 
 
    y : 0, 
 
    update(obj) { // camera 
 
     this.x = (obj.blobsExtent.minx + obj.blobsExtent.maxx)/2; 
 
     this.y = (obj.blobsExtent.miny + obj.blobsExtent.maxy)/2; 
 
     this.x -= width/2; 
 
     this.y -= height/2; 
 
    } 
 
}; 
 

 
const player = { 
 
    defaultMass : 54, 
 
    blobs : [], 
 
    blobsExtent : { // get the extent while updating the blobs save you having to iterate all the objects a second time to get extent 
 
     minx :0, 
 
     miny : 0, 
 
     maxx : 0, 
 
     maxy : 0, 
 
    }, 
 
    update () { 
 
     var be = this.blobsExtent; // be for Blob Extent alias to save typing and make code easier to read 
 
     for (var i = 0; i < this.blobs.length; i++) { 
 
      var blob1 = this.blobs[i]; 
 
      var x = mouseX - blob1.x; 
 
      var y = mouseY - blob1.y; 
 
      // to stop the divide by zero propigating NaN set length to 1 if less than 1 
 
      var length = Math.max(1,Math.sqrt(x * x + y * y)); // x * x is quicker than Math.pow(x,2) 
 
      var speed = 54/blob1.mass; 
 

 
      blob1.velX = x/length * speed * Math.min(1, Math.pow(x/blob1.mass, 2)); 
 
      blob1.velY = y/length * speed * Math.min(1, Math.pow(x/blob1.mass, 2)); 
 

 
      blob1.x += blob1.velX; 
 
      blob1.y += blob1.velY; 
 

 
      for (var j = 0; j < this.blobs.length; j++) { 
 
       if (j != 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); 
 
        var radTotal = blob1.mass + blob2.mass; 
 

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

 
      if(i === 0){ // use first blob to setup min max 
 
       be.maxx = be.minx = blob1.x; 
 
       be.maxy = be.miny = blob1.y; 
 
      }else{ 
 
       be.maxx = Math.max(be.maxx, blob1.x); 
 
       be.maxy = Math.max(be.maxy, blob1.y); 
 
       be.minx = Math.min(be.minx, blob1.x); 
 
       be.miny = Math.min(be.miny, blob1.y); 
 
      } 
 
     } 
 
    }, 
 
    split (cell) { 
 
     cell.mass /= 2; 
 
     this.blobs.push(createBlob(cell.x, cell.y, cell.mass)); 
 
    }, 
 
    draw() { 
 
     var b; // alias for blob 
 
     ctx.fillStyle = "red"; // all the same colour then can render as one path 
 
     ctx.setTransform(1,0,0,1,-camera.x,-camera.y); 
 
     ctx.beginPath(); 
 
     for (var i = 0; i < this.blobs.length; i++) { 
 
      b = this.blobs[i]; 
 
      ctx.arc(b.x, b.y, b.mass, 0, Math.PI * 2); 
 
      ctx.closePath(); 
 
     } 
 
     ctx.fill(); 
 
     ctx.setTransform(1,0,0,1,0,0); // restore default transform 
 
    } 
 
}; 
 

 
function handleMouseMove(e) { 
 
    mouseX = e.clientX + camera.x; 
 
    mouseY = e.clientY + camera.y; 
 
} 
 
function createBlob(x,y,mass){ return {x,y,mass} } 
 
function setup() { 
 
    canvas = document.getElementById("game"); 
 
    ctx = canvas.getContext("2d"); 
 
    canvas.width = width; 
 
    canvas.height = height; 
 
    addEventListener("mousemove", handleMouseMove); 
 
    player.blobs.push(createBlob(0,0,player.defaultMass)); 
 
    player.blobs.push(createBlob(100,100,player.defaultMass/2)); 
 
    player.blobs.push(createBlob(100,100,player.defaultMass * 2)); 
 
} 
 

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

 
function draw() { 
 
    ctx.fillStyle = "#fff"; 
 
    ctx.fillRect(0, 0, width, height); 
 
    player.draw(); 
 
}  
 
function loop() { 
 
    update(); 
 
    draw(); 
 
    requestAnimationFrame(loop); 
 
} 
 

 

 
setup(); 
 
requestAnimationFrame(loop);
\t body { 
 
\t \t margin: 0; 
 
\t \t padding: 0; 
 
\t }
<canvas id="game"></canvas>

2

Statt alles in Bezug auf Ihre Kamera von Computer benutzen, um Ihre Kamera, um die globale Transformationsmatrix Ihrer einstellen Leinwand, und nur dafür.
Auf diese Weise werden die Updates Ihrer Blobs sauberer und Ihre Kamera leichter zu verwalten.

Um nun die mittlere Position zwischen zwei Punkten zu erhalten, tun Sie (pt1 + pt2)/2.
Sie waren nicht klar in Ihrer Frage, wenn fartherstX und fartherstY dasselbe darstellen sollten blob. In deinem Code war es nicht, also habe ich es nicht geändert.

Auch ich bin nicht in all Ihre Logiken gegangen, aber Vorsicht NaN Werte, ich habe einige während der Bearbeitung.

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>

+0

Ich denke, ich habe das Problem herausgefunden, wie Sie am weitesten gesagt x und y sollte der gleiche Fleck sein. –

+0

Vielen Dank, Ihr Code funktioniert. –

Verwandte Themen