How to add a Get Ready screen in spritekit - ios

Hi I want to add a title or label that says Get Ready and when you tap it you start spawning custom sprites. Does any one know how to do this. As a reference I want the Get ready screen to act like Flappy Birds or Splashy Fish. Anywhere I can get info on this?

SKSpriteNode *getReady = [SKSpriteNode spriteNodeWithImageNamed:#"myImage.png"];
//remember to set position and other custom stuff here
[self addChild:getReady];
_isFirst = YES; //BOOL property
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
if (_isFirst)
{
SKAction *fadeOut = [SKAction fadeOutWithDuration:10];
[getReady runAction:fadeOut];
_isFirst = NO;
} else {
//other time you tap, code here
}
}

You need to creat a SKSpriteNode with the image you want and add to your scene.
SKSpriteNode *getReady = [SKSpriteNode spriteNodeWithImageNamed:#"myImage.png"];
//remember to set position and other custom stuff here
[self addChild:getReady];
Then when the user tap you can run an action to fade it out.
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
SKAction *fadeOut = [SKAction fadeOutWithDuration:10];
[getReady runAction:fadeOut];
}
Also, I think you would be great if you check out some tutorials, cause that's really basic stuff. I'm sure you can easily find then.

Related

Objective C - How to disable touch on 2nd Sknode when 1st SKnode is touched

