Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.


Messages - Dids

Pages: [1] 2
1
iOS / Re: Texture Atlas Tutorial
« on: Fri, Apr 27, 2012 »
Oh, I totally missed that, that's good to know, thanks. :)

2
iOS / Texture Atlas Tutorial
« on: Fri, Apr 27, 2012 »
Recently I noticed that Canabalt uses texture atlases instead of individual sprites and upon researching these further, I noticed that they (supposedly) have an impact on performance, especially in flixel-ios's case, because you can preload (cache) them on startup, so they only have to be loaded in to memory once.

After much trial and error, I found the right "path" to succesfully using texture atlases on all iOS devices, using the latest iOS SDK and latest XCode. The following tutorial is based on what worked for me.

1. Get an app that produces atlases. I experimented with many (including TexturePacker and ShoeBox) but ultimately went with the one that worked the best: Zwoptex. The free version should do just fine.

2a. Get all your sprite graphics ready and import them in to Zwoptex.

2b. It's important to note that you need to (I had to) fit everything inside a 512x512 texture atlas, so in case they just won't fit, you'll have to create multiple atlases and link them together (which is what I did), more on this later.

3. In Zwoptex, select all your sprites and uncheck the Trim(med) option, we don't want that. Also set all padding/margins/etc to zero (0). Remember to set the width and height to 512, as previously discussed.

4. Open up Zwoptex preferences, open up the Coordinates Formats tab and click the + sign to add a new format. I named mine Flixel iOS. Set the extension to .plist and paste the following in to the source box.
Code: [Select]
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>images</key>
<dict>{% for sprite in sprites %}
<key>{{ sprite.name }}</key>
<dict>
<key>atlas</key>
<string>{{ metadata.target.textureFileName }}{{ metadata.target.textureFileExtension }}</string>
<key>x</key>
<real>{{ sprite.textureRectX }}</real>
<key>y</key>
<real>{{ sprite.textureRectY }}</real>
<key>width</key>
<real>{{ sprite.sizeWidth }}</real>
<key>height</key>
<real>{{ sprite.sizeHeight }}</real>
</dict>{% /for %}
</dict>
</dict>
</plist>

5. Close the Preferences window and click on the big Layout-button in the upper left corner. This will automagically move your sprites around to fit the space of the atlas. Remember, if it seems like it's unable to fit them (ie. most of them are top of eachother in the upper left corner), remove some of them and add the removed sprites to a new atlas (using the same settings as before).

6. Once the layout process is done and it looks like it worked, click on Publish Settings in the upper right corner. For simplicitys sake, I changed the Save To File fields of both the atlas and the plist to say "MyAtlas.png" and "MyAtlas.plist", just seemed easier that way. From the Format-dropdown menu, select the previously created Flixel iOS format template and click Done.

7. You're ready to Publish, so go on ahead and click that big button (you've already set up the Publish Settings, so if it warns you about them, just click Done).

8. Repeat this process for any extra atlases that you might need, I separated my big and small sprites, so I had two atlases (SmallAtlas.png/plist & BigAtlas.png/plist).

9a. As Zwoptex doesn't seem to support multiple texture atlases using only one plist, we'll need to do a bit of work here.

9b. Open up your favorite text editor and open all of the plist files of the previously created atlas(es).

9c. Create a new file (I called mine CombinedAtlas.plist), which will hold all the atlas data combined. You'll need the basic plist structure, but you'll also need to copy and paste the relevant data from all of the plist files you've previously created. To recap: you'll create a plist template, then fill in the items from all the atlas plists you have, it should be pretty simple. Here's something to visualize that a bit better.
Code: [Select]
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>images</key>
<dict>
<key>BigSprite.png</key>
<dict>
<key>atlas</key>
<string>BigAtlas.png</string>
<key>x</key>
<real>160</real>
<key>y</key>
<real>0</real>
<key>width</key>
<real>32</real>
<key>height</key>
<real>224</real>
</dict>
<key>SmallSprite.png</key>
<dict>
<key>smoke.png</key>
<dict>
<key>atlas</key>
<string>SmallAtlas.png</string>
<key>x</key>
<real>464</real>
<key>y</key>
<real>74</real>
<key>width</key>
<real>16</real>
<key>height</key>
<real>16</real>
</dict>
</dict>
</dict>
</plist>

10. You're almost there! Add (copy) the CombinedAtlas.plist and both the SmallAtlas.png and BigAtlas.png to your XCode project (leaving the Small/Big plists out, because we don't need those anymore).

