Tuesday 11 April 2017

Node.js box2d collisions doesn't work as i expected at zero gravity?

i have local server runs on nodejs with box2d at zero gravity. And client with cocos2d-x. When i emit some movement data from my client, server gets and applies this movement data to the objects. Problem is about collisions. When force is applied to A dynamic object(Player), A object collides with another dynamic object called B (ball) at zero gravity world. B object never floats after collision. Just moves with small amount of unit and stops suddenly. ( i tried to set linear damping to 0 and it still stops suddenly.)

Server side 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;

Everything works when i emit "move" call from my client. But collisions don't work as i expected.



via anıl gülgör

No comments:

Post a Comment