can i adding b2body or b2fixture into NSmutableArray or NSArray.?
i've been looking for some solutions, one of them says it should be insert into NSValue first then adding the value to nsmutable array. so i write this in my code:
// Create ball body
b2BodyDef ballBodyDef;
ballBodyDef.type = b2_dynamicBody;
ballBodyDef.position.Set(0/PTM_RATIO, 300/PTM_RATIO);
ballBodyDef.userData = [ballSpriteArray objectAtIndex:a];
_ballBody = _world->CreateBody(&ballBodyDef);
// Create circle shape on ball
b2CircleShape circle;
circle.m_radius = 30.0/PTM_RATIO;
// Create shape definition and add to body
b2FixtureDef ballShapeDef;
ballShapeDef.shape = &circle;
ballShapeDef.density = 0.5f;
ballShapeDef.friction = 0.5f;
ballShapeDef.restitution = 0.6f;
_ballFixture = _ballBody->CreateFixture(&ballShapeDef);
fixValue = [NSValue valueWithBytes:&_ballFixture objCType:#encode(struct b2Fixture)];
[ballFixtureArray addObject:fixValue];
//memberi impulse awal terhadap bola
b2Vec2 force = b2Vec2(5, 10);
_ballBody->ApplyLinearImpulse(force, ballBodyDef.position);
bodyValue = [NSValue valueWithBytes:&_ballBody objCType:#encode(struct b2Body)];
[ballBodyArray addObject:bodyValue];
to get every b2Fixture and b2body on that nsmutablearray i did like this in CCtouchBegan Method:
for(NSValue *val in ballFixtureArray)
{
b2Fixture *ballFix;
[val getValue:&ballFix];
if (ballFix->TestPoint(locationWorld)) {
//if([ballFixtureArray objectAtIndex:0]->TestPoint(locationWorld)){
for (NSValue *bodyVal in ballBodyArray){
b2MouseJointDef md;
md.bodyA = _groundBody;
b2Body *ballBody;
[bodyVal getValue:&ballBody];
md.bodyB = ballBody;
md.target = locationWorld;
md.collideConnected = true;
md.maxForce = 1000.0f * ballBody->GetMass();
_mouseJoint = (b2MouseJoint *)_world->CreateJoint(&md);
ballBody->SetAwake(true);
}
}
}
but it doesnt work, in other hand the application just crash when i touch every location on the screen..
is there somebody can help me..??
thnx before for every advance..
regards
I suggest you to use std::list or std::vector to store this classes. But if really need to store this classes in NSArray wrap them with NSObject:
#interface Wrapper : NSObject
{
b2Body *body;
}
#property (nonatomic, assign) b2Body *body;
#end
Related
I have a fetchResultController that compiles an array by running through multiple methods. The final cells display a name and number (ranking). I'd like to take the cells from the tableview and sort them by the number (ascending). I've tried nssortdescriptor in the frc but run into issues when I try to call the 'ranking' because it isn't a keypath of the entity I'm fetching. Is there a place I can intercept this array that comes out of the frc to sort by valueForKey:#"ranking"? How would I implement this sort?
The methods it cycles through to create the valueForKey is here:
- (NSExpressionDescription*) rankingExpressionDescriptionForTags:(NSSet*)itemToTag
{
NSPredicate* p2 = [NSPredicate predicateWithFormat:#"SUBQUERY(itemToTag,$t,$t.tagName IN %#).#count > 0",[itemToTag valueForKey:#"tagName"]];
NSExpression* rankExpresion = [(NSComparisonPredicate*)p2 leftExpression];
NSExpressionDescription* rankExpDesc = [[NSExpressionDescription alloc] init];
rankExpDesc.name = #"ranking";
rankExpDesc.expression = rankExpresion;
rankExpDesc.expressionResultType = NSInteger64AttributeType;
return rankExpDesc;
}
- (NSExpressionDescription*) objectIDExpressionDescription
{
NSExpressionDescription* expDesc = [[NSExpressionDescription alloc] init];
expDesc.name = #"objectID";
expDesc.expressionResultType = NSObjectIDAttributeType;
expDesc.expression = [NSExpression expressionForEvaluatedObject];
return expDesc;
}
- (NSFetchRequest*) rankingRequestForItem:(Item*)item
{
NSFetchRequest* r = [NSFetchRequest fetchRequestWithEntityName:#"Item"];
NSPredicate* p = [NSPredicate predicateWithFormat:#"SELF != %#",item.objectID];
r.resultType = NSDictionaryResultType;
r.propertiesToFetch = #[[self objectIDExpressionDescription],#"itemName",
[self rankingExpressionDescriptionForTags:[item mutableSetValueForKey:#"itemToTag"]]];
r.predicate = p;
r.sortDescriptors = #[[NSSortDescriptor sortDescriptorWithKey:#"itemName" ascending:YES]];
return r;
}
and the frc with cell config is here:
- (NSFetchedResultsController *)fetchedResultsController
{
if (_fetchedResultsController != nil) {
return _fetchedResultsController;
}
NSLog(#"selected item: %#, itemToTag: %#",selectedItem.itemName,[selectedItem.itemToTag valueForKey:#"tagName"]);
NSFetchRequest *fetchRequest = [self rankingRequestForItem:selectedItem];
// Edit the section name key path and cache name if appropriate.
// nil for section name key path means "no sections".
NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:nil cacheName:nil];
aFetchedResultsController.delegate = self;
self.fetchedResultsController = aFetchedResultsController;
NSError *error = nil;
if (![self.fetchedResultsController performFetch:&error]) {
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
abort();
}
return _fetchedResultsController;
}
- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath
{
NSDictionary *item = [self.fetchedResultsController objectAtIndexPath:indexPath];
cell.textLabel.text = [NSString stringWithFormat:#"%# - %#",[item valueForKey:#"itemName"],[item valueForKey:#"ranking"]];
}
Thanks for the help!
As I explained HERE, there is no way (AFAIK) to sort based on the ranking expression. You will have to sort the results in-memory, thus nullifying completely the need for a FRC.
Simply execute the request on the given context and sort in-memory:
NSError* error = nil;
NSFetchRequest* r = [self rankingRequestForItem:selectedItem];
NSArray* results = [context executeFetchRequest:r error:&error];
NSSortDescriptor* sd = [NSSortDescriptor sortDescriptorWithKey:#"ranking" ascending:NO];
results = [results sortedArrayUsingDescriptors:#[sd]];
The results array will now hold your sorted information, use it as a datasource for your table.
Store the results in a view controller property like:
self.results = results;
This code might go in your viewDidLoad method for example.
everywhere you access the FRC to get an object, you now access your table datasource for that information (assuming you have only 1 section):
NSIndexPath* someIndexPath = //some index path you might get as parameter
[self.results objectAtIndex:someIndexPath.row]; //return NSDictionary
I have written a specific init-override-function where i want to pass an index number to be called in an array. The index number itself is defined by selecting a tablerow in a tableview by the user. So.. the rownumber that is selected shall be passed into the init function and used there for further processing.
Well.. now there is my problem.. In my opinion the methods I've created are all correctly coded. But when I click my defined Connect Button an error message appears in the console, that, the index is out of bounds. So.. I've checked the array for entries and there are all available. So the indexnumber should be fine.
Maybe fyi: I've created a copy of the array in the TableViewController that is originally located in the PortConnection file.
Here are the necessary files. Can anyone give me a helping hand, where to search for?
PORTTABLEVIEWCONTROLLER.M
- (IBAction)pushConnect:(id)sender {
NSInteger selectedRow = [tableView selectedRow];
[portConnection initPort:selectedRow];
}
- (id)init {
self = [super init];
if (self) {
// Initialization of port Connection instance
portConnection = [[PortConnection alloc] init];
// Fill array in Portconnection.m with devices
[portConnection listDevices];
// Fill tableView Data Array with data from portConnection array
self.tableViewDataArray = [NSMutableArray arrayWithArray:portConnection.portArray];
}
return self;
}
PORTCONNECTION.H
#
interface PortConnection : NSObject {
// Instance of AMSerialPort
AMSerialPort *port;
// Port Array to be filled with found ports
NSMutableArray *portArray;
}
// List Devices into an given array
- (void)listDevices;
// Connect to selected port
- (void)initPort:(NSInteger)selectedRow;
#property (nonatomic, retain) NSMutableArray *portArray;
#property (nonatomic, retain) AMSerialPort *port;
#end
PORTCONNECTION.M
#implementation PortConnection
#synthesize port;
#synthesize portArray;
#pragma mark -
#pragma mark Serial Port Access
- (void)listDevices {
// get an port enumerator
NSEnumerator *enumerator = [AMSerialPortList portEnumerator];
AMSerialPort *aPort;
while ((aPort = [enumerator nextObject])) {
[portArray addObject:[PortItem portItemWithTitle:[aPort name] andPath:[aPort bsdPath]]];
}
}
- (void)initPort:(NSInteger)selectedRow {
//Create object of selected port searched in array
PortItem *portSelected = [portArray objectAtIndex:selectedRow];
NSString *deviceNameSelected = [portSelected valueForKey:#"bsdPath"];
// Start Connection
if (![deviceNameSelected isEqualToString:[self.port bsdPath]]) {
[self.port close];
[self setPort:[[[AMSerialPort alloc] init:deviceNameSelected withName:deviceNameSelected type:(NSString *)CFSTR(kIOSerialBSDModemType)] autorelease]];
[self.port setDelegate:self.port];
if ([self.port open]) {
NSLog(#"Connected...");
[self.port setSpeed:B38400];
[self.port readDataInBackground];
} else {
NSLog(#"error connecting");
[self setPort:nil];
}
}
}
#pragma mark -
#pragma mark initialization / deallocation
- (id)init {
self = [super init];
if (self) {
portArray = [NSMutableArray array];
}
return self;
}
- (void)dealloc {
portArray = NULL;
[super dealloc];
}
#end
Well.. my idea is, that something is wrong with the method INITPORT:(NSINTEGER)SELECTEDROW
but I am not sure at all....
Thanks so much for giving me advice again!
Sebastian
Your problem is this line,
portArray = [NSMutableArray array];
Although it is a retained variable, it will retain the value when you use the property setter method. This is a direct assignment of an autoreleased object will be released in a while and baring any other object retaining it (which doesn't happen), it should get deallocated. This is something which you don't want. Remedy this by using the property setter,
self.portArray = [NSMutableArray array];
I'm writing a program which uses MapKit to display a map which will load custom annotations from a plist file. Each annotation is a dictionary item in the root array, with a title, subtitle, latitude, and longitude. When I hard-coded in the annotations for test purposes, the program worked beautifully. But with the addition of the MapDemoAnnotation class and my attempt to read in the property list, the program crashes upon launch.
Here is my annotation implementation:
#import "MapDemoAnnotation.h"
#implementation MapDemoAnnotation
#synthesize coordinate;
#synthesize title;
#synthesize subtitle;
-(id)initWithDictionary:(NSDictionary *)dict{
self = [super init];
if(self!=nil){
coordinate.latitude = [[dict objectForKey:#"latitude"] doubleValue];
coordinate.longitude = [[dict objectForKey:#"longitude"] doubleValue];
self.title = [dict objectForKey:#"name"];
self.subtitle = [dict objectForKey:#"desc"];
}
return self;
}
-(void)dealloc{
[title release];
[subtitle release];
[super dealloc];
}
#end
I'm guessing the viewDidLoad method in my RootViewController class is the problem, though.
- (void)viewDidLoad {
[super viewDidLoad];
MKMapView *mapView = (MKMapView*)self.view;
mapView.delegate = self;
mapView.mapType=MKMapTypeHybrid;
CLLocationCoordinate2D coordinate;
coordinate.latitude = 39.980283;
coordinate.longitude = -75.157568;
mapView.region = MKCoordinateRegionMakeWithDistance(coordinate, 2000, 2000);
//All the previous code worked fine, until I added the following...
NSString *plistPath = [[NSBundle mainBundle] pathForResource:#"Locations" ofType:#"plist"];
NSData* data = [NSData dataWithContentsOfFile:plistPath];
NSMutableArray* array = [NSPropertyListSerialization propertyListFromData:data
mutabilityOption:NSPropertyListImmutable
format:NSPropertyListXMLFormat_v1_0
errorDescription:nil];
if (array) {
NSMutableDictionary* myDict = [NSMutableDictionary dictionaryWithCapacity:[array count]];
for (NSDictionary* dict in array) {
MapDemoAnnotation* annotation = [[MapDemoAnnotation alloc]initWithDictionary:dict];
[mapView addAnnotation:annotation];
[annotation release];
}
NSLog(#"The count: %i", [myDict count]);
}
else {
NSLog(#"Plist does not exist");
}}
The program crashes for reasons I cannot figure, but I figure I must have done something wrong in reading in the property list or else in the MapDemoAnnotation class. Am I missing something obvious, or making a novice mistake?
My code is largely borrowed, so I could be way off base with how I'm approaching it.
Thanks in advance!
The third parameter in the call to propertyListFromData is wrong. The compiler must be giving you a "makes pointer from integer without a cast" warning there because the format parameter expects a pointer to a NSPropertyListFormat variable (so the method can return the format to you). So you need to do:
NSPropertyListFormat propertyListFormat;
NSMutableArray* array = [NSPropertyListSerialization
propertyListFromData:data
mutabilityOption:NSPropertyListImmutable
format:&propertyListFormat
errorDescription:nil];
However, the documentation mentions that the above method is obsolete and you should use propertyListWithData:options:format:error: instead.
However, it's much easier to just call NSArray's initWithContentsOfFile: method instead:
NSString *plistPath = [[NSBundle mainBundle] pathForResource...
NSArray *array = [[NSArray alloc] initWithContentsOfFile:plistPath];
if (array) {
//your existing code here...
}
else {
NSLog(#"Plist does not exist");
}
[array release];
I'm trying to create a squishy ball with Cocos2d and Chipmunk (via SpaceManager) using a bunch of rects all chained together then joined with springs to a central body.
Something like these examples
But in order to do this, i think I need to store all the cpShapes in an array after I've created them so I can then loop through the array to link them all together with constraints.
However, when i try to put cpShapes in an array, I get an error telling me it's an "incompatible pointer type". So... I either need to use something other than an array (I've tried a set, that didn't work either) or I need to do something to the shape to make it compatible... but what? OR I need another aproach.
Any ideas?
Here's the code so far should it be relevant...
- (id) init
{
if ( (self = [super init]) ) {
SpaceManager * spaceMgr = [[SpaceManager alloc] init];
[spaceMgr addWindowContainmentWithFriction:1.0 elasticity:1.0 inset:cpv(5, 5)];
// This is a layer that draws all the chipmunk shapes
ChipmunkDrawingLayer *debug = [[ChipmunkDrawingLayer node] initWithSpace:spaceMgr.space];
[self addChild:debug];
int ballPeices = 10; // the number of peices I want my ball to be composed of
int ballRadius = 100;
float circum = M_PI * (ballRadius * 2);
float peiceSize = circum / ballPeices;
float angleIncrement = 360 / ballPeices;
CGPoint origin = ccp(240, 160);
float currentAngleIncrement = 0;
NSMutableArray *peiceArray = [NSMutableArray arrayWithCapacity:ballPeices];
for (int i = 0; i < ballPeices; i++) {
float angleIncrementInRadians = CC_DEGREES_TO_RADIANS(currentAngleIncrement);
float xp = origin.x + ballRadius * cos(angleIncrementInRadians);
float yp = origin.y + ballRadius * sin(angleIncrementInRadians);
// This is wrong, I need to figure out what's going on here.
float peiceRotation = atan2( origin.y - yp, origin.x - xp);
cpShape *currentPeice = [spaceMgr addRectAt:ccp(xp, yp) mass:1 width:peiceSize height:10 rotation:peiceRotation];
currentAngleIncrement += angleIncrement;
[peiceArray addObject:currentPeice]; //!! incompatible pointer type
}
spaceMgr.constantDt = 0.9/55.0;
spaceMgr.gravity = ccp(0,-980);
spaceMgr.damping = 1.0;
}
return self;
}
The incompatible pointer type is easy to explain :)
[NSMutableArray addObject] is defined as such:
- (void)addObject:(id)anObject
So what is an id then? Great question! Remember, Objective-C is still C at it's core. According to the Objective-C Programming Guide
typedef struct objc_object {
Class isa;
} *id;
That's great, now we know about *id but what about id itself? That's what is referenced in the method signature. For that, we have to look at objc.h
typedef id (*IMP)(id, SEL, ...);
Clearly, cpSpace* doesn't fit that, so you'll be getting incompatible pointer type if you try to put those into NSMutableArray using that message.
What follows is an initializer method. It creates a Movie structure from a file, with an eye to extracting the raw pixels for processing, as per Apple QA1443. This is then wrapped in a QTMovie – sourceMovie = [QTMovie movieWithQuickTimeMovie: ...] – for convenience.
After initializing such an object, the second method is called, and we attempt to use sourceMovie. However, it turns out that any attempt to access sourceMovie here results in EXC_BAD_ACCESS For instance, NSLog(#"%#", sourceMovie) is impossible. The movie appears to have been deallocated, although it is not clear why.
Furthermore, in this second method, the usual methods to obtain a CVPixelBufferRef do not properly function: QTVisualContextIsNewImageAvailable seems always to return NO, and QTVisualContextCopyImageForTime always gives you an imageBuffer pointing at 0x00. (I guess this is not surprising if the QTMovie, Movie or visualContext are somehow being deallocated.)
The question then is, why is sourceMovie inaccessible from the second method? Is it being deallocated as it seems? If so, why?
And now the code, and sorry in advance for the length.
// From the .h, we have the following inst var declarations:
Movie myMovie;
QTMovie *sourceMovie;
QTVisualContextRef visualContext;
CVPixelBufferRef imageBuffer;
pixels_xy sourceSize;
MovieAnalyzer *analyzer;
// And now to the #implementation...
-(id)initWithFileString:(NSString *)file {
if (self = [super init]) {
NSError *e;
// Bit of a hack - get the movie size using temporary QTMovie.
sourceMovie = [QTMovie movieWithFile:file error:&e];
if (e) {
[self release];
NSLog(#"Could not open movie.");
return nil;
}
NSSize movieSize = [[sourceMovie posterImage] size];
CGRect bounds = CGRectMake(0, 0, movieSize.width, movieSize.height);
// Save the size in pixels.
sourceSize.x = (int)movieSize.width, sourceSize.y = (int)movieSize.height;
CFStringRef movieLocation = (CFStringRef) file;
// Get a QT Visual Context, and create a movie inialized to use it for output.
visualContext = NULL;
OSStatus status = CreatePixelBufferContext(k32ARGBPixelFormat, &bounds, &visualContext);
if (noErr != status && NULL == visualContext) {
[self release];
NSLog(#"Problem initializing QT Visual Context.");
return nil;
}
/*** Instantiate the Movie ***/
myMovie = NULL;
Boolean trueValue = true;
QTNewMoviePropertyElement newMovieProperties[3] = {0};
// Setup movie location
newMovieProperties[0].propClass = kQTPropertyClass_DataLocation;
newMovieProperties[0].propID = kQTDataLocationPropertyID_CFStringPosixPath;
newMovieProperties[0].propValueSize = sizeof(CFStringRef);
newMovieProperties[0].propValueAddress = &movieLocation;
// Assign the visual context - could also be NULL
newMovieProperties[1].propClass = kQTPropertyClass_Context;
newMovieProperties[1].propID = kQTContextPropertyID_VisualContext;
newMovieProperties[1].propValueSize = sizeof(visualContext);
newMovieProperties[1].propValueAddress = &visualContext;
// Make the movie active
newMovieProperties[2].propClass = kQTPropertyClass_NewMovieProperty;
newMovieProperties[2].propID = kQTNewMoviePropertyID_Active;
newMovieProperties[2].propValueSize = sizeof(trueValue);
newMovieProperties[2].propValueAddress = &trueValue;
status = NewMovieFromProperties(3, newMovieProperties, 0, NULL, &myMovie);
if (status != noErr || myMovie == NULL) {
NSLog(#"Problem initializing theMovie"); // problem
[self release];
return nil;
}
// Create a new QTMovie with the Movie as its backing object
sourceMovie = [QTMovie movieWithQuickTimeMovie:myMovie disposeWhenDone:NO error:&e];
if (e) {
NSLog(#"Could not initialize QTMovie from Movie.");
[self release];
return nil;
}
[sourceMovie stepForward];
analyzer = [[MovieAnalyzer alloc] initWithColorString:"BGRA" andSourceSize:sourceSize];
}
return self;
}
-(NSImage*) supplyCalibrationImage {
NSLog(#"%x", &sourceMovie);
[sourceMovie stepForward]; // This fails!
....
}
[QTMovie movieWithQuickTimeMovie:disposeWhenDone:error:] is returning an autoreleased movie. If you want it to stick around past that one method, you need to retain it.