11. Open up your AppDelegate and mofify the preloadTextureAtlases() function like seen below.
Code: [Select]
void preloadTextureAtlases()
{
    NSDictionary * infoDictionary = nil;
    infoDictionary = [NSDictionary dictionaryWithContentsOfFile:[NSString stringWithFormat:@"%@/%@", [[NSBundle mainBundle] resourcePath], @"CombinedAtlas.plist"]];
    NSDictionary *images = [infoDictionary objectForKey:@"images"];
    for (NSString *image in images)
    {
        NSDictionary * imageInfo = [images objectForKey:image];
        CGRect placement;
        placement.origin.x = [[imageInfo objectForKey:@"x"] floatValue];
        placement.origin.y = [[imageInfo objectForKey:@"y"] floatValue];
        placement.size.width = [[imageInfo objectForKey:@"width"] floatValue];
        placement.size.height = [[imageInfo objectForKey:@"height"] floatValue];
NSString * atlas = [imageInfo objectForKey:@"atlas"];
        SemiSecretTexture * textureAtlas = [FlxG addTextureWithParam1:atlas param2:NO];
        SemiSecretTexture * texture = [SemiSecretTexture textureWithAtlasTexture:textureAtlas offset:placement.origin size:placement.size];
        [FlxG setTexture:texture forKey:image];
    }
}

12. Make sure you're calling it in the AppDelegate's didFinishLaunchingWithOptions function after you've initialized your game and before returning YES.

13. You're welcome. (yes, that's it, no more steps!)

Hopefully I didn't forget anything, as I just figured all this out myself, so writing it mostly out of memory. :-)

