Node.js box2d碰撞不起作用,因为我预计在零重力?

问题描述:

我有本地服务器运行在box2d在零重力nodejs。和客户端使用cocos2d-x。当我从客户端发出一些移动数据时,服务器会获取这些移动数据并将其应用到对象。问题是关于碰撞。当强制应用于动态对象(玩家)时,对象在零重力世界与另一个名为B(球)的动态对象发生碰撞。 B对象在碰撞后不会漂浮。只需少量单位移动并突然停止。 (我试过设置线性衰减到0,它仍然突然停止。)Node.js box2d碰撞不起作用,因为我预计在零重力?

服务器端代码:

World.js

var Box2D = require('./box2d.js'); 
var s = require('./Server.js'); 

var b2Vec2 = Box2D.Common.Math.b2Vec2, 
    b2BodyDef = Box2D.Dynamics.b2BodyDef, 
    b2AABB = Box2D.Collision.b2AABB, 
    b2Body = Box2D.Dynamics.b2Body, 
    b2FixtureDef = Box2D.Dynamics.b2FixtureDef, 
    b2Fixture = Box2D.Dynamics.b2Fixture, 
    b2World = Box2D.Dynamics.b2World, 
    b2MassData = Box2D.Collision.Shapes.b2MassData, 
    b2PolygonShape = Box2D.Collision.Shapes.b2PolygonShape, 
    b2CircleShape = Box2D.Collision.Shapes.b2CircleShape, 
    b2DebugDraw = Box2D.Dynamics.b2DebugDraw, 
    b2MouseJointDef = Box2D.Dynamics.Joints.b2MouseJointDef, 
    b2EdgeShape = Box2D.Collision.Shapes.b2EdgeShape; 

function World(world, gravity, velocity, name, room) { 

    this._room = room; 
    this._name = name; 
    this._world = world; 
    this._gravity = gravity; 
    this._velocity = velocity; 
    this._gameElements = {}; 
    this._scale = 30; 
    this._interval; 

    this._size = 50; 
    this._w = 900; 
    this._h = 500; 
    this._fps = 60; 
    this._inteval; 

    this._PI2 = Math.PI * 2; 
    this._D2R = Math.PI/180; 
    this._R2D = 180/Math.PI; 
    this._debug = false; 

} 

World.prototype.startEnv = function() { 

    this._world = new b2World(new b2Vec2(0, this._gravity), true); 

    this.createArea(0, 0, this._w, 5, true); 
    this.createArea(0, this._h, this._w, 5, true); 
    this.createArea(0, 0, 5, this._h, true); 
    this.createArea(this._w, 0, 5, this._h, true); 

    this.createBox(0.1,450, 250, 12, 12, false, true, 'ball','ball'); 
    this.createBox(1,250,250, 25, 25, false, true, 'blue','anilgulgor'); 
    //this.createBox(650, 250, 25, 25, false, true, 'red', username); 

    this._inteval = setInterval(() => { 

     this.update(); 

    }, 1000/this._fps); 

    this.update(); 

} 

World.prototype.update = function() { 

    this._world.Step(1/this._fps, this._gravity, this._velocity); 

    this._gameElements = this.gameStep(); 

    s.emitObjectsToClients(this._room.name, this._gameElements); 

    console.log(this._gameElements + "name : " + this._name); 

    this._world.ClearForces(); 

} 



World.prototype.gameStep = function() { 

    var elements = []; 
    var i = 0; 
    for (var b = this._world.m_bodyList; b; b = b.m_next) { 
     for (var f = b.m_fixtureList; f; f = f.m_next) { 

      if (f.m_body.m_userData) { 

       var x = Math.floor(f.m_body.m_xf.position.x * this._scale); 
       var y = Math.floor(f.m_body.m_xf.position.y * this._scale); 
       var r = Math.round(((f.m_body.m_sweep.a + this._PI2) % this._PI2) * this._R2D * 100)/100; 
       var width = f.m_body.m_userData.width; 
       var height = f.m_body.m_userData.height; 
       var static = f.m_body.m_userData.static; 
       var type = f.m_body.m_userData.type; 

       var gameObj = { 

        x: x, 
        y: y, 
        r: r, 
        w: width, 
        h: height, 
        s: static, 
        t: type 
       } 

       elements.push(gameObj); 

      } 

     } 
    } 

    console.log(elements); 

    return { elements: elements }; 

} 

