在不移动所有其他对象的情况下以 canvas 旋转?
Rotating in canvas without moving all other objects?
我正在尝试制作一个 2 人坦克游戏,其中有两辆坦克互相射击,使用键盘控制它们。我已经为两者提供了向前和向后的运动,但是当我尝试旋转它们时,它也会旋转另一个。 (目前坦克只是矩形。)
如何旋转一个而不移动另一个?
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 Whosebug
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();
});
我试过使用缓冲区,但这对我不起作用,清除然后旋转 canvas、重绘第一个坦克然后将 canvas 旋转回来(所以坦克旋转),然后按原样重新绘制其余部分。我不知道还能做什么。
目前我已经得到了我在 Tank1 的旋转缓冲区和 Tank2 的 canvas 旋转中尝试过的东西。
提前感谢您的帮助。
存储坦克的绝对旋转并使用它而不是累积变换矩阵(只是add/subtract旋转角度到这个值,f.ex一个 tank1_rotation
)。如果你保持相对,你必须相对地转换场景中的所有东西,这使得跟踪事物变得复杂。
旋转并绘制坦克后,approach/change 将允许您简单地调用以下命令来检查所有内容:
context.setTransform(1,0,0,1,0,0);
这会将转换矩阵重置为初始状态,并且比使用 save/restore 快很多倍。
下次绘制坦克时,只需使用存储的角度,绘制并重复上述步骤。
在尝试了这些之后,我发现最直接的做法(我是一名数学专业的学生)是手动绘制坦克的所有点并使用矩阵相应地旋转每个点。
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();
}
感谢大家的帮助和建议
我正在尝试制作一个 2 人坦克游戏,其中有两辆坦克互相射击,使用键盘控制它们。我已经为两者提供了向前和向后的运动,但是当我尝试旋转它们时,它也会旋转另一个。 (目前坦克只是矩形。)
如何旋转一个而不移动另一个?
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 Whosebug
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();
});
我试过使用缓冲区,但这对我不起作用,清除然后旋转 canvas、重绘第一个坦克然后将 canvas 旋转回来(所以坦克旋转),然后按原样重新绘制其余部分。我不知道还能做什么。
目前我已经得到了我在 Tank1 的旋转缓冲区和 Tank2 的 canvas 旋转中尝试过的东西。
提前感谢您的帮助。
存储坦克的绝对旋转并使用它而不是累积变换矩阵(只是add/subtract旋转角度到这个值,f.ex一个 tank1_rotation
)。如果你保持相对,你必须相对地转换场景中的所有东西,这使得跟踪事物变得复杂。
旋转并绘制坦克后,approach/change 将允许您简单地调用以下命令来检查所有内容:
context.setTransform(1,0,0,1,0,0);
这会将转换矩阵重置为初始状态,并且比使用 save/restore 快很多倍。
下次绘制坦克时,只需使用存储的角度,绘制并重复上述步骤。
在尝试了这些之后,我发现最直接的做法(我是一名数学专业的学生)是手动绘制坦克的所有点并使用矩阵相应地旋转每个点。
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();
}
感谢大家的帮助和建议