# Build a Better Obstacle

In the SlippyFlippy challenge we have a small obstacle. In Flappy Bird there are two obstacles which the bird has to pass between.  Let’s change our current obstacle into a pass-through obstacle like Flappy Bird.

# Make a Random Obstacle

Our current obstacle is a bit boring. It always shows up in the same place. Let’s randomize it a bit.

Here is our current method for making a obstacle:

```-(void)makeObstacle{
//make the obstacle sprite
UIColor *obstacleColor = [UIColor blueColor];
CGSize obstacleSize = CGSizeMake(64, 128);
SKSpriteNode *obstacle = [SKSpriteNode spriteNodeWithColor:obstacleColor size:obstacleSize];
obstacle.name = @"obstacle";

//set its position
obstacle.position = CGPointMake(CGRectGetMaxX(self.frame)+ 2.0 * obstacle.size.width, CGRectGetMidY(self.frame));

//set the physics for the obstacle
obstacle.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:obstacle.size];
obstacle.physicsBody.affectedByGravity = NO;
obstacle.physicsBody.allowsRotation = NO;

//move the obstacle
SKAction *obstacleAction = [SKAction moveToX:0.0 - 2.0 * obstacle.size.width duration:4];
[obstacle runAction:obstacleAction completion:^{[obstacle removeFromParent];}];
}
```

Change the position code to the following:

``` //set its position
NSInteger maxNumber = self.frame.size.height;
CGFloat y = arc4random_uniform(maxNumber);
obstacle.position = CGPointMake(CGRectGetMaxX(self.frame)+ (2.0 * obstacle.size.width), y);
```

We create a random number between the origin at 0 and the height of the frame. Now the center of the obstacle will randomly show on the screen.

Build and run our code. You will see the obstacle randomly appears.

# How to Make a Gap: The Theory

We don’t have two obstacles on top of each other. We have one big obstacle with a gap in it. The obstacle is so big that it will fill any size device. The gap is just always somewhere in a mid range on the screen. We can make the obstacle as one sprite, but with other sprites in it.

Sprites do not have to be single objects. They may have their own hierarchy. In this case we define three sprites inside the bigger obstacle. We don’t need a sprite for the gap. We could use just two obstacle objects. I decided to use one for the gap, for an expansion later. I define the upper and lower obstacles by the anchor point of the parent node, which is 0,0. With center anchor points, we can find the position of the upper and lower obstacle from:

`0.5*gap.height + 0.5*obstacle.height`

The distributive property makes this a bit simpler:

` 0.5*(gapHeight+obstacleHeight)`

We add that to the origin.y of the obstacle parent to get a position for an upper obstacle. We subtract that from the origin.y of the parent obstacle to get a position for the lower obstacle. We turn off physics for the parent, but turn it on for the upper and lower obstacles to handle collisions. That gives us an obstacle that we can move around with a gap in it.

We make the obstacles as big as our largest possible frame. The upper and lower obstacles are always partially off-screen for a portion, but appears solid no matter what device we are playing on. To be big enough, the upper and lower obstacle sizes are the height of the frame.

# Make the Parent Obstacle

Start by making our current obstacle bigger. Make it as big as the frame. Change the code to initialize the obstacle sprite to the following:

```//make the obstacle sprite
UIColor *obstacleColor = [UIColor colorWithRed:0.0 green:0.0 blue:1.0 alpha:0.5]; //for debugging visulization
CGSize obstacleSize;
obstacleSize.width = 64;
obstacleSize.height = self.frame.size.height;

SKSpriteNode *obstacle = [SKSpriteNode spriteNodeWithColor:obstacleColor size:obstacleSize];
obstacle.name = @"obstacle";
```

We changed our color to a blue with an alpha value. In the real game this is transparent, but for debugging purposes it will be helpful to see it. We broke up obstacle size from a `CGSizeMake` function to two setters. For the height, we set

```obstacleSize.height = self.frame.size.height;
```

Build and run.

We have a solid stripe trying to push SlippyFlippy off the screen, then squeezing past him like Jello. That is because we have the physics turned on. Let’s turn it off for the obstacle. Comment out the physics for the main obstacle:

```//set the physics for the obstacle
//obstacle.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:obstacle.size];
//obstacle.physicsBody.affectedByGravity = NO;
//obstacle.physicsBody.allowsRotation = NO;
```

Add a gap sprite by adding the following code under the commented out physics:

```//make the gap
SKSpriteNode *gapNode = [SKSpriteNode spriteNodeWithColor:[UIColor blueColor] size:CGSizeMake(obstacleSize.width, 64)];
gapNode.position = CGPointMake( 0, 0);
```

This time we do not add the sprite to `self`. We add it to `obstacle` to build a hierarchy of sprites in `obstacle`. Build and run this.

You will notice three things:

• The obstacle still shows bottom and top edges. We need to make it bigger.
• The gap is too small.
• The stuttering motion of the obstacle disappears and it now smoothly crosses the screen.

