Cocos2D project with tileMap. Invalid positions returned - objective-c

I have a project in which I am trying to implement a pathfinding class but I have stumbled upon an issue I can't seem to fix.
A video of the error as it occurs can be found here:
https://www.dropbox.com/s/25ajb0mc5p4a3a9/Tilemap%20Error.mov
The error message thrown is: Assertion failure in -[CCTMXLayer tileGIDAt:withFlags:], /Users/Dave/Desktop/AI_DISS_new copy/AI_DISS/libs/cocos2d/CCTMXLayer.m:304
Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'TMXLayer: invalid position'.
The point returns as pixel values while the map and layer sizes return in tile values so I tried dividing variables holding pixel values by the width or height of the tiles but nothing seems to have worked.
GID for tileAt:point returns too high when using pixel values (understandably) and when converted to tile values, searches for a very long time, eventually moving off the map and continuously searching until Xcode crashes.
I have tried to explain in as much detail as possible I apologize if this isn't the kind of question best suited to this forum. I would really appreciate any assistance.
If you need further details please ask.
The original instructions for using the class were on cocos2d forums which have just had an overhaul and the thread appears to have been moved or deleted so I can't quote them but I am sure the tilemap (a TMX Tilemap) and layer attributes have been passed in correctly.
From my HelloWorldLayer class the values are:
//Pathfinding related code
////////////////////////////
_tileMap = [CCTMXTiledMap tiledMapWithTMXFile:#"NewMap.tmx"];
_pathFinder = [[AStar alloc] initWithTileMap:_tileMap groundLayer:#"Collision"]; //collidable Tiles
[_pathFinder setCollideKey:#"Collidable"]; // defaults to COLLIDE
[_pathFinder setCollideValue:#"True"]; // defaults to 1
_pathFinder2 = [[AStar alloc] initWithTileMap:_tileMap groundLayer:#"Collision"]; //collidable Tiles
[_pathFinder2 setCollideKey:#"Collidable"]; // defaults to COLLIDE
[_pathFinder2 setCollideValue:#"True"]; // defaults to 1
/////////////////////////////
and the move method is called as:
/////////////// player path finding related code //////////////////
[_pathFinder moveSprite:_player from:s to:f atSpeed:0.003];
///////////// end player path finding related code //////////////
Thanks in advance.
GID Code as commented on below:
if (tileGid)
{
// check the tile for the collide property.
NSDictionary *dict = [tileMap propertiesForGID:tileGid];
if (dict)
{
//check the tile for the collideKey and return Yes if a match
NSString *collide = [dict valueForKey:collideKey];
if (collide && [collide compare:collideValue] == NSOrderedSame)
return YES;
}
}

Related

cicle for is blocker, how to resolve it?

I have a problem in objective-c with a for loop. I want to wait the end of the loop before printing the elements on screen
for (NSDictionary *item in allItems) {
[self print:item];
};
when the loop ends, everything is print, but I would like printing during the loop.
how can i resolve it?
i tried with blocks without success
the print method:
-(void)print:(NSDictionary*)item{
NSString *message=[item objectForKey:#"message"];
if(message){
int userid = 0;
NSString *nome=[item objectForKey:#"name"];
NSString *sesso=[item objectForKey:#"sex"];
NSString *foto=[item objectForKey:#"photo"];
.........
It's not clear what your -print: method does, but I assume that it draws something on screen. Drawing in iOS and MacOS X doesn't happen immediately -- you draw into a graphics context that's managed by the graphics system, and that context is composed with others to generate the image that's ultimately drawn on the screen.
In other words, the screen drawing doesn't happen when you execute drawing commands, it happens when the graphics system periodically updates the screen. This is normal behavior -- it's not a problem.

Mac app NSArrayController bindings not autosaving Core Data

I was under the impression that when using bindings (been following this tutorial despite being outdated. http://cocoadevcentral.com/articles/000085.php - You can use it to see what I'm doing) the Persistent Store would automagically save the changes you make. In fact, though it was hours ago and I wouldn't be surprised if I'm now going mad, I got it working, and when I made a change it would persist on rebuilding the app.
However, the test app I've built following the tutorial no longer saves and despite showing the changes I make within the app, they disappear once I re-run the app. I've been checking the Core Data debug menu and nothing happens when I press the "+" button which is set up to the "Add" method of my NSArrayController. I know it's accessing my data model too as my textField for the Title (again, see the tutorial so you know what I'm referring to) adopts the default text I put in the DataModel section. The only thing missing therefore is the actual saving.
So my real question is, based on the tutorial, what part of the bindings actually makes the managedObjectContext save? Is there a flag or something that isn't checked?
I don't know if it's important or not, but there were differences between the tutorial and my project, mainly that the NSArrayControllers are bound to "App Delegate"with a Model Key Path of "self.managedObjectContext". Also, I removed all the relationships in an attempt to whittle down the issue.
Any help would be greatly appreciated.
Regards,
Mike
UPDATE: Here are some pictures that show the bindings.
How I set up the NSArrayController:
Here is how is how my Data Model Looks:
Lastly, this is how I set up the TextFields to update the NSArrayControllers:
I hope this helps to get a an ideas as to the set up.
Thanks,
Mike
Could you check to make sure you've copied all the Core Data boiler-plate code from the source code of the tutorial you mentioned.
Specifically this part in the App Delegate:
- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender {
NSError *error;
NSManagedObjectContext *context;
int reply = NSTerminateNow;
context = [self managedObjectContext];
if (context != nil) {
if ([context commitEditing]) {
if (![context save:&error]) {
// This default error handling implementation should be changed to make sure the error presented includes application specific error recovery. For now, simply display 2 panels.
BOOL errorResult = [[NSApplication sharedApplication] presentError:error];
if (errorResult == YES) { // Then the error was handled
reply = NSTerminateCancel;
} else {
// Error handling wasn't implemented. Fall back to displaying a "quit anyway" panel.
int alertReturn = NSRunAlertPanel(nil, #"Could not save changes while quitting. Quit anyway?" , #"Quit anyway", #"Cancel", nil);
if (alertReturn == NSAlertAlternateReturn) {
reply = NSTerminateCancel;
}
}
}
} else {
reply = NSTerminateCancel;
}
}
return reply;
}
If it's there, changes will be saved when the app is terminated normally. Pressing the 'stop' button in Xcode will terminate the app immediately, without going through the method mentioned above.
My guess is that you are not going mad, but first exited the app properly and have been pressing the 'stop' button later ;).

set texture of a sprite is not working

i am trying to set texture with this :
[[self setSpriteByTag] setTexture:[[CCTextureCache sharedTextureCache] addImage:[NSString stringWithFormat:#"%#0001.png",face]]];
when [self setSpriteByTag] return a sprite face is an image string, and they both ok because i have logged them.
this sprite is a child of a page in ccscrolayer :
one page of the layer pages :
CCLayer *page1 = [[CCLayer alloc] init];
BACK.position=ccp(screenSize.width/2,screenSize.height/2);
[page1 addChild:BACK];
when i was trying to change BACK's image , with the command i wrote here.
what happen is that i see a white screen.
i have check that the image is in my assets .
what could be the problem ?
the facr that i change a sprite that is a child of a page ?
edit :
this is the function that gives me the sprite BACK:
-(CCSprite*)setSpriteByTag
{
int currentPage=[scroller currentScreen];
[globals sharedGlobals].currentPageG=currentPage; //move to touch ended?
currentPage=currentPage+1;
//NSLog(#"PAGE:%d",currentPage);
if(currentPage==1)
{[globals sharedGlobals].WhatFace =#"BeastFace"; return BACK;}
else if(currentPage==2)
{[globals sharedGlobals].WhatFace =#"BlueFace"; return BACK1;}
else if(currentPage==3)
It gets white only in case when image is not present in the resources.. I checked running same code.. It works fine.. If I put wrong name of the image which is not present.. It changes to white... Please check for the image
[NSString stringWithFormat:#"%#0001.png",face]
M sure problem is in the image name.. :)
[NSString stringWithFormat:#"%#0001.png",face]
Your filenames will have to have the format "xxxxx0001.png". Assuming the face variable is the string "BeastFace" then the filename to load will be "BeastFace0001.png".
So far the obvious but keep in mind that the file "Beastface0001.png" will not load on the device, and neither will "beastface0001.png" because iOS devices use a case-sensitive file system. It will work on the iOS Simulator though.

Cocoa app behaves diffirently with breakpoint on & off

Important update: I found out that most part of my question was based on a false premise (see my answer below). Notifications actually got to the receiver, they just got there too fast. (Although, it still doesn't explain why the behavior with breakpoint and without it was different.)
I'm developing the app that calculates the hashes of files given to it. The calculation takes place in SHHashComputer. It's an abstract class (well, intended to be abstract, as there are no abstract classes in Objective C) that takes the file path and creates an NSInvocationOperation. It, in turn, calls the method (void)computeAndSendHash, which uses the file path saved in the object to compute hash and sends it as notification. The actual computing takes place in (NSString*)computeHash method that child classes need to override.
Here's SHHashComputer.m:
- (NSString*)computeHash {
return [NSString stringWithFormat:#"unimplemented hash for file %#", self.path];
}
- (void)computeAndSendHash {
NSString *result = [self computeHash];
NSString *notificationName = [NSString stringWithFormat:#"%#%#",
gotResultNotification,
self.hashType];
[[NSNotificationCenter defaultCenter] postNotificationName:notificationName
object:result];
self.operation = nil;
}
And here's SHMD5Computer.m (the child class of SHHashComputer):
- (NSString*)computeHash {
return #"MD5 test"; // it actually doesn't matter what it returns
}
I won't bother you with the receivers of notification. Let's just say that as long as I comment out the computeHash method in SHMD5Computer.m everything works just fine: the notification with text "unimplemented ..." is received & displayed in GUI. But if I don't — then it gets really interesting.
If I don't set up any breakpoints, the notification just never comes. However, if I set up a breakpoint at the declaration of computeHash in SHMD5Computer.h and then step over until the line 'self.operation = nil', and continue execution at that point, the notification gets to destination. If I don't stop there, the debugger suddenly switches to the state as if it isn't debugging anything, and the app freezes.
I don't think that 'WTF' is a good form for a question here, so let me put it this way: am I missing something? Are there errors in my code? What can cause this type of behavior in xcode? How can I fix this?
(If you'll want to get all my code to reproduce it, I'll gladly give it to you.)
More experiments:
If I continute execution exactly after stopping at breakpoint, the application encounters EXC_BAD_ACCESS error in the code that receives the notification, at the last line:
id newResult = [newResultNotification object];
if (newResult == nil)
[NSException raise:#"No object"
format:#"Expected object with notification!"];
else if (![newResult isKindOfClass:[NSString class]])
[NSException raise:#"Not NSString"
format:#"Expected NSString object!"];
else
self.result = (NSString*) newResult;
[self.textField setStringValue:self.result];
When I tried to reproduce the previous experiment, something even stranger happenned. In my debug setup, I have two hash computer objects: one SHMD5HashComputer (which we're talking about), and one SHHashComputer (which, of course, produces the "unimpemented" hash). In all previous experiments, as long as app didn't crash, the notification form SHHashComputer always successfully arrived. But in this case, both notifications didn't arrive, and the app didn't crash. (All the steps are exactly the same as in previous one).
As Josh Caswell pointer out in the comments, I wasn't using the notifications correctly. I should've sent the object itself as notification object, as described in documentation. I fixed that, and I'm getting exactly the same results. (Which means that I fixed it correctly, because sometimes the notifications work correctly, and also that it wasn't the problem).
More updates:
The notification that I'm sending should arrive at SHHashResultViewController. That's how I create it and register for notification:
- (id)initWithHashType:(NSString *)hashType {
self = [self initWithNibName:#"SHHashResultView" bundle:[NSBundle mainBundle]];
if (self) {
[self setHashType:hashType];
}
return self;
}
- (void)setHashType:(NSString *)hashType {
[self.label setStringValue:[NSString stringWithFormat:#"%#:", hashType]];
_hashType = hashType;
NSString *notificationName = [NSString stringWithFormat:#"%#%#",
gotResultNotification,
_hashType];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(gotResult:)
name:notificationName
object:nil];
}
Actually, the question was based on a false premise. I thought that notification never came through because I never saw the information displayed in the GUI; however, my error was in the code of controllers (not published there) which made possible the situation in which the GUI first got results of hash calculation and only after that got information about a new input — which resulted in deleting all the text and activating progress animation.

Using NSManagedObject manually - something wrong with the NSManagedContext I get?

I'm new to Cocoa programming, and decided for my first project to create a small application to monitor and remember certain battery stats for my laptop. (I have it plugged in most of the time, and apple recommend you discharge it now and again, so why not try to make a small program to help you remember to do this? :))
Anyway, I have a standard Objective-C project, with a DataModel file.
It contains an Entity, BatteryEvent, with properties, charge and event.
I then have PowerListener.m (and .h).
PowerListener.m is implemented as follows:
#implementation PowerListener
void myPowerChanged(void * context) {
printf("Is charging: %d\n", [PowerFunctions isCharging]);
printf("Is on ac: %d\n", [PowerFunctions isOnAC]);
printf("Charge left: %d\n", [PowerFunctions currentCapacity]);
printf("Powerchanged\n");
NSManagedObject *newBatteryEvent = [NSEntityDescription
insertNewObjectForEntityForName:#"BatteryEvent"
inManagedObjectContext:context];
}
- (PowerListener*) init {
self = [super init];
if(self) {
CFRunLoopSourceRef loop = IOPSNotificationCreateRunLoopSource(myPowerChanged, [[NSApp delegate] managedObjectContext]);
CFRunLoopAddSource(CFRunLoopGetCurrent(), loop, kCFRunLoopDefaultMode);
CFRelease(loop);
} else {
printf("Error\n");
}
return self;
}
#end
My problem is that once I run this (inited through main.m's main-method) and the power actually DOES change, I get thrown an error where I try to create the new BatteryEvent object:
2009-08-19 17:59:46.078 BatteryApp[5851:813] +entityForName: could not locate an NSManagedObjectModel for entity name 'BatteryEvent'
So it looks to me like I have the wrong ManagedContext? How do I get the right one?
Am I even on the right track here?
I've tried passing another kind of NSManagedObjectContext to the callback function as well.
I followed this guide: Core Data Guide, but, again same error...
I'm at my wits end!
Any help appreciated!
It looks like your app isn't loading the managed object model as a part of the launch and/or Core Data stack initialization.
Where is your model loaded?
Also, make sure you spelled the entity name correctly in the model.