Win an Ipad
  Developer   Tutorials   Advanced tutorials   Game optimalization
Lesson 3

Game optimalization

Game Life Cycle

Game's life cycle is exactly the same as common Moscrif native application. Immediately after a game starts, a splash screen is displayed. After that Game.start is invoked. Splash screen is delayed until this event is completly finished. That means, you should load mostly used game resources in the Game.start event. The good practice is to prepare all mostly used graphics, sounds, data during the splash screen. Users expect to wait a few seconds for starting the game, but don't expect to wait any longer after they click on "new game" button.

// create new game instance var game = new Game(); // prepare game instance before its run
game.onStart = function()
{
     // load graphics
    GFX.load();
    //load sounds and musics
    SFX.load();
    // create menu scene
    this.menu = new MenuScene();
    // start with menu scene
    this.push(this.menu); } game.run();

Note, If you like more object oriented code, you will overwrite the start method instead of handling the onStart event.

class MyGame : Game {      // prepare game instance before its run
     function start()
     {
          // load graphics
         GFX.load();
         //load sounds and musics
         SFX.load();
         // create menu scene
         this.menu = new MenuScene();
         // start with menu scene
         this.push(this.menu);
     }
} new MyGame().run();

Loading Resources

As mentioned before, the best place to load external graphics, sounds, musics, fonts, data, etc. is Game.onStart/Game.start. This is especially true for frequently used objects (game backgrounds, buttons, sprites, HUD, etc). Whereas these objects are used often, wrapping classes will be implemented as static and/or with static members only. Let's say graphics resources are wrapped by GFX class:

// This class manages graphical resources such as bitmaps, vectors etc. class GFX
{
    // root dir for graphics files
    const root = "app://gfx/";     // static bitmap for game's background
    var background;
    // ... etc     // this function is also static
    function load()
    {
        assert this === GFX;
        background = Bitmap.fromFile(root + "background.jpg");
        // ... etc
    } }

Loading of the GFX, called within Game.onStart/Game.start can look like:

class MyGame : Game {     // prepare game instance before its run      function start()
     {
         // load graphics
         GFX.load();
         // … etc
     } }

… and the usage of the GFX and its fields will be pretty straightforward:

function draw(canvas) {
    canvas.drawBitmap(GFX.background, 0, 0);
    // ... other drawings ... }

Source File Optimalization

If you want to deliver a high quality game, the graphics must be high quality too. That's a problem nowadays because you have to cope with a big fragmentation of screen resolutions. Probably you will have to embed several sets of graphics which leads to a bigger installation files. Here are some tools, that can reduce an image size:

Scalable vector graphics (SVG) allows you to solve screen fragmentation very effectively, but you have to keep it in mind before you start developing. Even though SVG will also reduce file size drastically, it isn't applicable for all scenarios (e.g.: backgrounds, pixel-art graphics)...

See Canvas.path and Path class for more info related to SVG in Moscrif.

Use the Advantages of Offscreen rendering

Moscrif uses OpenGL for drawing elements which renders the graphics to the devices window directly using GPU (if present). Moscrif also allows you to use advanced techniques such as: a drawing of a shadows or an outlines,  several types of gradients, applying an effects to a fonts and/or a bitmaps, an advanced color and mask filters, a basic image effects like blur, dilate, erode etc… But these advanced techniques do additional computation out of GPU. As a result, using these advanced features can decrease performance (for 40-50FPS down to 20FPS or less).


In this case, the offscreen rendering makes a sense. The offscreen render is an approach, where you don't draw directly to the screen, but to memory (bitmap rather) instead.All complicated drawings are pre-rendered, like the following:

include "lib://core/log.ms" include "lib://game2d/game.ms"
include "app://gfx.ms" // custom game class
class Offscreen : Game
{
    function start()
    {
        super.start();         // load graphical resources
        GFX.load();         // offscreen drawing
        this._offscreen = Bitmap.fromRect(200, 200);        // created offscreen bitmap
        var canvas = Canvas.fromBitmap(this._offscreen);    // get canvas to paint to
        var paint = new Paint();
        paint.imageFilter = ImageFilter.blur(5, 5);         // apply blur filter to a bitmap
        canvas.drawBitmap(GFX.box, (this._offscreen.width - GFX.box.width)/2, (this._offscreen.height - GFX.box.height)/2, paint);         // prepare game with two sprites, the first on has "normal" bitmap, the second one has bitmap altered by "advance" method
        this._initSprites(GFX.box, this._offscreen);
    }     function draw(canvas)
    {
        // custom drawings - background
        canvas.drawBitmap(GFX.background, 0, 0);
        // default drawings
        super.draw(canvas);
    }     function process()
    {
        // just rotate all sprites
        for (var sprite in this._sprites)
            sprite.angle += 0.1;
    }     function _initSprites(normal, offscreen)
    {
        // create the first sprite
        this.add(new Sprite({image:normal, x:System.width/3, y:System.height/2}));
        // create the second sprite
        this.add(new Sprite({image:offscreen, x:System.width/3*2, y:System.height/2}));
    } } // create instace and run the game new Offscreen().run();

In this example there is just one bitmap used for sprites. The first sprite, displayed on the left side of the screenshot uses "normal" bitmap. No special effects, just simple bitmap.

The second sprite, shown on the right side of the screenshot is based on the same bitmap, but there is advanced technique applied (a blur image effect). Check out the result:

Imagine how many awesome things can be done using offscreen rendering. Some examples of things that can leverage offscreen:

  • using SVG to reduce file size but keep high quality, This saves you from screen resolution fragmentation
  • applying effects to fonts or images without additional resources
  • pre-rendering complicated game objects or scenes
  • etc...
 Designing for optima ...   Game optimalization   Publishing for Apple ... 
Tutorial details and chapters
Technology:
iOS, Android
Difficulty:
Advanced
Completion:
30 min
Advanced tutorials chapters