2017-04-11 2 views
0

Ich habe lokalen Server läuft auf Nodejs mit Box2d bei Schwerelosigkeit. Und Client mit cocos2d-x. Wenn ich einige Bewegungsdaten von meinem Client austrage, bekommt der Server diese Bewegungsdaten und wendet sie auf die Objekte an. Das Problem betrifft Kollisionen. Wenn die Kraft auf ein dynamisches Objekt (Player) angewendet wird, kollidiert ein Objekt mit einem anderen dynamischen Objekt namens B (Ball) in der Schwerelosigkeitswelt. B Objekt schwebt niemals nach einer Kollision. Bewegt sich nur mit geringer Menge und stoppt plötzlich. (Ich habe versucht, linear auf 0 gesetzt Dämpfung und hält noch einmal.)Node.js Box2d Kollisionen funktioniert nicht wie erwartet bei Schwerelosigkeit?

Server-Seite-Codes:

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; 

alles funktioniert wenn ich einen "move" -Aufruf von meinem Client ausstelle. Kollisionen funktionieren jedoch nicht wie erwartet.

+0

ich denke, ich habe eine Lösung gefunden, die nicht zuverlässig ist. Stellen Sie die Schwerkraft einfach auf 0,0001 auf der Y-Achse ein. Impuls auf Objekte nach Kollisionen funktioniert jetzt. –

Antwort

0

Ihre Frage scheint im Wesentlichen zu sein: Warum stoppt der Körper plötzlich nach einer Kollision?

Dies kann aufgrund der Einstellung der Geschwindigkeitsschwelle (b2_velocityThreshold) der Fall sein. Der Quellcode-Kommentar hierzu (in der Basis 2.3.2 Box2D C++ - Code) besagt Folgendes über diese Einstellung:

Eine Geschwindigkeitsschwelle für elastische Kollisionen. Jede Kollision mit einer relativen linearen Geschwindigkeit unterhalb dieser Schwelle wird als unelastisch behandelt.

Und im "unelastischen" Fall wird keine Restitution angewendet; Nur die Positionsauflösung - die dazu dient, jede Überlappung der beiden Körper rückgängig zu machen, fügt ihnen jedoch keine Geschwindigkeit hinzu.

Wenn dies das Problem ist, kann die Geschwindigkeitsschwelleneinstellung auf Null gesenkt werden, um zu sehen, dass immer weniger Körper zur Ruhe kommen. Wenn der Geschwindigkeitsschwellenwert für Ihre Anwendung zu hoch ist, ist dies tatsächlich das Problem - und es hört sich so an, als ob er wirklich ist -, dann ist nicht die die richtige Lösung.

Beachten Sie, dass Erin Cato - wer der ursprüngliche Autor von Box2D ist - raises the following point über das, was man mit Absenken der Geschwindigkeitsschwelle auf Null erwarten:

Wenn Sie den Schwellenwert auf Null, nicht Null Restitution gesetzt wird Lass deine Körper für immer hüpfen.

Hoffe das beantwortet Ihre Frage.

+0

danke Louis, mein Problem ist wie das gleiche wie Sie oben erwähnt, ich löse dieses Problem durch Einstellen der Schwerkraft 0,0001 auf Y-Achse, die vernachlässigbar ist und irgendwelche Auswirkungen auf das System haben. Aber ich werde versuchen, velocity_threshold auf Null zu setzen und Sie darauf aufmerksam zu machen. –

Verwandte Themen