World.prototype.createBox = function (d,x, y, w2, h2, static, circle, type, username) { 

    var bodyDef = new b2BodyDef; 
    bodyDef.type = static ? b2Body.b2_staticBody : b2Body.b2_dynamicBody; 
    bodyDef.position.x = x/this._scale; 
    bodyDef.position.y = y/this._scale; 
    bodyDef.userData = { width: w2, height: h2, static: static, type: type, userName: username }; 
    bodyDef.allowSleep = false; 
    bodyDef.linearDamping = 0.5; 
    bodyDef.fixedRotation = true; 

    var fixDef = new b2FixtureDef; 
    fixDef.density = d; 
    fixDef.friction = 0.1; 
    fixDef.restitution = 1; 

    if (circle) { 
     var circleShape = new b2CircleShape; 
     circleShape.m_radius = w2/this._scale; 
     fixDef.shape = circleShape; 
    } else { 
     fixDef.shape = new b2PolygonShape; 
     fixDef.shape.SetAsBox(w2/this._scale, h2/this._scale); 
    } 

    return this._world.CreateBody(bodyDef).CreateFixture(fixDef); 

} 

World.prototype.applyForce = function (username, force) { 

    for (var b = this._world.m_bodyList; b; b = b.m_next) { 

     for (var f = b.m_fixtureList; f; f = f.m_next) { 

      if(f.m_body.m_userData){ 

      if (f.m_body.m_userData.userName == username) { 

       var forceVec = JSON.parse(force); 

       f.m_body.ApplyForce(new b2Vec2(forceVec.forceX, forceVec.forceY) , f.m_body.m_xf.position); 

       //f.m_body.SetLinearVelocity(new b2Vec2(forceVec.forceX, forceVec.forceY)); 

       console.log(forceVec.forceX + " " + forceVec.forceY); 

      } 

      } 

     } 

    } 

} 

World.prototype.createArea = function (x, y, w2, h2, static) { 

    var bodyDef = new b2BodyDef; 
    bodyDef.type = static ? b2Body.b2_staticBody : b2Body.b2_dynamicBody; 
    bodyDef.position.x = x/this._scale; 
    bodyDef.position.y = y/this._scale; 

    var fixDef = new b2FixtureDef; 
    fixDef.density = 1.5; 
    fixDef.friction = 0.2; 
    fixDef.restitution = 1.0; 

    fixDef.shape = new b2PolygonShape; 
    fixDef.shape.SetAsBox(w2/this._scale, h2/this._scale); 

    return this._world.CreateBody(bodyDef).CreateFixture(fixDef); 

} 

module.exports = World; 

Server.js

const http = require('http'); 
const express = require('express'); 
const socketIO = require('socket.io'); 
const World = require('./World.js'); 

var usernames = []; 
var roomToJoin; 

//port 
const port = process.env.PORT || 3000; 

var app = express(); 
var server = http.createServer(app); 
var io = socketIO(server); 

//server listen 
server.listen(port,() => { 

    console.log(`Server is on port ${port}`); 

}); 

