Skip to content

Commit eddddd8

Browse files
author
iBednar
committed
Collision detection, score counting etc.
1 parent 6c655e6 commit eddddd8

File tree

2 files changed

+112
-13
lines changed

2 files changed

+112
-13
lines changed

FlappyBird/GameScene.swift

+112-13
Original file line numberDiff line numberDiff line change
@@ -8,23 +8,42 @@
88

99
import SpriteKit
1010

11-
class GameScene: SKScene {
11+
class GameScene: SKScene, SKPhysicsContactDelegate{
1212
let verticalPipeGap = 150.0
13-
13+
1414
var bird:SKSpriteNode!
1515
var skyColor:SKColor!
1616
var pipeTextureUp:SKTexture!
1717
var pipeTextureDown:SKTexture!
1818
var movePipesAndRemove:SKAction!
19-
19+
var moving:SKNode!
20+
var pipes:SKNode!
21+
var canRestart = Bool()
22+
var scoreLabelNode:SKLabelNode!
23+
var score = NSInteger()
24+
25+
let birdCategory: UInt32 = 1 << 0
26+
let worldCategory: UInt32 = 1 << 1
27+
let pipeCategory: UInt32 = 1 << 2
28+
let scoreCategory: UInt32 = 1 << 3
29+
2030
override func didMoveToView(view: SKView) {
31+
32+
canRestart = false
33+
2134
// setup physics
2235
self.physicsWorld.gravity = CGVectorMake( 0.0, -5.0 )
36+
self.physicsWorld.contactDelegate = self
2337

2438
// setup background color
2539
skyColor = SKColor(red: 81.0/255.0, green: 192.0/255.0, blue: 201.0/255.0, alpha: 1.0)
2640
self.backgroundColor = skyColor
2741

42+
moving = SKNode()
43+
self.addChild(moving)
44+
pipes = SKNode()
45+
moving.addChild(pipes)
46+
2847
// ground
2948
let groundTexture = SKTexture(imageNamed: "land")
3049
groundTexture.filteringMode = SKTextureFilteringMode.Nearest
@@ -38,7 +57,7 @@ class GameScene: SKScene {
3857
sprite.setScale(2.0)
3958
sprite.position = CGPointMake(i * sprite.size.width, sprite.size.height / 2.0)
4059
sprite.runAction(moveGroundSpritesForever)
41-
self.addChild(sprite)
60+
moving.addChild(sprite)
4261
}
4362

4463
// skyline
@@ -55,7 +74,7 @@ class GameScene: SKScene {
5574
sprite.zPosition = -20
5675
sprite.position = CGPointMake(i * sprite.size.width, sprite.size.height / 2.0 + groundTexture.size().height * 2.0)
5776
sprite.runAction(moveSkySpritesForever)
58-
self.addChild(sprite)
77+
moving.addChild(sprite)
5978
}
6079

6180
// create the pipes textures
@@ -96,15 +115,27 @@ class GameScene: SKScene {
96115
bird.physicsBody.dynamic = true
97116
bird.physicsBody.allowsRotation = false
98117

118+
bird.physicsBody.categoryBitMask = birdCategory
119+
bird.physicsBody.collisionBitMask = worldCategory | pipeCategory
120+
bird.physicsBody.contactTestBitMask = worldCategory | pipeCategory
121+
99122
self.addChild(bird)
100123

101124
// create the ground
102125
var ground = SKNode()
103126
ground.position = CGPointMake(0, groundTexture.size().height)
104127
ground.physicsBody = SKPhysicsBody(rectangleOfSize: CGSizeMake(self.frame.size.width, groundTexture.size().height * 2.0))
105128
ground.physicsBody.dynamic = false
129+
ground.physicsBody.categoryBitMask = worldCategory
106130
self.addChild(ground)
107131

132+
// Initialize label and create a label which holds the score
133+
score = 0
134+
scoreLabelNode = SKLabelNode(fontNamed:"MarkerFelt-Wide")
135+
scoreLabelNode.position = CGPointMake( CGRectGetMidX( self.frame ), 3 * self.frame.size.height / 4 )
136+
scoreLabelNode.zPosition = 100
137+
scoreLabelNode.text = String(score)
138+
self.addChild(scoreLabelNode)
108139

109140
}
110141

@@ -123,6 +154,8 @@ class GameScene: SKScene {
123154

124155
pipeDown.physicsBody = SKPhysicsBody(rectangleOfSize: pipeDown.size)
125156
pipeDown.physicsBody.dynamic = false
157+
pipeDown.physicsBody.categoryBitMask = pipeCategory
158+
pipeDown.physicsBody.contactTestBitMask = birdCategory
126159
pipePair.addChild(pipeDown)
127160

128161
let pipeUp = SKSpriteNode(texture: pipeTextureUp)
@@ -131,21 +164,57 @@ class GameScene: SKScene {
131164

132165
pipeUp.physicsBody = SKPhysicsBody(rectangleOfSize: pipeUp.size)
133166
pipeUp.physicsBody.dynamic = false
167+
pipeUp.physicsBody.categoryBitMask = pipeCategory
168+
pipeUp.physicsBody.contactTestBitMask = birdCategory
134169
pipePair.addChild(pipeUp)
135170

171+
var contactNode = SKNode()
172+
contactNode.position = CGPointMake( pipeDown.size.width + bird.size.width / 2, CGRectGetMidY( self.frame ) )
173+
contactNode.physicsBody = SKPhysicsBody(rectangleOfSize: CGSizeMake( pipeUp.size.width, self.frame.size.height ))
174+
contactNode.physicsBody.dynamic = false
175+
contactNode.physicsBody.categoryBitMask = scoreCategory
176+
contactNode.physicsBody.contactTestBitMask = birdCategory
177+
pipePair.addChild(contactNode)
178+
136179
pipePair.runAction(movePipesAndRemove)
137-
self.addChild(pipePair)
180+
pipes.addChild(pipePair)
181+
182+
}
183+
184+
func resetScene (){
185+
// Move bird to original position and reset velocity
186+
bird.position = CGPointMake(self.frame.size.width / 2.5, CGRectGetMidY(self.frame))
187+
bird.physicsBody.velocity = CGVectorMake( 0, 0 )
188+
bird.physicsBody.collisionBitMask = worldCategory | pipeCategory
189+
bird.speed = 1.0
190+
bird.zRotation = 0.0
191+
192+
// Remove all existing pipes
193+
pipes.removeAllChildren()
194+
195+
// Reset _canRestart
196+
canRestart = false
197+
198+
// Reset score
199+
score = 0
200+
scoreLabelNode.text = String(score)
201+
202+
// Restart animation
203+
moving.speed = 1
138204
}
139205

140206
override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
141207
/* Called when a touch begins */
142-
143-
for touch: AnyObject in touches {
144-
let location = touch.locationInNode(self)
145-
146-
bird.physicsBody.velocity = CGVectorMake(0, 0)
147-
bird.physicsBody.applyImpulse(CGVectorMake(0, 30))
148-
208+
if moving.speed > 0 {
209+
for touch: AnyObject in touches {
210+
let location = touch.locationInNode(self)
211+
212+
bird.physicsBody.velocity = CGVectorMake(0, 0)
213+
bird.physicsBody.applyImpulse(CGVectorMake(0, 30))
214+
215+
}
216+
}else if canRestart {
217+
self.resetScene()
149218
}
150219
}
151220

@@ -165,4 +234,34 @@ class GameScene: SKScene {
165234
/* Called before each frame is rendered */
166235
bird.zRotation = self.clamp( -1, max: 0.5, value: bird.physicsBody.velocity.dy * ( bird.physicsBody.velocity.dy < 0 ? 0.003 : 0.001 ) )
167236
}
237+
238+
func didBeginContact(contact: SKPhysicsContact) {
239+
if moving.speed > 0 {
240+
if ( contact.bodyA.categoryBitMask & scoreCategory ) == scoreCategory || ( contact.bodyB.categoryBitMask & scoreCategory ) == scoreCategory {
241+
// Bird has contact with score entity
242+
score++
243+
scoreLabelNode.text = String(score)
244+
245+
// Add a little visual feedback for the score increment
246+
scoreLabelNode.runAction(SKAction.sequence([SKAction.scaleTo(1.5, duration:NSTimeInterval(0.1)), SKAction.scaleTo(1.0, duration:NSTimeInterval(0.1))]))
247+
} else {
248+
249+
moving.speed = 0
250+
251+
bird.physicsBody.collisionBitMask = worldCategory
252+
bird.runAction( SKAction.rotateByAngle(CGFloat(M_PI) * CGFloat(bird.position.y) * 0.01, duration:1), completion:{self.bird.speed = 0 })
253+
254+
255+
// Flash background if contact is detected
256+
self.removeActionForKey("flash")
257+
self.runAction(SKAction.sequence([SKAction.repeatAction(SKAction.sequence([SKAction.runBlock({
258+
self.backgroundColor = SKColor(red: 1, green: 0, blue: 0, alpha: 1.0)
259+
}),SKAction.waitForDuration(NSTimeInterval(0.05)), SKAction.runBlock({
260+
self.backgroundColor = self.skyColor
261+
}), SKAction.waitForDuration(NSTimeInterval(0.05))]), count:4), SKAction.runBlock({
262+
self.canRestart = true
263+
})]), withKey: "flash")
264+
}
265+
}
266+
}
168267
}
5.04 KB
Loading

0 commit comments

Comments
 (0)