Jump to content

Mobile performance, what am I doing wrong?


trueicecold
 Share

Recommended Posts

Hello all

 

I've started to look at pixijs, and it's awesome. I tested BunnyMark on a several devices:

 

Samsung Galaxy 1 with some mediocre results (about 130 bunnies on my screen got about 23fps) - default browser doesn't have canvas support, so I used Firefox Mobile.

iPhone 4S - pretty cool (522 bunnies with a steady 52fps)

iPhone 3GS - 112 bunnies at 40fps

LG G2 - off the charts :)

S3: same as G2, stopped after couple of thousands.

 

While those results are pretty decent, I'm drawing a card deck, which is basically 54 textures and 54 sprites to hold the textures, and use GSAP from greenshock to position them and animate them towards the center of the screen when clicked upon. It's 54 of those:

 

this.texture = PIXI.Texture.fromImage("images/cards/processed/" + this.number + this.shape + ".png");
this.sprite  = new PIXI.Sprite(this.texture);
 
Problem is, even on S3, the animation is somewhat choppy. on S1, it's pretty bad, about 15fps, and I'm talking about throwing cards to the pile (max 5 at the same time)...on iPhone 4S, it's somewhat choppy as well...
 
After looking at Bunnymark, I'm pretty sure I'm missing some magic/secret ingredient to get my game really perform like it should...
 
One thing I can think of is that my sprites are scaled to 0.25 because the cards images I use are pretty big. Could this be a serious factor? again, I'm talking about choppiness when animating even 2-3 cards towards the center...
 
Has anyone encountered this weird behavior? am I missing something?
 
Thanks a lot :)
Link to comment
Share on other sites

You should consider using a smaller images since you are scaling them by 0.25. Additionally bunnymark is using spirtebatch which is a completely different way to render images. You cannot expect the renderer to act the same way with many single sprites.

 

Second could you provide a little bit more of your code? (Loop design, loaders etc.)

 

The example above should work fine. Maybe you have mad some bad decisions about designing your game loop that influence your performance?

 

Additionally, maybe you are using a normal browser size viewport (stage, game container - however you call it) on a mobile device. A bigger viewport means more pixels to render. I would love to help you but the code you have provided is not enough.

 

http://www.sevenative.com

Link to comment
Share on other sites

A large performance boost on webGL can be gained by having all of your cards loaded from a single image, via a sprite sheet or texture atlas. Oversimplifying things significantly, but this basically allows the GPU to cheat and only 'draw' the entire deck once, rather than draw each card separately.

Link to comment
Share on other sites

 how do I take parts of the spritesheet as part of a new sprite?

First, you should consider making the sprite sheet using some software like Texture Packer, because it makes the whole process a lot easier.

 

http://www.codeandweb.com/texturepacker

 

Texture Packer will generate a PNG file of your sprite sheet and a JSON data file.

The JSON data file stores the size and position of each sub-image on the sprite sheet (this is called a *texture atlas*)

Load the JSON file into Pixi like this:

var loader = new PIXI.JsonLoader("spritesheet.json");loader.onLoaded = makeTheSprites();loader.load();

