将游戏实现为快速游戏
问题描述:
我已经在Xcode中创建了一个游戏,但是我想在玩家输掉的时候切换到屏幕上的游戏,此时main.storyboard文件是空白的。我发现这个解决方案Using a view controller for a game over scene将游戏实现为快速游戏
但是,我不确定如何实现这个到我的代码。我附上了我的代码,如果有人可以帮助我,这将不胜感激。
import SpriteKit
import GameplayKit
class GameScene: SKScene, SKPhysicsContactDelegate {
var bird = SKSpriteNode()
var bg = SKSpriteNode()
var scoreLabel = SKLabelNode()
var score = 0
var gameOverLabel = SKLabelNode()
var timer = Timer()
enum ColliderType: UInt32 {
case Bird = 1
case Object = 2
case Gap = 4
}
var gameOver = false
func makePipes() {
let movePipes = SKAction.move(by: CGVector(dx: -2 * self.frame.width, dy: 0), duration: TimeInterval(self.frame.width/100))
let gapHeight = bird.size.height * 4
let movementAmount = arc4random() % UInt32(self.frame.height/2)
let pipeOffset = CGFloat(movementAmount) - self.frame.height/4
let pipeTexture = SKTexture(imageNamed: "pipe1.png")
let pipe1 = SKSpriteNode(texture: pipeTexture)
pipe1.position = CGPoint(x: self.frame.midX + self.frame.width, y: self.frame.midY + pipeTexture.size().height/2 + gapHeight/2 + pipeOffset)
pipe1.run(movePipes)
pipe1.physicsBody = SKPhysicsBody(rectangleOf: pipeTexture.size())
pipe1.physicsBody!.isDynamic = false
pipe1.physicsBody!.contactTestBitMask = ColliderType.Object.rawValue
pipe1.physicsBody!.categoryBitMask = ColliderType.Object.rawValue
pipe1.physicsBody!.collisionBitMask = ColliderType.Object.rawValue
pipe1.zPosition = -1
self.addChild(pipe1)
let pipe2Texture = SKTexture(imageNamed: "pipe2.png")
let pipe2 = SKSpriteNode(texture: pipe2Texture)
pipe2.position = CGPoint(x: self.frame.midX + self.frame.width, y: self.frame.midY - pipe2Texture.size().height/2 - gapHeight/2 + pipeOffset)
pipe2.run(movePipes)
pipe2.physicsBody = SKPhysicsBody(rectangleOf: pipeTexture.size())
pipe2.physicsBody!.isDynamic = false
pipe2.physicsBody!.contactTestBitMask = ColliderType.Object.rawValue
pipe2.physicsBody!.categoryBitMask = ColliderType.Object.rawValue
pipe2.physicsBody!.collisionBitMask = ColliderType.Object.rawValue
pipe2.zPosition = -1
self.addChild(pipe2)
let gap = SKNode()
gap.position = CGPoint(x: self.frame.midX + self.frame.width, y: self.frame.midY + pipeOffset)
gap.physicsBody = SKPhysicsBody(rectangleOf: CGSize(width: pipeTexture.size().width, height: gapHeight))
gap.physicsBody!.isDynamic = false
gap.run(movePipes)
gap.physicsBody!.contactTestBitMask = ColliderType.Bird.rawValue
gap.physicsBody!.categoryBitMask = ColliderType.Gap.rawValue
gap.physicsBody!.collisionBitMask = ColliderType.Gap.rawValue
self.addChild(gap)
}
func didBegin(_ contact: SKPhysicsContact) {
if gameOver == false {
if contact.bodyA.categoryBitMask == ColliderType.Gap.rawValue || contact.bodyB.categoryBitMask == ColliderType.Gap.rawValue {
score += 1
scoreLabel.text = String(score)
} else {
self.speed = 0
gameOver = true
timer.invalidate()
gameOverLabel.fontName = "Helvetica"
gameOverLabel.fontSize = 30
gameOverLabel.text = "Game Over! Tap to play again."
gameOverLabel.position = CGPoint(x: self.frame.midX, y: self.frame.midY)
self.addChild(gameOverLabel)
}
}
}
override func didMove(to view: SKView) {
self.physicsWorld.contactDelegate = self
setupGame()
}
func setupGame() {
timer = Timer.scheduledTimer(timeInterval: 3, target: self, selector: #selector(self.makePipes), userInfo: nil, repeats: true)
let bgTexture = SKTexture(imageNamed: "bg.png")
let moveBGAnimation = SKAction.move(by: CGVector(dx: -bgTexture.size().width, dy: 0), duration: 7)
let shiftBGAnimation = SKAction.move(by: CGVector(dx: bgTexture.size().width, dy: 0), duration: 0)
let moveBGForever = SKAction.repeatForever(SKAction.sequence([moveBGAnimation, shiftBGAnimation]))
var i: CGFloat = 0
while i < 3 {
bg = SKSpriteNode(texture: bgTexture)
bg.position = CGPoint(x: bgTexture.size().width * i, y: self.frame.midY)
bg.size.height = self.frame.height
bg.run(moveBGForever)
bg.zPosition = -2
self.addChild(bg)
i += 1
}
let birdTexture = SKTexture(imageNamed: "flappy1.png")
let birdTexture2 = SKTexture(imageNamed: "flappy2.png")
let animation = SKAction.animate(with: [birdTexture, birdTexture2], timePerFrame: 0.1)
let makeBirdFlap = SKAction.repeatForever(animation)
bird = SKSpriteNode(texture: birdTexture)
bird.position = CGPoint(x: self.frame.midX, y: self.frame.midY)
bird.run(makeBirdFlap)
bird.physicsBody = SKPhysicsBody(circleOfRadius: birdTexture.size().height/2)
bird.physicsBody!.isDynamic = false
bird.physicsBody!.contactTestBitMask = ColliderType.Object.rawValue
bird.physicsBody!.categoryBitMask = ColliderType.Bird.rawValue
bird.physicsBody!.collisionBitMask = ColliderType.Bird.rawValue
self.addChild(bird)
let ground = SKNode()
ground.position = CGPoint(x: self.frame.midX, y: -self.frame.height/2)
ground.physicsBody = SKPhysicsBody(rectangleOf: CGSize(width: self.frame.width, height: 1))
ground.physicsBody!.isDynamic = false
ground.physicsBody!.contactTestBitMask = ColliderType.Object.rawValue
ground.physicsBody!.categoryBitMask = ColliderType.Object.rawValue
ground.physicsBody!.collisionBitMask = ColliderType.Object.rawValue
self.addChild(ground)
scoreLabel.fontName = "Helvetica"
scoreLabel.fontSize = 60
scoreLabel.text = "0"
scoreLabel.position = CGPoint(x: self.frame.midX, y: self.frame.height/2 - 220)
self.addChild(scoreLabel)
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
if gameOver == false {
bird.physicsBody!.isDynamic = true
bird.physicsBody!.velocity = CGVector(dx: 0, dy: 0)
bird.physicsBody!.applyImpulse(CGVector(dx: 0, dy: 80))
} else {
gameOver = false
score = 0
self.speed = 1
self.removeAllChildren()
setupGame()
}
}
override func update(_ currentTime: TimeInterval) {
// Called before each frame is rendered
}
}
答
您应该设置GameOverScene并在需要时显示此场景。该RayWenderlich网站已经很多教程将告诉你如何做到这一点,很可能过多解释这里
这里是到
This page链接展示了如何实现一个级别完整覆盖)
但基本上你只需要创建一个新的场景,添加任何UI元素它,你需要的,然后从视图控制器,你可以拨打PresentScene,像这样
view.presentScene(scene)
示例代码:
class GameScene: SKScene {
var notificationLabel = SKLabelNode(text: "Tap the screen to win")
override func didMove(to view: SKView) {
self.backgroundColor = SKColor.black
addChild(notificationLabel)
notificationLabel.fontSize = 32.0
notificationLabel.color = SKColor.white
notificationLabel.fontName = "Thonburi-Bold"
notificationLabel.position = CGPoint(x: size.width/2, y: size.height/2)
}
func displayGameOver() {
let gameOverScene = GameOverScene(size: size)
gameOverScene.scaleMode = scaleMode
let reveal = SKTransition.flipHorizontal(withDuration: 0.5)
view?.presentScene(gameOverScene, transition: reveal)
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
displayGameOver()
}
}
class GameOverScene: SKScene {
var notificationLabel = SKLabelNode(text: "You Won")
override init(size: CGSize) {
super.init(size: size)
self.backgroundColor = SKColor.darkGray
addChild(notificationLabel)
notificationLabel.fontSize = 32.0
notificationLabel.color = SKColor.white
notificationLabel.fontName = "Thonburi-Bold"
notificationLabel.position = CGPoint(x: size.width/2, y: size.height/2)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
let gameScene = GameScene(size: size)
gameScene.scaleMode = scaleMode
let reveal = SKTransition.flipHorizontal(withDuration: 0.5)
view?.presentScene(gameScene, transition: reveal)
}
}
在任一场景中点击屏幕都会显示其他场景。你也应该可以通过viewcontroller来管理它,并做几乎相同的事情,但是我还没有这样做,我自己对SpriteKit还是比较新的。
希望这有助于
所有上面的代码是在GameScene.swift,本教程显示了IBOutlets添加到GameViewController.swift如果我添加一切都在那里,我怎么能叫它当游戏结束运行。目前我只有一个标签,弹出并停止游戏运行。对不起,如果我不理解,我是新的发展 – uz7
我会做一个例子,并很快发布 – Scriptable
谢谢,我期待着看到它。 – uz7