Javascript 画布:使用缩放和旋转模拟摄影机

Javascript 画布:使用缩放和旋转模拟摄影机,javascript,math,canvas,Javascript,Math,Canvas,我创建了一个摄影机对象,它的位置作为屏幕的中心。相机允许缩放和旋转。所以基本上我所做的是将画布的中心平移到原点,应用比例,然后旋转,现在我需要知道我需要使用什么样的复杂数学来将其平移回中心,这是我到目前为止的代码: __Stage__.prototype.__cameraTransform = function() { var canvas = this.__canvas; var cam = this.camera; var context = this.__canva

我创建了一个摄影机对象,它的位置作为屏幕的中心。相机允许缩放和旋转。所以基本上我所做的是将画布的中心平移到原点,应用比例,然后旋转,现在我需要知道我需要使用什么样的复杂数学来将其平移回中心,这是我到目前为止的代码:

__Stage__.prototype.__cameraTransform = function() {
    var canvas = this.__canvas;
    var cam = this.camera;
    var context = this.__canvasContext;

    var cx = canvas.width/2;
    var cy = canvas.height/2;
    context.translate(-cx,-cy);

    var scale = {x: canvas.width/cam.width, y: canvas.height/cam.height};
    context.scale(scale.x,scale.y);

    var rotation = Math.PI*2 - (cam.rotation%(Math.PI*2));
    context.rotate(-rotation);

    context.translate(/*What translation to get the point back in the center*/);
}

首先,出于某种原因,您可能希望保存上下文或重置上下文。
对于保存/还原,我猜不出您将如何处理它,重置是通过以下方式完成的:

function resetTransform() {
    c.setTransform(1, 0, 0, 1, 0, 0);
}
第二件事是你没有提到相机在看什么,我假设它看的是
centerX
centerY

第三件事是,您希望避免在缩放时更改纵横比,因此更应该计算画布的纵横比,并使用摄影机视图高度=摄影机视图宽度*画布比率

Object.defineProperty允许在对象上定义属性,因此您可以以干净的方式执行此操作:

// at the global level, after document loaded
//    OR where you handle the canvas
var canvasRatio = canvas.height / canvas.width;

//... in your camera constructor 
Object.defineProperty(this, 'height', {
    get: function () {
        return canvasRatio * this.width ;
    },
    set: function (val) {},
    enumerable: true
});
然后,您可能希望缓存画布大小,以避免在游戏期间访问DOM

对于旋转计算,我没有得到它,但不需要钳制[0,2*PI]或类似的东西:只需使用您拥有的任何弧度值(初始化为0)

现在,对于您的相机,代码如下所示:

__Stage__.prototype.__cameraTransform = function() {
    var canvas = this.__canvas;
    var cam = this.camera;
    var context = this.__canvasContext;
   // O. reset ??
   resetTransform();
    //
    var cx = this.__canvasWidth/2;
    var cy = this.__canvasHeight/2;
    // 1 .  translate  to the middle of the canvas
    context.translate(cx,cy);
    // 2. scale
    var scale = this.__canvasWidth/cam.width;
    context.scale(scale,scale);
    // 3. translate to where the camera looks
    context.translate(-cam.centerX,-cam.centerY);
    // 4. rotate
    context.rotate(cam.rotation);    
}

另外,如果删除旋转位,我会在使用以下行进行缩放后将其恢复到中心:context.translate(cx*(2/scale.x-1),cy*(2/scale.y-1));嗯,这是一个非常简单的解决方案,而且很有效。谢谢你,好心的先生!