3
iOS / Re: iPad 3 & Texturebuffer Zooming
« on: Wed, Apr 18, 2012 »
It's based on the original (and old) flixel-ios code on Github. Since then, I've had to modify it quite a bit to support Game Center (there's still orientation issues) and to fix all of the warnings.

4
iOS / Re: iPad 3 & Texturebuffer Zooming
« on: Wed, Apr 18, 2012 »
And input's fixed!

For future reference, here's a small how to. You'll have to modify two files, FlxGame.m and FlxTouches.m. Granted, I could've snipped away most of it, but the reason I included entire blocks was so that it's easier to find the parts that you need to modify.

1. Enable textureBufferZoom for when both FlxG.iPad and FlxG.retinaDisplay return true
2. Open up FlxGame.m and search for textureBufferZoom and do the following changes

(these are the modified versions, but shouldn't take long to find & replace)

Code: [Select]
//which way are we oriented?
        if (textureBufferZoom) {
if (FlxG.iPad && FlxG.retinaDisplay)
{
if (gameOrientation == FlxGameOrientationPortrait)
                    [FlxG setGameData:self
                                width:(int)(glView.bounds.size.width/2/_zoom)
                               height:(int)(glView.bounds.size.height/2/_zoom)
                                 zoom:Zoom];
                else
                    [FlxG setGameData:self
                                width:(int)(glView.bounds.size.height/2/_zoom)
                               height:(int)(glView.bounds.size.width/2/_zoom)
                                 zoom:Zoom];
}
            else if (!FlxG.iPad && FlxG.retinaDisplay) {
                if (gameOrientation == FlxGameOrientationPortrait)
                    [FlxG setGameData:self
                                width:(int)(glView.bounds.size.width/_zoom)
                               height:(int)(glView.bounds.size.height/_zoom)
                                 zoom:Zoom];
                else
                    [FlxG setGameData:self
                                width:(int)(glView.bounds.size.height/_zoom)
                               height:(int)(glView.bounds.size.width/_zoom)
                                 zoom:Zoom];
            } else {
                if (gameOrientation == FlxGameOrientationPortrait)
                    [FlxG setGameData:self
                                width:(int)(glView.bounds.size.width/_zoom/2)
                               height:(int)(glView.bounds.size.height/_zoom/2)
                                 zoom:Zoom];
                else
                    [FlxG setGameData:self
                                width:(int)(glView.bounds.size.height/_zoom/2)
                               height:(int)(glView.bounds.size.width/_zoom/2)
                                 zoom:Zoom];
            }
        } else {
            if (FlxG.retinaDisplay && !FlxG.iPad) {
                if (gameOrientation == FlxGameOrientationPortrait)
                    [FlxG setGameData:self
                                width:(int)(glView.bounds.size.width)
                               height:(int)(glView.bounds.size.height)
                                 zoom:Zoom];
                else
                    [FlxG setGameData:self
                                width:(int)(glView.bounds.size.height)
                               height:(int)(glView.bounds.size.width)
                                 zoom:Zoom];
            } else {
                if (gameOrientation == FlxGameOrientationPortrait)
                    [FlxG setGameData:self
                                width:(int)(glView.bounds.size.width/_zoom)
                               height:(int)(glView.bounds.size.height/_zoom)
                                 zoom:Zoom];
                else
                    [FlxG setGameData:self
                                width:(int)(glView.bounds.size.height/_zoom)
                               height:(int)(glView.bounds.size.width/_zoom)
                                 zoom:Zoom];
            }       
        }   

Code: [Select]
//redundant on iphone (not ipad), since we only bind one framebuffer
    if (textureBufferZoom) {
        glBindFramebufferOES(GL_FRAMEBUFFER_OES, textureFrameBuffer);
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();

if (FlxG.iPad && FlxG.retinaDisplay)
glOrthof(0, backingHeight/4, backingWidth/4, 0, -1, 1);
else
glOrthof(0, backingHeight/2, backingWidth/2, 0, -1, 1);
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
        //flip and shift...
        glScalef(-1.0, 1.0, 1.0);

if (FlxG.iPad && FlxG.retinaDisplay)
glTranslatef(-backingHeight/4, 0, 0);
else
glTranslatef(-backingHeight/2, 0, 0);
    }

Code: [Select]
if (textureBufferZoom && FlxG.iPad && FlxG.retinaDisplay)
{
glDisable(GL_BLEND);
        glBindFramebufferOES(GL_FRAMEBUFFER_OES, frameBuffer);
        glPushMatrix();
       
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        glOrthof(0, backingWidth/2, backingHeight/2, 0, -1, 1);
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
       
        glViewport(0, 0, backingWidth, backingHeight);
       
        switch (gameOrientation) {
            case FlxGameOrientationPortrait:
                glTranslatef(backingWidth/2/2, backingHeight/2/2, 0);
                glRotatef(actualAngle, 0, 0, 1);
                glTranslatef(-backingWidth/2/2, -backingHeight/2/2, 0);
                break;
            default:
            case FlxGameOrientationLandscape:
                glTranslatef(backingWidth/2/2, backingHeight/2/2, 0);
                glRotatef(-90+actualAngle, 0, 0, 1);
                glTranslatef(-backingHeight/2/2, -backingWidth/2/2, 0);
                break;
        }
       
        glTranslatef(FlxG.quake.x*2, FlxG.quake.y*2, 0);
       
        glClear(GL_COLOR_BUFFER_BIT);
       
        [FlxObject unbind];
       
        //     glDisableClientState(GL_COLOR_ARRAY);
        //     glEnableClientState(GL_VERTEX_ARRAY);
        //     glEnableClientState(GL_TEXTURE_COORD_ARRAY);
       
        glBindTexture(GL_TEXTURE_2D, renderTexture);
        glVertexPointer(2, GL_SHORT, 4*sizeof(GLshort), &renderVerticesUVs[0]);
        glTexCoordPointer(2, GL_SHORT, 4*sizeof(GLshort), &renderVerticesUVs[2]);
        glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
       
        //glDisableClientState(GL_TEXTURE_COORD_ARRAY);
       
        glBindTexture(GL_TEXTURE_2D, 0);
        glEnableClientState(GL_COLOR_ARRAY);
        glColorPointer(4, GL_UNSIGNED_BYTE, 0, blackColors);
        glVertexPointer(2, GL_SHORT, sizeof(GLshort)*2, blackVertices);
        glDrawArrays(GL_TRIANGLE_STRIP, 0, 10);
        glDisableClientState(GL_COLOR_ARRAY);
       
        //glEnableClientState(GL_TEXTURE_COORD_ARRAY);
       
        glPopMatrix();
       
        glEnable(GL_BLEND);
}
    else if (textureBufferZoom) {
        glDisable(GL_BLEND);
        glBindFramebufferOES(GL_FRAMEBUFFER_OES, frameBuffer);
        glPushMatrix();
       
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        glOrthof(0, backingWidth/2, backingHeight/2, 0, -1, 1);
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
       
        glViewport(0, 0, backingWidth, backingHeight);
       
        switch (gameOrientation) {
            case FlxGameOrientationPortrait:
                glTranslatef(backingWidth/2/2, backingHeight/2/2, 0);
                glRotatef(actualAngle, 0, 0, 1);
                glTranslatef(-backingWidth/2/2, -backingHeight/2/2, 0);
                break;
            default:
            case FlxGameOrientationLandscape:
                glTranslatef(backingWidth/2/2, backingHeight/2/2, 0);
                glRotatef(-90+actualAngle, 0, 0, 1);
                glTranslatef(-backingHeight/2/2, -backingWidth/2/2, 0);
                break;
        }
       
        glTranslatef(FlxG.quake.x*2, FlxG.quake.y*2, 0);
       
        glClear(GL_COLOR_BUFFER_BIT);
       
        [FlxObject unbind];
       
        //     glDisableClientState(GL_COLOR_ARRAY);
        //     glEnableClientState(GL_VERTEX_ARRAY);
        //     glEnableClientState(GL_TEXTURE_COORD_ARRAY);
       
        glBindTexture(GL_TEXTURE_2D, renderTexture);
        glVertexPointer(2, GL_SHORT, 4*sizeof(GLshort), &renderVerticesUVs[0]);
        glTexCoordPointer(2, GL_SHORT, 4*sizeof(GLshort), &renderVerticesUVs[2]);
        glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
       
        //glDisableClientState(GL_TEXTURE_COORD_ARRAY);
       
        glBindTexture(GL_TEXTURE_2D, 0);
        glEnableClientState(GL_COLOR_ARRAY);
        glColorPointer(4, GL_UNSIGNED_BYTE, 0, blackColors);
        glVertexPointer(2, GL_SHORT, sizeof(GLshort)*2, blackVertices);
        glDrawArrays(GL_TRIANGLE_STRIP, 0, 10);
        glDisableClientState(GL_COLOR_ARRAY);
       
        //glEnableClientState(GL_TEXTURE_COORD_ARRAY);
       
        glPopMatrix();
       
        glEnable(GL_BLEND);
    }

And finally in FlxTouches
Code: [Select]
if (FlxG.game.textureBufferZoom)
  {
  if (FlxG.iPad && FlxG.retinaDisplay)
  {
  p.x /= 4;
  p.y /= 4;
  }
  else
  {
  p.x /= 2;
  p.y /= 2;
  }
}
  return p;

5
iOS / Re: iPad 3 & Texturebuffer Zooming
« on: Wed, Apr 18, 2012 »
Well I'll be damned, I actually got it to display correctly (as in, identical to the iPad 1/2 version).

Only thing still screwed up is the touch input.

6
iOS / iPad 3 & Texturebuffer Zooming
« on: Tue, Apr 17, 2012 »
As it stands, flixel-ios doesn't support the new iPad (3), as the previously working iPad solution has been to double the texturebuffer(s), but with the release of the new iPad, that texturebuffer would have to be quadrupled.

Has anyone succeeded in this yet?

7
iOS / Re: flixel-iOS for native mac games?
« on: Sun, Apr 1, 2012 »
I just had a go at porting Flixel from a custom iOS version to OS X, but the main problem is that iOS uses OpenGL ES while OS X uses pure OpenGL, so a lot of OpenGL knowledge is required for a succesfull port.

8
help / Re: FlxTilemap and FlxTileBlock
« on: Wed, Aug 17, 2011 »
Hmm, so if in fact FlxTilemap holds tiles as FlxTiles, shouldn't I be able to access them by for example using a foreach loop?
I also noticed that FlxTile has no alpha, so that's out of the question. I'd also need to set the health of certain tile types, but I'm still confused as to what way I can access the tiles, apart from setting the tile image using getTile/setTile. :-/

EDIT: Nevermind, got the hang of it now!

9
help / Re: FlxTilemap and FlxTileBlock
« on: Wed, Aug 17, 2011 »
Doh! Completely overlooked FlxTile, hence the confusion. Thank you once again, photonstorm. :)

10
help / FlxTilemap and FlxTileBlock
« on: Wed, Aug 17, 2011 »
Hey guys,

I'm a bit confused about FlxTilemap, as I need to access individual tiles as sprites, mainly so I can set their alpha value manually.

Does FlxTilemap contain the tiles as FlxTileBlocks and if not, is there a handy way of doing this so I could access them?

My tilemap is 500x500 at the moment, so it's pretty big and takes a while to load.

EDIT: I guess I could draw duplicate tiles with preset transparency, but that seems a bit hacky and overcomplicated.
EDIT2: Also, on a somewhat related note, how would I go about setting the tile graphic to be bigger than the actual tile size? Ie. tile would be 16x16 but the graphic would be 16x20.

11
help / [SOLVED] [Flixel 2.5] onFocus crashing FlxSound
« on: Thu, May 19, 2011 »
Heh, found the problem. I was playing the music clip in the constructor of my playstate, so just have to move that in create() and it's all good. ;)

12
help / Re: [Flixel 2.5] onFocus crashing FlxSound
« on: Mon, May 16, 2011 »
Weirdly enough, this works just fine:

Code: [Select]
package
{
import org.flixel.*;

public class PlayState extends FlxState
{
[Embed(source = "test.mp3")] private var sfxTest:Class;

override public function create():void
{
super.create();

FlxG.playMusic(sfxTest);
}

override public function update():void
{
super.update();

if (FlxG.keys.justPressed("SPACE"))
FlxG.play(sfxTest);
}
}
}

I'll keep searching to see what might be causing it, as I'm playing several sounds on various events (hurt, die, touch, etc.).

The specific error I get in my own project is:

Code: [Select]
TypeError: Error #1009: Cannot access a property or method of a null object reference.
at org.flixel::FlxSound/play()
at org.flixel::FlxG$/playSounds()
at org.flixel::FlxGame/onFocus()

I just noticed that if I press "continue", the game continues as expected and all sound clips play, until I go out of focus again and the error just repeats itself. :)

