Sprite game with OpenGL/GLKit

Posts: 3
Joined: 2012.09
Post: #1
hi, after a year or something that i didn't touch xcode i wanna try to make a game again, i think last time i messed with it GLKit didn't exist, so i thought what the hell, maybe i should give it a try. (i'm not that good with opengl anyways).
i tried to follow this tutorial :

what i need is drawing a texture with rotation, alpha, xscale, yscale... pretty standard for a sprite game i think. i managed to add all the capabilities i wanted, but i think the performance is really sucky. (i'm trying to render at 60 fps)
i get a huge lag at around 300 objects on the screen. i suppose maybe it's because that he calls prepareToDraw (GLKBaseEffect) every time it renders?
anyways, i'm just wondering what's the best way to do it. (should i just diss GLKit? how am i supposed to use it? i would love to see a good example or tutorial)
i know the iphone can do better, so i'm probably doing something really wrong.

the game i'm trying to make is a scrolling game, and i tried to put 4 background "sprites" that each one scrolls at a different speed and the frame rate got insanely SLOW. how can i do that???

and one last thing- is it possible that my iphone runs my game with better performance than the simulator on my MBP?
Quote this message in a reply
Posts: 713
Joined: 2002.04
Post: #2
(Sep 29, 2012 01:32 PM)InvisibleMoustache Wrote:  is it possible that my iphone runs my game with better performance than the simulator on my MBP?

Yes; and the inverse is also possible.

Mark Bishop
Student and freelance OS X & iOS developer
Quote this message in a reply
Posts: 5,143
Joined: 2002.04
Post: #3
Generally, anything relying on the CPU will be faster on the simulator, and anything relying on the GPU will be faster on the device.

For a 2D game you should be attempting to get down to ~3 calls to glDrawElements per frame. Use a sprite atlas and build your vertex arrays manually each frame.

You can probably continue to use GLKEffect, but you certainly shouldn't be calling -prepareToDraw for each sprite; once or twice for all sprites is more reasonable.
Quote this message in a reply
Posts: 3
Joined: 2012.09
Post: #4
hey thanks for the advice, but i got a few problems-
1. i have lots of animation, i'm not sure everything will get into a single sprite atlas, and that will be a hell to manage since i have varying sizes of sprites... any tips?
(and if i remember correctly there is a size limit of 2048 X 2048 per texture, right?)
2. the game is quite random (i randomly create objects which scroll through the screen, and i also hope to add particle effects) so i how am i supposed to draw more than one object in roughly the same space? (i mean if i have three balls which overlap, is it possible to draw them on top of each other in a single glDrawElements call)?

it seems really weird that i got such a low performance, it's not that i'm trying to draw something highly graphic, i was hoping not to mess around with atlases, batching and all that stuff... i'm pretty sure i got something basic wrong
Quote this message in a reply
Posts: 5,143
Joined: 2002.04
Post: #5
Get an app to manage it. If you need multiple sprite atlases, you need multiple sprite atlases (and it may be worth splitting opaque from transparent anyway), but ideally you can do only one draw call per atlas. If you have ridiculous amounts of graphics with transparency and arbitrary ordering, that might get screwed up, but you probably have worse problems then than too many draw calls Wink

Yes, you can draw overlapping sprites in a single DrawElements. In the absence of depth testing, the sprites earlier in the call will be behind the sprites later in the call.

Anyway, worrying about performance in the simulator is pretty futile. You need a device, or just start with the Mac port of your game Rasp
Quote this message in a reply
Posts: 3
Joined: 2012.09
Post: #6
hi, so after further development (btw i had a device all along i just wondered why the performance is so different between the device and the simulator Rasp ) performance became pretty sucky (in "heavy" situations)
so i've put many of the graphics into an atlas and i send all consecutive sprites of the same atlas in one call, i think it helped a little, but i still have a feeling that the iphone can do better...
i ran instruments with opengl es analysis and these are the results:
i honestly have no idea what that means. and i'm pretty weak with OpenGL/iphone development, but i would really like to finish this game and put it on the app store, i've done lots of work and it's really awesome Grin
can anyone give me any advice?
basically this is the class that does the drawing:
#import "Batcher.h"
#import "SGGSprite.h"

@implementation Batcher
static Batcher *_instance;
TexturedQuad vert[1000];
int sprCount;
GLushort indices[6000];

+(Batcher*) instance {
    return _instance;

+ (void)initialize
    static BOOL initialized = NO;
        initialized = YES;
        _instance = [[Batcher alloc] init];
        sprCount = 0;
        for(int i=0; i < 1000; i++) {
            indices[6 * i + 0] = 4 * i + 0;
            indices[6 * i + 1] = 4 * i + 1;
            indices[6 * i + 2] = 4 * i + 2;
            indices[6 * i + 3] = 4 * i + 1;
            indices[6 * i + 4] = 4 * i + 2;
            indices[6 * i + 5] = 4 * i + 3;

- (void) addQuad: (TexturedQuad*) quad {
    vert[sprCount] = *quad;

-(void) batch {
    long offset = (long)&vert;
    glVertexAttribPointer(GLKVertexAttribPosition, 2, GL_FLOAT, GL_FALSE, sizeof(TexturedVertex), (void *) (offset + offsetof(TexturedVertex, geometryVertex)));
    glVertexAttribPointer(GLKVertexAttribTexCoord0, 2, GL_FLOAT, GL_FALSE, sizeof(TexturedVertex), (void *) (offset + offsetof(TexturedVertex, textureVertex)));
    glVertexAttribPointer(GLKVertexAttribColor, 4, GL_FLOAT, GL_FALSE, sizeof(TexturedVertex), (void *) (offset + offsetof(TexturedVertex, colorVertex)));
    glDrawElements(GL_TRIANGLES, sprCount * 6, GL_UNSIGNED_SHORT,  &indices);
    sprCount = 0;

when every sprite object needs to be drawn it calls the addQuad function (all the calculations are done on the cpu), and if the texture is different from the last drawn texture then (before the addQuad call) it calls the batch function. sorry about the names and the 1000 thing, i work alone so no one cares. Smile
also if my code has like obvious mistakes or something i would like to know!!!

Quote this message in a reply
Posts: 5,143
Joined: 2002.04
Post: #7
I can't tell you much about your profile other than parroting the exact words that are already right there for you to see Wink

You've got a lot of redundant state changes (eg. glEnable(GL_BLEND) when it's already enabled). You've got a lot of calls per frame to glDrawElements still, many of which contain few vertices. 20000 times you even called glDrawElements with NO vertices! You're not using VBOs, which might help (or might not, given your usage pattern, but at least it would shut the analyzer up). Your framerate is pretty consistent (and I'm guessing it's pretty close to 60 except the one big hitch, but without any kind of scale I can't be certain). Focusing in on the big hitch might reveal more information about why you had problems at that time in particular.

Make sure you disable blending for opaque sprites (eg. tiles and backgrounds).

From what you've said, it sounds like depending upon sprite ordering you might have to switch atlases many times. Can you not put all the transparent sprites into the same atlas?
Quote this message in a reply
Post Reply 

Possibly Related Threads...
Thread: Author Replies: Views: Last Post
  Sprite transparency in OpenGL? Guest! 26 39,944 Feb 17, 2012 09:24 AM
Last Post: Skorche
  OpenGL Sprite Structure Stalin55 2 5,630 Aug 18, 2006 03:40 PM
Last Post: AnotherJake
  SDL + OpenGL Sprite Loading Problem Greywhind 3 6,421 Jun 29, 2006 04:44 PM
Last Post: OneSadCookie
  2D Sprite Tutorial in OpenGL DJBlufire 4 9,107 May 12, 2003 12:46 AM
Last Post: arekkusu