Sprite Kit shooting projectiles at target - sprite-kit

I wanted to make my turret Sprite shoot at the monster. i have already got the turret to turn to the monster and follow it until its out of range, now i just need to make the shooting occur.
what is the best way to shoot a projectile from the turret to the monster?
i have already done this part:
-(void)shoot
{
SKSpriteNode *bullet = [SKSpriteNode spriteNodeWithImageNamed:#"CannonMissile-hd.png"]; ... i don't know what to do next
}
also, i need it to shoot at intervals of x seconds,
thanks

-(void)shoot
{
SKSpriteNode *turretNode;//I assume you have this node already in the scene . Dont use this line
SKSpriteNode *enemy;//I assume you have this node already in the scene . Dont use this line
SKSpriteNode *bullet = [SKSpriteNode spriteNodeWithImageNamed:#"CannonMissile-hd.png"];
bullet.zPosition = turretNode.zPosition -1;//if you want your bullet not to spawn on top of your turret
[turretNode addChild:bullet];
//you need to set the physics body of the bullet so you can detect contacts
SKAction *move = [SKAction moveTo:enemy.position duration:0.5];//if u have multiple enemies then you have to deceide which one to hit
[bullet runAction:move completion:^{
[bullet removeFromParent];//removes the bullet when it reaches target
//you can add more code here or in the didBeginContact method
}];
//repeat the process
[self performSelector:#selector(shoot) withObject:nil afterDelay:5];//replace 5 with ur x seconds
//that's it
}

Related

How to translate SKPhysicsContact contactPoint into my SKSpriteNode position

I've spent too long on this. Someone has solved this already, please help.
Enemy fires on my ship. SKPhysicsContact takes over and I get contactPoint. I explode the fired missile at the contactPoint, in world coordinates. All good. Now I would like to use the point, not in the scene coordinates returned by contactPoint, but in my ship coordinates to start emitting smoke from the ship, where I've been hit. I've used convertPoint function before, with success, but I can't seem to get it right here...Docs say the contactPoint is expressed in Scene coordinates, while myShip has its coordinates, living as a child of a world node, which is a child of the scene node. They are in the same Node hierarchy. I think...I have a Scene->World->Camera, where myShip is a child of World. My code, I think, is saying convert contactPoint from Scene coordinates to coordinates in myShip. But this does not work. Nor does any other combination. What am I missing? I suspect the Camera hierarchy, but unsure. The numbers being returned into smoke.position are way out of whack...
- (SKEmitterNode *) newSmokeEmitter: (SKPhysicsContact *) contact
{
NSString *smokePath = [[NSBundle mainBundle] pathForResource:#"ShipSmoke" ofType:#"sks"];
SKEmitterNode *smoke = [NSKeyedUnarchiver unarchiveObjectWithFile:smokePath];
smoke.targetNode = myShip;
smoke.name = #"shipSmoke";
smoke.position = [self convertPoint:contact.contactPoint toNode:myShip];
//my temporary kludge that places the smoke on the ship, randomly
//smoke.position = CGPointMake(skRand(-25,25), skRand(-25,+25));
NSLog(#"Ship at world pos: %f,%f", myShip.position.x, myShip.position.y);
NSLog(#"Contact at scene pos: %f,%f", contact.contactPoint.x, contact.contactPoint.y);
NSLog(#"Smoke position at ship pos: %f,%f", smoke.position.x, smoke.position.y);
[myShip addChild:smoke];
return smoke;
}
If you haven't solved it already, the answer is to convert from the node's scene:
smoke.position = [self convertPoint:contact.contactPoint fromNode:self.scene];
Or, in Swift:
smoke.position = convertPoint(contact.contactPoint, fromNode: scene)
If I understand your node hierarchy correctly this could fix the issue.
CGPoint contact = [self convertPoint:contact.contactPoint toNode:self.world];
smoke.position = [self.world convertPoint:contact toNode:myShip];
I don't think you can convert the point directly to ship. You have to convert it down the hierarchy until you get to the node you want.
Hopefully that helps.
Edit
To verify that the actual contact point is on the scene where I would expect you could try this.
SKSpriteNode *sprite = [SKSpriteNode spriteNodeWithColor:[SKColor greenColor] size:CGSizeMake(50, 50)];
sprite.position = contact.contactPoint;
[self addChild:sprite];
This should add a sprite exactly where the contact point is if the point returned is in the scene coordinate system. If it it does show up at the right spot than it truly does come down to converting points correctly.

SpriteKit SKAction group is running, but the SKSpriteNode image isn't being affected

I have created an SKAction group that alters the SKSpriteNode image (alpha and rotation) whilst playing a sound effect. However, when I runAction: the sound effect is played, but the image remains fixed.
In my subclassed SKSpriteNode (The Sheep) I have the following code that adds another SKSpriteNode (The Food) as a child:
-(void)setupEatingAction
{
_grassEating = [SKSpriteNode spriteNodeWithImageNamed:#"SheepFood"];
_grassEating.size = self.size;
_grassEating.anchorPoint = CGPointMake(0.5, 0.5);
_grassEating.alpha = 0.5;
_grassEating.zPosition = -1;
SKAction *fadeIn = [SKAction fadeInWithDuration:0.01];
SKAction *soundFX = [SKAction playSoundFileNamed:#"Munching2s.mp3" waitForCompletion:NO];
SKAction *rotate = [SKAction sequence:#[[SKAction rotateToAngle:degsToRads(-20.0) duration:kMovementAnimationInterval/4.0],[SKAction rotateToAngle:degsToRads(0.0) duration:kMovementAnimationInterval/4.0]]];
SKAction *eatAction = [SKAction group:#[fadeIn,soundFX,rotate]];
_grassEating.userData = [NSMutableDictionary dictionaryWithObject:eatAction forKey:KEY_EatAction];
[self addChild:_grassEating];
}
Then when I want the action group to run, I do the following:
-(void)eat
{
if(![_grassEating actionForKey:KEY_EatAction])
{
[_grassEating runAction:[_grassEating.userData objectForKey:KEY_EatAction] withKey:KEY_EatAction];
}
}
_grassEating is a property of my parent node:
#property (nonatomic,retain) SKSpriteNode *grassEating;
As I said, I can hear the sound effect playing, but the image isn't changed?!? For the life of me I can't work out why, and I've spent a lot of time trying to work out what is going on... any ideas?
I should also point out (although I don't think is anything to do with it) that this problem appears in both simulator and on hardware - both running iOS7.
I don't know if this is related iOS Spritekit Cannot Run SKAction on a Subclassed SKSpriteNode
But, it's the closest I can find and doesn't appear to be the same problem (on the surface).
Found the problem. It was a logical issue. The SKSpriteNode was being added and the sound FX started playing, but in the next frame or so the sprite was being removed.
As a result, it appeared that the sprite wasn't being displayed, but didn't have time to move into view. The sound FX continued to play, hence the confusion.

Reanimating a bouncing ball in sprite-kit

Reanimating a bouncing ball in sprite-kit
I have a question about the best way to reanimate a bouncing ball. Using Ray Wenderlich's tutorial on building a break out game as a reference I have a number of circular shape nodes which continually bounce around a gravity-less environment. When the user touches one of them, it centers on the screen, stops moving, and transforms into something else. When the user touches it again, it is supposed to transform back into the circular shape node and then continue bouncing around the screen.
I have it all working as I like except for reanimating the ball. The manner in which I stop the animation is simply to set the physicsBody to nil. Once I want to reanimate, I call the method that sets up the physicsBody for the node and I apply an impulse to it. But frustratingly, the impulse does not have the effect I think it should. Clearly, my expectations are incorrect.
Here is the code in question:
- (void)applyPhysics
{
// Set physics properties
self.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:self.frame.size.width/2];
self.physicsBody.friction = 0.0f;
self.physicsBody.restitution = 1.0f;
self.physicsBody.linearDamping = 0.0f;
self.physicsBody.allowsRotation = NO;
self.physicsBody.collisionBitMask = wallCategory;
self.physicsBody.categoryBitMask = bubbleCategory;
}
- (void)morphPicker
{
BOOL check = NO;
if (check) NSLog(#"morphPicker called.");
[self runAction:[SKAction fadeAlphaTo:0.0 duration:.5]];
if (self.flipped) {
if (check) NSLog(#"The information side is showing.");
self.fillColor = bubbleColors[self.index % bubbleColors.count];
self.alpha = .9;
// Resume physics:
[self applyPhysics];
[self.physicsBody applyImpulse:CGVectorMake(10.0f, -10.0f)];
} else {
// stop physics:
self.physicsBody = nil;
if (check) NSLog(#"The statistic side is showing.");
self.fillColor = [SKColor blackColor];
self.alpha = .9;
[self transformToPickerNode];
[self removeAllChildren];
}
self.flipped = !self.flipped;
}
So my questions are these:
How should I be reanimating the ball if applying an impulse to it is not the correct method?
Is there a more elegant way to stop the animation after centering the node than setting the physicsBody to nil? Even to my novice instincts it feels like a brutish method.
After all my trials and searching for an answer to this I firmly believe that there is no elegant way to apply a new impulse to a sprite and expect it to move in the physics world. Thus my answer must be "it cannot be done at this point." However, my solution of removing all the the animated sprites from the scene and recreating them turned out to be the best solution for a completely different reason. The nature of my physics world caused my "floating bubbles" to eventually end up in the corners of the scene where they remained unmoving. Occasionally removing and recreating them had the effect of sending them happily bouncing around the scene again :)

Destroying Sprites in and around the Collided Sprite

I need help in destroying the sprites which are in and around the collided sprites ie in a radius of 2.5 cms all sprites should be destroyed. Idea here is i will be shooting a projectile from bottom to the objects falling from the top. Once collision happens all the sprites around that radius also should be destroyed. Like a Bomb Effect. I have used box2d for collision ie contact listener. How to go about doing that?
Please Suggest:-)
Regards,
Karthik
Hold an array of your sprites, or if you are using a batchNode you can do that.
When the collision happens, go through your sprites. Check the distance with their position and the explosion center and kill them if they are in range.
e.g.
CCSprite *sprite;
for (sprite in [batchNode descendants]) {
if ([sprite isInRangeOf:[explosionSprite position]]) {
[sprite yourRemovalMethod];
}
}
the method 'isInRangeOf:' would be within your sprite subclass
Something like..
-(BOOL) isInRangeOf:(CGPoint)explosionCenter {
//Use pythagoras theorem to work out the distance between [sprite position] and [explosionCenter]
CGFloat dx = explosionCenter.x - [self position].x;
CGFloat dy = explosionCenter.y - [self position].y;
float distance = sqrt(dx*dx + dy*dy );
// If your distance is less than or equal to your 'death radius' return YES, else No.
if (distance <= 25) {
return TRUE;
} else {
return FALSE;
}
}
Hope that helps.

How do I animate a sprite using cocos2d?

I have a sprite which will move right,left and jump.
I need to add the action to a animated sprite ie an animated sprite should jump, turn right and left.
Can anyone please tell me how to do it with sample code.
This is quite simple with cocos2d code here:
Sprite *mySprite = [Sprite spriteWithFile#"mySprite.png"];
[mySprite setPosition:ccp(x,y)];
[self addChild:mySprite]; //This displays the Sprite in your layer
Now for the sequence you intend to do...
id moveRight = [MoveBy actionWithDuration:2 position ccp(x+k,y) //Where k is how much to the right you want it to go.
id moveLeft = [MoveBy actionWithDuration:2 position ccp(x-k,y)];
id jump = [JumpBy actionWithDuration:1 position:ccp (x,y) height:1 jumps:1];
id sequence = [Sequence actions:moveRight,moveLeft,jump,nil];
[mySprite runAction:sequence];
Hope that's clear.
-Oscar