Quick-cocos2d-x3.3 Study (十五)--------- 为小鸟添加一个物理加速度
一下代码是:
创建一个物理边界;
创建3个小鸟;
将三个小鸟添加到一个table表中;
在GameScene:ctor()函数中添加如下代码:
1 -- 创建物理世界的边界 2 -- 创建物理世界的上边界 3 -- 通过设置两个点来创建一条带物理效果的线条 4 local top = display.newNode() 5 local topBody = cc.PhysicsBody:createEdgeSegment( 6 -- 第一个点的位置 7 cc.p( 100, display.top - 100 ), 8 -- 第二个点的位置 9 cc.p( display.right - 100, display.top - 200) 10 ) 11 -- 添加物理特效 12 top:setPhysicsBody( topBody ) 13 -- 添加到场景中 14 self:addChild( top ) 15 16 -- 添加物理世界的左边界 17 local left = display.newNode(); 18 local leftBody = cc.PhysicsBody:createEdgeSegment( 19 cc.p( 100, display.top - 100 ), 20 cc.p( 300, display.bottom + 100) 21 ) 22 left:setPhysicsBody( leftBody ) 23 self:addChild( left ) 24 25 -- 添加物理世界的右边界 26 local right = display.newNode(); 27 local rightBody = cc.PhysicsBody:createEdgeSegment( 28 cc.p( display.right - 100, display.top - 100 ), 29 cc.p( display.right - 100, display.bottom + 100) 30 ) 31 right:setPhysicsBody( rightBody ) 32 self:addChild( right ) 33 34 35 -- 添加物理世界的下边界 36 local bottom = display.newNode(); 37 local bottomBody = cc.PhysicsBody:createEdgeSegment( 38 cc.p( 100, display.bottom + 100 ), 39 cc.p( display.right - 100, display.bottom + 100) 40 ) 41 bottom:setPhysicsBody( bottomBody ) 42 self:addChild( bottom ) 43 44 45 -- 添加可以飞行的小鸟,并添加到物理引擎中 46 self.bird = {} 47 -- 设置物体的密度、反弹力、摩擦力, 48 -- 将其都设置为 0 是为了在碰撞的时候不发生任何物理变化 49 local MATERIAL_DEFAULT = cc.PhysicsMaterial( 0.0, 0.0, 0.0 ) 50 -- 创建第一个冰蘑菇 51 self.sprite1 = display.newSprite( "image/animations/binggu_01.png" ) 52 self.sprite1:pos( display.right - 200, display.top * 0.75 ) 53 self.sprite1:addTo( self ) 54 local sprite1Body = cc.PhysicsBody:createCircle( 55 self.sprite1:getContentSize().width / 2, MATERIAL_DEFAULT 56 ) 57 -- 为物体添加物理引擎 58 self.sprite1:setPhysicsBody( sprite1Body ) 59 -- 屏蔽物理世界中的刚体收到重力的影响 60 self.sprite1:getPhysicsBody():setGravityEnable(false) 61 -- 添加到table表中 62 table.insert( self.bird, self.sprite1 ) 63 -- 创建第二个冰蘑菇 64 self.sprite2 = display.newSprite( "image/animations/binggu_02.png" ) 65 :pos( display.right - 200, display.top * 0.55 ) 66 :addTo( self ) 67 local sprite2Body = cc.PhysicsBody:createCircle( 68 self.sprite2:getContentSize().width / 2, MATERIAL_DEFAULT 69 ) 70 -- 为物体添加物理引擎 71 self.sprite2:setPhysicsBody( sprite2Body ) 72 -- 屏蔽物理世界中的刚体收到重力的影响 73 self.sprite2:getPhysicsBody():setGravityEnable(false) 74 table.insert(self.bird, self.sprite2) 75 -- 创建第三个冰蘑菇 76 self.sprite3 = display.newSprite( "image/animations/binggu_03.png" ) 77 :pos( display.right - 200, display.top * 0.25 ) 78 :addTo( self ) 79 local sprite3Body = cc.PhysicsBody:createCircle( 80 self.sprite3:getContentSize().width / 2, MATERIAL_DEFAULT 81 ) 82 -- 为物体添加物理引擎 83 self.sprite3:setPhysicsBody( sprite3Body ) 84 -- 屏蔽物理世界中的刚体收到重力的影响 85 self.sprite3:getPhysicsBody():setGravityEnable(false) 86 table.insert(self.bird, self.sprite3)
在重新创建一个函数:
遍历table中的对象
1 -- 给小鸟添加一个物理加速度 2 function GameScene:addVelocityToBird() 3 4 -- 遍历表中的所有对象,对其添加飞行动画 5 local dict = nil 6 local i = 0 7 local len = table.getn(self.bird) 8 9 for i = 0, len - 1, 1 do 10 dict = self.bird[ i + 1 ] 11 print("---- dict ----" , dict) 12 -- 如果表中没有对象了就跳出循环 13 if dict == nil then 14 break; 15 end 16 -- 获取图片的x轴位置 17 local x = dict:getPositionX() 18 -- 如果图片的位置还在屏幕中 19 if x <= display.right then 20 if dict:getPhysicsBody():getVelocity().x == 0 then 21 dict:getPhysicsBody():setVelocity( cc.p( -70, math.random( -40, 40 ) ) ) 22 else 23 table.remove( self.bird, i + 1 ) 24 print("---- remove ----", i + 1) 25 end 26 end 27 end 28 end
在该函数中,我们遍历 self.bird 数组中的所有 Bird 对象,
当检测到某个 Bird 对象刚好要进入屏幕,且还没给过它任何速度时,
我们会给它一个向左的速度,这个速度的范围从(-70, -40)到(-70, 40)。
通俗一点就是说:
Bird 对象将在横坐标上有一个大小为70,方向向左的速度;
在纵坐标上有一个大小在(-40, 40)之间,方向不定的速度。
其中math.random(-40, 40)可以产生-40到40的随机数。
为了不产生相同的随机数,我们需要在MyApp:run()中“种”一棵随机数种子,即添加如下的一行代码:
1 math.randomseed(os.time())
当已经给过某些 Bird 对象速度时,我们要把该对象从 self.bird 数组中移除,
这样可以减短遍历数组的时间。table.remove(table, pos)函数将删除并返回 table 数组中位于 pos 位置上的元素。
总的来讲,addVelocityToBird 函数的目的就是在小鸟进入屏幕时给它一个速度,让它朝着游戏角色冲过来。
最后,因为我们需要不停的遍历 self.bird 数组、不停的检测是否给小鸟加上速度,
所以我们需要在刷新屏幕时调用以上的 addVelocityToBird() 函数。
那就偷个懒,直接在 scrollBackgrounds(dt) 函数的最后面添加下列函数:
1 self:addVelocityToBird()
效果图:
补充
因为游戏中的Player、Heart、Airship、Bird都是刚体,
所以现在把这些刚体放在同一个物理世界是很容易发生碰撞、反弹、旋转、被挤出场景等等问题的。
所以,这里我们要补充的就是怎样有效的解决这些问题,
当然,制定具体的解决方案还需要结合碰撞检测来做。
setDynamic(dynamic):如果你想你的刚体固定不动,那么你可以调用该函数。
如游戏中的心心,它在物理世界中就是个相对固定不动的对象,
所以我们可以设置它的刚体属性dynamic为false,即 body:setDynamic(false) 。
setRotationEnable(enable):如果你想你的刚体不旋转,那么你可以调用该函数。
如 Player、Airship 和 Bird 对象,它们在物理世界中是 Dynamic(动态)的,
但我们不希望它们在动的过程中重心不稳发生旋转,
所以,我们可以给 Player 刚体添加这样的属性加以约束,即:body:setRotationEnable(false)。