sbiermanlytle / iioEngine

iio Engine: A JavaScript game engine for HTML5 Canvas
http://iioengine.com
455 stars 81 forks source link

Canvas problem #27

Closed lcnvdl closed 9 years ago

lcnvdl commented 10 years ago

Hello, I'm using iioengine with Phonegap. Works fine, but I have a problem (also in a desktop browser):

How can I update the canvas size when my game is running? (for example, if a user rotate the phone, or resize the browser's screen)

This is my function to set the size, but I need to refresh the engine or something.

function resizeCanvas() {
    var aspect = 1920/1080,
        screen = getScreen(),
        opt1   = {
            w: screen.w,
            h: Math.round(screen.w / aspect)
        },
        opt2   = {
            w: Math.round(screen.h * aspect),
            h: screen.h
        };

    var opt;

    if(opt1.h > screen.h)
    {
        opt = opt2;
    }
    else {
        opt = opt1;
    }

    $("#canvas").attr("width", opt.w).attr("height", opt.h);

    // HERE: I need to refresh my game to use the new size 
};
sbiermanlytle commented 10 years ago

iio sets a window resize listener by default like this:

window.onresize=function(){ ... }

which automatically resizes the canvas if its fullscreen and updates the canvas properties in iio. You can run custom code after a resize by implementing the resize function in your app:

var ResizableApp = function(app){

    //iio 1.3
    this.resize = function(){ ... }

    //iio 1.2
    this.onResize = function(){ ... }
}

If you need to update the canvas values manually, it is accessible through app:

var canvas = app.canvas;

lcnvdl commented 10 years ago

Hi, thank you for answer me!

My problem is (maybe I'm doing something wrong) that when I resize the canvas, the content is not scaled to the new size.

If I resize the canvas using CSS looks pretty good, but I know that is not a good practice.

This is now my code:

/**
 *  Game
 */
function MyGame(io){
    // ...
};

/**
 *  Gets the viewport size.
 */
function getScreen() {

    var w = window,
        d = document,
        e = d.documentElement,
        g = d.getElementsByTagName('body')[0],
        x = w.innerWidth || e.clientWidth || g.clientWidth,
        y = w.innerHeight|| e.clientHeight|| g.clientHeight;

    return {
        w: x,
        h: y
    };
};

/**
 *  Resizes the canvas maintaining the desired aspect.
 */
function resizeCanvas() {

    //  Calculate the best size choice
    var aspect = 1920/1080,
        scr = getScreen(),
        opt1   = {
            w: scr.w,
            h: Math.round(scr.w / aspect)
        },
        opt2   = {
            w: Math.round(scr.h * aspect),
            h: scr.h
        };

    var opt;

    if(opt1.h > scr.h)
    {
        opt = opt2;
    }
    else {
        opt = opt1;
    }

    //  Set the new size

    //  OLD method
    /*$("#game")
        .attr("width", opt.w)
        .attr("height", opt.h);*/

    //  NEW method
    $("#game")
        .css("width", opt.w*0.98+"px")
        .css("height", opt.h*0.98+"px"); 

};

/**
 *  Starts the game engine.
 */
function startGame()  {

    resizeCanvas();
    window.onresize = function(event) {
        resizeCanvas();
    };

    soundManager.setup({
            // required: path to directory containing SM2 SWF files
            url: 'bower_components/iioEngineSDK/extensions/SM2/swf/',
            preferFlash:false,
            onready: function() {
            iio.start(MyGame, "game");
        }
    });
};

How can I use "this.onResize = function(){ ... }" on my code? I don't understand what is.

When I use this.onResize: Do I need to move and scale all objects manually?

Thank you very much!

Regards

sbiermanlytle commented 10 years ago

Is CSS scaling not good practice? That's how I've been handling scaling so far in 1.3, like with the apps here: http://iioapps.com. I wonder if it is faster for the browser to scale the whole canvas, or for iio to scale the rendering of each object - I will test this for 1.3.

In your code, the window.onresize function will overwrite iio's resize handler, so if you removed that and put this in MyGame:

this.onResize = function(event){
    resizeCanvas(); //this happens by default with fullscreen apps
    //but overwriting it should be okay

    //resize game objects
    //...  
}

the canvas is accessible through io.canvas, and you have access to io and all the game objects. You would have to move and scale all the objects manually to resize them.

lcnvdl commented 10 years ago

I said that is not a good practice because I'm using iioengine with Phonegap for Android,

and this (for example)

<canvas width="1920" height="1080" style="width:480px;height:270px;"></canvas>

is very heavy in comparison with:

<canvas width="480" height="270"></canvas>

The first draws in a big canvas and then transforms it with css.

The second draw a small canvas.

That's why I said that.

lcnvdl commented 10 years ago

I'm trying to implement fast-canvas because Phonegap + Canvas on Android is very slow, but I'm having problems...

sbiermanlytle commented 10 years ago

Ok, if its that big of a size difference, then the most efficient thing to do would be to scale all the objects upon creation. If you pass a width and height to the objects constructor, it will override the image's width and height and scale it. If you have to rescale the objects at any point, put that code in the onResize function.

lcnvdl commented 10 years ago

interesting... thank you!