13
help / Re: [Flixel 2.5] onFocus crashing FlxSound
« on: Mon, May 16, 2011 »
Ah, I was under the impression that the loss of focus did some rudimentary pausing on its own. :)
Does it atleast change Flixel's paused state so I could compare against that?

14
help / [Flixel 2.5] onFocus crashing FlxSound
« on: Mon, May 16, 2011 »
So, I've been able to reproduce some weird behavious with the way the loss of focus/gained focus detection handles pausing sounds.

I'm playing a looping music track on the background via just FlxG.play(track) and doing the same for all the other sound effects.
If I do an action in-game that causes a sound to start playing, then click outside the play-window, the game pauses just like intended, however, when I click back in FlxSound crashes on the following line:

Code: [Select]
channel = _sound.play(0,9999,_transform);
With a typical Cannot access a property or method of a null object reference.

Am I supposed to handle the sound pausing myself, or is this indeed a bug?

15
help / Re: 2.50 & "fixed" collisions
« on: Thu, May 5, 2011 »
Heh, now I just feel stupid. ;)
Somehow I've overlooked immovable completely. :)

16
help / 2.50 & "fixed" collisions
« on: Thu, May 5, 2011 »
I noticed that setting an object's fixed collisions is gone.

How would I go about implementing collisions where objects simply stop when they collide?

