我正在使用 swift 构建一个船舶游戏.无法检测到冲突



我正在使用 swift 构建一个飞船游戏。目标是避开来袭的石头,随着等级的增加,尽可能多地得分。石头从相反的方向来击中船。但是我无法检测到船和石头之间的碰撞,石头穿过船。船可以向左或向右移动。

我使用 rect1.interects(rect2) 进行交叉。

谢谢。

这是视图控制器.swift

import UIKit
class ViewController: UIViewController {

@IBOutlet weak var moveWater: MovingWater!
var boat:UIImageView!
var stone:UIImageView!
var boatLeftRight : UILongPressGestureRecognizer!
var tapTimer:Timer!
var leftM:UInt32 = 55
var rightM:UInt32 = 250
var leftS:UInt32 = 35
var rightS:UInt32 = 220
func startGame() {
boat = UIImageView(image: UIImage(named: "boat"))
boat.frame = CGRect(x: 0, y: 0, width: 60, height: 90)
boat.frame.origin.y = self.view.bounds.height - boat.frame.size.height - 10
boat.center.x = self.view.bounds.midX
self.view.insertSubview(boat, aboveSubview: moveWater)
boatLeftRight = UILongPressGestureRecognizer(target: self, action: #selector(ViewController.leftRight(tap:)))
boatLeftRight.minimumPressDuration = 0.001
moveWater.addGestureRecognizer(boatLeftRight)

}
func leftRight(tap:UILongPressGestureRecognizer) {

if tap.state == UIGestureRecognizerState.ended {
if (tapTimer != nil)  {
self.tapTimer.invalidate()
}
} else if tap.state == UIGestureRecognizerState.began {
let touch = tap.location(in: moveWater)
if touch.x > moveWater.frame.midX {
tapTimer = Timer.scheduledTimer(timeInterval: TimeInterval(0.005), target: self, selector: #selector(ViewController.moveBoat(time:)), userInfo: "right", repeats: true)
} else {
tapTimer = Timer.scheduledTimer(timeInterval: TimeInterval(0.005), target: self, selector: #selector(ViewController.moveBoat(time:)), userInfo: "left", repeats: true)
}
}

}
func moveBoat(time:Timer) {
if let d = time.userInfo as? String! {
var bot2 = boat.frame
if d == "right" {
if bot2.origin.x < CGFloat(rightM) {
bot2.origin.x += 2
}

} else {
if bot2.origin.x > CGFloat(leftM) {
bot2.origin.x -= 2
}
}
boat.frame = bot2
}

}
func movingStone() {

stone = UIImageView(image: UIImage(named: "stones.png"))
var stone2 = leftS + arc4random() % rightS

stone.bounds = CGRect(x:10, y:10, width:81.0, height:124.0)
stone.contentMode = .center;
stone.layer.position = CGPoint(x: Int(stone2), y: 10)
stone.transform = CGAffineTransform(rotationAngle: 3.142)

self.view.insertSubview(stone, aboveSubview: moveWater)

UIView.animate(withDuration: 5, delay: 0, options: UIViewAnimationOptions.curveLinear, animations: { () -> Void in
self.stone.frame.origin.y = self.view.bounds.height + self.stone.frame.height + 10
}) { (success:Bool) -> Void in
self.stone.removeFromSuperview()
self.movingStone()
}

}
func update() {
if(boat.bounds.intersects(stone.bounds)) {
boat.image = //set new image
}
}

override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
moveWater.backgroundStart()
startGame()
movingStone()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}

}

我看到了你自己的答案。 这确实是基本的碰撞检测。 你仍然应该看看SpriteKit。 我看到您正在使用计时器,这不是最好的方法,因为从长远来看,计时器会给您带来性能问题。 这是开始游戏开发时常见的错误。

也许您认为可以通过设置非常快的计时器来确保帧速率。 问题是计时器不一致,它们的优先级也很低。 这意味着如果后台发生更重要的事情,您的计时器调用将被延迟。 如果你的动作是基于强制刷新率,它会很快变得断断续续。 此外,您在计时器中运行的代码可能会变快或变慢,具体取决于您使用的逻辑。

SpriteKit为您提供了每帧运行一次的更新功能,让您了解每一帧的当前系统时间。 通过跟踪该值,您可以计算两帧之间经过的时间,然后可以相应地缩放移动以补偿两帧之间的时间差。

最重要的是,SpriteKit为您提供了许多碰撞检测和移动选项。 它集成了一个制作精良的物理引擎和碰撞检测系统。 它还将对复杂形状进行碰撞检测,对身体施加力等。

我强烈建议您按照上面答案中提供给您的Ray Wenderlich网站的链接进行操作。 如果你有预算,你可能还想买他们关于如何为苹果设备制作2D游戏的书。 我已经读过封面了,我可以说我喜欢它。 我现在可以使用SpriteKit做我自己的事情,对于新手来说,这也是一个非常好的入门。

你选择UIKit来制作你的游戏有什么原因吗?

如果你做一个游戏,你真的应该使用SpriteKit而不是UIKit。

查看谷歌和YouTube的SpriteKit教程,有负载。

一个非常好的开始是这个教你SpriteKit场景编辑器的基础知识以及如何进行碰撞等。

https://www.raywenderlich.com/118225/introduction-sprite-kit-scene-editor

我建议你不要再这样下去了。

希望这有帮助

我自己解决了这个问题。这很容易,没有任何SpriteKit,我检测到了碰撞。

func intersectsAt(tap2 : Timer) {

var f1 : CGRect!
var f2 : CGRect!
f1 = boat.layer.presentation()?.frame
f2 = stone.layer.presentation()?.frame
if(f1.intersects(f2)) {
stopGame()
}
}

最新更新