今天写一个精灵的随机碰撞第一次接触到了物理引擎这个概念,首先先来讲一下引擎的概念:游戏引擎是指一些已编写好的可编辑电脑游戏系统或者一些交互式实时图像应用程序的核心组件,引擎并不是什么玄乎的东西,无论是2D游戏还是3D游戏,无论是角色扮演游戏、即时策略游戏、冒险解谜游戏或是动作射击游戏,哪怕是一个只有1兆的小游戏,都有这样一段起控制作用的代码。游戏引擎是一个为运行某一类游戏的机器设计的能够被机器识别的代码(指令)集合。它像一个发动机,控制着游戏的运行。一个游戏作品可以分为游戏引擎和游戏资源两大部分。游戏资源包括图象,声音,动画等部分,列一个公式就是:游戏=引擎(程序代码)+资源(图象,声音,动画等)。游戏引擎则是按游戏设计的要求顺序的调用这些资源。
chipmunk是一个用C写成的物理引擎,quick-cocos2d-x已经用C++对其进行封装,导出到lua的类有:
CCPhysicsWorld CCPhysicsBody CCPhysicsShape CCPhysicsDebugNode CCPhysicsCollisionEvent CCPhysicsVector
可以看出,quick-cocos2d-x没有对joint(连接)进行封装,下面将就如何在quick-cocos2d-x中使用chipmunk作详细的介绍。
一、简介
1、World,Body,Shape可用下图说明其关系
可以看出,World由Body组成,而Body又由Shape组成。就像我们所处的世界一样,世界由房屋,树木等等构成,而房屋由门窗,墙壁等组成,树木由叶子,树干,树枝等组成。
2、CCPhysicsDebugNode是用于显示各个物体的边框等等信息,主要用于调试。
3、CCPhysicsCollisionEvent是物体之间发生碰撞时产生的事件,事件中携带有碰撞时的信息。
4、CCPhysicsVector则是向量,物体受力时将会用到。
二、使用流程
1、建立World
我们要使用chipmunk,首选要建立一个世界(CCPhysicsWorld)
-- 建立没有引力的世界 CCPhysicsWorld:create() -- 指定两个方向上的引力 CCPhysicsWorld:create(gravityX, gravityY)示例:
-- 引力向下的世界(跟地球类似) self.world=CCPhysicsWorld:create(0,-200) self:addChild(self.world)2、建立Body
-- 当mass<=0时会创建一个StaticBody World:createBoxBody(mass, width, height) -- offset为偏移量 World:createCircleBody(mass, radius, offsetX, offsetY) -- vertexes格式为{x1, y1, x2, y2, x3, y3},目前的版本有bug,不可以设置offset World:createPolygonBody(mass, vertexes, offsetX, offsetY)示例:
local body = self.world:createBoxBody(10, 100, 100) local body = self.world:createCircleBody(0, 20, 50, 50) -- 创建一个三角形 local vertexes = {0,0,50,50,100,0} local body=self.world:createPolygonBody(0, vertexes)2)通过Body里的方法创建:
CCPhysicsBody:createStaticBody(world) CCPhysicsBody:create(world, mass, moment)示例:
local body = CCPhysicsBody:createStaticBody(self.world) -- 这种创建方式要记得把body放到world里 self.world:addBody(body)3)重要属性或方法:
-- 摩擦系数 0-1.0 body:setFriction(friction) -- 反弹系数 0-1.0 body:setElasticity(elasticity) -- 是否是感应 body:setIsSensor(isSensor) body:isSensor() -- 速度 body:setVelocity(velocityX, velocityY) -- 角速度 body:setAngleVelocity(velocity) -- 推力 body:applyForce(forceX, forceY, offsetX, offsetY) body:applyForce(force, offsetX, offsetY) body:applyImpulse(forceX, forceY, offsetX, offsetY) body:applyImpulse(force, offsetX, offsetY)4)删除
-- unbind=true时将解除绑定的CCNode,但不会从场景里删除node,只是执行CC_SAFE_RELEASE_NULL(node); -- unbind=false时CCNode将继续绑定在该Body上,默认为true body:removeSelf(unbind) World:removeBody(body, unbind) World:removeBodyByTag(tag, unbind)3、建立Shape
-- 线段,lowerLeft和lowerRight为CCPoint,thickness为粗细 Body:addSegmentShape(lowerLeft, lowerRight, thickness) Body:addCircleShape(radius, offsetX, offsetY) Body:addBoxShape(width, height) -- 目前好像不能运行,已发issue到官方仓库 Body:addPolygonShape(vertexes, offsetX, offsetY)
2)Shape的属性
-- 摩擦系数 0-1.0 shape:setFriction(friction) -- 反弹系数 0-1.0 shape:setElasticity(elasticity) -- 是否是感应 shape:setIsSensor(isSensor) shape:isSensor()3)删除
body:removeShape(shapeObject) body:removeShapeAtIndex(index) body:removeAllShape()4、绑定
-- node为CCNode类型 Body:bind(node) Body:unbind()来完成绑定和解绑。
self.worldDebug=self.world:createDebugNode() self:addChild(self.worldDebug)
大家都玩过愤怒的小鸟--一个物理引擎经典的案例,下面讲一个简单的例子:
<span style="font-size:12px;">local GameScene = class("GameScene",function() return cc.Scene:createWithPhysics() <span style="white-space:pre"> </span>end)--创建一个物理世界 function GameScene.create() local scene = GameScene.new() local gravity = cc.vertex2F(0,-100) scene:getPhysicsWorld():setGravity(gravity)--设置重力 scene:getPhysicsWorld():setDebugDrawMask(cc.PhysicsWorld.DEBUGDRAW_ALL) local edgeBody = cc.PhysicsBody:createEdgeBox(scene.visibleSize, cc.PhysicsMaterial(1,1,0), 3)--设置世界的边界 local edgeNode = cc.Node:create() scene:addChild(edgeNode) edgeNode:setPosition(scene.visibleSize.width * 0.5, scene.visibleSize.height * 0.5) edgeNode:setPhysicsBody(edgeBody) local menuSprite = cc.Sprite:create("menu1.png")--添加一个物体 local menuBody = cc.PhysicsBody:createBox(menuSprite:getContentSize(), cc.PhysicsMaterial(1,1,0)) scene:addChild(menuSprite) menuSprite:setPosition(400,600) menuSprite:setPhysicsBody(menuBody) return scene end</span>
上述例子利用物理引擎完成了对一个自由落体的精灵的创建。