Estou participando da competição individual do Nuggets Community Game Creativity Contest. Para mais detalhes, consulte: Game Creativity Contest
prefácio
Não sei se você encontrou este jogo de pinball na rua. Quando você o experimenta, você pode jogá-lo assim que jogar. Você não pode jogá-lo enquanto você paga por ele. Lembro que a primeira vez que entrei em contato com este jogo, eu estava no ensino médio. Vi esse jogo na rua. Meus amigos e eu ficamos profundamente atraídos por esse jogo, então todos os nossos pertences foram incluídos. Feliz por ir casa. Naquela época, a Internet ainda não estava desenvolvida, e eu não sabia que essa coisa ainda tinha um mecanismo. Depois de entender o princípio , sinto que sou xxx. Em seguida, vamos usá-lo SpriteKit
para implementar um jogo de pinball sem rotinas
Instalar
1. Use e instale TestFlight
o mesmo que a instalação anterior do jogo Airplane Wars
2. Você pode executar o código para instalar, o endereço de demonstração está aqui
introdução do jogo
Puxe a haste da mola, de modo que a bola seja submetida a diferentes forças elásticas para fazê-la entrar na grade. A jogabilidade é bem simples, não vou falar muito, vamos implementá-la abaixo.
concluir
1. O alcance (limite) que a bola pode mover
Podemos ver que o alcance de atividade da bola é a área vermelha, então como podemos fazer a bola apenas na área vermelha? De fato, o SpriteKit
sistema nos fornece corpos físicos do tipo limite, incluindo os seguintes
// 在两点之间创建边
public /*not inherited*/ init(edgeFrom p1: CGPoint, to p2: CGPoint)
// 从路径创建边链
public /*not inherited*/ init(edgeChainFrom path: CGPath)
// 从路径创建循环边
public /*not inherited*/ init(edgeLoopFrom path: CGPath)
// 从矩形创建循环边
public /*not inherited*/ init(edgeLoopFrom rect: CGRect)
复制代码
Usamos o método de inicialização de criar loops de borda de caminhos para physicsBody
criar um limite para a cena atual, aqui usamos curvas de Bezier para desenhar o caminho
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)
}
复制代码
2. Puxe a mola para fazer a bola sair
2.1. Primeiro, touchesBegan
julgamos se o toque é uma mola no método, em caso afirmativo, registramos o ponto inicial do toque e definimos a aceleração gravitacional do mundo físico atual para (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
}
}
复制代码
2.2. touchesMoved
Calcule o deslocamento do movimento do dedo no método
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)
}
}
}
复制代码
touchesEnded
2.3. Calcule a força de tração necessária da bola de acordo com o deslocamento no método de liberação da mola e defina uma aceleração gravitacional para o mundo físico atual. O padrão é (0,-9,8), aqui nós o alteramos para (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
// 给小球添加一个向上的拉力
ballNode.physicsBody?.applyForce(CGVector(dx: 0, dy: dy))
offsetY = 0
view?.isUserInteractionEnabled = false
reward -= 50
}
}
复制代码
3. Detecte a área de queda da bola
Existem 9 áreas onde a bola finalmente cai, ou seja, a área onde estão localizados os 8 minérios e a área onde está localizada a nascente. Aqui usamos o didBegin
lado para detectar a área de queda da bola
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
}
}
}
}
复制代码
Neste ponto, a realização deste jogo acabou