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