0

I'm building a game in Html and Javascript using the <canvas> element. As I need to flip an image horizontally, in adition to the principal canvas I create a secondary one that isn't visible for flipping the images (to avoid downloading another image for the other position) Then I draw the result of the secondary canvas in the principal one. This method works without any problem in Firefox 27, while in Chrome, Chrome mobile, Opera mobile and Firefox mobile for an unknown reason it doesn't.

The code for the secondary canvas is the following:

var flip = function (image) {
'use strict';
var offscreenCanvas = document.createElement('canvas'),
    offscreenCtx = offscreenCanvas.getContext('2d');

offscreenCanvas.width = image.width;

offscreenCtx.translate(image.width, 0);
offscreenCtx.scale(-1, 1);
offscreenCtx.drawImage(image, 0, 0);
return offscreenCanvas;
};

And the code for drawing the result in the principal canvas:

var flippedCharImg = flip(charImg);
ctx.drawImage(flippedCharImg, character.xpos, character.ypos, character.stopped.width, character.stopped.height);

Any idea of why it doesn't work on those browsers and how to make it work?

Sorry for the syntax!

dieortin
  • 514
  • 5
  • 16
  • 1
    You don't need two canvas. Draw, say, left part of the image on the main and single canvas, then copy the left half part of it on itself, on the right part, with a translate and a flip (==scale(-1,1)). The canvas specifications explicitly allows such copy. This could quite help the framerate (0.5 screen copy per frame vs 1.5 screen copy per frame). (you don't need to bother about tearing, Canvas's internal buffers will be swapped only after you stopped drawing). – GameAlchemist Feb 08 '14 at 22:44
  • Interesting. Have you tested your proposed fix in the mobile browsers mentioned? – markE Feb 08 '14 at 22:52
  • @markE Nope. But using half the memory and 1 third of the byte copy per frame should help things get better i guess :-) – GameAlchemist Feb 08 '14 at 23:40
  • 1
    Did you make sure that the image is already loaded? Maybe Firefox is loading it from cache so the image is available immediately while the other browsers need time to load it so it isn't available yet when you draw it. – Philipp Feb 09 '14 at 02:28
  • @Philipp it's probably that, because I've tried loading it from a server and the first time the flipped images didn't show. Then when I reloaded the page it worked correctly. – dieortin Feb 09 '14 at 13:58
  • @GameAlchemist sorry, could you explain it in a easier way? I didn't understand it all (my english level is so limited) – dieortin Feb 09 '14 at 14:03

1 Answers1

1

As @Philipp suggests, your code works when I make sure the images are fully loaded before trying to drawImage them.

Here's an image loader that fully loads all image and then calls your code in the start() function:

// first load all your images

var imageURLs=[];  
var imagesOK=0;
var imgs=[];

// put the URLs to any images you need in the imageURLs[] array
imageURLs.push("yourCharImg.png");

loadAllImages(start);

function loadAllImages(callback){
    for (var i=0; i<imageURLs.length; i++) {
        var img = new Image();
        imgs.push(img);
        img.onload = function(){ 
            imagesOK++; 
            if (imagesOK>=imageURLs.length ) {
                callback();
            }
        };
        img.onerror=function(){alert("image load failed");} 
        img.crossOrigin="anonymous";
        img.src = imageURLs[i];
    }      
}

// after all images are loaded, start using the images here

function start(){

    // the imgs[] array holds fully loaded images
    // the imgs[] are in the same order as imageURLs[]

    // get an image from the imgs[] array

    var charImg=imgs[0];  // or whatever image index you need

    // draw a flipped image

    var flippedCharImg = flip(charImg);
    ctx.drawImage(flippedCharImg, 
        character.xpos, character.ypos, 
        character.stopped.width, character.stopped.height
    );

}
markE
  • 102,905
  • 11
  • 164
  • 176
  • @Philipp @markE Perfect! **Thanks!** After moving some variables to global scope it's working perfectly. The only issue is a weird thing: for some reason the image (that has as y position value `canvas.height / 2`) isn't drawn in the _vertical middle_ of the canvas but much higher. It worked correctly before, I don't know what happened. Anyway it's a secondary issue and I'll probably fix it soon. – dieortin Feb 09 '14 at 18:55