How to remove or destroy SKSpriteNode once it disappears from screen - ios

I am making a Flappy Bird kind of a game using Swift 3. I spawn pipes with the help of a function 'makePipes()' which I'm calling every 3 seconds with the a timer. The 'makePipes()' function makes SKSpriteNode for the Pipes and moves them from right of the screen to left of the screen.
What I wanna do is, destroy the Node of the Pipe after it has vanished from the screen or after it has completed its movement from one side of the screen to other.
Another solution could be to Re-use the pipes once they have moved from right to left.
pipe1.run(movePipes) {
self.pipe1.removeFromParent()
}
I tried the above solution and it does not work. It shows weird blinking lines across the screen and pipes become weirdly and randomly placed instead of uniform.
Any help is appreciated. I'm very new to iOS.

You could have done something like this:-
movePipesForward = SKAction.moveByX(-dx, y: 0 ,duration: duration)
removePipes = SKAction.removeFromParent()
moveForwardAndRemove = SKAction.sequence([movePipesForward, removePipes])
pipe1.runAction(moveForwardAndRemove)
self.addChild(pipe)

Related

Node movement lag in Spritekit, Xcode

In my game I have a node that the player controls with the PanGesture. When the PanGesture function is called, it adds its velocity to that of the Node in question, making it move.
However, I have encountered a problem where the Node (under specific yet inconsistent circumstances) moves slower and not as smoothly as intended.
When I start the application it (sometimes) has the correct movement speed. As soon as I "die", and restart (remove all nodes and recognizers, restart the scene, remake all nodes and recognizers) the node does not move at the correct speed.
This is where things get weird.
After restarting the game and seeing that the node has the incorrect speed, I can access the "swipe up menu" and then promptly dismiss it, at which point the node will revert back to its intended speed. This however, does not always work. On top of that, I can leave the scene to have the same thing happen. This happens even less frequently.
This is the code I use to make a GestureRecognizer:
let Panned:UIPanGestureRecognizer = UIPanGestureRecognizer(target: self, action: #selector(GameScene.Panned))
view.addGestureRecognizer(Panned)
These lines are only run once per scene. (Making multiple GestureRecognizers causes the entire scene to experience dramatic frame drops each time the screen is touched.)
This is the code which adds the velocity of the movement to the Node:
func Panned(sender:UIPanGestureRecognizer){
velocity = sender.velocity(in: view)
if movement == true{
Node.position.x = Node.position.x+(velocity.x/100)/1
Node.position.y = Node.position.y-(velocity.y/100)/1
}
}
This function is called each time the PanGestureRecognizer detects a "pan" movement.
This is my restart function, which prepares the scene for the next instance of the game:
func restartScene(){
removeAllChildren()
removeAllActions()
createScene()
}
removeAllChildren will kill my stuttering node, and createScene() will revive it again. (It should be noted that createScene() is the same function used at the initial start of the game, and can therefor not be related to the problem.)
The restart is however where my problem starts. This function is missing certain (in my opinion) irrelevant lines that manipulate certain values and handle labels.
The main gist of my problem is as follows:
Do I fully understand GestureRecognizers?
What effect does the "swipe up menu" have on my current scene? Does it clear/restart certain things, or does it simply pause my scene?
Edit:
The most confusing thing about the problem is how it arises after a "restart", when the restart process does not touch the PanGesture in anyway. I'm considering remaking the game to create a version where the problem isn't present, but this leaves the problem unsolved.

SpriteNode/Shapes change size and disappear after returning to GameScene (Swift SpriteKit)

GIF of the issue in action:
http://i.imgur.com/hiF5lyw.gifv
As you can see, the main Player is a SKSpriteNode, and when you hit a falling block which is a SKShapeNode, the game switches to the GameOver scene. When you click restart in the GameOver scene and move back to the GameScene the falling blocks disappear and the dimensions of the Player sprite is changed along with its y position.
All the code contains pretty detailed comments but if you have any questions about it feel free to ask.
Since the size of my Player sprite is based on the size of the screen, It might have something to do with screen size changes when switching scenes maybe. Also, its strange the falling block enemies dont show up for a few seconds, but then the node count drastically increases and another GameOver scene transition is triggered.
Maybe I have to change something with the GameViewController?
Any help would be greatly appreciated, I've been working at it for hours and I cant seem to figure out why its messing up.
Figured it out.
I created two new variables:
var transition:SKTransition = SKTransition.fadeWithDuration(0.5)
and
var gameOver:SKScene = GameOver(size: self.size)
And then implemented both when calling the scene switch with:
self.view?.presentScene(gameOver, transition: transition)
I think the size: self.size is what fixed it.
If you have troubles with changing size of your nodes when you do transitions, instead of size: self.size, you should use fileNamed: nameOfYourScene. This worked for me.

How can I stop a UIView movement in Swift?

I'm messing around with Swift for the first time and have a square on the screen. The square starts by moving to the right. When I tap on it I want it to go up. I don't want it to continue to the right at all, I want it to just go straight up. Unfortunately the physics and gravity make it curve to the right some more before it goes up. What can I do to completely stop the gravity pull and acceleration of my object, before setting the gravity to the new value?
This turns the object in the right direction, but I need it to come to an instant stop before doing this.
if(self.gravity.gravityDirection.dx == 1){
self.gravity.gravityDirection = CGVectorMake(-1.0, 0.0)
}
The way to stop an item being affected by a behavior is to remove the item from the behavior or remove the behavior from the animator. For example, here you might remove self from the existing gravity behavior.

How to make a UIImageView repeat forever across the screen [x-axis]

I am developing a game on xCode, but I ran into a problem.
I was able to make the UIImageView move <------- left across the iPhone screen, but it I want it to repeat as soon as it begins to move so it could look endless.
Lets say that one piece of the floor in that app is a UIImageView, how can I make that UIImageView repeat across the screen [x-axis] as shown in that app. [NOT MY APP]
-(void)whiteFloor{
whiteFloor.center = CGPointMake(whiteFloor.center.x-1);
if(whiteFloor.center.x < 130){
[self placeGround];
}
}
-(void)placeGround {
// Also would I need to make a int?
//what would write here
}
I'm sure there are better ways to do it if you use SpriteKit, but if you don't want to use it, you can maybe use 2 UIImageView one after another to create the endless effect.

Update UISnapBehavior Point

In my app, I have small views that can be moved around by dragging them. When the user begins dragging on one of the small views, it stays in place, but is 'stretched' for a certain distance (~200 points). After the distance is exceeded, then the small view should perform a 'snap' effect to the user's finger. The whole animation is best described as a rubber band breaking.
So far, I've implemented the snap effect like so:
UISnapBehavior *snapBehavior = [[UISnapBehavior alloc] initWithItem:iconView snapToPoint:[[touches anyObject] locationInView:self.view]];
[self.snapAnimator addBehavior:snapBehavior];
The problem is, if the user continues moving their finger while the snap animation is being performed, the view continues to move towards the point where the finger was when the effect began.
Is there any way to update UISnapBehavior's destination when touches are moved?
No, there isn't. Snap behavior is extremely simple: it just snaps to the point you tell it, right then. That's all it does. One behavior, one point, one item, one snap.
You would need, therefore, to remove the snap behavior and substitute a different snap behavior with a different point. Or use a different kind of behavior, one where you can move the target point as the user's finger moves (such as UIAttachmentBehavior).
In iOS 9 and above, you can. There is now:
#property (nonatomic, assign) CGPoint snapPoint NS_AVAILABLE_IOS(9_0);
It works as expected.

Resources