Even though the docs say that setting an objects mass only affects elasticity, setting elasticity to 0 and mass to something really big does make a difference.

At the moment I have several blocks that are supposed to "stack" on top of eachother, without any bounciness, jitter and such.

17
help / Re: Flixel 2.50 & Pausing
« on: Tue, May 3, 2011 »
Figures, as settings FlxG.paused to true had no effect. Oh well, no biggie!
Just have to remove the out of focus code, but found that already.

PS. A bit off topic, but I absolutely love Quartet. :-)

18
help / Flixel 2.50 & Pausing
« on: Tue, May 3, 2011 »
So, what happened to pausing with the new Flixel release? :-)

Looking to either customize the pause screen or disable it altogether, but there aren't any posts about pausing in 2.50, so I'm a bit lost here.

19
releases / Re: v2.50 beta thread!
« on: Thu, Apr 28, 2011 »
Not really sure if this belong in this thread anymore, but it's worth a short. ;-)

Does anyone have any tips on updating the path while moving at a relatively high velocity? So far all my efforts have ended up in laggy movement, no matter how often/rarely I update an object with a new path.

Should I just calculate the path, then iterate through the nodes one by one, instead of using followPath altogether?

20
releases / Re: v2.50 beta thread!
« on: Mon, Apr 25, 2011 »
Got a bit further using a really simple Mappy-generated tilemap.

It seems my problem is with collisions, as it's returning null when checking for allowCollisions, even though I'm only using two tiles and setting their properties so that one's collidable (walls) and one's not (floors).

EDIT: Gotten as far as getting calculating the distance, so getting there, but the following if sentence seems to be null:
Code: [Select]
if((_tileObjects[_data[i]] as FlxTile).allowCollisions)Guess I could try yet another tile editor. :-P

EDIT2: Err what the heck, it's working now, apparently had a problem with tile collisions.

Pages: [1] 2