The third issue has to do with physics and collision detection. We have a physics setup where the penguin won’t fall off the edge of the screen by using an edge loop on `self`. The obstacle is set to start off-frame on the right and slide off-frame to the right. With physics on for the obstacle, collision detection makes being off-screen impossible. So the obstacle stutters. We will discuss this much more next time.

Let’s fix the second one. We are using constant value of 64. Set a variable for this value and set it to a large number, for example 150. Call the identifier `gapSize`. Add this identifier above the declaration for obstacleSize.

```static int gapSize = 150;
```

Now change the code to use `gapSize`:

```SKSpriteNode *gapNode = [SKSpriteNode spriteNodeWithColor:[UIColor blueColor] size:CGSizeMake(obstacleSize.width, gapSize)];
```

Build and run.

SlippyFlippy has a chance of getting throughout the gap. Let’s make one more change to keep the gap proportional:

```CGSize obstacleSize;
obstacleSize.width = gapSize / 2.0;
obstacleSize.height = self.frame.size.height;
```

We will always have a 1:2 width to height proportion if we change `gapSize`.

# Make the Ice blocks

Add the lower and upper obstacle sprites:

```CGFloat iceYPosition = 0.5* (gapSize + obstacleSize.height);
//make the first obstacle -- the lower obstacle
SKSpriteNode *obstacle1 = [SKSpriteNode spriteNodeWithColor:obstacleColor size:obstacleSize];
obstacle1.position = CGPointMake( 0,0 - iceYPosition );
obstacle1.name = @"obstacle1";

//make the second obstacle
SKSpriteNode *obstacle2 = [SKSpriteNode spriteNodeWithColor:obstacleColor size:obstacleSize];
obstacle2.position = CGPointMake(0, iceYPosition);
obstacle2.name = @"obstacle2";
```

We calculate a position for the two blocks surrounding the gap, which I called `iceYposition`. Since the origin on `obstacle` is `(0,0)`, just add or subtract from zero to get the y position of the sprite. Set the size of the upper and lower sprites to be as big as the frame. With obstacle more than twice the height of the frame, the obstacle sprite will always be bigger than the frame.

Comment out the declaration of `obstacle` and change it to a generic node:

```  //SKSpriteNode *obstacle = [SKSpriteNode spriteNodeWithColor:obstacleColor size:obstacleSize];
SKSpriteNode *obstacle = [SKSpriteNode node];
```

The `obstacle1` and `obstacle2` block obstacle from view. `Obstacle`‘s function is positioning and containment, not viewing. `Obstacle` does not need to be visual. Thus simplify it to a initialization of `node.`

Change the color of the gap to clear:

```SKSpriteNode *gapNode = [SKSpriteNode spriteNodeWithColor:[UIColor clearColor] size:CGSizeMake(obstacleSize.width, gapSize)];
```

We now have a gap in an obstacle that spans the whole frame. Run and build and we have a nice looking gap.

SlippyFlippy still passes right through it. We need to turn on physics, but not gravity. As we mentioned earlier, that’s a bit of a problem. Collision physics has to be selective about what it does and does not collide with. We want `obstacel1` and `obstacle2` to collide with the penguin, but not the walls of the frame. The penguin needs to collide with all of them. How to handle collisions will be the topic for the next installment.

# Source Code

```
-(void)makeObstacle{
//make the obstacle sprite
UIColor *obstacleColor = [UIColor colorWithRed:0.0 green:0.0 blue:1.0 alpha:0.5]; //for debugging visulization
static int gapSize = 150;
CGSize obstacleSize;
obstacleSize.width = gapSize / 2.0;
obstacleSize.height = self.frame.size.height;

//SKSpriteNode *obstacle = [SKSpriteNode spriteNodeWithColor:obstacleColor size:obstacleSize];
SKSpriteNode *obstacle = [SKSpriteNode node];
obstacle.name = @"obstacle";

//set its position
NSInteger maxNumber = self.frame.size.height;
CGFloat y = arc4random_uniform(maxNumber);
obstacle.position = CGPointMake(CGRectGetMaxX(self.frame)+ (2.0 * obstacle.size.width), y);

//set the physics for the obstacle
//obstacle.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:obstacle.size];
//obstacle.physicsBody.affectedByGravity = NO;
//obstacle.physicsBody.allowsRotation = NO;

//make the gap
SKSpriteNode *gapNode = [SKSpriteNode spriteNodeWithColor:[UIColor clearColor] size:CGSizeMake(obstacleSize.width, gapSize)];
gapNode.position = CGPointMake( 0, 0);

// set up the position of the solif parts of the obstacles relative to the root obstacle
CGFloat iceYPosition = 0.5* (gapSize + obstacleSize.height);
//make the first obstacle -- the lower obstacle
SKSpriteNode *obstacle1 = [SKSpriteNode spriteNodeWithColor:obstacleColor size:obstacleSize];
obstacle1.position = CGPointMake( 0,0 - iceYPosition );
obstacle1.name = @"obstacle1";

//make the second obstacle
SKSpriteNode *obstacle2 = [SKSpriteNode spriteNodeWithColor:obstacleColor size:obstacleSize];
obstacle2.position = CGPointMake(0, iceYPosition);
obstacle2.name = @"obstacle2";