天天看點

cocos creator 做一個塗鴉跳躍

cocos creator 做一個塗鴉跳躍

問題1:如何實作主角跟随

問題2:如何實作向上跳動時,所有跳闆都能穿透,向下掉落時,所有跳闆都能彈起

問題3:如果實作不同跳闆有不同的彈跳高度

問題4:如何實作背景滾動

問題5:添加怪物

問題6:添加子彈

實作主角跟随

cocos 有一個錄影機的概念,在錄影機裡面的東西,就能看到,在這之外 的就看不到,是以,隻需要把錄影機一直跟着主角,就能實作主角跟随的效果了

代碼其實就一點點:

cc.Class {
    extends: cc.Component

    properties: {
        player: cc.Node
    }
    lateUpdate: (dt) ->
        targetPos = this.player.convertToWorldSpaceAR(cc.Vec2.ZERO)
        pos = this.node.parent.convertToNodeSpaceAR(targetPos)
        this.node.position = cc.v2(this.node.position.x, pos.y)
        return
}
           

因為主角在遊戲過程中,一直在移動,是以要先擷取主角的世界坐标

之後為了讓錄影機和跟随主角,需要把錄影機的坐标設定成主角的坐标

主角的世界坐标算出來後,再把它換算成錄影機的模型坐标,這樣就可以直接 setposition了

跳躍過程彈闆狀态

嘗試過程很複雜,嘗試過上升過程設定所有彈闆為sensor,發現無效,嘗試過隐藏collider,也無效,最後把rigidbody隐藏就好了

于是,有了下面的步驟:

1、根據角色目前位置和上一次位置的正負,判斷角色是在上升還是在下落

_getPlayerDir: ->
        @_lastPlayerY ?= 0
        playerPos = this.player.convertToWorldSpaceAR(cc.Vec2.ZERO)
        dir = "up"
        if playerPos.y > @_lastPlayerY
            dir = "up"
        else
            dir = "down"
        @_lastPlayerY = playerPos.y
        return dir
           

2、上升時隐藏所有彈闆的rigidBody

3、下降時顯示所有彈闆的rigidBody

_changeRigidBodyActive: (dt) ->
        return unless @_isTimeOk()
        playerDir = @_getPlayerDir()
        for platform, index in @_platformList
            rigidBody = platform.getComponent(cc.RigidBody)
            rigidBody.active = playerDir is "down"
        return
           

實作不同跳闆有不同的彈跳高度

先生成三個預制體,每個預制體挂同一個腳本檔案

然後在腳本屬性裡,設定不同的參數即可

cc.Class {
    extends: cc.Component

    properties: {
        impulse: cc.v2(0, 3000)
    }

    onLoad: ->
        this.node.getComponent(cc.PhysicsBoxCollider).name = "impulse_platform"
        @_createAction() if Math.random() > 0.8
        
    _createAction: ->
        ac1 = cc.moveBy(1, 200, 0)
        ac2 = cc.moveBy(1, -200, 0)
        this.node.runAction(cc.repeatForever(cc.sequence(ac1, ac2)))

    onBeginContact: (contact, selfCollider, otherCollider) ->
        manifold = contact.getWorldManifold()
        return if manifold.normal.y isnt 1
        body = otherCollider.body
        body.linearVelocity = cc.v2()
        body.applyLinearImpulse(this.impulse, body.getWorldCenter(), true)
        return
}
           

實作背景滾動

遊戲中錄影機是跟随角色移動的,是以很多書上講的那種背景移動,即循環減一個數,減到小于一定值後,再重置回去的方法,就無效了。因為這種方法是要保證錄影機不動的情況下才有用的。是以,得想另一種方法來滿足這個背景滾動

之前做過一個動态scrollview的插件,其實這個就和背景滾動的原理是一樣的。當角色往上移動時,如果最高的背景到目前位置的距離小于一定值,則把最低位置的背景移動到最高背景的上方,當角色往下降落時,如果最低位置的背景與目前位置的距離小于一定值時,則把最高位置的背景移動下最低背影的下方。

步驟為:

1、将所有layer放在一個數組中,這個遊戲中用到了4個

2、在update中調用

3、對layer按y坐标按從小到大排序

4、如果要比較最遠距離的,則取數組中最大索引值對應的layer,反之取0

cc.Class {
    extends: cc.Component

    properties: {
        player: cc.Node
        bgLayerTable: [cc.Node]
    }

    onLoad: ->
        @speed = 5

    _fillUpLayer: ->
        playerPos = @player.convertToWorldSpaceAR(cc.Vec2.ZERO)
        maxY = @bgLayerTable[@bgLayerTable.length - 1].getBoundingBox().yMax
        if maxY - playerPos.y < cc.winSize.height
            @bgLayerTable[0].setPosition(cc.v2(0, maxY + cc.winSize.height / 2))
        return

    _fillDownLayer: ->
        playerPos = @player.convertToWorldSpaceAR(cc.Vec2.ZERO)
        minY = @bgLayerTable[0].getBoundingBox().yMin
        if playerPos.y - minY < cc.winSize.height
            pos = cc.v2(0, minY - cc.winSize.height / 2)
            @bgLayerTable[@bgLayerTable.length - 1].setPosition(pos)
        return

    _updateBackgroundLayer: (dt) ->
        @_orderLayerTable()
        @_fillUpLayer()
        @_fillDownLayer()
        
    _orderLayerTable: ->
        this.bgLayerTable.sort( (a, b) -> a.y - b.y)

    update: (dt) ->
        @_updateBackgroundLayer(dt)
}
           

添加怪物

1、建立預制體

2、寫一個腳本

cc.Class {
    extends: cc.Component

    properties: {
        
    }
    onLoad: ->
        this.node.getComponent(cc.PhysicsBoxCollider).name = "monster"
        @_createAction()

    _createAction: ->
        ac1 = cc.moveBy(1, 200, 0)
        ac2 = cc.moveBy(1, -200, 0)
        this.node.runAction(cc.repeatForever(cc.sequence(ac1, ac2)))

    update: (dt) ->
        # do your update here

    onBeginContact: (contact, selfCollider, otherCollider) ->
        if otherCollider.name is "player"
            cc.director.emit("game_over")
        return
}
           

添加子彈

_createBullet: ->
        bullet = cc.instantiate(this.bulletPrefab)
        this.platformRootNode.addChild(bullet)
        bullet.setPosition(this.player.x, this.player.y + this.player.height * 1.5)
        body = bullet.getComponent(cc.RigidBody)
        body.linearVelocity = cc.v2()
        speedY = this.player.getComponent(cc.RigidBody).linearVelocity.y / 3
        body.applyLinearImpulse(cc.v2(10, Math.max(speedY, 200)), body.getWorldCenter(), true)
        @_bulletList.push bullet
           

繼續閱讀