Cocoa: Tile Question

Criollo
Unregistered
 
Post: #1
Hey everyone. I'm trying to create a simple tile-based game in Cocoa, but I'm having some problems. Basically, I have a custom view in which all the tiles are drawn in the drawRect method. The problem is that everytime I move my character, the entire view updates, which is slowing down my program. Is there any way that I could just update the portions of the view that need updating, and not the entire view? Thanks.

-Criollo
Quote this message in a reply
Member
Posts: 370
Joined: 2002.04
Post: #2
One way to do that would be to keep an array of tiles which need to be updated. Every time the player touched a tile, it would be added to that list. Every frame, the renderer renders each tile in the list and then clears the list.

Did you ever wonder why we had to run for shelter when the promise of a brave new world unfurled beneath the clear blue sky?
Quote this message in a reply
Sage
Posts: 1,232
Joined: 2002.10
Post: #3
Figure out which portion of your drawing is taking up "too much" time and optimize it or redesign your tiling approach.

Any recent Mac should have no problem drawing a few hundred tiles filling the display at several hundred frames per second.
Quote this message in a reply
Member
Posts: 269
Joined: 2005.04
Post: #4
Are you using NSImages and Quartz to draw the tiles? If so, then you shouldn't be. Switch to OpenGL. Quartz is far too slow for games.
Quote this message in a reply
Criollo
Unregistered
 
Post: #5
Quote:One way to do that would be to keep an array of tiles which need to be updated. Every time the player touched a tile, it would be added to that list. Every frame, the renderer renders each tile in the list and then clears the list.

How would I render just the tiles that need to be rendered, though? When I set setNeedsDisplay to YES, it redraws the entire view.

Quote:Any recent Mac should have no problem drawing a few hundred tiles filling the display at several hundred frames per second.

Well, the program is noticeably slow drawing a matrix of 16X12 on my computer(blueberry iMac).

-Criollo
Quote this message in a reply
Criollo
Unregistered
 
Post: #6
Quote:Are you using NSImages and Quartz to draw the tiles? If so, then you shouldn't be. Switch to OpenGL. Quartz is far too slow for games.

Yes, I am using NSImages with gif and tiff files. I understand that Quartz is slower than OpenGL, but do I really need 3D acceleration just to create a simple tile based game? The current speed would be acceptable if I could only update the portion of the view that needed updating, instead of redrawing the view everytime. Is there any way to do this? Thanks.

-Criollo
Quote this message in a reply
Member
Posts: 22
Joined: 2003.06
Post: #7
Quote:Originally posted by Criollo
How would I render just the tiles that need to be rendered, though? When I set setNeedsDisplay to YES, it redraws the entire view.

I think you can simply make an NSView subclass and override drawRect:
Btw, when I was looking for a way to implement my tile-based uDG entry (Bubble Blast!), I noticed that OpenGL is the best. If you don't want to learn it, you can use the amazing CocoaBlitz framework, as I did.

if ( [[iDevGames uDevGame] started] )
{
Thought *uDevGameEntry = (Thought*)[[brain thoughts] objectForKey:kUDevGameEntry];

[self setMainProgrammingProject:uDevGameEntry];
}
Quote this message in a reply
Member
Posts: 156
Joined: 2002.11
Post: #8
I've been trying to do something similar, a vertical scrolling shoot'em-up. I put together a base structure to load the pic files from the main bundle or from a resource file - in Carbon, not in Cocoa - and three blocks of code to draw the pics with QuickDraw, Quartz, or OpenGL.

From what I've seen, you can have 20 sprites (32 bits) moving on the screen in a old iMac 333 (no hardware acceleration) and get 40+ fps, but then you start scrolling the background (16 bits), the framerate drops drastically to about 7 fps. The same 20 sprites with a scrolling background (320 x 480 pixels) averages 30 fps on a new 12" Powerbook 1GHz (that's with Quickdraw or Quartz).

With Quickdraw, you can get good results if you reduce the number of colors of your bitmaps and tell the program which rectangles to update. That's kind of trick to do with Quartz because the graphics context depends on the current screen setting and it only accepts 8, 16 or 32 bits images. I have the impression that scaling the bit depth of your pics is easier with Cocoa.

Now, with OpenGL, you are sure to get better frame rates on newer Macs, but I understand that the textures need to be at least 64 x 64 pixels, with dimensions always a power of 2, etc. It's not that hard to load TGA pics with an embedded alpha channel (to create transparency effects - colorkeying) to create your OpenGL textures. I am loading bitmaps from the main bundle and converting the actual bitmap data from the TGA files into OpenGL textures. No sweat there - check the NeHe web-site for sample code in Cocoa.
Quote this message in a reply
Sage
Posts: 1,232
Joined: 2002.10
Post: #9
If you read the docs for NSView, right next to setNeedsDisplay you'll find setNeedsDisplayInRect. Be warned that the view system may stupidly coalesce disparate rects into one large dirty rect on pre-Panther systems, though. Another useful place for QuartzDebug.

