stop Impulse on sprite touch [duplicate] - ios

This question already has an answer here:
stop impulse on SKSpriteKit click
(1 answer)
Closed 8 years ago.
i'm creating an game where there is a pause button. For checking wether its touched i'm checking the location of the touch and if its equal to the paused button name.
When the pausedButton is clicked its call a method which pause the scene.
The problem is that in the touchBegan method whenever you touch the screen it apply an impulse, so when i press the pauseButton and unpause it the applyforce will come after. This is not ideal for the game. I've tried with a bool like shouldImpulse, but havent got it to work. here is my touchedBegan method:
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
CGPoint location = [touch locationInNode:self];
SKNode *node = [self nodeAtPoint:location];
if ([node.name isEqualToString:#"home"]) {
SKTransition *reveal = [SKTransition fadeWithDuration:2.0 ];
Menu *newScene = [[Menu alloc] initWithSize: CGSizeMake(self.size.width,self.size.height)];
// Optionally, insert code to configure the new scene.
[self.scene.view presentScene: newScene transition: reveal];
}
if ([node.name isEqualToString:#"pause"]) {
[self pausedMenu];
}
if ([node.name isEqualToString:#"start"]) {
[self startMenu];
}
showpipes = showpipes + 1;
if (showpipes == 1) {
self.physicsWorld.gravity = CGVectorMake( 0.0, -5.0 );
SKAction* spawn = [SKAction performSelector:#selector(spawnPipes) onTarget:self];
SKAction* delay = [SKAction waitForDuration:2.0];
SKAction* spawnThenDelay = [SKAction sequence:#[spawn, delay]];
SKAction* spawnThenDelayForever = [SKAction repeatActionForever:spawnThenDelay];
[self runAction:spawnThenDelayForever];
}
started = 1;
if (started == 1) {
mover.physicsBody.restitution = 0.0;
mover.physicsBody.velocity = CGVectorMake(0, 0);
[mover.physicsBody applyImpulse:CGVectorMake(0, 15)];
}
}

You can do that with a simple IF, ELSE IF, ELSE:
if([node.name isEqualToString:#"home"])
{
// do stuff...
} else if ([node.name isEqualToString:#"pause"])
{
// do stuff...
} else if ([node.name isEqualToString:#"start"])
{
// do stuff...
} else
{
// do whatever else here...
}

Related

iOS SpriteKit - Touch at a specific location, want node at specific zPosition

I have a project where when I tap I check to see if the tap is on a specific node. If it is then I create a new SpriteNode at that position that is only visible for .1s before being deleted. I want to be able to spam tapping on the screen but with that current check the node that I end up tapping on is the new SpriteNode that I've created.
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
for (UITouch *touch in touches) {
CGPoint location = [touch locationInNode:self];
SKNode *node = [self nodeAtPoint:location];
if (node == shutdahellup){
[self runAction:[SKAction playSoundFileNamed:#"shut-da-hell-uh.mp3" waitForCompletion:NO]];
}else if (node == hotdamn){
[self runAction:[SKAction playSoundFileNamed:#"hot-damn.mp3" waitForCompletion:NO]];
}else if (node == wafflewednesday){
[self runAction:[SKAction playSoundFileNamed:#"waffle-wednesday.mp3" waitForCompletion:NO]];
}else if (node == damnwaffle){
[self runAction:[SKAction playSoundFileNamed:#"get-a-damn-waffle.mp3" waitForCompletion:NO]];
}
[self createFace:touch];
}
}
-(void) createFace:(UITouch *)touch {
SKSpriteNode * face = [SKSpriteNode spriteNodeWithImageNamed:#"shane.png"];
CGPoint location = [touch locationInNode:self];
face.position = location;
face.zPosition = 100;
[self addChild:face];
SKAction * wait = [SKAction waitForDuration:0.1];
SKAction * remove = [SKAction removeFromParent];
SKAction * sequence = [SKAction sequence:#[wait, remove]];
[face runAction:sequence];
}
Any ideas? Thanks!

Issues with touchesBegan method

So the problem is that when I start it the soundOff button is above the soundOn but it's invisible. So all I see is the soundOn button, when I try to tap the soundOn button it really is just hitting the soundOff button and not giving it a chance to run the touchesBegan method properly.
#implementation GameScene
{
SKSpriteNode *soundLogo;
SKSpriteNode *soundOff;
}
-(void) addSoundOff:(CGSize)size {
soundOff = [SKSpriteNode spriteNodeWithImageNamed:#"soundOff"];
//resize sprite
soundOff.size = CGSizeMake(soundOff.size.width/2.25, soundOff.size.height/2.25);
//position it
soundOff.position = CGPointMake(65, 25);
//name sound off
soundOff.name = #"soundOff";
soundOff.alpha = 0;
[self addChild:soundOff];
}
-(void) addSoundOn:(CGSize)size {
SKTexture *soundOn = [SKTexture textureWithImageNamed:#"soundLogo"];
soundLogo = [SKSpriteNode spriteNodeWithTexture:soundOn];
//resize sprite
soundLogo.size = CGSizeMake(soundLogo.size.width/2.25, soundLogo.size.height/2.25);
//position sprite
CGPoint myPoint = CGPointMake(65, 25);
soundLogo.position = myPoint;
//name sound logo
soundLogo.name = #"soundOn";
//add action
[self addChild:soundLogo];
}
-(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
CGPoint location = [touch locationInNode:self];
SKNode *node = [self nodeAtPoint:location];
//sound logo pressed to turn sound on/off
if ([node.name isEqualToString:#"soundOn"]) {
soundOff.alpha = 1;
soundLogo.alpha = 0;
NSLog(#"sound on is pressed");
}
if ([node.name isEqualToString:#"soundOff"]) {
soundOff.alpha = 0;
soundLogo.alpha = 1;
NSLog(#"sound off is pressed");
}
}
Rather then changing the alpha to 0/1 what you can do is remove sprite from parent and you can add to child.
Don't add sound off and sound on button at same time first add the default button that is sound on.
now when the sound on button is clicked then remove the sound on button from parent and add sound off.
-(void) addSoundOff:(CGSize)size {
soundOff = [SKSpriteNode spriteNodeWithImageNamed:#"soundOff"];
//resize sprite
soundOff.size = CGSizeMake(soundOff.size.width/2.25, soundOff.size.height/2.25);
//position it
soundOff.position = CGPointMake(65, 25);
//name sound off
soundOff.name = #"soundOff";
soundOff.alpha = 0;
//-------------Remove below line-----------------//
//[self addChild:soundOff];
//Dont add sound off button.....
}
-(void) addSoundOn:(CGSize)size {
SKTexture *soundOn = [SKTexture textureWithImageNamed:#"soundLogo"];
soundLogo = [SKSpriteNode spriteNodeWithTexture:soundOn];
//resize sprite
soundLogo.size = CGSizeMake(soundLogo.size.width/2.25, soundLogo.size.height/2.25);
//position sprite
CGPoint myPoint = CGPointMake(65, 25);
soundLogo.position = myPoint;
//name sound logo
soundLogo.name = #"soundOn";
//add action
[self addChild:soundLogo];
}
-(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
CGPoint location = [touch locationInNode:self];
SKNode *node = [self nodeAtPoint:location];
//sound logo pressed to turn sound on/off
if ([node.name isEqualToString:#"soundOn"]) {
[soundLogo removeFromParent];
[self addChild:soundOff];
NSLog(#"sound on is pressed");
}
if ([node.name isEqualToString:#"soundOff"]) {
[soundOff removeFromParent];
[self addChild:soundLogo];
}
}

stop impulse on SKSpriteKit click

i'm trying to create an pause button in my game. at the moment when you click on the screen it will apply an impulse on the mover spriteNode. The problem is that it still applying the impulse when i click the pause button. How can i create an pause button without creating the impulse also.
i've tried changing the if statements to an else if and then making the last impulse part the else part, but this wont work.
touchBegan method:
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
CGPoint location = [touch locationInNode:self];
SKNode *node = [self nodeAtPoint:location];
//if fire button touched, bring the rain
if ([node.name isEqualToString:#"repeat"]) {
SKTransition *reveal = [SKTransition fadeWithDuration:2.0 ];
MyScene *newScene = [[MyScene alloc] initWithSize: CGSizeMake(self.size.width,self.size.height)];
// Optionally, insert code to configure the new scene.
[self.scene.view presentScene: newScene transition: reveal];
}
if ([node.name isEqualToString:#"home"]) {
SKTransition *reveal = [SKTransition fadeWithDuration:2.0 ];
Menu *newScene = [[Menu alloc] initWithSize: CGSizeMake(self.size.width,self.size.height)];
// Optionally, insert code to configure the new scene.
[self.scene.view presentScene: newScene transition: reveal];
}
if ([node.name isEqualToString:#"pause"]) {
[self pausedMenu];
}
if ([node.name isEqualToString:#"start"]) {
[self startMenu];
}
showpipes = showpipes + 1;
if (showpipes == 1) {
self.physicsWorld.gravity = CGVectorMake( 0.0, -5.0 );
SKAction* spawn = [SKAction performSelector:#selector(spawnPipes) onTarget:self];
SKAction* delay = [SKAction waitForDuration:2.0];
SKAction* spawnThenDelay = [SKAction sequence:#[spawn, delay]];
SKAction* spawnThenDelayForever = [SKAction repeatActionForever:spawnThenDelay];
[self runAction:spawnThenDelayForever];
}
started = 1;
if (noImpulse == 1) {
if (started == 1) {
mover.physicsBody.restitution = 0.0;
mover.physicsBody.velocity = CGVectorMake(0, 0);
[mover.physicsBody applyImpulse:CGVectorMake(0, 15)];
}
}
}
PAUSEDMENU METHOD:
-(void)pausedMenu
{
self.scene.paused = YES;
mover.scene.paused = YES;
[repeatButton removeFromParent];
[homeButton removeFromParent];
[menuBackground removeFromParent];
menuBackground = [SKSpriteNode spriteNodeWithColor:[SKColor colorWithWhite:0.0 alpha:0.3] size:CGSizeMake(self.frame.size.width*2, self.frame.size.height*2)];
[self addChild:menuBackground];
[pauseButton removeFromParent];
startButton = [SKSpriteNode spriteNodeWithImageNamed:#"staart"];
startButton.name = #"start";
startButton.position = CGPointMake(20, self.size.height-20);
startButton.size = CGSizeMake(40, 40);
[self addChild:startButton];
repeatButton = [SKSpriteNode spriteNodeWithImageNamed:#"repeat"];
repeatButton.name = #"repeat";
repeatButton.position = CGPointMake(self.size.width/2+30, self.size.height/2);
repeatButton.size = CGSizeMake(repeatButton.size.width/2, repeatButton.size.height/2);
[self addChild:repeatButton];
homeButton = [SKSpriteNode spriteNodeWithImageNamed:#"home"];
homeButton.name = #"home";
homeButton.position = CGPointMake(self.size.width/2-30, self.size.height/2);
homeButton.size = CGSizeMake(homeButton.size.width/2, homeButton.size.height/2);
[self addChild:homeButton];
}
Check out
https://developer.apple.com/library/ios/documentation/SpriteKit/Reference/SKView/Reference/Reference.html#//apple_ref/occ/instp/SKView/paused
If you pause your SKView that contains the game, all the state will be truly paused and you will be able to resume it after the pause menu has been dismissed. You'll have to present the pause menu in another SKView then the one that your game is contained in.

After rotating SKLabelNode it becomes difficult to get location in touchesBegan:

I have an SKLabel Node setup as a button in my app and it works fine. However, when I rotate the SKLabelNode with this code my touchesBegan method no longer executes correctly and it becomes very difficult to have the SKLabelNode touches register correctly:
[_menuButton runAction:[SKAction sequence:#[[SKAction rotateByAngle:M_PI duration:.2],
[SKAction moveByX:0 y:-15 duration:.2]]]];
Here is my touches began method:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
CGPoint location = [touch locationInNode:self];
SKNode *node = [self nodeAtPoint:location];
CGPoint positionInScene = [touch locationInNode:self];
[self selectNodeForTouch:positionInScene];
if ([node.name isEqualToString:menuButtonName]) {
//Touched Menu Button
[self animateMenuAndShow:YES];
}
}
EDIT: One additional piece of information is that I'm using SKTEffects which requires that instead of using self.scene as my base I'm using _worldLayer to add all elements in the scene to. Is it possible that this is throwing off my touch calculations? And if so how can I correct this?
self.scaleMode = SKSceneScaleModeResizeFill;
self.anchorPoint = CGPointMake(0.5, 0.5);
// The origin of the pivot node must be the center of the screen.
_worldPivot = [SKNode node];
[self addChild:_worldPivot];
// Create the world layer. This is the only node that is added directly
// to the pivot node. If you have a HUD layer you would add that directly
// to the scene and make it sit above the world layer.
_worldLayer = [SKNode node];
_worldLayer.position = self.frame.origin;
[_worldPivot addChild:_worldLayer];
Also after following sangony's advice here is my updated touchesBegan: method which works well at first, but runs into the same problem after rotating the label by M_PI
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
CGPoint location = [touch locationInNode:_worldLayer];
CGPoint locationInMenu = [touch locationInNode:_menuBackground];
if (CGRectContainsPoint(_menuButton.frame, location)) {
//Touched Menu Button
if (!self.menuVisible) {
[self animateMenuAndShow:YES];
}
else
{
[self animateMenuAndShow:NO];
}
}
}
EDIT2:
Here is my animateMenuAndShow: method
-(void)animateMenuAndShow:(BOOL)show
{
if (show == YES) {
// self.paused = YES;
self.menuVisible = !self.menuVisible;
[self createMenu];
SKAction *showMenuAction = [SKAction sequence:#[
[SKAction moveTo:CGPointMake(self.size.width / 2, self.size.height/2) duration:0.3],
[SKAction runBlock:^{
[self jelly:self.menuBackground];
}],
[SKAction waitForDuration:1.5]
]];
[self.menuBackground runAction: showMenuAction completion:^{
self.paused = YES;
}];
if (_flipped == YES) {
[self.menuBackground runAction:[SKAction sequence:#[
[SKAction moveByX:0 y:0 duration:.2],[SKAction rotateByAngle:M_PI duration:.2]]]];// [SKAction rotateByAngle:M_PI duration:.2]
}
}
else
{
self.paused = NO;
SKAction *removeMenuAction = [SKAction sequence:#[
[SKAction moveTo:CGPointMake(self.size.width / 2, -self.size.height + 300) duration:0.3],
]];
[self.menuBackground runAction:removeMenuAction completion:^{
[self.menuBackground removeFromParent];
}];
self.menuVisible = !self.menuVisible;
}
}
Try this touchesBegan instead:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
CGPoint touchLocation = [touch locationInNode:self.scene];
if (CGRectContainsPoint(myLabel.frame, touchLocation))
{
[self animateMenuAndShow:YES];
}
}

Move a SKSpriteNode with a single tap, but move continously when long tap - Sprite Kit

I'm trying to change some SKActions of an existing Sprite Kit tutorial project, but I'm running into issues when it comes to movement. The Tutorial and GitHub project is here:
https://www.codefellows.org/blogs/simple-sprite-kit-game-tutorial-part1
https://github.com/megharastogi/GameTutorial
As you can see in the code below, each tap only moves the node once. How do I change it so that a long tap will move continuous move the node? I tried a few things like repeatActionForever, but that didn't work very well.
-(void)addShip
{
//initalizing spaceship node
ship = [SKSpriteNode spriteNodeWithImageNamed:#"Spaceship"];
[ship setScale:0.5];
ship.zRotation = - M_PI / 2;
//Adding SpriteKit physicsBody for collision detection
ship.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:ship.size];
ship.physicsBody.categoryBitMask = shipCategory;
ship.physicsBody.dynamic = YES;
ship.physicsBody.contactTestBitMask = obstacleCategory;
ship.physicsBody.collisionBitMask = 0;
ship.physicsBody.usesPreciseCollisionDetection = YES;
ship.name = #"ship";
ship.position = CGPointMake(120,160);
actionMoveUp = [SKAction moveByX:0 y:30 duration:.2];
actionMoveDown = [SKAction moveByX:0 y:-30 duration:.2];
[self addChild:ship];
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
CGPoint touchLocation = [touch locationInNode:self.scene];
if(touchLocation.y >ship.position.y){
if(ship.position.y < 270){
[ship runAction:actionMoveUp];
}
}else{
if(ship.position.y > 50){
[ship runAction:actionMoveDown];
}
}
}
- (void)didMoveToView:(SKView *)view
{
UILongPressGestureRecognizer *tapper = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(tappedScreen:)];
tapper.minimumPressDuration = 0.1;
[view addGestureRecognizer:tapper];
}
- (void)tappedScreen:(UITapGestureRecognizer *)recognizer
{
float touchY = [self convertPointFromView:[recognizer locationInView:self.view]].y;
SKSpriteNode *ship = [self childNodeWithName:#"ship"];
if (recognizer.state == UIGestureRecognizerStateBegan) {
if(touchY >ship.position.y){
[ship runAction:[SKAction repeatActionForever:actionMoveUp] withKey:#"longTap"];
}else{
[ship runAction:[SKAction repeatActionForever:actionMoveDown] withKey:#"longTap"];
}
}
if (recognizer.state == UIGestureRecognizerStateEnded) {
[ship removeActionForKey:#"longTap"];
}
}
Add these two methods in your code.

Resources