Invisible Box2d Sprite using Position? - objective-c

Creating an CCNode, setting it to my player's position- in debug draw I see the physics object, but the sprite is invisible or nil or something. It doesn't crash the sprite simply doesn't appear. The bomb also travels the proper path and it's selector method is called.
Does NOT Appear:
GameObject *bomb = [_useBombArray nextSprite];
bomb.tag = kShipMissile;
[bomb stopAllActions];
NSLog(#"_bombSpawnPoint: %.0f, %.0f", _bombSpawnPoint.x, _bombSpawnPoint.y);
bomb.position = _bombSpawnPoint;
I have gotten it to appear by doing this:
GameObject *bomb = [_useBombArray nextSprite];
bomb.tag = kShipMissile;
[bomb stopAllActions];
bomb.position = ccp(_winSize.width * 0.5, _winSize.width * 0.5);
The _bombSpawnPoint is set prior to this and I do receive proper results on output.
Originally I thought I had called to create the object at an inopportune time in the update. So I changed the function slightly, to be sure it is called in proper order in the update method.
Not sure what's causing this! Please help!
I've created all my objects like this and they've all worked perfectly thus far!

The result of this was caused by the Texture of the Bomb was not in the proper BatchNode.
The error was not triggering until I removed the excess subclasses and used solely the sprite.
The error received was: 'CCSprite is not using the same texture id'
Once I used the other batch node everything worked perfect. Hope this helps someone!

Related

How to get spine current animation

I have a simple spine project in cocos2d and I want to know the current animation that's being played (the string name) but I can't find any function to get that in the CCSkeletonAnimation class,
Do you know if there's a way to get that?
Thanks
EDIT - SOLUTION
Hey I found how to to it
AnimationState *a = [mAnimationNode getAnimationState:0];
NSLog(#"Layer touched: %s",a->animation->name);
Where mAnimationNode is a CCSkeletonAnimation,
that works perfectly!!
Hey I found how to to it
AnimationState *a = [mAnimationNode getAnimationState:0];
NSLog(#"Layer touched: %s",a->animation->name);
Where mAnimationNode is a CCSkeletonAnimation,
that works perfectly!!
If Spine does not support a clear way to do it, you might be better off by storing the animation name in a property of your scene when you start it.
On the other hand, since an animation is usually implemented in cocos2d through an action, you could inspect the CCActionManager's numberOfRunningActionsInTarget: method implementation to check how you can access the list of running actions in a given target node.
This is for cocos2d 1.1:
tHashElement *element = NULL;
HASH_FIND_INT(targets, &target, element);
element->actions is the ccArray containing all the running actions.

Obj-C Text fields, float values and SIGBART

I am writing an iOS application for (among many features) calculating alcohol content from sugar before and after fermentation for homebrewers. Now the problem is; every time I run my app in the simulator, it crashes with "Thread 1: Signal SIGBART" once I enter the UIViewController with the text fields, labels and buttons used in this function (in the implementation):
- (IBAction)calcAlc:(id)sender {
double ogVal = [[oGtext text]floatValue];
double fgVal = [[fGtext text]floatValue];
double alcoContent = ((1.05*(ogVal-fgVal))/fgVal)/0.79;
NSString *theResult = [NSString stringWithFormat:#"%1.2f",alcoContent];
alcContent.text = theResult;
}
I'm really stuck here -- any help is very appreciated. Thanks in advance!
You should check if fgVal is ever 0, since you are dividing by fgVal.
You will also want to use doubleValue instead of floatValue, since you are declaring them as double.
I think you should try float in place of double.
Now put break points on each and every method and debug it to get the exact point where you application is getting crashed and then you will be able to find the solution.
Also be sure to connect each and every ib outlet and action in your storyboard or nib(whatever you are using).
Please notify if it works..:)

When is a NSManagedObject really accessible?

I have a problem.
I have an NSObjectController called "mapController" and I want to put some defaults when the object is created. I do this inside the windowControllerDidLoadNib method of my document, as suggested by the docs. But…
if (![mapController content]){ // No map defined yet.
[mapController add: self]; // This should create the instance.
NSLog(#"%#",[mapController content]); // Gives NULL.
I tried:
BOOL ok = [mapController fetchWithRequest:nil merge:NO error:nil];
NSLog(#"%#",[mapController content]); // Gives NULL.
The content of mapController is in the Core Data "scratch pad" but I can't access it. I have to set one of its attributes like this:
[[mapController content] setValue:[matrix colorReference] forKey:#"mapData"];
This gives no error, the file is marked as changed, but it I test the value:
NSLog(#"%#",[mapController content]); // Gives NULL.
When the heck it the controller's content really HERE? Something appears on the screen but… what actually? Reading the docs doesn't help me…
OK, I found the answer in the docs:
add: Creates a new object and sets it as the receiver’s content object.
Discussion
Creates a new object of the appropriate entity (specified by
entityName) or class (specified by objectClass)—see newObject—and sets
it as the receiver’s content object using addObject:.
Special Considerations
Beginning with Mac OS X v10.4 the result of this method is deferred
until the next iteration of the runloop so that the error presentation
mechanism can provide feedback as a sheet.
That's why
[[mapController content] setValue:[matrix colorReference] forKey:#"mapData"];
worked fine when called elsewhere in the app. It was a few iterations later…
Well… maybe this post will save you a couple of hours you could use to sleep longer.
Regards,
Bernard
I don't think its your mapController, I think it is your NSLog. Try this:
NSLog(#"%#", mapController);
also try getting simple data from the content, like the float value of the CGColorRef so you can use other formatters like %f.
I would have tested this but I cannot seem to create an instance of NSObjectController because it is an undeclared identifier. What framework is it defined in? Did you have to #import anything?

How to Change Speed while Animation CABasicAnimation

In my application i am using CABasicAnimation for animation. I want to change the speed of the animation dynamically so i have added one slider to change the speed. Following is my animation code. But i am not able to change the speed, when i change the value of speed nothing happens.
CABasicAnimation * a = [CABasicAnimation animationWithKeyPath:#"position"];
[a setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear]];
CGPoint startPt = CGPointMake(self.view.bounds.size.width + displayLabel.bounds.size.width / 2,
displayLabel.frame.origin.y);
CGPoint endPt = CGPointMake(displayLabel.bounds.size.width / -2, displayLabel.frame.origin.y);
[a setFromValue:[NSValue valueWithCGPoint:startPt]];
[a setToValue:[NSValue valueWithCGPoint:endPt]];
[a setAutoreverses:NO];
[a setDuration:speeds];
[a setRepeatCount:HUGE_VAL];
[displayLabel.layer addAnimation:a forKey:#"rotationAnimation"];
- (IBAction)speedSlider:(id)sender {
speeds = slider.value;
}
I think the best way to change speed is change your layer's time system
displayLabel.layer.timeOffset =
[displayLabel.layer convertTime:CACurrentMediaTime() fromLayer:nil];
displayLabel.layer.beginTime = CACurrentMediaTime();
displayLabel.layer.speed= slider.value;
You can see this for advance. https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/CoreAnimation_guide/AdvancedAnimationTricks/AdvancedAnimationTricks.html#//apple_ref/doc/uid/TP40004514-CH8-SW2
EDIT: It looks like you will have a further problem, though: it doesn't look like you can change values like that on a running animation. You will have to remove the current animation and add a new one with the altered value. This may need a bit of care to prevent a jarring effect when you add the new animation.
From the thread above, you might be able to do this by not repeating the animation, but by using a delegate (see here) to keep re-adding the animation, and setting the new speed for the next animation cycle instead.
Original post:
You are changing the value that you had originally passed in to the animation. This isn't going to affect the running animation. You'll need to get a reference to that, and change the duration property of the animation object. Something like this in your action method:
CABasicAnimation *a = [displayLabel.layer animationForKey:#"rotationAnimation"];
a.duration = slider.value;
I think jrturton is correct that you can't change properties on an animation that is already running. But what you could do is break the animation into short segments and change the speed for the next segment when the slider value changes.
Instead of animating from point A to point D, you'd animate from A-B, then B-C, then C-D. Use the parent class's animationDidStop to check the current point, check the slider value, and kick off the next animation.
This might produce jerky motion, but if you use very small segments, you might be able to smooth it out.
u should stop the animation and restart a new with a new duration time
but remember to log down the fromValue and the toValue , and use the old toValue as the new fromValue to perform a seamless change
set speed as what you need.
a.duration=0.5;
Try this...
If you just want Autoscrolling text then you can also use one class
http://blog.stormyprods.com/2009/10/simple-scrolling-uilabel-for-iphone.html
It might also work in your case, try it.

Error removing sprites from a spritesheet in Cocos2D

I'm in the initial building stages of an iphone game, and I'm using sprite sheets to create some random people, each one with sub-sprites for hair, clothing etc.
I'm storing my sprite images in spritesheets using CCSpriteBatchNode. I'm just doing an initial setup test now, where you tap the screen to generate a new random set of people. So the weird thing is, you can tap once and it will remove the old people and replace them with new people, but the second time, it crashes with the error:
"CCSpriteBatchNode doesn't contain the sprite. Can't remove it"
Now I'm sure I've added the sprite to the batch node, in my Person.m constructor I have this line:
[spriteSheet addChild:person];
In my test code in ccTouchesEnded I've got the following code:
//updated with changes suggested by Mazyod and Jer
for(int i=6; i>=0; i--){
Person *per = [_people objectAtIndex:i];
[_people fastRemoveObjectAtIndex:i];
[_spritesheet removeChild:per cleanup:YES];
per = nil;
}
for(int i = 0; i < 7; i++){
Person *per = nil;
per = [Citizen personFromCountry:_country1 WithSpriteSheet:_spritesheet];
per.position = ccp(100 + (50 * i),160);
[_people addObject:per];
[_spritesheet addChild:per];
}
Can anybody suggest what I'm missing? I've read a bunch about spritesheets in cocos2d and am given to understand that removing individual sprites is tricky so I'm sure there's some vital lines I need to add here. Thanks for your help!
Edit: I googled the error and found this thread: http://www.cocos2d-iphone.org/forum/topic/17170 which seems to confirm that Cocos2d thinks I'm not adding the sprite to the spritesheet - but I am, as proven by the fact that the sprites add correctly the first time, just not the second.
One solution is to simply avoid removing the sprites at all, just make them invisible and redraw them with new characteristics when they need to be reused. I'd rather know what the real solution is though because it seems cleaner.
Looks like you need to change
[_people addObject:per];
to
[_people replaceObjectAtIndex:i withObject:per];
In your first loop you are just setting the value of the object in the array to nil, but not removing it from the array. In the second loop you just add it onto the end of the array, but your array already has 7 nils in it.
Let me know if it works.
Well, I could help you clear out one thing for now:
Any CCNode can only be a child to one parent. ie It has to have a single parent.
But, what you have here:
for(int i=0; i<7; i++){
Person *per = [_people objectAtIndex:i];
[self removeChild:per cleanup:YES];
[_spritesheet removeChild:per cleanup:YES];
per = nil;
}
Suggest you are trying to add the person to both the spriteSheet and self at the same time.. Check your Log, it must have something like:
cocos2d: removeChild, child not found.
And from the error you are getting, I am betting that the person is added to self and not to the sprite sheet.
So, how to solve this?
Well, you have to add the person to the spriteSheet as a child, then add the spriteSheet to self as a child. (Actually, the order you add them doesn't matter).
Sort this out, and maybe this problem will go away, or at least it will be clearer so we can help you.
I just want to mention my experience here with this problem and how I solved it.
Remember, you are either trying to remove a child that was never added..
OR
Trying to remove a child TWICE.
This was the case for me. The collision detection in my game was solid (at least I thought). Then randomly, like 1 out of every 7-10 runs... I would get this crash. I realized it was because I had coded my projectiles to be removed once they intersected a target.
I did not however, put a failsafe where IF my tick method detected that it was in collision with MORE then 1 target at a time.
This was because for every projectile, I iterated through each target to check for a collision, then removed the respective projective if collision was detected. So I created a simple BOOL, and set it to YES if it had already collided with a target. Then I only checked for collision if the projectile had not collided with anything.
So... before:
if (CGRectIntersectsRect(projectileRect, targetRect))
{
//code to remove projectile
}
After:
if (CGRectIntersectsRect(projectileRect, targetRect) && projectile.hasHitaTarget == NO)
{
//code to remove projectile
}