IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    SceneKit一个3D场景角色的代码重构

    summer发表于 2016-07-08 06:00:38
    love 0

    SuperSpaceMan3D是一个以SceneKit为基础的小游戏项目,作者展示了用SceneKit开发3D游戏的强大威力.不过在实际运行时会发现有一些小bug,这里我们依次尝试将其修复

    首先,当spaceman接触到敌人的时候,游戏结束,弹出GameOver视图,然后当玩家再触摸屏幕时,开始新的游戏.在实际游戏中发现,spaceman接触敌人后GameOver视图很快闪过,游戏随即重新开始,不能达到等待用户触摸再开始的目的.

    分析发现didBeginContact代码逻辑缺少区分条件,在GameViewController类中添加类级属性:

    static var isGameOverViewShowing = false

    之所以添加static属性是因为需要在GameView中修改该属性,当然这是一种比较差的重构,应该make一个实例变量.

    在spaceman接触敌人的代码逻辑中添加如下代码:

    GameViewController.isGameOverViewShowing = true
    gameStarted = false

    在didSimulatePhysicsAtTime方法的第一个判断条件中加上isGameOverShowing这个条件:

    if sceneView.touchCount > 0 && !gameStarted && !GameViewController.isGameOverViewShowing{

    }

    进入GameView.swift中,在touchesBegan方法中添加以下一行:

    if GameViewController.isGameOverViewShowing{
    GameViewController.isGameOverViewShowing = false
    }

    这里是关键的一句,重新触发了游戏!

    运行游戏,此时发现虽然大多数情况下逻辑正常,但是当多次连续点击屏幕时会发生spaceman重置位置不正确的情况.

    进入setupSpaceMan方法,发现spaceManNode的物理对象类型是动态类型,但此游戏中spaceman位置全部都是通过代码手工调整,这里应该将其设置为Static类型,于是修改代码如下:

    spaceManNode!.physicsBody = SCNPhysicsBody(type: .Static, shape: nil)

    同时修改resetSpaceman方法为如下内容:

    func resetSpaceman(){
    spaceMan.removeAllActions()
    spaceMan.position = SCNVector3(x: 0, y: 0, z: 200)
    spaceMan.rotation = SCNVector4(x: 0, y: 1, z: 0, w: Float(M_PI))
    }

    再次运行游戏,这次基本达到了预期的效果(图片过大需要加载时间):

    这里写图片描述



沪ICP备19023445号-2号
友情链接