io.on('connection', function (socket) { 

    //event fired when we get a new connection 
    console.log('user connected'); 

    socket.emit('connected', `connected to the server`); 

    //wait for addMe command with username parameter 
    socket.on('addMe', function (username) { 

     //Starting procedure of joining room 
     console.log(`${username} started addMe procedure to join room`); 

     //socket username is binded with client username 
     socket.username = username; 
     //socket room name is statically given. 
     socket.room = 'room1'; 
     //add username to the global username list 
     usernames.push(username); 



     if (roomToJoin != null) { 

      if (roomToJoin.length < 2) { 

       //room is available to join 

       //client join static room 
       socket.join(socket.room, (err) => { 

        if (!err) { 

         roomToJoin = io.sockets.adapter.rooms[socket.room]; 

         roomToJoin.name = socket.room; 

         console.log(roomToJoin.length + " clients in room"); 

         //join room sucessfully 
         socket.emit('connectedToRoom', `connected to the room name : ${socket.room}`); 

         //broadcast to another users in the room to warn that some user has connected 
         socket.broadcast.to(socket.room).emit('userConnectedToRoom', 'GameServer', `${username} has connected to the ${socket.room}`); 

         //room capacity is full right now 
         //we can start and emit world object positions to the clients 

         //startEmittingObjectPositionsToClients(roomToJoin); 

        } 
        else { 

         socket.emit('canNotConnectRoom', 'can not connect to the room'); 

        } 

       }); 

      } 

     } 
     else { 

      //there is no room name socket.room 

      socket.join(socket.room, (err) => { 

       if (!err) { 

        roomToJoin = io.sockets.adapter.rooms[socket.room]; 

        roomToJoin.name = socket.room; 

        console.log(roomToJoin.length + " clients in room"); 

        //world definition 
        var world; 
        var w = new World(world, 0, 100, `${socket.room} world`, roomToJoin); 
        // assign creator world to the roomToJoin.world 
        roomToJoin.world = w; 

        //join room sucessfully 
        socket.emit('connectedToRoom', `connected to the room name : ${socket.room}`); 

        //broadcast to another users in the room to warn that some user has connected 
        socket.broadcast.to(socket.room).emit('userConnectedToRoom', 'GameServer', `${username} has connected to the ${socket.room}`); 

        startEmittingObjectPositionsToClients(roomToJoin); 

       } 
       else { 

        socket.emit('canNotConnectRoom', 'can not connect to the room'); 

       } 

      }); 

     } 

    }); 

    socket.on('move', function(moveData) { 

     var room = io.sockets.adapter.rooms[socket.room]; 

     console.log(room); 

     room.world.applyForce('anilgulgor', moveData); 

     console.log(moveData); 

    }); 

}); 



function startEmittingObjectPositionsToClients(room) { 

    room.world.startEnv(); 

} 

function emitObjectsToClients(roomName, gameElements) { 

    console.log(roomName); 

    io.sockets.in(roomName).emit('worldStep', gameElements); 

    console.log('gönderdiiiiiiiiiiiim'); 

} 

module.exports.emitObjectsToClients = emitObjectsToClients; 

一切正常当我发出“移动”来自我的客户的电话。但碰撞不能按我的预期工作。

+0

我想我找到了一个不可靠的解决方案。在Y轴上将重力设置为0.0001。碰撞后对象的冲动现在就起作用。 –

你的问题似乎基本上是:为什么碰撞后身体突然停下来?

由于速度阈值设置(b2_velocityThreshold值),可能会发生这种情况。此源代码注释(在基本2.3.2 Box2D C++代码中)陈述了以下关于此设置的内容:

弹性碰撞的速度阈值。相对线速度低于此阈值的任何碰撞都将被视为非弹性。

而在“无弹性”情况下,不应用恢复原则;只有位置分辨率 - 它可以消除两个物体的重叠,但不会增加速度。

如果这是问题,那么速度阈值设置可以降低到零,以看到越来越少的身体休息。如果速度阈值对于您的应用来说太高,确实是问题 - 并且听起来确实如此 - 那么设置一个小但非零重力不是解决它的正确方法。

注意,艾琳卡托 - 谁是Box2D的原作者 - raises the following point什么人能降低速度阈值为零期待:

如果将门槛设定为零,非零恢复原状会导致你的身体永远反弹。

希望能回答你的问题。

+0

感谢路易斯,我的问题就像你上面提到的一样,我通过在Y轴上设置重力0.0001来解决这个问题,这是微不足道的,并且对系统有任何影响。但我会尝试将velocity_threshold设置为零并让您意识到。 –