Need help with fps socket server!

i am making a 3d fps shooter game. i have got the basics down, but i need help with the server. i am using socket.io. does anyone know how to make a server in socket.io for a fps game? my server right now does not work it when i shoot the other player, and the other player’s health gets to 0, i die, not the other player. can someone help?

1 Like

I found this tutorial series to be extremely helpful when learning the basics: Client-Server Game Architecture - Gabriel Gambetta

My advice is to be patient and take your time, netcode is tricky.

2 Likes

thanks! i already have the server basics down though. i am having problems with the shooter part. the player who is shooting at the other player dies instead of the player that is being shot at.

For each bullet, you need to track the ID of the player who fired it. When the bullet collides with a player, check it’s ID to make sure it’s a different ID to the shooter. And it sounds like you’re calling the die() function on the wrong player. Is your server code available somewhere?

1 Like

i am not using die()
this is my health script:

var Health2 = pc.createScript('health2');
Health2.attributes.add('deathScreen', {type : 'entity'});
Health2.attributes.add('mainScreen', {type : 'entity'});
// initialize code called once per entity
Health2.prototype.initialize = function() {
   this.health = 100;
   this.entity.findByName("Health").element.text = this.health;

};

// update code called every frame
Health2.prototype.update = function(dt) {
 if(this.health <= 0)
   {
   this.entity.script.enabled = false;
   this.deathScreen.enabled = true;
   this.mainScreen.enabled = false;
   }
};

Health2.prototype.takeDamage = function(damage) {
   this.health = this.health - damage;
   this.entity.findByName("Health").element.text = this.health;
};


// swap method called for script hot-reloading
// inherit your script state here
// Health.prototype.swap = function(old) { };

// to learn more about script anatomy, please read:
// https://developer.playcanvas.com/en/user-manual/scripting/

and my shooting script:

var Shoot = pc.createScript('shoot');

Shoot.attributes.add('maxAmmo', {type : 'number', default : 30});
Shoot.attributes.add('range', {type : 'number', default : 30});
Shoot.attributes.add('text', {type : 'entity'});
Shoot.attributes.add('text2', {type : 'entity'});
Shoot.attributes.add('particleSys', {type : 'entity'});
Shoot.attributes.add('debugColor1', {type : 'rgba'});
Shoot.attributes.add('gunPoint', {type : 'entity'});
Shoot.attributes.add('hitImpulse', {type : 'number', default : 10});
Shoot.attributes.add('damage', {type : 'number', default : 10});
Shoot.attributes.add('camera', {type : 'entity'});





// initialize code called once per entity
Shoot.prototype.initialize = function() {
    this.currentAmmo = 0;
    this.currentAmmo = this.maxAmmo;
    this.canShoot = true;
    this.damage = 10;
};

// update code called every frame
Shoot.prototype.update = function(dt) {
    var from = this.gunPoint.getPosition();
    var to = this.camera.camera.screenToWorld(screen.width / 2 , screen.height / 2 - 37, this.range);
    var result = this.app.systems.rigidbody.raycastFirst(from, to);    
    
    
    if(this.currentAmmo === 0)
    {
        this.canShoot = false;
    }
    else
    {
        this.canShoot = true;
    }
    
    
    if(this.app.mouse.wasPressed(pc.MOUSEBUTTON_LEFT) && this.canShoot === true)
    {
        if(result)
        {
            result.entity.collision.entity.rigidbody.applyImpulse(this.camera.forward.scale(this.hitImpulse), result.normal);
            this.currentAmmo -= 1;
            
        }else
        {
            return;
        }
        
                if (result && result.entity.name === "Other") {
            result.entity.script.health2.takeDamage(10);
        }

        this.particleSys.particlesystem.play();
        this.particleSys.particlesystem.reset();
        
    }
    
    
    
    if(this.app.keyboard.wasPressed(pc.KEY_R))
    {
        
        this.currentAmmo = this.currentAmmo + (this.maxAmmo - this.currentAmmo);
        
         
    }
    
    this.text.element.text = this.currentAmmo;
    this.text2.element.text = '/ ' + this.maxAmmo;
    
};

In your health script, this line: this.deathScreen.enabled = true; is causing the the death screen to appear regardless of which player’s health reached 0.

Add an if statement around that line and see if it fixes your problem.

if(this.entity.name != "Other"){
    this.deathScreen.enabled = true;
}
1 Like

it works! thanks! now here is another problem. when the other player hits 0, no death screen shows up on there screen at all! is there a way for my to send the player who died back to a different scene when their health hits 0?

Make sure the names are set up correctly. Using the name ‘Other’ isn’t ideal if you have more than 2 players. The player being controlled should be named ‘LocalPlayer’ or something like that and all other players should be named ‘RemotePlayer1’, ‘RemotePlayer2’ and so on. Then instead of checking this.entity.name != "Other" make it this.entity.name == 'LocalPlayer'.

its not working!
here is my health script now:

var Health2 = pc.createScript('health2');
Health2.attributes.add('deathScreen', {type : 'entity'});
Health2.attributes.add('mainScreen', {type : 'entity'});
// initialize code called once per entity
Health2.prototype.initialize = function() {
    this.health = 100;
    this.entity.findByName("Health").element.text = this.health;

};

// update code called every frame
Health2.prototype.update = function(dt) {
  if(this.health <= 0)
    {
if(this.entity.name == "LocalPlayer"){
    this.deathScreen.enabled = true;
}
    }
};

Health2.prototype.takeDamage = function(damage) {
    this.health = this.health - damage;
    this.entity.findByName("Health").element.text = this.health;
};



// swap method called for script hot-reloading
// inherit your script state here
// Health.prototype.swap = function(old) { };

// to learn more about script anatomy, please read:
// https://developer.playcanvas.com/en/user-manual/scripting/

now it is not doing anything. if i change the this.entity.name to RemotePlayer, then the death screen activates on the other player, not the player who is being shot at.

Where are you setting the entity names? Is the server generating an ID for each player and sending it when the clients connect?

idk here look at it. here is my project link: https://playcanvas.com/editor/scene/1242249

It’s not working because you’re still using ‘Player’ and ‘Other’ in several places. You don’t have to use my suggested Local/Remote naming convention, just pick one and stay consistent.

Argh it is not working still! it is just killing the player that is doing the shooting! is it because i am launching the game twice on the same device?

If the server is correctly assigning a unique ID for each new websocket connection, you will be able to open multiple clients on the same device without an issue.

However, you seem to be getting confused between logic that belongs on the server and logic that belongs on the client. I highly recommend you read up on game client server architecture. See my earlier post for an excellent guide.

Netcode is tricky, take some time, be patient, learn the basics and you’ll get there.

thank you so much for the help

1 Like