2011-10-27 28 views
19

Estoy usando lienzo para mostrar algunos sprites, y tengo que voltear uno horizontalmente (de modo que mire hacia la izquierda o hacia la derecha). Sin embargo, no puedo ver ningún método para hacerlo con drawImage.Voltear un sprite en lienzo

Aquí está mi código relevante:

this.idleSprite = new Image(); 
this.idleSprite.src = "/game/images/idleSprite.png"; 
this.idleSprite.frameWidth = 28; 
this.idleSprite.frameHeight = 40; 
this.idleSprite.frames = 12; 
this.idleSprite.frameCount = 0; 

this.draw = function() { 
     if(this.state == "idle") { 
      c.drawImage(this.idleSprite, this.idleSprite.frameWidth * this.idleSprite.frameCount, 0, this.idleSprite.frameWidth, this.idleSprite.frameHeight, this.xpos, this.ypos, this.idleSprite.frameWidth, this.idleSprite.frameHeight); 
      if(this.idleSprite.frameCount < this.idleSprite.frames - 1) { this.idleSprite.frameCount++; } else { this.idleSprite.frameCount = 0; } 
     } else if(this.state == "running") { 
      c.drawImage(this.runningSprite, this.runningSprite.frameWidth * this.runningSprite.frameCount, 0, this.runningSprite.frameWidth, this.runningSprite.frameHeight, this.xpos, this.ypos, this.runningSprite.frameWidth, this.runningSprite.frameHeight); 
      if(this.runningSprite.frameCount < this.runningSprite.frames - 1) { this.runningSprite.frameCount++; } else { this.runningSprite.frameCount = 0; } 
     } 
    } 

Como se puede ver, estoy usando el método drawImage dibujar mis sprites a la lona. La única forma de voltear un objeto que puedo ver es voltear/rotar todo el lienzo, que no es lo que quiero hacer.

¿Hay alguna manera de hacerlo? ¿O tendré que hacer un nuevo sprite mirando hacia el otro lado y usar eso?

Respuesta

10

Puede transformar el contexto de dibujo de lienzo sin voltear todo el lienzo.

c.save(); 
c.scale(-1, 1); 

reflejarán el contexto. Dibuje su imagen, luego

c.restore(); 

y puede dibujar normalmente de nuevo. Para obtener más información, consulte https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Canvas_tutorial/Transformations

+2

Gracias! Pero debido a la respuesta de Simon, usaré su técnica. Aunque marcaré la tuya como la respuesta aceptada, ya que está respondiendo mi pregunta :) –

33

Mientras Gaurav ha mostrado la forma técnica para voltear un sprite en el lienzo ...

No hacer esto para su juego.

En lugar de hacer una segunda imagen (o hacer que su imagen actual sea más grande) que es una versión volteada de la hoja spite. La diferencia de rendimiento entre "voltear el contexto y dibujar una imagen" frente a "solo dibujar una imagen" puede ser enorme. En Opera y Safari, al girar el lienzo, el dibujo es diez veces más lento y en Chrome es dos veces más lento. Ver this jsPerf para un ejemplo.

El pre-cálculo de sus sprites invertidos siempre será más rápido, y en los juegos el rendimiento del canvas realmente importa.

+0

Gracias. Lo que terminé haciendo fue agregar otro sprite al mío existente (debajo) con mi personaje corriendo hacia otro lado, y agregué un código para usar ese conjunto de sprites dependiendo de la dirección. De esta manera: http://i.imgur.com/uIPvF.png –

+1

¡Se ve bien! Aunque reorganizaría la nueva fila: alinee verticalmente la versión volteada de cada uno, de modo que lo único que tiene que cambiar cuando se voltea es la coordenada y. –

+0

La respuesta de Gaurav es realmente solo el rendimiento costoso debido a ctx.save/restore. De hecho, si simplemente llama a ctx.scale (...) cada vez, hilarantemente la versión volteada se dibuja más rápido: http://jsperf.com/ctx-flip-performance/3. (Es incluso más rápido si llama a ctx.scale (-1) para el flipped y nada para el caso de no volteo: http://jsperf.com/ctx-flip-performance/4). –