I am participating in the nuggets Community game creative submission Contest. For details, please see: Game Creative Submission Contest

preface

Do not know everyone in the street have encountered this pinball game, try to play when a play into, as long as the money how to play are not into. I remember the first time I came into contact with this game when I was in junior high school. When I saw this game on the street, my friend and I were deeply attracted by this game, so all our possessions were taken into the game, and finally we couldn’t be reconciled to go home. The Internet wasn’t there, and I didn’t know this thing worked. After understanding the principle, I feel like XXX. Let’s use SpriteKit to create a pinball game with no tricks

The installation

1. Install using TestFlight, just as you did in the previous plane Wars game

Testflight.apple.com/join/YCDnN4…

2, can run code installation, demo address is here

The game is introduced

Pull on the spring rod, so that the ball receives different springs and enters the cell. The gameplay is very simple and without going into details, let’s implement it.

implementation

1. The range (boundary) where the ball can move

We can see that the ball is in the red area, so how do we make the ball only in the red area? In fact inSpriteKitThe inside system provides us with boundary types of physics, including the following ones

Public /*not inherited*/ init(edgeFrom P1: CGPoint, to P2: inherited) Public /* Not inherited*/ init(edgeChainFrom path: inherited Public /*not inherited*/ init(edgeLoopFrom path: inherited) Public /*not inherited*/ init(edgeLoopFrom rect: inherited)Copy the code

We use the initialization method of creating a loop edge from a path to create a boundary for physicsBody of the current scene, where we draw the path using a Bezier curve

private func setupPhysicsBody() {
    let path = UIBezierPath()
    path.lineWidth = 2
    path.move(to: CGPoint(x: 0, y: size.height-size.width-topOffset))
    path.addLine(to: CGPoint(x: 0, y: size.height-size.width/2-topOffset))
    path.addArc(withCenter: CGPoint(x: size.width/2, y: size.height-size.width/2-topOffset), radius: size.width/2, startAngle: -.pi, endAngle: 0, clockwise: false)
    path.addLine(to: CGPoint(x: size.width, y: size.height-size.width/2-topOffset))
    path.addLine(to: CGPoint(x: size.width, y: size.height-size.width-topOffset))
    path.close()
    physicsBody = SKPhysicsBody(edgeLoopFrom: path.cgPath)
}
Copy the code
2. Pull the spring to make the ball pop out

2.1. First, we determined whether the touch was a spring in the touchesBegan method. If so, we recorded the starting point of the touch and set the acceleration of gravity in the current physical world as (0,0).

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) { isTouch = false offsetY = 0 physicsWorld.gravity = .zero guard let touch = (touches as NSSet).anyObject() as? UITouch else { return } let point = touch.location(in: self) let node = atPoint(point) switch node.name { case "back": View?. PresentScene (MenuScene(size: size), transition:.fade(withDuration: 0.5)) case "Tanhuang" WHERE reward >= 50: isTouch = true startTouchPoint = point default: break } }Copy the code

2.2 calculate the offset of finger movement in the ‘touchesMoved’ method

override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) { guard let touch = (touches as NSSet).anyObject() as? UITouch else { return } let point = touch.location(in: self) if isTouch { offsetY = point.y-startTouchPoint.y if offsetY >= -80, offsetY <= 0 { springNode.size = CGSize(width: 28, height: 120+offsetY) ballNode.position = CGPoint(x: GridWidth * 8.5+3.5, y: size.height-size.width+ 74-topoffset +offsetY/2)}}Copy the code

2.3 In the “touchesEnded” method, calculate the tension required by the ball according to the offset, and set an acceleration of gravity for the current physical world. The default is (0,-9.8). Here we change it to (0,-3.5).

override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) { if isTouch { springNode.size = CGSize(width: 28, height: 120) physicsWorld.gravity = CGVector(dx: 0, dy: -3.5) let dy = 300 * -(offsetY/2) * 0.1 .applyForce(CGVector(dx: 0, dy: dy)) offsetY = 0 view? .isUserInteractionEnabled = false reward -= 50 } }Copy the code
3. Detect the drop area of the ball

The ball ends up falling in nine zones, eight ore zones and one spring zone. Here we use a proxy for collision detectiondidBeginTo detect the ball drop area

extension PinballScene: SKPhysicsContactDelegate { func didBegin(_ contact: SKPhysicsContact) {// Let springArea = CGRect(x: CGFloat(8)*gridWidth, y: size.height-size.width-topOffset, width: gridWidth, height: 28) if springArea.contains(ballN ode.position) { view? .isUserInteractionEnabled = true return } if let v = view, v.isUserInteractionEnabled { return } for model in rewards { if model.rewardArea.contains(ballNode.position) { reward +=  model.reward view? .isUserInteractionEnabled = true } } } }Copy the code

This is the end of the implementation of the game

My other games

SpriteKit: Airplane Wars