I have tried the following code when trying to transition between scenes in my Sprite Kit project:
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
XYZGameScene *gameScene = [[XYZGameScene alloc] initWithSize:CGSizeMake(self.size.width, self.size.height)];
crossFade = [SKTransition fadeWithColor:[UIColor blackColor] duration:2];
[playButtonSprite runAction:changePlayButtonTextureOFF];
if(toGameAction){
[self.scene.view presentScene:gameScene transition:crossFade];
}else{}
}
The problem is, when I press the button that triggers the TRUE with toGameAction and the transition begins, the SKActions I have which are moving some objects in the background stop. Which isn't what I want. I am trying to make the transition between the two scenes seamless. As the backgrounds are the same just that one scene is the menu and the other is the actual game.
If you are having trouble with understanding what I am trying to implement, it's essentially when you press the button in Flappy Bird and the background doesn't stop moving through the transition between the menu and the game.
SKTransition has a property for this named pausesOutgoingScene that has a default value of YES. All you have to do is set this property to NO.
crossFade.pausesOutgoingScene = NO;
Related
I am new to game development and was wondering what is the best approach for displaying game data on screen.
I have an endless runner where the sprite collects gems and I want the total to be displayed on screen. I was looking at placing a UIView with a UILabel above the SKView and getting the label to update after each touch.
I also want a game over screen to appear at the end and was also looking at creating this using a UIView.
Is this the best approach or should all data be kept within the SKView itself?
Hopefully this makes sense.
While I don't think there is anything very wrong with using UIKit components within a SpriteKit application, I would recommend using SpriteKit's own components as much as possible.
For text I would recommend using SKLabelNode instead of UILabel.
Also, for buttons and other GUI elements, I think SKSpriteNodes would be most sufficient.
Simple functional button example:
SKSpriteNode *fireNode = [SKSpriteNode spriteNodeWithImageNamed:#"fireButton.png"];
fireNode.position = CGPointMake(fireButtonX,fireButtonY);
fireNode.name = #"fireButtonNode";//how the node is identified later
Handle touches:
//handle touch events
- (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:#"fireButtonNode"]) {
//do whatever...
}
}
I'm working on a game using Sprite Kit. I have a particle effect that runs when an object collides with another object; however, this particle effect seems to disappear when I add a transition to another SKScene. What's causing this disappearance, and how do I solve this issue?
Edit: By disappear I mean that it does not appear in the current scene when the scene is still transitioning with all the sprites still showing. It has a 2 second time interval, so shouldn't I be able to see it?
Here's the code for the particle effect and scene transition:
- (void)player:(SKSpriteNode *)player didCollideWithEnemy:(SKSpriteNode *)enemy {
Enemy *monster = (Enemy *)enemy;
if(!monster.isMoving){
SKEmitterNode *emitter = [NSKeyedUnarchiver unarchiveObjectWithFile:[[NSBundle mainBundle] pathForResource:#"MyParticle" ofType:#"sks"]];
emitter.position = player.position;
[self addChild: emitter];
isAlive = FALSE;
NSLog(#"Hit");
CrowdedData *crowdedData = [CrowdedData sharedManager];
crowdedData.score = score;
[player removeFromParent];
SKTransition *reveal = [SKTransition fadeWithDuration:2];
GameOver *scene = [GameOver sceneWithSize:self.view.bounds.size];
scene.scaleMode = SKSceneScaleModeAspectFill;
[self.view presentScene:scene transition:reveal];
}
}
SKTransition has two properties that are relevant to this:
[transition setPausesOutgoingScene:NO];
[transition setPausesIncomingScene:NO];
Both default to YES, causing either the outgoing in incoming scenes to be paused, which in turn pauses your emitter. For your purposes, setting the pausesOutgoingScene property to NO should be enough to fix this. More info in the docs:
https://developer.apple.com/library/ios/documentation/SpriteKit/Reference/SKView/Reference/Reference.html
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.
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.
I've been experimenting with UIGestureRecognizers and the new SKScene/SKNode's in SpriteKit. I've had one problem, and I got close to fixing it but I am confused on one thing. Essentially, I have a pan gesture recognizer that allows the user to drag a sprite on the screen.
The single problem I have is that it takes ONE tap to actually initialize the pan gesture, and then only on the SECOND tap on it works correctly. I'm thinking that this is because my pan gesture is initialized in touchesBegan. However, I don't know where else to put it since initializing it in the SKScene's initWithSize method stopped the gesture recognizer from actually working.
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
if (!self.pan) {
self.pan = [[UIPanGestureRecognizer alloc]initWithTarget:self action:#selector(dragPlayer:)];
self.pan.minimumNumberOfTouches = 1;
self.pan.delegate = self;
[self.view addGestureRecognizer:self.pan];
}
}
-(void)dragPlayer: (UIPanGestureRecognizer *)gesture {
CGPoint trans = [gesture translationInView:self.view];
SKAction *moveAction = [SKAction moveByX:trans.x y:-trans.y duration:0];
[self.player runAction:move];
[gesture setTranslation:CGPointMake(0, 0) inView:self.view];
}
That's because you're adding the gesture in touches began, so the gesture doesn't exist until the screen has been tapped at least once. Additionally, I would verify that you're actually using initWithSize: as your initializer, because you shouldn't have any problems adding the gesture there.
Another option is to move the code to add the gesture into -[SKScene didMovetoView:] which gets called immediately after the scene has been presented. More info in the docs.
- (void)didMoveToView:(SKView *)view
{
[super didMoveToView:view];
// add gesture here!
}
This is my first post! Hoping to not trip over my own toes...
Hi guys, so I was having an issue with a UISwipeGestureRecognizer not working. I was initializing it in my initWithSize method so based on this post I moved it to my didMoveToView method. Now it works (thanks 0x7fffffff). All I did was cut the following two lines from one method and paste them in the other.
_warpGesture = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(warpToNextLevel:)];
[self.view addGestureRecognizer:_warpGesture];
In my "investigation" I came across userInteractionEnabled and tried to set it to YES in my initWithSize method...
self.view.userInteractionEnabled = YES;
NSLog(#"User interaction enabled %s", self.view.userInteractionEnabled ? "Yes" : "No");
This would log NO even though i'd just set it to YES. Further investigation found that if I don't try to manually set userInteractionEnabled then it's NO during initWithSize (I can't seem to change this if I want to) and automatically gets set to YES when i'm in didMoveToView.
This all strikes me as relevant but I would love for someone in the know to explain just what's going on here. Thanks!