I have two SKNodes, RMnode and RLnode, that receive touches. Unfortunately, at the same time.
I tried disabling the touch on the 2nd SKnode, when 1st has been touched and vice versa, but for some reason it doesn't seem to work.
Is there perhaps another approach to this?
(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
for (UITouch *touch in touches) {
CGPoint Rubyposition = [touch locationInNode:self];
[self selectNodeForTouch:Rubyposition]; //a helper method that asks the scene (self) for the node that is on the position touchLocation.
SKNode *RMnode = [self nodeAtPoint:Rubyposition];
SKNode *RLnode = [self nodeAtPoint:Rubyposition];
if ([RLnode.name isEqualToString:#"Ruby1"]) {
if(_TouchOnRubyRL == NO){
_TouchOnRubyRL = YES;
//RMnode.userInteractionEnabled = NO; //Not working
[self.level ActivatedBricks:_TouchOnRubyRL];
}
else if(_TouchOnRubyRL == YES){
_TouchOnRubyRL = NO;
//RMnode.userInteractionEnabled = YES; //not working
[self.level ActivatedBricks:_TouchOnRubyRL];
}
}
if ([RMnode.name isEqualToString:#"Ruby2"]) {
if(_TouchOnRubyRM == NO){
_TouchOnRubyRM = YES;
//RLnode.userInteractionEnabled = NO; //Not working
[self.level ActivatedBricks:_TouchOnRubyRM];
}
else if(_TouchOnRubyRM == YES){
_TouchOnRubyRM = NO;
//RLnode.userInteractionEnabled = YES; //Not working
[self.level ActivatedBricks:_TouchOnRubyRM];
}
}
}
}
The reason setting the node's userInteractionEnabled is not working as you expect is that your touchesBegan is in the scene, not the sprite. userInteractionEnabled only allows/disallows touches to the SKNode it is a property of (an SKScene is an SKNode too) - and in your code the scene's userInteractionEnabled is always true so the touch always gets through to the scene's touchesBegan method (your sprite's touchesBegan is being disabled - but you are not overriding it so you don't notice).
To use userInteractionEnabled in this way you would need to subclass the sprites themselves and handle touches within the subclassed sprite - then setting userInteractionEnabled will work as you expect.
If you do not want to refactor your code like that, you could mark each sprite as 'untouchable' in some other way (this SO answer suggests using the SKNode's existing zPosition property) and then use this in your scene before accepting the touch (e.g. if touchedNode.zPosition != 0 ...).

How to create button in sprite kit iOS (similar to toggle button)

I am trying to make a button in sprite kit using SKSpriteNode. I want the button image to change when it is pressed and revert back to old image as soon as the press ends. What i have done till now is following:-
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
self.startTouch = [[touches allObjects][0] locationInNode:self ];
for (UITouch *touch in touches){
CGPoint position = [touch locationInNode:self];
SKNode *node = [self nodeAtPoint:position];
if ([node.name isEqualToString:#"missileButton"]) {
TEMissileButtonNode *button = (TEMissileButtonNode*) node;
button.isPressed = YES;
}
}
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
for (UITouch *touch in touches){
CGPoint position = [touch locationInNode:self];
SKNode *node = [self nodeAtPoint:position];
if ([node.name isEqualToString:#"missileButton"]) {
TEMissileButtonNode *button = (TEMissileButtonNode*) node;
button.isPressed = NO;
}
}
}
inside the update method i am calling this method to check if the touch has ended
-(void)changeMissileButton{
if (self.missileButton.isPressed) {
[self.missileButton addMoreMissileButtons];
[self.missileButton setTexture:[SKTexture textureWithImageNamed:#"missileButtonPressed"]];
}else{
[self.missileButton setTexture:[SKTexture textureWithImageNamed:#"missileButtonDeselected"]];
[self.missileButton hideMissileButtons];
}
}
The issue is that the touch doesn't get registered at times. Sometimes it works the way i want. When i touch it, its texture changes and when i remove my finger, the texture reverts back to old texture. But most of the times, the button doesn't react to my touch. Am i missing something?
Use touchesBegan, touchesMoved, touchesEnded.
touchesBegan - check if the button (SKSpriteNode) contains the touch. If so, change you button texture.
touchesMoved- if button does not contain touch, change texture back.
touchesEnded- if touch stayed within button during touchesMoved, change texture back.
Above is the logic for how to efficiently accomplish what you are trying to do. Yes, it is annoying Spritekit decided to abandon buttons.

Mirror a sprite with touchesBegan?

Here is my current code:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
SKAction *moveNodeRight = [SKAction moveByX:-200.0 y:0.0 duration:0.7];
[_squirrelSprite runAction: moveNodeRight withKey:#"changeside"];
}
When I tap the screen I want my current sprite to mirror itself. If there isn't a way to mirror it, is there a way to change the sprite when the screen is tapped?
Also, when you tap the screen again I want the sprite to go back to it's original position on the screen and be flipped to the original sprite. Should I use code similar to this to determine which way it should go? Thank you!
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
if (isRightSide) {
//Change to sprite's position to the LEFT side
} else {
//Change to sprite's position to the RIGHT side
}
isRightSide = !isRightSide;
}
To horizontally mirror a SKSpriteNode's texture:
mySprite.xScale = -1.0;
To flip back and forth, in the touchesBegan use this code:
if(mySprite.xScale == -1.0)
{
mySprite.xScale = 1.0;
} else {
mySprite.xScale = -1.0;
}

Pausing game in Sprite Kit: Why doesn't this work?

So I added a pause button to my game and the freezing and unfreezing of the view works. However I want it to display a message saying "PAUSE" over the screen if the view is currently frozen. But if I'm touching my pause button it doesn't display the label. It's really strange, because I discovered that if I'm turning my device to landscape mode, the "PAUSE" message appears. (and vice versa too, so if I touch the button in landscape mode and turn my device to portrait, the pause label appears)
Can anyone figure this out?
BTW: I also tried out different methods to do this, like initializing the pause label as soon as the scene starts and hide/reveal it whenever needed. This didn't work either.
I also tried to do it with an if-statement in the update method ( if the scene is paused => reveal the pause label) this didn't work either.
I asked this question before on here and the apple devforums but no one could solve this problem yet. Someone thought I would present the scene in viewwilllayoutsubviews, which would explain the portrait-landscape behavior, but I never used that method in my whole application code.
-(void)gameScene{
//Pause
pauseButton = [SKSpriteNode spriteNodeWithImageNamed:#"pause.jpg"];
pauseButton.position = CGPointMake(screenWidth/2, screenHeight-80);
pauseButton.zPosition = 5;
pauseButton.name = #"pauseButton";
pauseButton.size = CGSizeMake(80, 80);
[self addChild:pauseButton];
//Pause Label (wenn Pause gedrückt wird)
pauseLabel = [SKLabelNode labelNodeWithFontNamed:#"Arial"];
pauseLabel.text = #"PAUSE";
pauseLabel.fontSize = 70;
pauseLabel.position = CGPointMake(screenWidth/2, screenHeight/2);
pauseLabel.zPosition = 5;
pauseCount = 1;
}
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
//Pause Button
UITouch *touch = [touches anyObject];
CGPoint location = [touch locationInNode:self];
SKNode *node = [self nodeAtPoint:location];
if ([node.name isEqualToString:#"pauseButton"]) {
pauseCount++;
if (pauseCount%2 == 0) {
self.scene.view.paused = YES;
[self addChild:pauseLabel];
}
else{
self.scene.view.paused = NO;
[pauseLabel runAction:remove];
}
}
}
I had a similar problem with pausing and found that the problem related to the fact that although the pauseLabel was getting added to the node tree the scene was pausing before it was displayed. The solution I used was to use SKAction to run the label add and pause in sequence.
SKAction *pauseLabelAction = [SKAction runBlock:^{
[[self scene] addChild:pauseLabel];
}];
SKAction *delayAction = [SKAction waitForDuration:0.1]; // Might not be needed.
SKAction *pauseSceneAction = [SKAction runBlock:^{
[[[self scene] view] setPause:YES];
}];
SKAction *sequence = [SKAction sequence:#[pauseLabelAction, delayAction, pauseSceneAction]];
[self runAction:sequence];
I have not tested this but there might also need to be a small delay in there to give the label time to display before the pause is fired.

SpriteKit: How to implement touchesBegan and touchesEnded to split action into two parts?

I'm trying to do a little archery game and at the moment I have a basic touchesBegan method that uses SKActions to animate an archer and shoot an arrow.
I'm having a hard time getting it so that I hold touch to draw the bow, then when I release, the rest of the animation plays out and the arrow shoots.
I tried it with using two separate NSMutableArray Atlases spread across touchesBegan and touchesEnded methods with userInteractionEnabled flags but that was a bit of a no-go...
Ultimately I want the duration of the hold to dictate a value for applyImpulse:CGVectorMake.
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
SKNode *archerNode = [self childNodeWithName:#"archerNode"];
if (archerNode != nil)
{
SKAction *draw = [SKAction animateWithTextures:self.archerDraw timePerFrame:0.075];
[archerNode runAction:draw];
SKAction *shootArrow = [SKAction runBlock:^{
SKNode *arrowNode = [self createArrowNode];
[self addChild:arrowNode];
[arrowNode.physicsBody applyImpulse:CGVectorMake(20.0, 0)];
}];
SKAction *sequence = [SKAction sequence:#[draw, shootArrow]];
[archerNode runAction:sequence];
}
}
Initiate the charging animation in the touchesBegan: section & move the arrow release code in the touchesEnded: (+ touchesCancelled:) function. Keeping the time at which the touches began in an instance variable will help you calculate the impulse vector.

Resources