UIImage Array.


If you're anything like me, you've probably already tried the next step.

We need a whole bunch of images, so why not make the UIImage into an array?

Simple, right?


Well, no.

That "Synthesize" keyword, which does something I'm not 100% sure about, seems to dislike arrays.

Which pretty much buggers things up.  D'oh!


After 20 minutes hunting google for an answer, I instead decided to just bash the keys and see what did and didn't work.

If we remove the "Synthesize" we get an error in the compiler, but it still seems to work..  It also suggests we try adding a Synthesize line, or Dynamic.


Having then given Dynamic a whirl, it seems that Dynamic is quite happy to do arrays.  Whoop!


This'll probably bite me in the ass later, but never mind.  We'll live and learn!



-> Controller.h

remove the UIImage* img_squareTile; lines, and replace them both with one single one..

UIImage* img_squareTiles[150];  // Other variable name we'll be using.


Further down, replace the two @property lines with one..

@property (nonatomic, retain) UIImage* img_squareTiles; // Something I don't understand about the variable we'll be using!

note, there's no array in that line.  Throws an error if you stick an array in it.  *shrugs*


-> Controller.m

Replace the two @synthesize lines with one.

@dynamic img_squareTiles;


Replace the loader with two array slots.

img_squareTiles[1]=[UIImage imageNamed:@"squareTile.png"]; // Loads image into Variable

img_squareTiles[2]=[UIImage imageNamed:@"squareTile2.png"]; // Loads image into Variable


Convert the ViewGrid to use it.

viewGrid[n]=[[UIImageView alloc] initWithImage:img_squareTiles[1]]; // Make viewGrid a ImageView using squareTile as the default image.


and inside perFrame

if (gameGrid[ID]==1) {viewGrid[ID].image=img_squareTiles[2];}

if (gameGrid[ID]==0) {viewGrid[ID].image=img_squareTiles[1];}



Now we head down to the bottom bit, and replace the dealloc part.

[*img_squareTiles dealloc]; // Clears it when we quit.


Done.

Build and test : Compiles fine, seems to run fine, no telling what else is going on...


If you click Run/Run with Performance Tool in the menu, you can play around with all manner of little bit and pieces.

Load up the Leaks viewer, and you can watch the little graph flap about, all over the place.   Except it doesn't.  It, in fact, appears to be quite stable.

I'm going to take that as a sign that things are ok, and carry on with the next bit!


----


Clickable Grid


So, we've got the grid of images.  We can expand that to use loads more images, and we can flick through them as required.  Next up, let's interact with our engine a little.


We can do this a whole bunch of ways.  The "New coder" way would be to give every object a way to interact with.  Call me old fashioned, but having EVERY object constantly checking everything around it, to see if it's doing anything, seems awfully wasteful.

"OldSkool" suggests we simply grab the x/y co-ordinates, and decide what's under it.  One check for X/Y, divide that by the grid size, blammo.. array reference!


So, first we need to grab X/Y co-ordinates.

We'll do that by adding an extra View that fits over the screen, and relays the co-ordinates.

(I'm typing this as I go, so if it all goes pearshaped, we'll have some backtracking to do!!)


First, head into .h and add a new view.  Since we're using this to grab X/Y points of the finger, we'll call it exactly that.

UIImageView* finger;  // View to find fingers.


Then in .m, inside viewDidLoad, we make our finger frame.

finger=[[UIView alloc] initWithFrame:CGRectMake(0,0,320,480)];


That's our view. 


Next, we need to set up a point system, where we can get our finger's location, and whether it's held.


-> .h


CGPoint fingerPoint;  // Where our finger is.

int fingerDown; // Whether our finger is down.


-> .m


inside M we need to add 3 new functions that'll track what the finger's up to.

// Touchyness!

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {

fingerPoint = [[touches anyObject] locationInView:finger];

fingerDown=1;

}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {

fingerPoint = [[touches anyObject] locationInView:finger];

fingerDown=2;

}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {

fingerPoint = [[touches anyObject] locationInView:finger];

fingerDown=0;

}


Began = Finger on the screen, Moved = is moved, Ended = Let go.

Simple stuff.

We set FingerDown to 1,2,0 so we can track things.

If in our game we need to tap, we can check if FingerDown==1, and then turn it off so it doesn't happen again.  Nice and easy.



Then inside the perFrame section, we're pretty much about to replace the whole lot..

if (fingerDown==1) {  // If onscreen

int x=floor((fingerPoint.x/32));  // Get x

int y=floor(((fingerPoint.y-24)/32)); // Get y  (note, the y position still seems to count the top bar, so we -24 to account for that.

if (x>-1 && x<10 && y>-1 && y<14) {

fingerDown=0;   // Switch off fingerDown, since we only need a single tap..

int ID=y*10+x; // And all of this stuff is the same as it was..

gameGrid[ID]=1-gameGrid[ID];

if (gameGrid[ID]==1) {viewGrid[ID].image=img_squareTiles[2];}

if (gameGrid[ID]==0) {viewGrid[ID].image=img_squareTiles[1];}

}

}


Well, except the ending, that's about the same as it was before.  But for the point seeking, that's now finger based, as opposed to being random.  Nice and simple..


Give it a test, and tap the boxes.

Should work just fine.

You can now tap the boxes off and on again, and then quit, because there's not a whole lot happening!