iOS Swift开发:移除StackLayoutView子视图约束及赛车游戏拖拽范围限制
问题2:限制拖拽车辆的移动范围
既然已经实现了拖拽和碰撞检测,限制移动范围的核心是在拖拽回调中,将车辆位置“约束”在允许的区域内。这里提供两种实用方案:
方案1:直接修改视图frame/center(适合简单场景)
假设你想让己方车辆仅在水平方向左右移动,垂直方向固定在底部,可在UIPanGestureRecognizer的处理方法中这样写:
@objc func handleCarPan(_ gesture: UIPanGestureRecognizer) { guard let carView = gesture.view else { return } let translation = gesture.translation(in: self.view) // 计算新的X坐标,叠加拖拽偏移量 var newCenterX = carView.center.x + translation.x // 限制X范围:避免车辆超出屏幕左右边缘 let minX = carView.bounds.width / 2 let maxX = self.view.bounds.width - minX newCenterX = max(minX, min(newCenterX, maxX)) // 固定Y坐标在底部(距离底部20pt的位置) let fixedY = self.view.bounds.height - carView.bounds.height / 2 - 20 carView.center = CGPoint(x: newCenterX, y: fixedY) // 重置拖拽偏移量,防止下次累加 gesture.setTranslation(.zero, in: self.view) }
如果需要让车辆在指定矩形区域内自由移动(比如底部1/3屏幕区域),可同时限制X和Y方向:
@objc func handleCarPan(_ gesture: UIPanGestureRecognizer) { guard let carView = gesture.view else { return } let translation = gesture.translation(in: self.view) var newFrame = carView.frame newFrame.origin.x += translation.x newFrame.origin.y += translation.y // 定义允许移动的区域(底部1/3屏幕) let allowedArea = CGRect( x: 0, y: self.view.bounds.height * 2/3, width: self.view.bounds.width, height: self.view.bounds.height / 3 ) // 限制X方向:车辆左边界不超出区域左边缘,右边界不超出区域右边缘 newFrame.origin.x = max(allowedArea.minX, min(newFrame.origin.x, allowedArea.maxX - newFrame.width)) // 限制Y方向:车辆上边界不超出区域上边缘,下边界不超出区域下边缘 newFrame.origin.y = max(allowedArea.minY, min(newFrame.origin.y, allowedArea.maxY - newFrame.height)) carView.frame = newFrame gesture.setTranslation(.zero, in: self.view) }
方案2:通过Auto Layout约束修改(适配屏幕旋转)
如果游戏需要支持屏幕旋转,用约束的方式更稳妥。先在初始化车辆时添加约束并保存关键约束引用:
var carCenterXConstraint: NSLayoutConstraint! // 初始化己方车辆 func setupPlayerCar() { let carView = UIImageView(image: UIImage(named: "player_car")) carView.translatesAutoresizingMaskIntoConstraints = false self.view.addSubview(carView) // 保存水平中心约束引用,用于拖拽时修改 carCenterXConstraint = carView.centerXAnchor.constraint(equalTo: self.view.centerXAnchor) carCenterXConstraint.isActive = true // 固定Y轴在底部 carView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor, constant: -20).isActive = true // 设置车辆固定宽高 carView.widthAnchor.constraint(equalToConstant: 80).isActive = true carView.heightAnchor.constraint(equalToConstant: 120).isActive = true // 添加拖拽手势 let panGesture = UIPanGestureRecognizer(target: self, action: #selector(handleCarPan(_:))) carView.addGestureRecognizer(panGesture) carView.isUserInteractionEnabled = true }
然后在拖拽处理方法中修改约束的constant值并限制范围:
@objc func handleCarPan(_ gesture: UIPanGestureRecognizer) { let translation = gesture.translation(in: self.view) // 修改水平中心约束的偏移量 carCenterXConstraint.constant += translation.x // 限制偏移量范围,确保车辆不超出屏幕左右 let maxOffset = self.view.bounds.width / 2 - carView.bounds.width / 2 carCenterXConstraint.constant = max(-maxOffset, min(carCenterXConstraint.constant, maxOffset)) // 重置拖拽偏移量 gesture.setTranslation(.zero, in: self.view) }
这种方式在屏幕旋转时会自动适配新尺寸,无需额外处理适配逻辑。
内容的提问来源于stack exchange,提问作者Wai Yan Hein
相关产品推荐
相关产品推荐