(You just need to load the JSON file, you don't need to load the sprite sheet PNG file. But to keep things simple, save the JSON and PNG files in the same folder.)

When the JSON file is loaded, all you need to do in Pixi is reference the *frame id* of the image on the sprite sheet that you want to use to make a sprite.

The frame id will have same name as the original image name.

So if you had an image called "aceOfSpades.png", and dragged that into Texture Packer to help make the sprite sheet, the frame id will also be "aceOfSpades.png"

You can then make a new sprite using the spritesheet frame like this:

var card = new PIXI.Sprite.fromFrame("aceOfSpades.png");
Link to comment
Share on other sites

Thanks lewster32 and d13, I've switched to SpriteSheet and resized my images, but that doesn't seem to improve the mobile perfromance...

 

 

 

You can view source the main page to see my implementation of the AssetLoader, and:

 

http://dl.dropboxusercontent.com/u/6074572/cards/scripts/objects/card.js

 

To see how I use it now...

 

Still, even with Galaxy S3, performance is lagging... :/

Link to comment
Share on other sites

Ok!

 

I have tested the script on my samsung galaxy s3 MINI and there are no performance issues at all. Which is weird! Very weird!

 

Other thing is that i can see that you are testing your application with a set timeout function after the game.init() method is called. Maybe this is causing you problems with your code while testing.

 

http://stackoverflow.com/questions/4211046/why-do-multiple-settimeout-calls-cause-so-much-lag

 

Another thing is that you are using all of the functions in your code as global visible in all parts of your script. In a simple game this is all right but in case that you are planning to scale your game into some thing larger that might cause you some trouble. Right now your memory footprint is very good and it looks like a saw tooth (in game design it is good so there is no memory leak, normally in other applications that would be bad - again THIS IS A GAME).

 

You could try with implementing something as a mediator pattern for your code instead keeping all your game elements globally. Additionally to this every element of mediator pattern should be ensured by a singleton pattern so there is no possibility for continuous instantiation of your objects.

 

https://github.com/wojciak/lithiumJS - this is a mediator pattern framework that I use. My friend did it a year ago.

http://www.sevenative.com/games/multiverse/App/ - this is a sample work in progress project using this pattern

 

Singletons pattern:

// your creaturevar singleton;//pseudo class for creating creaturesvar singletonInstance = function(){this.life = 10;this.position = {   x = 0,   y = 0}this.walk = function(){position.x += 1;}}var loop = function(){       // instantiate only when not instantiated   if(!singleton){        singleton = new singletonInstance();      }loop()}// start the looploop();

This is influencing your code in two ways. Mediator keeps everything encapsulated and only passes references to the values of the objects you have and singleton makes sure nothing is instantiated too many times.

 

I WENT THROUGH MOST OF YOUR CODE AND IT ALL LOOKS CORRECT!

 

The problem might be caused by the setTimeout or something with the tween library.

 

Other thing is that if you are using phonegap to pack your game please remember that different js engines on anroid devices are used. I did not dig deep into it what engine will be used on galaxy S3

 

http://phonegap.com/2011/01/14/android-your-js-engine-is-not-always-v8/

 

And last thing is that you might consider doing native binding in the future with ejecta or other library that gives you native performance for parts of your code!

 

I don't know what else to suggest. YOUR CODE LOOKS VALID AND BEHAVES NORMALLY ON SAMSUNG GALAXY S3 MINI

 

http://www.sevenative.com

Link to comment
Share on other sites

Thanks for the detailed answer, hubert.

 

The setTimeout is ran only once, obviously, and I put it there just for tests purposes. as for the manager, I'm working on my own SceneManager (for another game actually, but I might as well try it in here). in any case, the "big" managers will be instantiated only once (Game, Pile etc...) so no need for singleton or factory in that case (although I agree it's good practice nonetheless).

 

About GSAP, It's by far the fastest and the most robust tweening library I've ever seen, and I've tests a LOT, unfortunately...

 

About the V8, I'm going to target it to Android 4.0 and up, so I'm pretty sure old devices won't target it (unless they use custom roms). I'm also tinerking with the idea of using Ludei and CocoonJS to wrap it, still need to look at their addon support (FBConnect, IAP, Push etc...)

 

There MIGHT be a problem with my S3, since I'm using custom rom (CM11), so I'm not really sure about stock rom performance, I also checked it under chrome for mobile so I really can't understand how can there be no performance issues :/

 

Thanks a lot for you answer :)

Link to comment
Share on other sites

Thanks for the detailed answer, hubert.

 

The setTimeout is ran only once, obviously, and I put it there just for tests purposes. as for the manager, I'm working on my own SceneManager (for another game actually, but I might as well try it in here). in any case, the "big" managers will be instantiated only once (Game, Pile etc...) so no need for singleton or factory in that case (although I agree it's good practice nonetheless).

 

About GSAP, It's by far the fastest and the most robust tweening library I've ever seen, and I've tests a LOT, unfortunately...

 

About the V8, I'm going to target it to Android 4.0 and up, so I'm pretty sure old devices won't target it (unless they use custom roms). I'm also tinerking with the idea of using Ludei and CocoonJS to wrap it, still need to look at their addon support (FBConnect, IAP, Push etc...)

 

There MIGHT be a problem with my S3, since I'm using custom rom (CM11), so I'm not really sure about stock rom performance, I also checked it under chrome for mobile so I really can't understand how can there be no performance issues :/

 

Thanks a lot for you answer :)

Link to comment
Share on other sites

Thanks, lewster32, I'll make a spritesheet of 54 cards, but I didn't see any "crop" method on Pixi.js, so how do I take parts of the spritesheet as part of a new sprite?

just wanted to explicitly point out that cropped 'parts of a spritesheet' are called frames.. if you review the texture and the inherited baseTexture PIXI.js defined objects.. in the context of the JsonLoader or AssetLoader, you can of course develop your own Loader.. 

Link to comment
Share on other sites

just wanted to explicitly point out that cropped 'parts of a spritesheet' are called frames.. if you review the texture and the inherited baseTexture PIXI.js defined objects.. in the context of the JsonLoader or AssetLoader, you can of course develop your own Loader.. 

 

Yeah I know, so I had to replace Texture.fromImage to Texture.fromFrame :)

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...