街头骗术弹球游戏

·  阅读 2554
街头骗术弹球游戏

弹球.gif

我正在参加掘金社区游戏创意投稿大赛个人赛,详情请看:游戏创意投稿大赛

前言

不知道大家在街头有没有碰到过这个弹球游戏,试玩的时候一弹就进,只要交钱怎么弹都不进。记得第一次接触这个游戏的时候还是在上初中,街上逢会看到这个游戏,我和我的小伙伴深深的被这个游戏吸引,于是我俩所有的家当都搭进去了,最后不甘心的回家了。当时网络还不发达,也不知道这玩意还有机关。在了解原理后感觉自己就是xxx。下面我们就用SpriteKit来实现一个没有套路的弹球游戏

安装

1、使用TestFlight安装,和上一篇飞机大战游戏安装一样

testflight.apple.com/join/YCDnN4…

2、可以运行代码安装,demo地址在这

游戏介绍

拉动弹簧杆,使小球受到不同的弹力使其进入格子中。玩法很简单就不多说了,下面就来实现它。

实现

1、小球可以活动的范围(边界)

IMG_1029.PNG 我们可以看到小球活动的范围就是红色的区域,那么我们该怎么让小球只在红色的区域呢?其实在SpriteKit里面系统给我们提供了边界类型的物理体,有如下这几种

// 在两点之间创建边
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)
复制代码

我们使用从路径创建循环边这个初始化方法,为当前场景的physicsBody创建一个边界,这里我们使用贝塞尔曲线来画路径

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、拉动弹簧使小球弹出

2.1、首先我们在touchesBegan方法中判断触摸的是不是弹簧,如果是的话记录触摸的起始点,并设置当前物理世界的重力加速度为(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方法中计算手指移动的偏移量

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)
        }
    }
}
复制代码

2.3、在松开弹簧即touchesEnded方法中根据偏移量计算小球的所需的拉力,并给当前的物理世界设置一个重力加速度,默认是(0,-9.8),这里我们改成(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、检测小球掉落区域

截屏2022-04-13 14.42.59.png 小球最终掉落的区域有9个,分别是8个矿石所在的区域和弹簧所在的区域。这里我们使用碰撞检测的代理方didBegin中来检测小球掉落区域

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
            }
        }
    }
}
复制代码

到此这个游戏的实现就结束了

我的其他游戏

SpriteKit之飞机大战

分类:
iOS
标签:
收藏成功!
已添加到「」, 点击更改