A blueberry iMac is questionably "recent", in terms of Quartz Extreme.

OpenGL is not just 3D acceleration. It is graphics acceleration, 2D or 3D.

GL textures can be any size (up to a hardware limit, such as 2048x2048) and do not need to be a power of two. They may consume a power of two section of VRAM if you don't (or can't) use the rectangle texture extension, though.

Don't use TGA format. Ever.
Quote this message in a reply
Member
Posts: 42
Joined: 2002.09
Post: #10
Quote:Originally posted by Steven
One way to do that would be to keep an array of tiles which need to be updated. Every time the player touched a tile, it would be added to that list. Every frame, the renderer renders each tile in the list and then clears the list.


Criollo, you can do this without any subclassing.

In your drawInRect method, only render the tiles that are marked as needing to be drawn:

for (tileN=0;tileN<nTiles;tileN++){
if (needsToBeDrawn(tileN){
[[tileArray objectAtIndex:tileN] compositeToPoint... etc];
}
}

Visit http://www.theDailyGrind.net for your recommended daily intake of embittered satire.
Quote this message in a reply
Member
Posts: 156
Joined: 2002.11
Post: #11
Why not use TGA files? They conveniently store the alpha channel data, so it's a snap to create a texture from a TGA bitmap, without the need to load a separate file with a mask for colokeying. Am I missing something?

My application can also load textures from JPG or PNG files, but I couldn't see any difference from doing that or loading textures from a TGA file.

Older video cards won't accept textures in sizes which are not power of 2. You can assign sections of a texture to a quad, for instance, with you are working with older cards.

Or you may just disregard older iMacs, of course. If you use Quartz or Quickdraw, you won't have to worry that much about which kind of video card the end user has got in his computer.
Quote this message in a reply
Sage
Posts: 1,232
Joined: 2002.10
Post: #12
What's your size on disk for your TGA file, compared to PNG or TIFF?

See my older post.
Quote this message in a reply
Member
Posts: 156
Joined: 2002.11
Post: #13
Indeed, if the final download file size is critical to you, and you are not getting a good compression rate from your compressor of choice, then JPG and PNG would be the way to go.

As noted in that other thread, I've notice that PNGs get somewhat darker when displayed on screen. Also, I don't know if there's a way to embedded the alpha channel data into the JPG file, and the alternative of having the alpha mask in a separate file is not ideal.

One can always create a proprietary file fomat, or generate the alpha channel on-the-fly upon loading the JPG (based on a background color value), but I wouldn't do it either way unless the difference in download size were really significant. For this particular application I am building, the size of the audio files is far more of an issue than the size of the pic files.

I am not advocating the use of TGAs; it's just that the implementation of the alternatives seemed a little more involved to me, or less than ideal for a speedy production.
Quote this message in a reply
Criollo
Unregistered
 
Post: #14
Thanks for the suggestions everyone. I'll try them out in my application, and see how it goes.

FCCovett: No idea what a TGA file is or how to make one, but TIFFs and GIFs also have alpha channels.

-Criollo
Quote this message in a reply
Member
Posts: 156
Joined: 2002.11
Post: #15
Yeah, if you are working with Cocoa, it should be easier to keep on working with those formats.

The uncompressed TGA comes with a header of 12 bytes that describe the bit depth (24 or 32 bits/pixel) and the size of the actual bitmap (bytes). You just need to swap the Red and Blue bytes to get a RGB or RGBA for the OpenGL texture-create function.

Anyway, if you decide to work with OpenGL, you can find valuable pieces of source code (in Cocoa) at http://nehe.gamedev.net/
Quote this message in a reply
Post Reply 

Possibly Related Threads...
Thread: Author Replies: Views: Last Post
  Newbie question: Cocoa and Carbon - which for what and how to get started? BliTz 3 3,199 Jul 27, 2006 10:07 PM
Last Post: OneSadCookie
  Cocoa/Objective-C Question infernooo 2 3,148 Oct 18, 2005 11:26 PM
Last Post: infernooo
  Quick threaded OpenGL drawing question in Cocoa TomorrowPlusX 2 3,864 Nov 11, 2004 05:23 AM
Last Post: TomorrowPlusX
  Cocoa Filename Question Joseph Duchesne 3 3,314 Oct 26, 2003 03:55 PM
Last Post: Joseph Duchesne
  Cocoa Question Jake 7 4,189 Jun 2, 2003 07:03 PM
Last Post: Feanor