在画布中旋转而不移动所有其他物体?

时间:2015-03-08 13:35:43

标签: canvas rotation

我正在尝试制作一个双人坦克游戏,两个坦克使用键盘相互射击来控制它们。我有两个向前和向后的运动,但是当我尝试旋转它们时它也会旋转另一个。 (目前坦克只是矩形。)

如何在不移动另一个的情况下旋转一个?

var draw;
var context;
var DKey = false;
var AKey = false;
var WKey = false;
var SKey = false;
var tank1_x;
var tank1_y;
var tank1_w = 30;
var tank1_h = 30;
var UpKey = false;
var DownKey = false;
var RightKey = false;
var LeftKey = false;
var tank2_x;
var tank2_y;
var tank2_w = 30;
var tank2_h = 30;
var rad = Math.PI/180;

function init() {
    //canvas = document.getElementById('canvas');
    context = $('#myCanvas')[0].getContext('2d'); //sets the canvas as a jquery object to the variable 'context'
    WIDTH = $('#myCanvas').width();
    HEIGHT = $('#myCanvas').height();
    tank1_x = WIDTH * 1 / 4 - tank1_w / 2; //centre width TANK1
    tank1_y = HEIGHT * 1 / 4 - tank1_h / 2; //centre height TANK1
    tank2_x = WIDTH * 3 / 4 - tank2_w / 2; //centre width TANK2
    tank2_y = HEIGHT * 3 /4 - tank2_h / 2; //centre height TANK2
    setInterval('draw()', 25); //sets interval for draw method to repeat after
}
function clearCanvas() {
    context.clearRect(0,0,WIDTH,HEIGHT); // clears whole canvas
}

tank1 = function fillRect(x,y,w,h) {
    context.beginPath();
    context.fillRect(WIDTH*1/4, HEIGHT*1/4, tank1_w, tank1_h);
    context.endPath();
}

tank2 = function fillRect(x,y,w,h) {
    context.beginPath();
    context.fillRect(WIDTH*3/4, HEIGHT*3/4, tank2_w, tank2_h);
    context.endPath();
}

draw = function() { // redraws rectangle to canvas
    clearCanvas();
    //TANK1 ROTATION
    if (DKey) {
        var buffer = document.createElement('canvas');
        buffer.width = buffer.height = tank1_w*2;
        var bctx = buffer.getContext('2d');
        bctx.translate(tank1_x + tank1_w/2, tank1_y + tank1_h/2);
        bctx.rotate(5*rad);
        bctx.fillRect(tank1_x, tank1_y, tank1_w, tank1_h);
        ctx.drawImage(buffer, tank1_x, tank1_y);
    }
    else if (AKey) {
        context.save();
        context.clearRect(WIDTH, HEIGHT);
        context.translate(tank1_x + tank1_w/2, tank1_y + tank1_h/2); //http://www.williammalone.com/briefs/how-to-rotate-html5-canvas-around-center/ and StackOverflow
        context.rotate(5*rad); //Translates origin of rotation to centre of block, then rotates 5 degrees
        context.fillRect(tank1_x, tank1_y, tank1_w, tank1_h); //Redraw TANK1
        context.rotate(-5*rad);
        context.translate(-tank1_x - tank1_w/2, -tank1_y - tank1_h/2); //Translates origin of rotation back to top left of canvas
        context.restore();
    }
    //TANK1 MOVEMENT
    if (WKey) tank1_y -= 5;
    else if (SKey) tank1_y += 5;
    if (tank1_x <= 0) tank1_x = 0;
    if ((tank1_x + tank1_w) >= WIDTH) tank1_x = WIDTH - tank1_w;
    if (tank1_y <= 0) tank1_y = 0;
    if ((tank1_y + tank1_h) >= HEIGHT) tank1_y = HEIGHT - tank1_h;
    context.fillRect(tank1_x,tank1_y,tank1_w,tank1_h);

    //TANK2 ROTATION
    if(RightKey) {
        context.translate(tank2_x + tank2_w/2, tank2_y + tank2_h/2);
        context.rotate(5*Math.PI/180);
        context.translate(-tank2_x - tank2_w/2, -tank2_y - tank2_h/2);
    }
    else if (LeftKey) {
        context.translate(tank2_x + tank2_w/2, tank2_y + tank2_h/2);
        context.rotate(-5*Math.PI/180);
        context.translate(-tank2_x - tank2_w/2, -tank2_y - tank2_h/2);
    }
    //TANK2 MOVEMENT
    if (UpKey) tank2_y -= 5;
    else if (DownKey) tank2_y += 5;
    if (tank2_x <= 0) tank2_x = 0;
    if ((tank2_x + tank2_w) >= WIDTH) tank2_x = WIDTH - tank2_w;
    if (tank2_y <= 0) tank2_y = 0;
    if ((tank2_y + tank2_h) >= HEIGHT) tank2_y = HEIGHT - tank2_h;
    context.fillRect(tank2_x,tank2_y,tank2_w,tank2_h);
}

