I have some sprites coming from the bottom of the screen in a random order. I want to swipe the sprite in the direction of the swipe. I got the algorithm for swiping. Also, I get an NSLog message whenever any sprite has been touched in the screen. The NSLog gives correct responses to any and every object touched. But how do I know which sprite has been swiped to write the code for applying impulse to that particular sprite?
I am trying the following code:
SKNode *sprite = [self nodeAtPoint:location];
[ball.physicsBody applyImpulse:CGVectorMake(dx, dy) atPoint:location];
[self addChild:sprite];
Also,
userInteractionEnabled = YES for all the sprites
And all the sprites are performing an action (Just in case this is the reason why I cannot swipe them while they are already running an action, in this case what else should I use to move the sprites?)
Sorry if this is too dumb, I am a noob
Thanks in advance!
You will need to use the name of the sprite with the name property:
node.name = #"nodeName";
for(SKNode *node in [self nodesAtPoint:location])
{
if([node.name isEqualToString:#"nodeName"])
{
// your custom code here
}
}
I hope this is what you were looking for, if not i am always here to help.
Related
I wanted to mix 2 tutorials, namely:
http://hub.ae/blog/2014/03/26/soft-body-physics-jellyusing-spritekit/
and
https://developer.apple.com/library/ios/documentation/GraphicsAnimation/Conceptual/SpriteKit_PG/Actions/Actions.html
(Example: Centering the Scene on a Node part)
I got both working one by one, but I've a bug when I mix both.
If my code starts like this:
[self setAnchorPoint:CGPointMake(0.5f, 0.5f)];
_myWorld = [SKNode node];
[self addChild:_myWorld];
[self createPlayer]; // I replaced all [self addchild's to [_myWorld addChild]
then camera follows the player but there are no joints created!
If I put [self createPlayer] to the top and leave all [self addchilds] as they are (because _myWorld isn't created yet) then there are joints which are working perfectly but camera doesn't follow player, since player isn't in _myWorld.
I leave [self.physicsWorld addJoint:joint]; as it is all the time.
Any idea where I go wrong?
When I moved the parts into _myWorld as told in the Apple guide, I didn't know I also had to shift anchor points, as they are always in scene coordinates.
Adding these lines solved the problem:
CGPoint p1 = [self.scene convertPoint:CGPointMake(point1.position.x+self.frame.size.width/2, point1.position.y+self.frame.size.height/2) fromNode:_myWorld];
CGPoint p2 = [self.scene convertPoint:CGPointMake(point2.position.x+self.frame.size.width/2, point2.position.y+self.frame.size.height/2) fromNode:_myWorld];
in the AttachPoint function.
How could I go about moving all nodes in a view in the same direction except one? An example of the type of game I am creating would be a pokemon kind of structure where the main character in the center of the screen remains stationary at the center and all background objects move.
If anyone has any idea as to how I could accomplish this in the most efficient manner, I would greatly appreciate it.
Thanks in advance.
The usual approach is to add all your moving objects to a worldNode and then change the position of the worldNode. Add the character to the SKScene separately.
let worldNode = SKNode()
self.addChild(worldNode) // Add to SKScene
worldNode.addChild(childNode) //Add all nodes
//let character = SKSpriteNode
character.position = centerOfScreen
self.addChild(character) // Add to SKScene
To move all sprites, change the position of the worldNode
worldNode.position = newPosition
In the update method, use enumerateChildNodesWithName:usingBlock: and pass //* to enumerate all nodes, then inside the block check for the name, and if it's not the one you don't want to move, move.
[self enumerateChildNodesWithName:#"//*" usingBlock:^(SKNode *node, BOOL *stop) {
if (node.name != #"nameOfTheNodeYouDontWantToMove") {
node.position = CGPointMake(node.position.x - 1, node.position.y);
}
}];
ok first of all here is my code ..
-(IBAction)handlePan : (UIPanGestureRecognizer *) recognizer
{ CGPoint translation = [recognizer translationInView:self.view];
recognizer.view.center = CGPointMake(recognizer.view.center.x + translation.x,
recognizer.view.center.y + translation.y);
[recognizer setTranslation:CGPointMake(0,0) inView:self.view];
[self checkCollison];
}
-(void) checkCollison
{
if (CGRectIntersectsRect(Dot.frame, CollisionImage.frame))
{
AudioServicesPlaySystemSound(playSoundId);
}
}
- (void)viewDidLoad
{
NSURL *SoundURL = [ NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:#"beep"ofType:#"wav"]];
AudioServicesCreateSystemSoundID((__bridge CFURLRef)SoundURL, & playSoundId);
[super viewDidLoad];
// Do any additional setup after loading the view.
}
what I've been trying to do for EVER is having Dot.center to stop when it collide .. i don't want the screen to flip or alert to show or images disseapear or all of those that people show everywhere .. i got that one .. all i want is my image to act as a wall .. like a maze i just want Dot to stop going thru the other image and just stop there ...not stop the game.. i want a wall but it seem to be so hard to do because i can't find the right answer ANYWHERE .. all people are suggesting is something to happen when images collide .. please help lol
Currently you're moving your view based on the gesture recogniser, then checking for a collision. You need to add some sort of feedback mechanism so that the position isn't allowed to change if a collision happens.
Lets also assume that you'd like the user to keep their finger on the screen so that the dot will keep moving after a collision, it just can't go through the boundary.
I'd do something like:
Change the check collision method to return a BOOL - YES if a collision has occurred. You'll probably want to not call the beep from here as it might happen too often.
Save the center of the view at the start of your gesture recogniser method
Try to do the movement
If a collision occurs, set the position back again, and try it just on the x-axis. If no collision occurs, leave it. If a collision occurs, try it on the y-axis. If no collision occurs, leave it.
If any collision occurred, play the beep
This should allow you to, for example, hit the wall on your left but keep sliding up it by moving your finger.
I'm having trouble getting a repeatable background to work in my game menu.
The user can slide a finger across the screen to select a character to play.
I have a parallax effect working with various backgrounds as the characters slide into view.
Sample below.
- (void)didMoveToView:(SKView *)view
{
self.pan = [[UIPanGestureRecognizer alloc]initWithTarget:self action:#selector(dragScene:)];
self.pan.minimumNumberOfTouches = 1;
self.pan.delegate = self;
[self.view addGestureRecognizer:self.pan];
}
- (void)dragScene:(UIPanGestureRecognizer *)gesture
{
CGPoint trans = [gesture translationInView:self.view];
SKAction *moveSky = [SKAction moveByX:trans.x*0.03 y:0 duration:0];
[_skyBackground runAction:moveSky];
}
I would like to repeat the backgrounds. I know how to do this with automatically scrolling backgrounds but I can't seem to get it to work here. It needs to repeat in both directions, left and right.
Thanks for any help!
You can create two more background nodes - one to the left of your current background node and one to the right. Move them aswell any time you move your existing _skyBackground node.
Then, in the update method, check if any of the three nodes needs to be "shifted" - either to behind the other two or in front. You're basically swapping the three nodes' positions if needed.
-(void)update:(NSTimeInterval)currentTime {
//get the left background node (or if using an ivar just use _leftNode)
SKSpriteNode *leftNode = (SKSpriteNode*)[self childNodeWithName:#"leftNode"];
//my positioning might be off but you'll get the idea
if (leftNode.position.x < -leftNode.size.width*2)
{
leftNode.position = CGPointMake(leftNode.size.width, leftNode.position.y);
}
if (leftNode.position.x > leftNode.size.width*2)
{
leftNode.position = CGPointMake(-leftNode.size.width, leftNode.position.y);
}
//repeat the same for _skyBackground and _rightNode
}
You may need more than 3 images if there's a slight gap between images as they're shifted.
i have a method to create sprites with an initial position, final position, height, image of the sprite and a name property to the sprite (to access the sprite later)
The problem is when i need to debug, because i can't display, for example, a number (of a position in this case...)
In this case, i want to know what sprite is disapearing sooner than expected, so i want to set a new parameter in my method which would be an NSString number(1,2,3..)so i could localize what sprite is making troubles... but i cant display this number or i don't know how. The other debugging technique i thought to do were to put an if(x.position> 600)callAMethod with a label, but... the coordinates are CGPoint and not float. So i'm a bit lost... Do anybody know a technique to do this??
here is my method to create sprites:
-(void)crearMontanaconLaPosicionFinal:(CGFloat)xFinal inicial:(CGFloat)xInicial altura:(CGFloat)altura imagen:(NSString*)imagen nombre:(NSString*)nombre
{
CGPoint posicionFinal = CGPointMake(xFinal, altura);
SKSpriteNode *montaña = [SKSpriteNode spriteNodeWithImageNamed:imagen];
montaña.name = nombre;
SKAction* parallaxMoveAction3 = [SKAction sequence:#[[SKAction moveTo:posicionFinal duration:20],[SKAction customActionWithDuration:0 actionBlock:^(SKNode* montaña, CGFloat elapsedTime){
[montaña setPosition:CGPointMake(xInicial,altura)];
}]]];
montaña.position = CGPointMake(xInicial, altura);
SKAction *repetir=[SKAction repeatActionForever:parallaxMoveAction3];
[montaña runAction:repetir];
[self addChild:montaña];
}