diff --git a/cocos/physics/CCPhysicsContact.h b/cocos/physics/CCPhysicsContact.h index 987e5daf47..74092ba3b0 100644 --- a/cocos/physics/CCPhysicsContact.h +++ b/cocos/physics/CCPhysicsContact.h @@ -58,7 +58,7 @@ typedef struct PhysicsContactData /** * @brief Contact infomation. it will created automatically when two shape contact with each other. and it will destoried automatically when two shape separated. */ -class PhysicsContact : Event +class PhysicsContact : public Event { public: diff --git a/cocos/physics/CCPhysicsWorld.h b/cocos/physics/CCPhysicsWorld.h index bca81f35b4..4ce0a2bb2a 100644 --- a/cocos/physics/CCPhysicsWorld.h +++ b/cocos/physics/CCPhysicsWorld.h @@ -55,7 +55,7 @@ typedef struct PhysicsRayCastInfo { PhysicsShape* shape; Point start; - Point end; + Point end; //< in lua, it's name is "ended" Point contact; Vect normal; float fraction; diff --git a/cocos/scripting/lua/bindings/LuaBasicConversions.cpp b/cocos/scripting/lua/bindings/LuaBasicConversions.cpp index e03163e0d6..a2d97434c8 100644 --- a/cocos/scripting/lua/bindings/LuaBasicConversions.cpp +++ b/cocos/scripting/lua/bindings/LuaBasicConversions.cpp @@ -1615,7 +1615,7 @@ void physics_raycastinfo_to_luaval(lua_State* L, const PhysicsRayCastInfo& info) point_to_luaval(L, info.start); lua_rawset(L, -3); /* table[key] = value, L: table */ - lua_pushstring(L, "end"); /* L: table key */ + lua_pushstring(L, "ended"); /* L: table key */ point_to_luaval(L, info.end); lua_rawset(L, -3); /* table[key] = value, L: table */ @@ -1632,6 +1632,26 @@ void physics_raycastinfo_to_luaval(lua_State* L, const PhysicsRayCastInfo& info) lua_rawset(L, -3); /* table[key] = value, L: table */ } +void physics_contactdata_to_luaval(lua_State* L, const PhysicsContactData* data) +{ + if (nullptr == L || nullptr == data) + return; + + lua_newtable(L); /* L: table */ + + lua_pushstring(L, "points"); + points_to_luaval(L, data->points, data->count); + lua_rawset(L, -3); + + lua_pushstring(L, "normal"); + point_to_luaval(L, data->normal); + lua_rawset(L, -3); + + lua_pushstring(L, "POINT_MAX"); + lua_pushnumber(L, data->POINT_MAX); + lua_rawset(L, -3); +} + void size_to_luaval(lua_State* L,const Size& sz) { if (NULL == L) diff --git a/cocos/scripting/lua/bindings/LuaBasicConversions.h b/cocos/scripting/lua/bindings/LuaBasicConversions.h index 5d485daff0..361f421b02 100644 --- a/cocos/scripting/lua/bindings/LuaBasicConversions.h +++ b/cocos/scripting/lua/bindings/LuaBasicConversions.h @@ -205,6 +205,7 @@ extern void color4b_to_luaval(lua_State* L,const Color4B& cc); extern void color4f_to_luaval(lua_State* L,const Color4F& cc); extern void physics_material_to_luaval(lua_State* L,const PhysicsMaterial& pm); extern void physics_raycastinfo_to_luaval(lua_State* L, const PhysicsRayCastInfo& info); +extern void physics_contactdata_to_luaval(lua_State* L, const PhysicsContactData* data); extern void affinetransform_to_luaval(lua_State* L,const AffineTransform& inValue); extern void fontdefinition_to_luaval(lua_State* L,const FontDefinition& inValue); extern void array_to_luaval(lua_State* L,Array* inValue); diff --git a/cocos/scripting/lua/bindings/LuaScriptHandlerMgr.h b/cocos/scripting/lua/bindings/LuaScriptHandlerMgr.h index d1cb5d3a57..7cc980a37e 100644 --- a/cocos/scripting/lua/bindings/LuaScriptHandlerMgr.h +++ b/cocos/scripting/lua/bindings/LuaScriptHandlerMgr.h @@ -155,6 +155,11 @@ public: EVENT_MOUSE_SCROLL, EVENT_SPINE, + + EVENT_PHYSICS_CONTACT_BEGIN, + EVENT_PHYSICS_CONTACT_PRESOLVE, + EVENT_PHYSICS_CONTACT_POSTSOLVE, + EVENT_PHYSICS_CONTACT_SEPERATE, }; typedef int Handler; diff --git a/cocos/scripting/lua/bindings/lua_cocos2dx_physics_manual.cpp b/cocos/scripting/lua/bindings/lua_cocos2dx_physics_manual.cpp index 7da290e02a..f5e8f0b59f 100644 --- a/cocos/scripting/lua/bindings/lua_cocos2dx_physics_manual.cpp +++ b/cocos/scripting/lua/bindings/lua_cocos2dx_physics_manual.cpp @@ -900,7 +900,6 @@ int lua_cocos2dx_physics_PhysicsShape_getPolyonCenter(lua_State* tolua_S) if (nullptr == arg0){ LUA_PRECONDITION( arg0, "Invalid Native Object"); }} while (0); - ok &= luaval_to_int32(tolua_S, 3,(int *)&arg1); if(!ok) { CC_SAFE_FREE(arg0); @@ -1138,6 +1137,114 @@ tolua_lerror: return 0; } +static int tolua_cocos2dx_EventListenerPhysicsContact_registerScriptHandler(lua_State* tolua_S) +{ + if (nullptr == tolua_S) + return 0; + + int argc = 0; + EventListenerPhysicsContact* self = nullptr; +#if COCOS2D_DEBUG >= 1 + tolua_Error tolua_err; + if (!tolua_isusertype(tolua_S, 1, "EventListenerPhysicsContact", 0, &tolua_err)) goto tolua_lerror; +#endif + + self = static_cast(tolua_tousertype(tolua_S,1,0)); +#if COCOS2D_DEBUG >= 1 + if (nullptr == self) { + tolua_error(tolua_S,"invalid 'self' in function 'tolua_cocos2dx_EventListenerPhysicsContact_registerScriptHandler'\n", nullptr); + return 0; + } +#endif + argc = lua_gettop(tolua_S) - 1; + + if (argc == 2) + { +#if COCOS2D_DEBUG >= 1 + if (!toluafix_isfunction(tolua_S,2,"LUA_FUNCTION",0,&tolua_err) || + !tolua_isnumber(tolua_S, 3, 0, &tolua_err)) + { + goto tolua_lerror; + } +#endif + LUA_FUNCTION handler = toluafix_ref_function(tolua_S,2,0); + ScriptHandlerMgr::HandlerType type = static_cast((int)tolua_tonumber(tolua_S, 3, 0)); + switch (type) + { + case ScriptHandlerMgr::HandlerType::EVENT_PHYSICS_CONTACT_BEGIN: + { + ScriptHandlerMgr::getInstance()->addObjectHandler((void*)self, handler, type); + + self->onContactBegin = [handler](EventCustom* event, const PhysicsContact& contact) -> bool{ + LuaStack* stack = LuaEngine::getInstance()->getLuaStack(); + stack->pushObject(event, "EventCustom"); + stack->pushObject(const_cast(&contact), "PhysicsContact"); + bool ret = stack->executeFunctionByHandler(handler, 2); + stack->clean(); + + return ret; + }; + } + break; + case ScriptHandlerMgr::HandlerType::EVENT_PHYSICS_CONTACT_PRESOLVE: + { + ScriptHandlerMgr::getInstance()->addObjectHandler((void*)self, handler, type); + + self->onContactPreSolve = [handler](EventCustom* event, const PhysicsContact& contact, const PhysicsContactPreSolve& solve) -> bool{ + LuaStack* stack = LuaEngine::getInstance()->getLuaStack(); + stack->pushObject(event, "EventCustom"); + stack->pushObject(const_cast(&contact), "PhysicsContact"); + tolua_pushusertype(stack->getLuaState(), const_cast(&solve), "PhysicsContactPreSolve"); + bool ret = stack->executeFunctionByHandler(handler, 3); + stack->clean(); + + return ret; + }; + } + break; + case ScriptHandlerMgr::HandlerType::EVENT_PHYSICS_CONTACT_POSTSOLVE: + { + ScriptHandlerMgr::getInstance()->addObjectHandler((void*)self, handler, type); + + self->onContactPostSolve = [handler](EventCustom* event, const PhysicsContact& contact, const PhysicsContactPostSolve& solve){ + LuaStack* stack = LuaEngine::getInstance()->getLuaStack(); + stack->pushObject(event, "EventCustom"); + stack->pushObject(const_cast(&contact), "PhysicsContact"); + tolua_pushusertype(stack->getLuaState(), const_cast(&solve), "PhysicsContactPostSolve"); + stack->executeFunctionByHandler(handler, 3); + stack->clean(); + }; + } + break; + case ScriptHandlerMgr::HandlerType::EVENT_PHYSICS_CONTACT_SEPERATE: + { + ScriptHandlerMgr::getInstance()->addObjectHandler((void*)self, handler, type); + + self->onContactSeperate = [handler](EventCustom* event, const PhysicsContact& contact){ + LuaStack* stack = LuaEngine::getInstance()->getLuaStack(); + stack->pushObject(event, "EventCustom"); + stack->pushObject(const_cast(&contact), "PhysicsContact"); + stack->executeFunctionByHandler(handler, 2); + stack->clean(); + }; + } + break; + default: + break; + } + return 0; + } + + CCLOG("'registerScriptHandler' has wrong number of arguments: %d, was expecting %d\n", argc, 2); + return 0; + +#if COCOS2D_DEBUG >= 1 +tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'registerScriptHandler'.",&tolua_err); + return 0; +#endif +} + int register_all_cocos2dx_physics_manual(lua_State* tolua_S) { lua_pushstring(tolua_S, "cc.PhysicsBody"); @@ -1254,9 +1361,16 @@ int register_all_cocos2dx_physics_manual(lua_State* tolua_S) lua_pushnumber(tolua_S, PhysicsWorld::DEBUGDRAW_ALL); lua_rawset(tolua_S,-3); } - lua_pop(tolua_S, 1); + lua_pushstring(tolua_S, "EventListenerPhysicsContact"); + lua_rawget(tolua_S, LUA_REGISTRYINDEX); + if (lua_istable(tolua_S,-1)) + { + tolua_function(tolua_S, "registerScriptHandler", tolua_cocos2dx_EventListenerPhysicsContact_registerScriptHandler); + } + lua_pop(tolua_S, 1); + tolua_constant(tolua_S, "PHYSICS_INFINITY", PHYSICS_INFINITY); return 0; diff --git a/cocos/scripting/lua/script/Cocos2dConstants.lua b/cocos/scripting/lua/script/Cocos2dConstants.lua index 11c57e14b2..55f405a78b 100644 --- a/cocos/scripting/lua/script/Cocos2dConstants.lua +++ b/cocos/scripting/lua/script/Cocos2dConstants.lua @@ -343,6 +343,10 @@ cc.Handler.EVENT_MOUSE_UP = 49 cc.Handler.EVENT_MOUSE_MOVE = 50 cc.Handler.EVENT_MOUSE_SCROLL = 51 cc.Handler.EVENT_SPINE = 52 +cc.Handler.EVENT_PHYSICS_CONTACT_BEGIN = 53 +cc.Handler.EVENT_PHYSICS_CONTACT_PRESOLVE = 54 +cc.Handler.EVENT_PHYSICS_CONTACT_POSTSOLVE = 55 +cc.Handler.EVENT_PHYSICS_CONTACT_SEPERATE = 56 cc.EVENT_UNKNOWN = 0 cc.EVENT_TOUCH_ONE_BY_ONE = 1 @@ -352,8 +356,8 @@ cc.EVENT_MOUSE = 4 cc.EVENT_ACCELERATION = 5 cc.EVENT_CUSTOM = 6 -cc.PHYSICSSHAPE_MATERIAL_DEFAULT = {0.0, 0.5, 0.5} -cc.PHYSICSBODY_MATERIAL_DEFAULT = {0.1, 0.5, 0.5} +cc.PHYSICSSHAPE_MATERIAL_DEFAULT = {density = 0.0, restitution = 0.5, friction = 0.5} +cc.PHYSICSBODY_MATERIAL_DEFAULT = {density = 0.1, restitution = 0.5, friction = 0.5} cc.GLYPHCOLLECTION_DYNAMIC = 0 cc.GLYPHCOLLECTION_NEHE = 1 cc.GLYPHCOLLECTION_ASCII = 2 diff --git a/samples/Cpp/TestCpp/Classes/PhysicsTest/PhysicsTest.cpp b/samples/Cpp/TestCpp/Classes/PhysicsTest/PhysicsTest.cpp index b9c97830bd..aedc0f3e09 100644 --- a/samples/Cpp/TestCpp/Classes/PhysicsTest/PhysicsTest.cpp +++ b/samples/Cpp/TestCpp/Classes/PhysicsTest/PhysicsTest.cpp @@ -1151,7 +1151,6 @@ bool PhysicsDemoSlice::slice(PhysicsWorld &world, const PhysicsRayCastInfo& info Point normal = info.end - info.start; normal = normal.getPerp().normalize(); float dist = info.start.dot(normal); - dist = dist; clipPoly(dynamic_cast(info.shape), normal, dist); clipPoly(dynamic_cast(info.shape), -normal, -dist); diff --git a/samples/Lua/TestLua/Resources/luaScript/PhysicsTest/PhysicsTest.lua b/samples/Lua/TestLua/Resources/luaScript/PhysicsTest/PhysicsTest.lua index 0434b0a3c4..7bfffa2c24 100644 --- a/samples/Lua/TestLua/Resources/luaScript/PhysicsTest/PhysicsTest.lua +++ b/samples/Lua/TestLua/Resources/luaScript/PhysicsTest/PhysicsTest.lua @@ -26,7 +26,7 @@ local function initWithLayer(layer, callback) cc.Director:getInstance():getRunningScene():getPhysicsWorld():setDebugDrawMask(debug and cc.PhysicsWorld.DEBUGDRAW_ALL or cc.PhysicsWorld.DEBUGDRAW_NONE) end - layer.toggleDebug = toggleDebugCallback; + layer.toggleDebug = function(self) toggleDebugCallback(nil) end; cc.MenuItemFont:setFontSize(18) local item = cc.MenuItemFont:create("Toogle debug") item:registerScriptTapHandler(toggleDebugCallback) @@ -291,9 +291,6 @@ local function PhysicsDemoJoints() for j in range(0, 3) do local offset = cc.p(VisibleRect:leftBottom().x + 5 + j * width + width/2, VisibleRect:leftBottom().y + 50 + i * height + height/2); box:addShape(cc.PhysicsShapeEdgeBox:create(cc.size(width, height), cc.PHYSICSSHAPE_MATERIAL_DEFAULT, 1, offset)); - print("i,j") - print(i) - print(j) local index = i*4 + j if index == 0 then local sp1 = makeBall(layer, cc.p(offset.x - 30, offset.y), 10); @@ -597,13 +594,339 @@ local function PhysicsDemoRayCast() return layer end -local function registerOnEnter() - layer:registerOn(PhysicsDemoLogoSmash) +local function PhysicsDemoOneWayPlatform() + local layer = cc.Layer:create() + local function onEnter() + + local touchListener = cc.EventListenerTouchOneByOne:create(); + touchListener:registerScriptHandler(onTouchBegan, cc.Handler.EVENT_TOUCH_BEGAN); + touchListener:registerScriptHandler(onTouchMoved, cc.Handler.EVENT_TOUCH_MOVED); + touchListener:registerScriptHandler(onTouchEnded, cc.Handler.EVENT_TOUCH_ENDED); + local eventDispatcher = layer:getEventDispatcher() + eventDispatcher:addEventListenerWithSceneGraphPriority(touchListener, layer); + + local ground = cc.Node:create(); + ground:setPhysicsBody(cc.PhysicsBody:createEdgeSegment(cc.p(VisibleRect:leftBottom().x, VisibleRect:leftBottom().y + 50), cc.p(VisibleRect:rightBottom().x, VisibleRect:rightBottom().y + 50))); + layer:addChild(ground); + + local platform = makeBox(VisibleRect:center(), cc.size(200, 50)); + platform:getPhysicsBody():setDynamic(false); + layer:addChild(platform); + + local ball = makeBall(layer, cc.p(VisibleRect:center().x, VisibleRect:center().y - 50), 20); + ball:getPhysicsBody():setVelocity(cc.p(0, 150)); + ball:getPhysicsBody():setTag(DRAG_BODYS_TAG); + ball:getPhysicsBody():setMass(1.0); + layer:addChild(ball); + + local function onContactBegin(event, contact) + return contact:getContactData().normal.y < 0; + end + local contactListener = cc.EventListenerPhysicsContactWithBodies:create(platform:getPhysicsBody(), ball:getPhysicsBody()); + contactListener:registerScriptHandler(onContactBegin, cc.Handler.EVENT_PHYSICS_CONTACT_BEGIN); + eventDispatcher:addEventListenerWithSceneGraphPriority(contactListener, layer); + end + + initWithLayer(layer, onEnter) + Helper.titleLabel:setString("One Way Platform") + + return layer +end + +local function PhysicsDemoActions() + local layer = cc.Layer:create() + local function onEnter() + local touchListener = cc.EventListenerTouchOneByOne:create() + touchListener:registerScriptHandler(onTouchBegan, cc.Handler.EVENT_TOUCH_BEGAN) + touchListener:registerScriptHandler(onTouchMoved, cc.Handler.EVENT_TOUCH_MOVED) + touchListener:registerScriptHandler(onTouchEnded, cc.Handler.EVENT_TOUCH_ENDED) + local eventDispatcher = layer:getEventDispatcher() + eventDispatcher:addEventListenerWithSceneGraphPriority(touchListener, layer) + + local node = cc.Node:create(); + node:setPhysicsBody(cc.PhysicsBody:createEdgeBox(cc.size(VisibleRect:getVisibleRect().width, VisibleRect:getVisibleRect().height))); + node:setPosition(VisibleRect:center()); + layer:addChild(node); + + local sp1 = addGrossiniAtPosition(layer, VisibleRect:center()); + local sp2 = addGrossiniAtPosition(layer, cc.p(VisibleRect:left().x + 50, VisibleRect:left().y)); + local sp3 = addGrossiniAtPosition(layer, cc.p(VisibleRect:right().x - 20, VisibleRect:right().y)); + local sp4 = addGrossiniAtPosition(layer, cc.p(VisibleRect:leftTop().x + 50, VisibleRect:leftTop().y-50)); + sp4:getPhysicsBody():setGravityEnable(false); + + + local actionTo = cc.JumpTo:create(2, cc.p(100,100), 50, 4); + local actionBy = cc.JumpBy:create(2, cc.p(300,0), 50, 4); + local actionUp = cc.JumpBy:create(2, cc.p(0,50), 80, 4); + local actionByBack = actionBy:reverse(); + + sp1:runAction(cc.RepeatForever:create(actionUp)); + sp2:runAction(cc.RepeatForever:create(cc.Sequence:create(actionBy, actionByBack))); + sp3:runAction(actionTo); + sp4:runAction(cc.RepeatForever:create(cc.Sequence:create(actionBy:clone(), actionByBack:clone()))); + end + + initWithLayer(layer, onEnter) + Helper.titleLabel:setString("Actions") + + return layer +end + +local function PhysicsDemoPump() + local layer = cc.Layer:create() + local function onEnter() + layer:toggleDebug(); + + local distance = 0.0; + local rotationV = 0.0; + local function onTouchBeganEx(touch, event) + onTouchBegan(touch, event) + distance = touch:getLocation().x - VisibleRect:center().x; + return true; + end + + local function onTouchMovedEx(touch, event) + onTouchMoved(touch, event); + distance = touch:getLocation().x - VisibleRect:center().x; + end + + local function onTouchEndedEx(touch, event) + onTouchEnded(touch, event) + distance = 0; + end + + local touchListener = cc.EventListenerTouchOneByOne:create() + touchListener:registerScriptHandler(onTouchBeganEx, cc.Handler.EVENT_TOUCH_BEGAN) + touchListener:registerScriptHandler(onTouchMovedEx, cc.Handler.EVENT_TOUCH_MOVED) + touchListener:registerScriptHandler(onTouchEndedEx, cc.Handler.EVENT_TOUCH_ENDED) + local eventDispatcher = layer:getEventDispatcher() + eventDispatcher:addEventListenerWithSceneGraphPriority(touchListener, layer) + + local function update() + for _, body in ipairs(cc.Director:getInstance():getRunningScene():getPhysicsWorld():getAllBodies()) do + if body:getTag() == DRAG_BODYS_TAG and body:getPosition().y < 0.0 then + body:getNode():setPosition(cc.p(VisibleRect:leftTop().x + 75, VisibleRect:leftTop().y + math.random() * 90, 0)); + body:setVelocity(cc.p(0, 0)); + end + end + + local gear = cc.Director:getInstance():getRunningScene():getPhysicsWorld():getBody(1); + if gear then + if distance ~= 0.0 then + rotationV = rotationV + distance/2500.0; + end + if rotationV > 30 then rotationV = 30.0 end + if rotationV < -30 then rotationV = -30.0 end + + gear:setAngularVelocity(rotationV); + rotationV = rotationV*0.995; + end + end + + layer:scheduleUpdateWithPriorityLua(update, 0); + + local node = cc.Node:create(); + local body = cc.PhysicsBody:create(); + body:setDynamic(false); + + local staticMaterial = cc.PhysicsMaterial(cc.PHYSICS_INFINITY, 0, 0.5); + body:addShape(cc.PhysicsShapeEdgeSegment:create( + cc.p(VisibleRect:leftTop().x + 50, VisibleRect:leftTop().y), + cc.p(VisibleRect:leftTop().x + 50, VisibleRect:leftTop().y-130), staticMaterial, 2.0)); + body:addShape(cc.PhysicsShapeEdgeSegment:create( + cc.p(VisibleRect:leftTop().x + 190, VisibleRect:leftTop().y), + cc.p(VisibleRect:leftTop().x + 100, VisibleRect:leftTop().y-50), staticMaterial, 2.0)); + body:addShape(cc.PhysicsShapeEdgeSegment:create( + cc.p(VisibleRect:leftTop().x + 100, VisibleRect:leftTop().y-50), + cc.p(VisibleRect:leftTop().x + 100, VisibleRect:leftTop().y-90), staticMaterial, 2.0)); + body:addShape(cc.PhysicsShapeEdgeSegment:create( + cc.p(VisibleRect:leftTop().x + 50, VisibleRect:leftTop().y-130), + cc.p(VisibleRect:leftTop().x + 100, VisibleRect:leftTop().y-145), staticMaterial, 2.0)); + body:addShape(cc.PhysicsShapeEdgeSegment:create( + cc.p(VisibleRect:leftTop().x + 100, VisibleRect:leftTop().y-145), + cc.p(VisibleRect:leftBottom().x + 100, VisibleRect:leftBottom().y + 80), staticMaterial, 2.0)); + body:addShape(cc.PhysicsShapeEdgeSegment:create( + cc.p(VisibleRect:leftTop().x + 150, VisibleRect:leftTop().y-80), + cc.p(VisibleRect:leftBottom().x + 150, VisibleRect:leftBottom().y + 80), staticMaterial, 2.0)); + body:addShape(cc.PhysicsShapeEdgeSegment:create( + cc.p(VisibleRect:leftTop().x + 150, VisibleRect:leftTop().y-80), + cc.p(VisibleRect:rightTop().x -100, VisibleRect:rightTop().y-150), staticMaterial, 2.0)); + + body:setCategoryBitmask(1); + + for _ in range(1, 6) do + local ball = makeBall(layer, cc.p(VisibleRect:leftTop().x + 75 + math.random() * 90, VisibleRect:leftTop().y), 22, cc.PhysicsMaterial(0.05, 0.0, 0.1)); + ball:getPhysicsBody():setTag(DRAG_BODYS_TAG); + layer:addChild(ball); + end + + node:setPhysicsBody(body); + layer:addChild(node); + + local vec = + { + cc.p(VisibleRect:leftTop().x + 102, VisibleRect:leftTop().y-148), + cc.p(VisibleRect:leftTop().x + 148, VisibleRect:leftTop().y-161), + cc.p(VisibleRect:leftBottom().x + 148, VisibleRect:leftBottom().y + 20), + cc.p(VisibleRect:leftBottom().x + 102, VisibleRect:leftBottom().y + 20) + }; + + local world = cc.Director:getInstance():getRunningScene():getPhysicsWorld(); + + -- small gear + local sgear = cc.Node:create(); + local sgearB = cc.PhysicsBody:createCircle(44); + sgear:setPhysicsBody(sgearB); + sgear:setPosition(cc.p(VisibleRect:leftBottom().x + 125, VisibleRect:leftBottom().y)); + layer:addChild(sgear); + sgearB:setCategoryBitmask(4); + sgearB:setCollisionBitmask(4); + sgearB:setTag(1); + world:addJoint(cc.PhysicsJointPin:construct(body, sgearB, sgearB:getPosition())); + + + -- big gear + local bgear = cc.Node:create(); + local bgearB = cc.PhysicsBody:createCircle(100); + bgear:setPhysicsBody(bgearB); + bgear:setPosition(cc.p(VisibleRect:leftBottom().x + 275, VisibleRect:leftBottom().y)); + layer:addChild(bgear); + bgearB:setCategoryBitmask(4); + world:addJoint(cc.PhysicsJointPin:construct(body, bgearB, bgearB:getPosition())); + + + -- pump + local pump = cc.Node:create(); + local center = cc.PhysicsShape:getPolyonCenter(vec); + pump:setPosition(center); + local pumpB = cc.PhysicsBody:createPolygon(vec, cc.PHYSICSBODY_MATERIAL_DEFAULT, cc.p(-center.x, -center.y)); + pump:setPhysicsBody(pumpB); + layer:addChild(pump); + pumpB:setCategoryBitmask(2); + pumpB:setGravityEnable(false); + world:addJoint(cc.PhysicsJointDistance:construct(pumpB, sgearB, cc.p(0, 0), cc.p(0, -44))); + + -- plugger + local seg = {cc.p(VisibleRect:leftTop().x + 75, VisibleRect:leftTop().y-120), cc.p(VisibleRect:leftBottom().x + 75, VisibleRect:leftBottom().y-100)}; + local segCenter = cc.p((seg[2].x + seg[1].x)/2, (seg[2].y + seg[1].y)/2); + seg[2] = cc.p(seg[2].x - segCenter.x, seg[2].y - segCenter.y); + seg[1] = cc.p(seg[1].x - segCenter.x, seg[1].y - segCenter.y); + local plugger = cc.Node:create(); + local pluggerB = cc.PhysicsBody:createEdgeSegment(seg[1], seg[2], cc.PhysicsMaterial(0.01, 0.0, 0.5), 20); + pluggerB:setDynamic(true); + pluggerB:setMass(30); + pluggerB:setMoment(100000); + plugger:setPhysicsBody(pluggerB); + plugger:setPosition(segCenter); + layer:addChild(plugger); + pluggerB:setCategoryBitmask(2); + sgearB:setCollisionBitmask(5); + world:addJoint(cc.PhysicsJointPin:construct(body, pluggerB, cc.p(VisibleRect:leftBottom().x + 75, VisibleRect:leftBottom().y-90))); + world:addJoint(cc.PhysicsJointDistance:construct(pluggerB, sgearB, + pluggerB:world2Local(cc.p(VisibleRect:leftBottom().x + 75, VisibleRect:leftBottom().y)), cc.p(44, 0))); + end + + initWithLayer(layer, onEnter) + Helper.titleLabel:setString("Pump") + Helper.subtitleLabel:setString("touch screen on left or right") + + return layer +end + +local function PhysicsDemoSlice() + local layer = cc.Layer:create() + local function onEnter() + layer:toggleDebug() + local sliceTag = 1; + + local function clipPoly(shape, normal, distance) + local body = shape:getBody(); + local count = shape:getPointsCount(); + local points = {} + + local j = count - 1 + for i in range(0, count-1) do + local a = body:local2World(shape:getPoint(j)); + local aDist = cc.pDot(a, normal) - distance; + + if aDist < 0.0 then + points[#points + 1] = a; + end + + local b = body:local2World(shape:getPoint(i)); + local bDist = cc.pDot(b, normal) - distance; + + if aDist*bDist < 0.0 then + local t = math.abs(aDist)/(math.abs(aDist) + math.abs(bDist)); + points[#points + 1] = cc.pLerp(a, b, t); + end + j = i + end + + local center = cc.PhysicsShape:getPolyonCenter(points); + local node = cc.Node:create(); + local polyon = cc.PhysicsBody:createPolygon(points, cc.PHYSICSBODY_MATERIAL_DEFAULT, cc.p(-center.x, -center.y)); + node:setPosition(center); + node:setPhysicsBody(polyon); + polyon:setVelocity(body:getVelocityAtWorldPoint(center)); + polyon:setAngularVelocity(body:getAngularVelocity()); + polyon.tag = sliceTag; + layer:addChild(node); + end + + + local function slice(world, info) + if info.shape:getBody().tag ~= sliceTag then + return true; + end + + if not info.shape:containsPoint(info.start) and not info.shape:containsPoint(info.ended) then + local normal = cc.p(info.ended.x - info.start.x, info.ended.y - info.start.y); + normal = cc.pNormalize(cc.pPerp(normal)); + local dist = cc.pDot(info.start, normal); + + clipPoly(info.shape, normal, dist); + clipPoly(info.shape, cc.p(-normal.x, -normal.y), -dist); + + info.shape:getBody():removeFromWorld(); + end + return true; + end + + local function onTouchEnded(touch, event) + cc.Director:getInstance():getRunningScene():getPhysicsWorld():rayCast(slice, touch:getStartLocation(), touch:getLocation()); + end + + local touchListener = cc.EventListenerTouchOneByOne:create(); + touchListener:registerScriptHandler(function() return true end, cc.Handler.EVENT_TOUCH_BEGAN); + touchListener:registerScriptHandler(onTouchEnded, cc.Handler.EVENT_TOUCH_ENDED); + local eventDispatcher = layer:getEventDispatcher() + eventDispatcher:addEventListenerWithSceneGraphPriority(touchListener, layer); + + local ground = cc.Node:create(); + ground:setPhysicsBody(cc.PhysicsBody:createEdgeSegment(cc.p(VisibleRect:leftBottom().x, VisibleRect:leftBottom().y + 50), + cc.p(VisibleRect:rightBottom().x, VisibleRect:rightBottom().y + 50))); + layer:addChild(ground); + + local box = cc.Node:create(); + local points = {cc.p(-100, -100), cc.p(-100, 100), cc.p(100, 100), cc.p(100, -100)}; + box:setPhysicsBody(cc.PhysicsBody:createPolygon(points)); + box:setPosition(VisibleRect:center()); + box:getPhysicsBody().tag = sliceTag; + layer:addChild(box); + end + + initWithLayer(layer, onEnter) + Helper.titleLabel:setString("Slice") + Helper.subtitleLabel:setString("click and drag to slice up the block") + + return layer end function PhysicsTest() - cclog("PhysicsTest") - local scene = cc.Scene:createWithPhysics() + cclog("PhysicsTest") + local scene = cc.Scene:createWithPhysics() + Helper.usePhysics = true Helper.createFunctionTable = { @@ -612,6 +935,10 @@ function PhysicsTest() PhysicsDemoClickAdd, PhysicsDemoRayCast, PhysicsDemoJoints, + PhysicsDemoActions, + PhysicsDemoPump, + PhysicsDemoOneWayPlatform, + PhysicsDemoSlice, } scene:addChild(Helper.createFunctionTable[1]()) diff --git a/tools/tolua/cocos2dx_physics.ini b/tools/tolua/cocos2dx_physics.ini index 7c6c3ed78f..84ca321e42 100644 --- a/tools/tolua/cocos2dx_physics.ini +++ b/tools/tolua/cocos2dx_physics.ini @@ -37,12 +37,13 @@ classes = Event(.*(Physics).*) Physics.* skip = PhysicsBody::[getJoints createPolygon createEdgeChain createEdgePolygon], PhysicsShape::[recenterPoints getPolyonCenter], - PhysicsShapeBox::[getPoints], - PhysicsShapeEdgeBox::[getPoints], - PhysicsShapePolygon::[getPoints], - PhysicsShapeEdgePolygon::[getPoints], - PhysicsShapeEdgeChain::[getPoints], - PhysicsWorld::[getScene queryPoint queryRect rayCast] + PhysicsShapeBox::[^getPoints$], + PhysicsShapeEdgeBox::[^getPoints$], + PhysicsShapePolygon::[^getPoints$], + PhysicsShapeEdgePolygon::[^getPoints$], + PhysicsShapeEdgeChain::[^getPoints$], + PhysicsWorld::[getScene queryPoint queryRect rayCast], + PhysicsContact::[getData setData] rename_functions =