function onKeyDown(event) {
    //TANK1 (WASD Keys)
    if (event.keyCode == 68) DKey = true;
    else if (event.keyCode == 65) AKey = true;
    if (event.keyCode == 87) WKey = true;
    else if (event.keyCode == 83) SKey = true;
    //TANK2 (Arrow Keys)
    if (event.keyCode == 39) RightKey = true;
    else if (event.keyCode == 37) LeftKey = true;
    if (event.keyCode == 38) UpKey = true;
    else if (event.keyCode == 40) DownKey = true;
}

function onKeyUp(event) {
    //TANK1
    if (event.keyCode == 68) DKey = false;
    else if (event.keyCode == 65) AKey = false;
    if (event.keyCode == 87) WKey = false;
    else if (event.keyCode == 83) SKey = false;
    //TANK2
    if (event.keyCode == 39) RightKey = false;
    else if (event.keyCode == 37) LeftKey = false;
    if (event.keyCode == 38) UpKey = false;
    else if (event.keyCode == 40) DownKey = false;
}

$(document).keydown(onKeyDown);
$(document).keyup(onKeyUp);

init();
});

我尝试过使用一个缓冲区并且对我不起作用,也没有清理然后旋转画布,重新绘制第一个坦克,然后向后旋转画布(让坦克旋转),然后重新绘制其余部分,因为它是。我不知道还能做什么。

目前我已经尝试了坦克1旋转中的缓冲区以及Tank2中的画布旋转。

感谢您提前提供任何帮助。

2 个答案:

答案 0 :(得分:0)

存储坦克的绝对旋转并使用它而不是累积变换矩阵(只需将旋转角度添加/减去此值,f.ex a tank1_rotation)。如果你保持它的相对性,你必须改变场景中的所有内容,这使得跟踪事物变得复杂。

旋转并绘制坦克后,此方法/更改将允许您只需调用以下内容即可控制所有内容:

context.setTransform(1,0,0,1,0,0);

这会将转换矩阵重置为初始状态,并且比使用保存/恢复快许多倍。

下次绘制水箱时,只需使用已存储的角度,绘制并重复上述步骤。

答案 1 :(得分:0)

在尝试这些之后,我发现最直接的事情(我是一名数学学生)是手动绘制坦克的所有点并使用矩阵相应地旋转每个点。

drawTank1 = function(x, y, w, h) {
    cos1 = Math.cos(tank1_angle);
    sin1 = Math.sin(tank1_angle);
    var centre_x = tank1_x;
    var centre_y = tank1_y;
    var corner1_x = - 20 * cos1 - 20 * sin1 + centre_x;
    var corner1_y = 20 * sin1 - 20 * cos1 + centre_y;
    var corner2_x = - 20 * cos1 + 20 * sin1 + centre_x;
    var corner2_y = 20 * sin1 + 20 * cos1 + centre_y;
    var corner3_x = 20 * cos1 + 20 * sin1 + centre_x;
    var corner3_y = - 20 * sin1 + 20 * cos1 + centre_y;
    var corner4_x = 20 * cos1 - 20 * sin1 + centre_x;
    var corner4_y = - 20 * sin1 - 20 * cos1 + centre_y;
    var corner5_x = 5 * cos1 - 20 * sin1 + centre_x;
    var corner5_y = - 5 * sin1 - 20 * cos1 + centre_y;
    var corner6_x = 5 * cos1 - 30 * sin1 + centre_x;
    var corner6_y = - 5 * sin1 - 30 * cos1 + centre_y;
    var corner7_x = - 5 * cos1 - 30 * sin1 + centre_x;
    var corner7_y = 5 * sin1 - 30 * cos1 + centre_y;
    var corner8_x = - 5 * cos1 - 20 * sin1 + centre_x;
    var corner8_y = 5 * sin1 - 20 * cos1 + centre_y;
    context.beginPath();
    context.fillStyle = '#00FF00';
    context.moveTo(corner1_x, corner1_y);
    context.lineTo(corner2_x, corner2_y);
    context.lineTo(corner3_x, corner3_y);
    context.lineTo(corner4_x, corner4_y);
    context.lineTo(corner5_x, corner5_y);
    context.lineTo(corner6_x, corner6_y);
    context.lineTo(corner7_x, corner7_y);
    context.lineTo(corner8_x, corner8_y);
    context.lineTo(corner1_x, corner1_y);
    context.closePath();
    context.fill();
    context.stroke();
}

感谢大家的帮助和建议