Networking: Host is receiving messages, but movement does not sync up

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
Post Reply
User avatar
Sammm
Prole
Posts: 37
Joined: Fri Sep 09, 2022 4:39 pm

Networking: Host is receiving messages, but movement does not sync up

Post by Sammm »

Hello!

This is a somewhat difficult question to answer, since it deals with networking, but I'm trying to make a basic multiplayer game. I followed this tutorial https://rvagamejams.com/learn2love/page ... art-1.html for the networking setup and movement, but the movement and entities weren't physics based. Therefore, I tried to add physics on my own. The movement now works for window the player is controlling and the host is receiving the messages as you can see here:
Screenshot 2022-09-24 9.36.58 AM.png
Screenshot 2022-09-24 9.36.58 AM.png (110.08 KiB) Viewed 1021 times
However, when I have both windows side by side, the movement is only being seen by the player itself. For all the other windows the movement is not synced, even though they are receiving the messages with the player's position. Here is my entity code:

Code: Select all

local input = require('input')

local entity = {}
entity.entities = {} --All entities

entity.spawn = function(id, x, y)
    local sprites = {
        blueSprite,
        yellowSprite,
        redSprite,
        purpleSprite,
    }
    local body = love.physics.newBody(world, x, y, "dynamic")
    local shape = love.physics.newCircleShape(100)
    return {
        sprite = sprites[(tonumber(id) % #sprites) + 1],
        id = id,
        x = x,
        y = y,
        body = body,
        shape = shape,
        fixture = love.physics.newFixture(body, shape)
    }
end

entity.draw = function(entity)
    love.graphics.setColor(1, 1, 1, 1)
    love.graphics.draw(entity.sprite, entity.body:getX(), entity.body:getY(), nil, 0.5, 0.5)
end

entity.move = function()
    local player = entity.entities[entity.id]

    if input.right then --press the right arrow key to push the ball to the right
        player.body:applyForce(400, 0)
    elseif input.left then --press the left arrow key to push the ball to the left
        player.body:applyForce(-400, 0)
    elseif input.up then --press the up arrow key to set the ball in the air
        player.body:applyLinearImpulse(0, -500)
    end

    player.x = player.body:getX()
    player.y = player.body:getY()

end

return entity
The server code for handling the movement:

Code: Select all

local message_handlers = {
	['move'] = function(message, event, is_server)
		local player_id = message[2]
		local x_pos = message[3]
		local y_pos = message[4]
		entity.entities[player_id].x = x_pos
		entity.entities[player_id].y = y_pos
		if is_server then
		-- Relay this message to the other players
			for id, peer in pairs(peers) do
				if id ~= player_id then
					peer:send(event.data)
				end
			end
		end
	end
}

local event_handlers = {

	connect = function(event, is_server)
		--Only server needs to do stuff during connect
		if is_server then
			local player = entity.spawn(tostring(event.peer:connect_id()), 100, 100) --connect_id() creates a number as an id
			entity.entities[player.id] = player --Store this player in the player table with the player ID as the key.
			event.peer:send('your-id|' .. player.id .. '|' .. player.x .. '|' .. player.y) -- Send the initial "your-id" message back to the connecting client so they can spawn this entity too.

			-- Let all the other peers know about this player
			for _, peer in pairs(peers) do
				local peer_player = entity.entities[tostring(peer:connect_id())]
				peer:send('peer-id|' .. player.id .. '|' .. player.x .. '|' .. player.y)
				event.peer:send('peer-id|' .. peer_player.id .. '|' .. player.x .. '|' .. player.y)
			end
			peers[tostring(event.peer:connect_id())] = event.peer --Add this peer to the peer list
		end
	end,
}
And the main.lua movement portion of the file

Code: Select all

   if entity.id then
        local player = entity.entities[entity.id]
        local old_x = player.x
        local old_y = player.y
        entity.move()
        if player.x ~= old_x or player.x ~= old_y then
            server.send('move|' .. player.id .. '|' .. player.x .. '|' .. player.y)
        end
    end

    server.update()
    world:update(dt)
As always, please try out the code yourself:
networking.zip
(67.69 KiB) Downloaded 49 times
networking.love
(33.59 KiB) Downloaded 45 times

I understand that this is quite a hard problem to track down, since I've been trying to figure it out myself for a few days now :cry:
Thanks for any help though!! I really appreciate it.
Lua is LÖVE, lua is life
User avatar
pgimeno
Party member
Posts: 3541
Joined: Sun Oct 18, 2015 2:58 pm

Re: Networking: Host is receiving messages, but movement does not sync up

Post by pgimeno »

It's not really about networking. Networking seems to be working fine.

You're updating the entity position with:

Code: Select all

                entity.entities[player_id].x = x_pos
                entity.entities[player_id].y = y_pos
However, you're not using the x and y fields later; at the time of drawing you're using:

Code: Select all

    love.graphics.draw(entity.sprite, entity.body:getX(), entity.body:getY(), ...)
If you don't update the physics object's position, you can't expect it to be updated. Setting the x and y fields won't update the physics body.

That's the immediate cause, but the fix is not so simple as using entity.body:setPosition(entity.x, entity.y). Something that is missing is the velocity, which is important for the physics engine, and you're not transmitting it.
User avatar
Sammm
Prole
Posts: 37
Joined: Fri Sep 09, 2022 4:39 pm

Re: Networking: Host is receiving messages, but movement does not sync up

Post by Sammm »

Thank you SO much! Passing the velocity finally solved the issue!! :D
Lua is LÖVE, lua is life
Post Reply

Who is online

Users browsing this forum: Ahrefs [Bot] and 10 guests