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 inSpriteKit
The 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 detectiondidBegin
To 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