Javascript 画布如何在不旋转整个上下文的情况下旋转图像和重画

Javascript 画布如何在不旋转整个上下文的情况下旋转图像和重画,javascript,canvas,rotation,Javascript,Canvas,Rotation,我正试图用canvas和JS来重建小行星,但根据它的角度旋转飞船时遇到了麻烦。我已经测试了计算角度和转换为弧度的方法,这些方法可以检查,并且在draw()中调用时定义了角度,但没有发生旋转。当我可以进行一些旋转时,它会旋转整个上下文,而不是船 我已经包括了整个船舶类,但是相关的函数是底部的draw函数 function Ship(posOptions) { let options = {game: posOptions['game'], color: 'green', pos: posOpt

我正试图用canvas和JS来重建小行星,但根据它的角度旋转飞船时遇到了麻烦。我已经测试了计算角度和转换为弧度的方法,这些方法可以检查,并且在draw()中调用时定义了角度,但没有发生旋转。当我可以进行一些旋转时,它会旋转整个上下文,而不是船

我已经包括了整个船舶类,但是相关的函数是底部的draw函数

function Ship(posOptions) {
  let options = {game: posOptions['game'], color: 'green', pos: posOptions['pos'], radius: 20, vel: [0,0], wrappable: true, type: 0}
  MovingObject.call(this, options);
  this.facingDir = 0;
  this.H = window.innerHeight; //*0.75,
  this.W = window.innerWidth; //*0.75;
  this.xc = this.W/2; //zeby bylo w centrum :v
  this.yc = this.H/2; //jw.
  this.x =  this.xc;
  this.y =  this.yc;
  this.dv = 0.2;
  this.dt = 1;
  this.vx = 0;
  this.vy = 0;
  this.maxVel = 10;
}

Utils.inherits(Ship, MovingObject);

//Relocate ship if hit by asteroid.
Ship.prototype.relocate = function () {
  this.pos = this.game.randomPosition();
  this.vel = [0,0];
};


Ship.prototype.fireBullet = function () {
  let bulletVel = [(this.vel[0] * 4), (this.vel[1] * 5) - 10];
  let bullet = new Bullet({pos: this.pos, vel: bulletVel, game: this.game});
  this.game.bullets.push(bullet);
};

//Calculate velocity based on keyboard input and angle of rotation

Ship.prototype.power = function (impulse) {
  if (impulse[0] === -2 && this.facingDir !== Math.PI) {
    this.facingDir <= Math.PI ? this.facingDir += 30 / 180 * Math.PI : this.facingDir -= 30 / 180 * Math.PI;
  }
  if (impulse[0] === 2 && this.facingDir !== 0) {
    this.facingDir <= 0 ? this.facingDir += 30 / 180 * Math.PI : this.facingDir -= 30 / 180 * Math.PI;
  }
  if (impulse[1] === 2 && this.facingDir !== (Math.PI / 2 * 3)) {
    this.facingDir <= (3 * Math.PI / 2) ? this.facingDir += 30 / 180 * Math.PI : this.facingDir -= 30 / 180 * Math.PI;
  }
  if (impulse[1] === -2 && this.facingDir !== (Math.PI / 2)) {
    this.facingDir <= (Math.PI / 2) ? this.facingDir += 30 / 180 * Math.PI : this.facingDir -= 30 / 180 * Math.PI;
  }
  this.vel[0] += impulse[0];
  this.vel[1] += impulse[1];
};


Ship.prototype.move = function () {
  if (this.isWrappable) {
    this.pos = this.game.wrap(this.pos);
  }

  this.pos[0] += this.vel[0];
  this.pos[1] += this.vel[1];
  //Attenuate the velocity over time so it doesn't accelerate forever. 
  this.vel[0] *= .98;
  this.vel[1] *= .98;
};

Ship.prototype.convertToRadians = function(degree) {
  return degree*(Math.PI/180);
}

Ship.prototype.draw = function (ctx) {
  const img = new Image();
  img.onload = function () {
    ctx.drawImage(img, this.pos[0]-this.radius, this.pos[1]-this.radius)
  };
  img.src = 'galaga_ship.png';
  ctx.drawImage(img, this.pos[0]-this.radius, this.pos[1]-this.radius);

  **//This is where I am stuck.**
  ctx.save();
  ctx.translate(this.x,this.y);
  ctx.rotate(this.facingDir);
  ctx.translate(-7,-10);
  ctx.restore();

};

module.exports = Ship;
功能发货(posOptions){
让选项={game:posOptions['game'],颜色:'green',位置:posOptions['pos'],半径:20,级别:[0,0],包装:true,类型:0}
MovingObject.call(此选项);
this.facingDir=0;
此.H=window.innerHeight;//*0.75,
此.W=window.innerWidth;//*0.75;
this.xc=this.W/2;//zeby bylo W centrum:v
this.yc=this.H/2;//jw。
this.x=this.xc;
this.y=this.yc;
这是0.dv=0.2;
这是1.dt=1;
该值为0.vx=0;
这是0.vy=0;
这个.maxVel=10;
}
Utils.继承(船舶、移动对象);
//如果被小行星击中,重新定位飞船。
Ship.prototype.relocate=函数(){
this.pos=this.game.randomPosition();
this.vel=[0,0];
};
Ship.prototype.fireball=函数(){
让bulletVel=[(this.vel[0]*4),(this.vel[1]*5)-10];
let bullet=new bullet({pos:this.pos,vel:bulletVel,game:this.game});
这个。游戏。子弹。推(子弹);
};
//根据键盘输入和旋转角度计算速度
Ship.prototype.power=功能(脉冲){
if(脉冲[0]==-2&&this.facingDir!==Math.PI){

this.facingDir在还原上下文之前,您没有绘制任何内容。方法是
ctx.save()
ctx.restore()
应该使用的方法是保存它,使用原点的原始旋转和位置,对其进行变换,绘制图形,然后将其恢复到原来的位置。因此,只有图形使用变换后的坐标系,然后其他所有操作都恢复正常

  **//This is where I am stuck.**
  ctx.save();
  ctx.translate(this.x,this.y);
  ctx.rotate(this.facingDir);
  ctx.translate(-7,-10);
// PUT DRAWING YOUR SHIP HERE
  ctx.restore();